dri3_request.c revision 1b5d61b8
1/* 2 * Copyright © 2013 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_XORG_CONFIG_H 24#include <xorg-config.h> 25#endif 26 27#include "dri3_priv.h" 28#include <syncsrv.h> 29#include <unistd.h> 30#include <xace.h> 31#include "../Xext/syncsdk.h" 32#include <protocol-versions.h> 33#include <drm_fourcc.h> 34 35static Bool 36dri3_screen_can_one_point_two(ScreenPtr screen) 37{ 38 dri3_screen_priv_ptr dri3 = dri3_screen_priv(screen); 39 40 if (dri3 && dri3->info && dri3->info->version >= 2 && 41 dri3->info->pixmap_from_fds && dri3->info->fds_from_pixmap && 42 dri3->info->get_formats && dri3->info->get_modifiers && 43 dri3->info->get_drawable_modifiers) 44 return TRUE; 45 46 return FALSE; 47} 48 49static int 50proc_dri3_query_version(ClientPtr client) 51{ 52 REQUEST(xDRI3QueryVersionReq); 53 xDRI3QueryVersionReply rep = { 54 .type = X_Reply, 55 .sequenceNumber = client->sequence, 56 .length = 0, 57 .majorVersion = SERVER_DRI3_MAJOR_VERSION, 58 .minorVersion = SERVER_DRI3_MINOR_VERSION 59 }; 60 61 REQUEST_SIZE_MATCH(xDRI3QueryVersionReq); 62 63 for (int i = 0; i < screenInfo.numScreens; i++) { 64 if (!dri3_screen_can_one_point_two(screenInfo.screens[i])) { 65 rep.minorVersion = 0; 66 break; 67 } 68 } 69 70 for (int i = 0; i < screenInfo.numGPUScreens; i++) { 71 if (!dri3_screen_can_one_point_two(screenInfo.gpuscreens[i])) { 72 rep.minorVersion = 0; 73 break; 74 } 75 } 76 77 /* From DRI3 proto: 78 * 79 * The client sends the highest supported version to the server 80 * and the server sends the highest version it supports, but no 81 * higher than the requested version. 82 */ 83 84 if (rep.majorVersion > stuff->majorVersion || 85 (rep.majorVersion == stuff->majorVersion && 86 rep.minorVersion > stuff->minorVersion)) { 87 rep.majorVersion = stuff->majorVersion; 88 rep.minorVersion = stuff->minorVersion; 89 } 90 91 if (client->swapped) { 92 swaps(&rep.sequenceNumber); 93 swapl(&rep.length); 94 swapl(&rep.majorVersion); 95 swapl(&rep.minorVersion); 96 } 97 WriteToClient(client, sizeof(rep), &rep); 98 return Success; 99} 100 101int 102dri3_send_open_reply(ClientPtr client, int fd) 103{ 104 xDRI3OpenReply rep = { 105 .type = X_Reply, 106 .nfd = 1, 107 .sequenceNumber = client->sequence, 108 .length = 0, 109 }; 110 111 if (client->swapped) { 112 swaps(&rep.sequenceNumber); 113 swapl(&rep.length); 114 } 115 116 if (WriteFdToClient(client, fd, TRUE) < 0) { 117 close(fd); 118 return BadAlloc; 119 } 120 121 WriteToClient(client, sizeof (rep), &rep); 122 123 return Success; 124} 125 126static int 127proc_dri3_open(ClientPtr client) 128{ 129 REQUEST(xDRI3OpenReq); 130 RRProviderPtr provider; 131 DrawablePtr drawable; 132 ScreenPtr screen; 133 int fd; 134 int status; 135 136 REQUEST_SIZE_MATCH(xDRI3OpenReq); 137 138 status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess); 139 if (status != Success) 140 return status; 141 142 if (stuff->provider == None) 143 provider = NULL; 144 else if (!RRProviderType) { 145 return BadMatch; 146 } else { 147 VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); 148 if (drawable->pScreen != provider->pScreen) 149 return BadMatch; 150 } 151 screen = drawable->pScreen; 152 153 status = dri3_open(client, screen, provider, &fd); 154 if (status != Success) 155 return status; 156 157 if (client->ignoreCount == 0) 158 return dri3_send_open_reply(client, fd); 159 160 return Success; 161} 162 163static int 164proc_dri3_pixmap_from_buffer(ClientPtr client) 165{ 166 REQUEST(xDRI3PixmapFromBufferReq); 167 int fd; 168 DrawablePtr drawable; 169 PixmapPtr pixmap; 170 CARD32 stride, offset; 171 int rc; 172 173 SetReqFds(client, 1); 174 REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); 175 LEGAL_NEW_RESOURCE(stuff->pixmap, client); 176 rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); 177 if (rc != Success) { 178 client->errorValue = stuff->drawable; 179 return rc; 180 } 181 182 if (!stuff->width || !stuff->height) { 183 client->errorValue = 0; 184 return BadValue; 185 } 186 187 if (stuff->width > 32767 || stuff->height > 32767) 188 return BadAlloc; 189 190 if (stuff->depth != 1) { 191 DepthPtr depth = drawable->pScreen->allowedDepths; 192 int i; 193 for (i = 0; i < drawable->pScreen->numDepths; i++, depth++) 194 if (depth->depth == stuff->depth) 195 break; 196 if (i == drawable->pScreen->numDepths) { 197 client->errorValue = stuff->depth; 198 return BadValue; 199 } 200 } 201 202 fd = ReadFdFromClient(client); 203 if (fd < 0) 204 return BadValue; 205 206 offset = 0; 207 stride = stuff->stride; 208 rc = dri3_pixmap_from_fds(&pixmap, 209 drawable->pScreen, 1, &fd, 210 stuff->width, stuff->height, 211 &stride, &offset, 212 stuff->depth, stuff->bpp, 213 DRM_FORMAT_MOD_INVALID); 214 close (fd); 215 if (rc != Success) 216 return rc; 217 218 pixmap->drawable.id = stuff->pixmap; 219 220 /* security creation/labeling check */ 221 rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, 222 pixmap, RT_NONE, NULL, DixCreateAccess); 223 224 if (rc != Success) { 225 (*drawable->pScreen->DestroyPixmap) (pixmap); 226 return rc; 227 } 228 if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap)) 229 return BadAlloc; 230 231 return Success; 232} 233 234static int 235proc_dri3_buffer_from_pixmap(ClientPtr client) 236{ 237 REQUEST(xDRI3BufferFromPixmapReq); 238 xDRI3BufferFromPixmapReply rep = { 239 .type = X_Reply, 240 .nfd = 1, 241 .sequenceNumber = client->sequence, 242 .length = 0, 243 }; 244 int rc; 245 int fd; 246 PixmapPtr pixmap; 247 248 REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); 249 rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, 250 client, DixWriteAccess); 251 if (rc != Success) { 252 client->errorValue = stuff->pixmap; 253 return rc; 254 } 255 256 rep.width = pixmap->drawable.width; 257 rep.height = pixmap->drawable.height; 258 rep.depth = pixmap->drawable.depth; 259 rep.bpp = pixmap->drawable.bitsPerPixel; 260 261 fd = dri3_fd_from_pixmap(pixmap, &rep.stride, &rep.size); 262 if (fd < 0) 263 return BadPixmap; 264 265 if (client->swapped) { 266 swaps(&rep.sequenceNumber); 267 swapl(&rep.length); 268 swapl(&rep.size); 269 swaps(&rep.width); 270 swaps(&rep.height); 271 swaps(&rep.stride); 272 } 273 if (WriteFdToClient(client, fd, TRUE) < 0) { 274 close(fd); 275 return BadAlloc; 276 } 277 278 WriteToClient(client, sizeof(rep), &rep); 279 280 return Success; 281} 282 283static int 284proc_dri3_fence_from_fd(ClientPtr client) 285{ 286 REQUEST(xDRI3FenceFromFDReq); 287 DrawablePtr drawable; 288 int fd; 289 int status; 290 291 SetReqFds(client, 1); 292 REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); 293 LEGAL_NEW_RESOURCE(stuff->fence, client); 294 295 status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); 296 if (status != Success) 297 return status; 298 299 fd = ReadFdFromClient(client); 300 if (fd < 0) 301 return BadValue; 302 303 status = SyncCreateFenceFromFD(client, drawable, stuff->fence, 304 fd, stuff->initially_triggered); 305 306 return status; 307} 308 309static int 310proc_dri3_fd_from_fence(ClientPtr client) 311{ 312 REQUEST(xDRI3FDFromFenceReq); 313 xDRI3FDFromFenceReply rep = { 314 .type = X_Reply, 315 .nfd = 1, 316 .sequenceNumber = client->sequence, 317 .length = 0, 318 }; 319 DrawablePtr drawable; 320 int fd; 321 int status; 322 SyncFence *fence; 323 324 REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq); 325 326 status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); 327 if (status != Success) 328 return status; 329 status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess); 330 if (status != Success) 331 return status; 332 333 fd = SyncFDFromFence(client, drawable, fence); 334 if (fd < 0) 335 return BadMatch; 336 337 if (client->swapped) { 338 swaps(&rep.sequenceNumber); 339 swapl(&rep.length); 340 } 341 if (WriteFdToClient(client, fd, FALSE) < 0) 342 return BadAlloc; 343 344 WriteToClient(client, sizeof(rep), &rep); 345 346 return Success; 347} 348 349static int 350proc_dri3_get_supported_modifiers(ClientPtr client) 351{ 352 REQUEST(xDRI3GetSupportedModifiersReq); 353 xDRI3GetSupportedModifiersReply rep = { 354 .type = X_Reply, 355 .sequenceNumber = client->sequence, 356 }; 357 WindowPtr window; 358 ScreenPtr pScreen; 359 CARD64 *window_modifiers = NULL; 360 CARD64 *screen_modifiers = NULL; 361 CARD32 nwindowmodifiers = 0; 362 CARD32 nscreenmodifiers = 0; 363 int status; 364 int i; 365 366 REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq); 367 368 status = dixLookupWindow(&window, stuff->window, client, DixReadAccess); 369 if (status != Success) 370 return status; 371 pScreen = window->drawable.pScreen; 372 373 dri3_get_supported_modifiers(pScreen, &window->drawable, 374 stuff->depth, stuff->bpp, 375 &nwindowmodifiers, &window_modifiers, 376 &nscreenmodifiers, &screen_modifiers); 377 378 rep.numWindowModifiers = nwindowmodifiers; 379 rep.numScreenModifiers = nscreenmodifiers; 380 rep.length = bytes_to_int32(rep.numWindowModifiers * sizeof(CARD64)) + 381 bytes_to_int32(rep.numScreenModifiers * sizeof(CARD64)); 382 383 if (client->swapped) { 384 swaps(&rep.sequenceNumber); 385 swapl(&rep.length); 386 swapl(&rep.numWindowModifiers); 387 swapl(&rep.numScreenModifiers); 388 for (i = 0; i < nwindowmodifiers; i++) 389 swapll(&window_modifiers[i]); 390 for (i = 0; i < nscreenmodifiers; i++) 391 swapll(&screen_modifiers[i]); 392 } 393 394 WriteToClient(client, sizeof(rep), &rep); 395 WriteToClient(client, nwindowmodifiers * sizeof(CARD64), window_modifiers); 396 WriteToClient(client, nscreenmodifiers * sizeof(CARD64), screen_modifiers); 397 398 free(window_modifiers); 399 free(screen_modifiers); 400 401 return Success; 402} 403 404static int 405proc_dri3_pixmap_from_buffers(ClientPtr client) 406{ 407 REQUEST(xDRI3PixmapFromBuffersReq); 408 int fds[4]; 409 CARD32 strides[4], offsets[4]; 410 ScreenPtr screen; 411 WindowPtr window; 412 PixmapPtr pixmap; 413 int rc; 414 int i; 415 416 SetReqFds(client, stuff->num_buffers); 417 REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq); 418 LEGAL_NEW_RESOURCE(stuff->pixmap, client); 419 rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); 420 if (rc != Success) { 421 client->errorValue = stuff->window; 422 return rc; 423 } 424 screen = window->drawable.pScreen; 425 426 if (!stuff->width || !stuff->height || !stuff->bpp || !stuff->depth) { 427 client->errorValue = 0; 428 return BadValue; 429 } 430 431 if (stuff->width > 32767 || stuff->height > 32767) 432 return BadAlloc; 433 434 if (stuff->depth != 1) { 435 DepthPtr depth = screen->allowedDepths; 436 int j; 437 for (j = 0; j < screen->numDepths; j++, depth++) 438 if (depth->depth == stuff->depth) 439 break; 440 if (j == screen->numDepths) { 441 client->errorValue = stuff->depth; 442 return BadValue; 443 } 444 } 445 446 if (!stuff->num_buffers || stuff->num_buffers > 4) { 447 client->errorValue = stuff->num_buffers; 448 return BadValue; 449 } 450 451 for (i = 0; i < stuff->num_buffers; i++) { 452 fds[i] = ReadFdFromClient(client); 453 if (fds[i] < 0) { 454 while (--i >= 0) 455 close(fds[i]); 456 return BadValue; 457 } 458 } 459 460 strides[0] = stuff->stride0; 461 strides[1] = stuff->stride1; 462 strides[2] = stuff->stride2; 463 strides[3] = stuff->stride3; 464 offsets[0] = stuff->offset0; 465 offsets[1] = stuff->offset1; 466 offsets[2] = stuff->offset2; 467 offsets[3] = stuff->offset3; 468 469 rc = dri3_pixmap_from_fds(&pixmap, screen, 470 stuff->num_buffers, fds, 471 stuff->width, stuff->height, 472 strides, offsets, 473 stuff->depth, stuff->bpp, 474 stuff->modifier); 475 476 for (i = 0; i < stuff->num_buffers; i++) 477 close (fds[i]); 478 479 if (rc != Success) 480 return rc; 481 482 pixmap->drawable.id = stuff->pixmap; 483 484 /* security creation/labeling check */ 485 rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, 486 pixmap, RT_NONE, NULL, DixCreateAccess); 487 488 if (rc != Success) { 489 (*screen->DestroyPixmap) (pixmap); 490 return rc; 491 } 492 if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap)) 493 return BadAlloc; 494 495 return Success; 496} 497 498static int 499proc_dri3_buffers_from_pixmap(ClientPtr client) 500{ 501 REQUEST(xDRI3BuffersFromPixmapReq); 502 xDRI3BuffersFromPixmapReply rep = { 503 .type = X_Reply, 504 .sequenceNumber = client->sequence, 505 }; 506 int rc; 507 int fds[4]; 508 int num_fds; 509 uint32_t strides[4], offsets[4]; 510 uint64_t modifier; 511 int i; 512 PixmapPtr pixmap; 513 514 REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq); 515 rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, 516 client, DixWriteAccess); 517 if (rc != Success) { 518 client->errorValue = stuff->pixmap; 519 return rc; 520 } 521 522 num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier); 523 if (num_fds == 0) 524 return BadPixmap; 525 526 rep.nfd = num_fds; 527 rep.length = bytes_to_int32(num_fds * 2 * sizeof(CARD32)); 528 rep.width = pixmap->drawable.width; 529 rep.height = pixmap->drawable.height; 530 rep.depth = pixmap->drawable.depth; 531 rep.bpp = pixmap->drawable.bitsPerPixel; 532 rep.modifier = modifier; 533 534 if (client->swapped) { 535 swaps(&rep.sequenceNumber); 536 swapl(&rep.length); 537 swaps(&rep.width); 538 swaps(&rep.height); 539 swapll(&rep.modifier); 540 for (i = 0; i < num_fds; i++) { 541 swapl(&strides[i]); 542 swapl(&offsets[i]); 543 } 544 } 545 546 for (i = 0; i < num_fds; i++) { 547 if (WriteFdToClient(client, fds[i], TRUE) < 0) { 548 while (i--) 549 close(fds[i]); 550 return BadAlloc; 551 } 552 } 553 554 WriteToClient(client, sizeof(rep), &rep); 555 WriteToClient(client, num_fds * sizeof(CARD32), strides); 556 WriteToClient(client, num_fds * sizeof(CARD32), offsets); 557 558 return Success; 559} 560 561int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { 562 proc_dri3_query_version, /* 0 */ 563 proc_dri3_open, /* 1 */ 564 proc_dri3_pixmap_from_buffer, /* 2 */ 565 proc_dri3_buffer_from_pixmap, /* 3 */ 566 proc_dri3_fence_from_fd, /* 4 */ 567 proc_dri3_fd_from_fence, /* 5 */ 568 proc_dri3_get_supported_modifiers, /* 6 */ 569 proc_dri3_pixmap_from_buffers, /* 7 */ 570 proc_dri3_buffers_from_pixmap, /* 8 */ 571}; 572 573int 574proc_dri3_dispatch(ClientPtr client) 575{ 576 REQUEST(xReq); 577 if (!client->local) 578 return BadMatch; 579 if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data]) 580 return BadRequest; 581 return (*proc_dri3_vector[stuff->data]) (client); 582} 583 584static int _X_COLD 585sproc_dri3_query_version(ClientPtr client) 586{ 587 REQUEST(xDRI3QueryVersionReq); 588 REQUEST_SIZE_MATCH(xDRI3QueryVersionReq); 589 590 swaps(&stuff->length); 591 swapl(&stuff->majorVersion); 592 swapl(&stuff->minorVersion); 593 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 594} 595 596static int _X_COLD 597sproc_dri3_open(ClientPtr client) 598{ 599 REQUEST(xDRI3OpenReq); 600 REQUEST_SIZE_MATCH(xDRI3OpenReq); 601 602 swaps(&stuff->length); 603 swapl(&stuff->drawable); 604 swapl(&stuff->provider); 605 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 606} 607 608static int _X_COLD 609sproc_dri3_pixmap_from_buffer(ClientPtr client) 610{ 611 REQUEST(xDRI3PixmapFromBufferReq); 612 REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); 613 614 swaps(&stuff->length); 615 swapl(&stuff->pixmap); 616 swapl(&stuff->drawable); 617 swapl(&stuff->size); 618 swaps(&stuff->width); 619 swaps(&stuff->height); 620 swaps(&stuff->stride); 621 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 622} 623 624static int _X_COLD 625sproc_dri3_buffer_from_pixmap(ClientPtr client) 626{ 627 REQUEST(xDRI3BufferFromPixmapReq); 628 REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); 629 630 swaps(&stuff->length); 631 swapl(&stuff->pixmap); 632 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 633} 634 635static int _X_COLD 636sproc_dri3_fence_from_fd(ClientPtr client) 637{ 638 REQUEST(xDRI3FenceFromFDReq); 639 REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); 640 641 swaps(&stuff->length); 642 swapl(&stuff->drawable); 643 swapl(&stuff->fence); 644 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 645} 646 647static int _X_COLD 648sproc_dri3_fd_from_fence(ClientPtr client) 649{ 650 REQUEST(xDRI3FDFromFenceReq); 651 REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq); 652 653 swaps(&stuff->length); 654 swapl(&stuff->drawable); 655 swapl(&stuff->fence); 656 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 657} 658 659static int _X_COLD 660sproc_dri3_get_supported_modifiers(ClientPtr client) 661{ 662 REQUEST(xDRI3GetSupportedModifiersReq); 663 REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq); 664 665 swaps(&stuff->length); 666 swapl(&stuff->window); 667 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 668} 669 670static int _X_COLD 671sproc_dri3_pixmap_from_buffers(ClientPtr client) 672{ 673 REQUEST(xDRI3PixmapFromBuffersReq); 674 REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq); 675 676 swaps(&stuff->length); 677 swapl(&stuff->pixmap); 678 swapl(&stuff->window); 679 swaps(&stuff->width); 680 swaps(&stuff->height); 681 swapl(&stuff->stride0); 682 swapl(&stuff->offset0); 683 swapl(&stuff->stride1); 684 swapl(&stuff->offset1); 685 swapl(&stuff->stride2); 686 swapl(&stuff->offset2); 687 swapl(&stuff->stride3); 688 swapl(&stuff->offset3); 689 swapll(&stuff->modifier); 690 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 691} 692 693static int _X_COLD 694sproc_dri3_buffers_from_pixmap(ClientPtr client) 695{ 696 REQUEST(xDRI3BuffersFromPixmapReq); 697 REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq); 698 699 swaps(&stuff->length); 700 swapl(&stuff->pixmap); 701 return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 702} 703 704int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { 705 sproc_dri3_query_version, /* 0 */ 706 sproc_dri3_open, /* 1 */ 707 sproc_dri3_pixmap_from_buffer, /* 2 */ 708 sproc_dri3_buffer_from_pixmap, /* 3 */ 709 sproc_dri3_fence_from_fd, /* 4 */ 710 sproc_dri3_fd_from_fence, /* 5 */ 711 sproc_dri3_get_supported_modifiers, /* 6 */ 712 sproc_dri3_pixmap_from_buffers, /* 7 */ 713 sproc_dri3_buffers_from_pixmap, /* 8 */ 714}; 715 716int _X_COLD 717sproc_dri3_dispatch(ClientPtr client) 718{ 719 REQUEST(xReq); 720 if (!client->local) 721 return BadMatch; 722 if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data]) 723 return BadRequest; 724 return (*sproc_dri3_vector[stuff->data]) (client); 725} 726