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 
35 static Bool
dri3_screen_can_one_point_two(ScreenPtr screen)36 dri3_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 
49 static int
proc_dri3_query_version(ClientPtr client)50 proc_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 
101 int
dri3_send_open_reply(ClientPtr client,int fd)102 dri3_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 
126 static int
proc_dri3_open(ClientPtr client)127 proc_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, DixGetAttrAccess);
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 
163 static int
proc_dri3_pixmap_from_buffer(ClientPtr client)164 proc_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 
234 static int
proc_dri3_buffer_from_pixmap(ClientPtr client)235 proc_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 
283 static int
proc_dri3_fence_from_fd(ClientPtr client)284 proc_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 
309 static int
proc_dri3_fd_from_fence(ClientPtr client)310 proc_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 
349 static int
proc_dri3_get_supported_modifiers(ClientPtr client)350 proc_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, DixGetAttrAccess);
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 
404 static int
proc_dri3_pixmap_from_buffers(ClientPtr client)405 proc_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 
498 static int
proc_dri3_buffers_from_pixmap(ClientPtr client)499 proc_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 
561 int (*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 
573 int
proc_dri3_dispatch(ClientPtr client)574 proc_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 
584 static int _X_COLD
sproc_dri3_query_version(ClientPtr client)585 sproc_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 
596 static int _X_COLD
sproc_dri3_open(ClientPtr client)597 sproc_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 
608 static int _X_COLD
sproc_dri3_pixmap_from_buffer(ClientPtr client)609 sproc_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 
624 static int _X_COLD
sproc_dri3_buffer_from_pixmap(ClientPtr client)625 sproc_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 
635 static int _X_COLD
sproc_dri3_fence_from_fd(ClientPtr client)636 sproc_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 
647 static int _X_COLD
sproc_dri3_fd_from_fence(ClientPtr client)648 sproc_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 
659 static int _X_COLD
sproc_dri3_get_supported_modifiers(ClientPtr client)660 sproc_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 
670 static int _X_COLD
sproc_dri3_pixmap_from_buffers(ClientPtr client)671 sproc_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 
693 static int _X_COLD
sproc_dri3_buffers_from_pixmap(ClientPtr client)694 sproc_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 
704 int (*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 
716 int _X_COLD
sproc_dri3_dispatch(ClientPtr client)717 sproc_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