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