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