xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/dri2/dri2ext.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2008 Red Hat, Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Soft-
6*4882a593Smuzhiyun  * ware"), to deal in the Software without restriction, including without
7*4882a593Smuzhiyun  * limitation the rights to use, copy, modify, merge, publish, distribute,
8*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun  * Software is furnished to do so, provided that the above copyright
10*4882a593Smuzhiyun  * notice(s) and this permission notice appear in all copies of the Soft-
11*4882a593Smuzhiyun  * ware and that both the above copyright notice(s) and this permission
12*4882a593Smuzhiyun  * notice appear in supporting documentation.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15*4882a593Smuzhiyun  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16*4882a593Smuzhiyun  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17*4882a593Smuzhiyun  * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18*4882a593Smuzhiyun  * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19*4882a593Smuzhiyun  * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22*4882a593Smuzhiyun  * MANCE OF THIS SOFTWARE.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  * Except as contained in this notice, the name of a copyright holder shall
25*4882a593Smuzhiyun  * not be used in advertising or otherwise to promote the sale, use or
26*4882a593Smuzhiyun  * other dealings in this Software without prior written authorization of
27*4882a593Smuzhiyun  * the copyright holder.
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * Authors:
30*4882a593Smuzhiyun  *   Kristian Høgsberg (krh@redhat.com)
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
34*4882a593Smuzhiyun #include <xorg-config.h>
35*4882a593Smuzhiyun #endif
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include <X11/X.h>
38*4882a593Smuzhiyun #include <X11/Xproto.h>
39*4882a593Smuzhiyun #include <X11/extensions/dri2proto.h>
40*4882a593Smuzhiyun #include <X11/extensions/xfixeswire.h>
41*4882a593Smuzhiyun #include "dixstruct.h"
42*4882a593Smuzhiyun #include "scrnintstr.h"
43*4882a593Smuzhiyun #include "pixmapstr.h"
44*4882a593Smuzhiyun #include "extnsionst.h"
45*4882a593Smuzhiyun #include "xfixes.h"
46*4882a593Smuzhiyun #include "dri2.h"
47*4882a593Smuzhiyun #include "dri2int.h"
48*4882a593Smuzhiyun #include "protocol-versions.h"
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /* The only xf86 includes */
51*4882a593Smuzhiyun #include "xf86Module.h"
52*4882a593Smuzhiyun #include "xf86Extensions.h"
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun static int DRI2EventBase;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun static Bool
validDrawable(ClientPtr client,XID drawable,Mask access_mode,DrawablePtr * pDrawable,int * status)58*4882a593Smuzhiyun validDrawable(ClientPtr client, XID drawable, Mask access_mode,
59*4882a593Smuzhiyun               DrawablePtr *pDrawable, int *status)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun     *status = dixLookupDrawable(pDrawable, drawable, client,
62*4882a593Smuzhiyun                                 M_DRAWABLE_WINDOW | M_DRAWABLE_PIXMAP,
63*4882a593Smuzhiyun                                 access_mode);
64*4882a593Smuzhiyun     if (*status != Success) {
65*4882a593Smuzhiyun         client->errorValue = drawable;
66*4882a593Smuzhiyun         return FALSE;
67*4882a593Smuzhiyun     }
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun     return TRUE;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun static int
ProcDRI2QueryVersion(ClientPtr client)73*4882a593Smuzhiyun ProcDRI2QueryVersion(ClientPtr client)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun     REQUEST(xDRI2QueryVersionReq);
76*4882a593Smuzhiyun     xDRI2QueryVersionReply rep = {
77*4882a593Smuzhiyun         .type = X_Reply,
78*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
79*4882a593Smuzhiyun         .length = 0,
80*4882a593Smuzhiyun         .majorVersion = dri2_major,
81*4882a593Smuzhiyun         .minorVersion = dri2_minor
82*4882a593Smuzhiyun     };
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun     if (client->swapped)
85*4882a593Smuzhiyun         swaps(&stuff->length);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2QueryVersionReq);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun     if (client->swapped) {
90*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
91*4882a593Smuzhiyun         swapl(&rep.length);
92*4882a593Smuzhiyun         swapl(&rep.majorVersion);
93*4882a593Smuzhiyun         swapl(&rep.minorVersion);
94*4882a593Smuzhiyun     }
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun     return Success;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun static int
ProcDRI2Connect(ClientPtr client)102*4882a593Smuzhiyun ProcDRI2Connect(ClientPtr client)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun     REQUEST(xDRI2ConnectReq);
105*4882a593Smuzhiyun     xDRI2ConnectReply rep = {
106*4882a593Smuzhiyun         .type = X_Reply,
107*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
108*4882a593Smuzhiyun         .length = 0,
109*4882a593Smuzhiyun         .driverNameLength = 0,
110*4882a593Smuzhiyun         .deviceNameLength = 0
111*4882a593Smuzhiyun     };
112*4882a593Smuzhiyun     DrawablePtr pDraw;
113*4882a593Smuzhiyun     int fd, status;
114*4882a593Smuzhiyun     const char *driverName;
115*4882a593Smuzhiyun     const char *deviceName;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2ConnectReq);
118*4882a593Smuzhiyun     if (!validDrawable(client, stuff->window, DixGetAttrAccess,
119*4882a593Smuzhiyun                        &pDraw, &status))
120*4882a593Smuzhiyun         return status;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun     if (!DRI2Connect(client, pDraw->pScreen,
123*4882a593Smuzhiyun                      stuff->driverType, &fd, &driverName, &deviceName))
124*4882a593Smuzhiyun         goto fail;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun     rep.driverNameLength = strlen(driverName);
127*4882a593Smuzhiyun     rep.deviceNameLength = strlen(deviceName);
128*4882a593Smuzhiyun     rep.length = (rep.driverNameLength + 3) / 4 +
129*4882a593Smuzhiyun         (rep.deviceNameLength + 3) / 4;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun  fail:
132*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2ConnectReply), &rep);
133*4882a593Smuzhiyun     WriteToClient(client, rep.driverNameLength, driverName);
134*4882a593Smuzhiyun     WriteToClient(client, rep.deviceNameLength, deviceName);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun     return Success;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static int
ProcDRI2Authenticate(ClientPtr client)140*4882a593Smuzhiyun ProcDRI2Authenticate(ClientPtr client)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun     REQUEST(xDRI2AuthenticateReq);
143*4882a593Smuzhiyun     xDRI2AuthenticateReply rep;
144*4882a593Smuzhiyun     DrawablePtr pDraw;
145*4882a593Smuzhiyun     int status;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2AuthenticateReq);
148*4882a593Smuzhiyun     if (!validDrawable(client, stuff->window, DixGetAttrAccess,
149*4882a593Smuzhiyun                        &pDraw, &status))
150*4882a593Smuzhiyun         return status;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun     rep = (xDRI2AuthenticateReply) {
153*4882a593Smuzhiyun         .type = X_Reply,
154*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
155*4882a593Smuzhiyun         .length = 0,
156*4882a593Smuzhiyun         .authenticated = DRI2Authenticate(client, pDraw->pScreen, stuff->magic)
157*4882a593Smuzhiyun     };
158*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun     return Success;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun static void
DRI2InvalidateBuffersEvent(DrawablePtr pDraw,void * priv,XID id)164*4882a593Smuzhiyun DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv, XID id)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun     ClientPtr client = priv;
167*4882a593Smuzhiyun     xDRI2InvalidateBuffers event = {
168*4882a593Smuzhiyun         .type = DRI2EventBase + DRI2_InvalidateBuffers,
169*4882a593Smuzhiyun         .drawable = id
170*4882a593Smuzhiyun     };
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun     WriteEventsToClient(client, 1, (xEvent *) &event);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun static int
ProcDRI2CreateDrawable(ClientPtr client)176*4882a593Smuzhiyun ProcDRI2CreateDrawable(ClientPtr client)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun     REQUEST(xDRI2CreateDrawableReq);
179*4882a593Smuzhiyun     DrawablePtr pDrawable;
180*4882a593Smuzhiyun     int status;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixAddAccess,
185*4882a593Smuzhiyun                        &pDrawable, &status))
186*4882a593Smuzhiyun         return status;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun     status = DRI2CreateDrawable(client, pDrawable, stuff->drawable,
189*4882a593Smuzhiyun                                 DRI2InvalidateBuffersEvent, client);
190*4882a593Smuzhiyun     if (status != Success)
191*4882a593Smuzhiyun         return status;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun     return Success;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun static int
ProcDRI2DestroyDrawable(ClientPtr client)197*4882a593Smuzhiyun ProcDRI2DestroyDrawable(ClientPtr client)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun     REQUEST(xDRI2DestroyDrawableReq);
200*4882a593Smuzhiyun     DrawablePtr pDrawable;
201*4882a593Smuzhiyun     int status;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2DestroyDrawableReq);
204*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixRemoveAccess,
205*4882a593Smuzhiyun                        &pDrawable, &status))
206*4882a593Smuzhiyun         return status;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun     return Success;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun static int
send_buffers_reply(ClientPtr client,DrawablePtr pDrawable,DRI2BufferPtr * buffers,int count,int width,int height)212*4882a593Smuzhiyun send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
213*4882a593Smuzhiyun                    DRI2BufferPtr * buffers, int count, int width, int height)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun     xDRI2GetBuffersReply rep;
216*4882a593Smuzhiyun     int skip = 0;
217*4882a593Smuzhiyun     int i;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun     if (buffers == NULL)
220*4882a593Smuzhiyun         return BadAlloc;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun     if (pDrawable->type == DRAWABLE_WINDOW) {
223*4882a593Smuzhiyun         for (i = 0; i < count; i++) {
224*4882a593Smuzhiyun             /* Do not send the real front buffer of a window to the client.
225*4882a593Smuzhiyun              */
226*4882a593Smuzhiyun             if (buffers[i]->attachment == DRI2BufferFrontLeft) {
227*4882a593Smuzhiyun                 skip++;
228*4882a593Smuzhiyun                 continue;
229*4882a593Smuzhiyun             }
230*4882a593Smuzhiyun         }
231*4882a593Smuzhiyun     }
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun     rep = (xDRI2GetBuffersReply) {
234*4882a593Smuzhiyun         .type = X_Reply,
235*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
236*4882a593Smuzhiyun         .length = (count - skip) * sizeof(xDRI2Buffer) / 4,
237*4882a593Smuzhiyun         .width = width,
238*4882a593Smuzhiyun         .height = height,
239*4882a593Smuzhiyun         .count = count - skip
240*4882a593Smuzhiyun     };
241*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun     for (i = 0; i < count; i++) {
244*4882a593Smuzhiyun         xDRI2Buffer buffer;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun         /* Do not send the real front buffer of a window to the client.
247*4882a593Smuzhiyun          */
248*4882a593Smuzhiyun         if ((pDrawable->type == DRAWABLE_WINDOW)
249*4882a593Smuzhiyun             && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
250*4882a593Smuzhiyun             continue;
251*4882a593Smuzhiyun         }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun         buffer.attachment = buffers[i]->attachment;
254*4882a593Smuzhiyun         buffer.name = buffers[i]->name;
255*4882a593Smuzhiyun         buffer.pitch = buffers[i]->pitch;
256*4882a593Smuzhiyun         buffer.cpp = buffers[i]->cpp;
257*4882a593Smuzhiyun         buffer.flags = buffers[i]->flags;
258*4882a593Smuzhiyun         WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
259*4882a593Smuzhiyun     }
260*4882a593Smuzhiyun     return Success;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun static int
ProcDRI2GetBuffers(ClientPtr client)264*4882a593Smuzhiyun ProcDRI2GetBuffers(ClientPtr client)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun     REQUEST(xDRI2GetBuffersReq);
267*4882a593Smuzhiyun     DrawablePtr pDrawable;
268*4882a593Smuzhiyun     DRI2BufferPtr *buffers;
269*4882a593Smuzhiyun     int status, width, height, count;
270*4882a593Smuzhiyun     unsigned int *attachments;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xDRI2GetBuffersReq);
273*4882a593Smuzhiyun     /* stuff->count is a count of CARD32 attachments that follows */
274*4882a593Smuzhiyun     if (stuff->count > (INT_MAX / sizeof(CARD32)))
275*4882a593Smuzhiyun         return BadLength;
276*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * sizeof(CARD32));
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
279*4882a593Smuzhiyun                        &pDrawable, &status))
280*4882a593Smuzhiyun         return status;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun     if (DRI2ThrottleClient(client, pDrawable))
283*4882a593Smuzhiyun         return Success;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun     attachments = (unsigned int *) &stuff[1];
286*4882a593Smuzhiyun     buffers = DRI2GetBuffers(pDrawable, &width, &height,
287*4882a593Smuzhiyun                              attachments, stuff->count, &count);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun     return send_buffers_reply(client, pDrawable, buffers, count, width, height);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun static int
ProcDRI2GetBuffersWithFormat(ClientPtr client)294*4882a593Smuzhiyun ProcDRI2GetBuffersWithFormat(ClientPtr client)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun     REQUEST(xDRI2GetBuffersReq);
297*4882a593Smuzhiyun     DrawablePtr pDrawable;
298*4882a593Smuzhiyun     DRI2BufferPtr *buffers;
299*4882a593Smuzhiyun     int status, width, height, count;
300*4882a593Smuzhiyun     unsigned int *attachments;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xDRI2GetBuffersReq);
303*4882a593Smuzhiyun     /* stuff->count is a count of pairs of CARD32s (attachments & formats)
304*4882a593Smuzhiyun        that follows */
305*4882a593Smuzhiyun     if (stuff->count > (INT_MAX / (2 * sizeof(CARD32))))
306*4882a593Smuzhiyun         return BadLength;
307*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xDRI2GetBuffersReq,
308*4882a593Smuzhiyun                        stuff->count * (2 * sizeof(CARD32)));
309*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
310*4882a593Smuzhiyun                        &pDrawable, &status))
311*4882a593Smuzhiyun         return status;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun     if (DRI2ThrottleClient(client, pDrawable))
314*4882a593Smuzhiyun         return Success;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun     attachments = (unsigned int *) &stuff[1];
317*4882a593Smuzhiyun     buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
318*4882a593Smuzhiyun                                        attachments, stuff->count, &count);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun     return send_buffers_reply(client, pDrawable, buffers, count, width, height);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun static int
ProcDRI2CopyRegion(ClientPtr client)324*4882a593Smuzhiyun ProcDRI2CopyRegion(ClientPtr client)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun     REQUEST(xDRI2CopyRegionReq);
327*4882a593Smuzhiyun     xDRI2CopyRegionReply rep;
328*4882a593Smuzhiyun     DrawablePtr pDrawable;
329*4882a593Smuzhiyun     int status;
330*4882a593Smuzhiyun     RegionPtr pRegion;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2CopyRegionReq);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixWriteAccess,
335*4882a593Smuzhiyun                        &pDrawable, &status))
336*4882a593Smuzhiyun         return status;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun     VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun     status = DRI2CopyRegion(pDrawable, pRegion, stuff->dest, stuff->src);
341*4882a593Smuzhiyun     if (status != Success)
342*4882a593Smuzhiyun         return status;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun     /* CopyRegion needs to be a round trip to make sure the X server
345*4882a593Smuzhiyun      * queues the swap buffer rendering commands before the DRI client
346*4882a593Smuzhiyun      * continues rendering.  The reply has a bitmask to signal the
347*4882a593Smuzhiyun      * presense of optional return values as well, but we're not using
348*4882a593Smuzhiyun      * that yet.
349*4882a593Smuzhiyun      */
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun     rep = (xDRI2CopyRegionReply) {
352*4882a593Smuzhiyun         .type = X_Reply,
353*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
354*4882a593Smuzhiyun         .length = 0
355*4882a593Smuzhiyun     };
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2CopyRegionReply), &rep);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun     return Success;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun static void
load_swap_reply(xDRI2SwapBuffersReply * rep,CARD64 sbc)363*4882a593Smuzhiyun load_swap_reply(xDRI2SwapBuffersReply * rep, CARD64 sbc)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun     rep->swap_hi = sbc >> 32;
366*4882a593Smuzhiyun     rep->swap_lo = sbc & 0xffffffff;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun static CARD64
vals_to_card64(CARD32 lo,CARD32 hi)370*4882a593Smuzhiyun vals_to_card64(CARD32 lo, CARD32 hi)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun     return (CARD64) hi << 32 | lo;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun static void
DRI2SwapEvent(ClientPtr client,void * data,int type,CARD64 ust,CARD64 msc,CARD32 sbc)376*4882a593Smuzhiyun DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc,
377*4882a593Smuzhiyun               CARD32 sbc)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun     DrawablePtr pDrawable = data;
380*4882a593Smuzhiyun     xDRI2BufferSwapComplete2 event = {
381*4882a593Smuzhiyun         .type = DRI2EventBase + DRI2_BufferSwapComplete,
382*4882a593Smuzhiyun         .event_type = type,
383*4882a593Smuzhiyun         .drawable = pDrawable->id,
384*4882a593Smuzhiyun         .ust_hi = (CARD64) ust >> 32,
385*4882a593Smuzhiyun         .ust_lo = ust & 0xffffffff,
386*4882a593Smuzhiyun         .msc_hi = (CARD64) msc >> 32,
387*4882a593Smuzhiyun         .msc_lo = msc & 0xffffffff,
388*4882a593Smuzhiyun         .sbc = sbc
389*4882a593Smuzhiyun     };
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     WriteEventsToClient(client, 1, (xEvent *) &event);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun static int
ProcDRI2SwapBuffers(ClientPtr client)395*4882a593Smuzhiyun ProcDRI2SwapBuffers(ClientPtr client)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun     REQUEST(xDRI2SwapBuffersReq);
398*4882a593Smuzhiyun     xDRI2SwapBuffersReply rep = {
399*4882a593Smuzhiyun         .type = X_Reply,
400*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
401*4882a593Smuzhiyun         .length = 0
402*4882a593Smuzhiyun     };
403*4882a593Smuzhiyun     DrawablePtr pDrawable;
404*4882a593Smuzhiyun     CARD64 target_msc, divisor, remainder, swap_target;
405*4882a593Smuzhiyun     int status;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable,
410*4882a593Smuzhiyun                        DixReadAccess | DixWriteAccess, &pDrawable, &status))
411*4882a593Smuzhiyun         return status;
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun     /*
414*4882a593Smuzhiyun      * Ensures an out of control client can't exhaust our swap queue, and
415*4882a593Smuzhiyun      * also orders swaps.
416*4882a593Smuzhiyun      */
417*4882a593Smuzhiyun     if (DRI2ThrottleClient(client, pDrawable))
418*4882a593Smuzhiyun         return Success;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
421*4882a593Smuzhiyun     divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
422*4882a593Smuzhiyun     remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun     status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
425*4882a593Smuzhiyun                              &swap_target, DRI2SwapEvent, pDrawable);
426*4882a593Smuzhiyun     if (status != Success)
427*4882a593Smuzhiyun         return BadDrawable;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun     load_swap_reply(&rep, swap_target);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun     return Success;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun static void
load_msc_reply(xDRI2MSCReply * rep,CARD64 ust,CARD64 msc,CARD64 sbc)437*4882a593Smuzhiyun load_msc_reply(xDRI2MSCReply * rep, CARD64 ust, CARD64 msc, CARD64 sbc)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun     rep->ust_hi = ust >> 32;
440*4882a593Smuzhiyun     rep->ust_lo = ust & 0xffffffff;
441*4882a593Smuzhiyun     rep->msc_hi = msc >> 32;
442*4882a593Smuzhiyun     rep->msc_lo = msc & 0xffffffff;
443*4882a593Smuzhiyun     rep->sbc_hi = sbc >> 32;
444*4882a593Smuzhiyun     rep->sbc_lo = sbc & 0xffffffff;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun static int
ProcDRI2GetMSC(ClientPtr client)448*4882a593Smuzhiyun ProcDRI2GetMSC(ClientPtr client)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun     REQUEST(xDRI2GetMSCReq);
451*4882a593Smuzhiyun     xDRI2MSCReply rep = {
452*4882a593Smuzhiyun         .type = X_Reply,
453*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
454*4882a593Smuzhiyun         .length = 0
455*4882a593Smuzhiyun     };
456*4882a593Smuzhiyun     DrawablePtr pDrawable;
457*4882a593Smuzhiyun     CARD64 ust, msc, sbc;
458*4882a593Smuzhiyun     int status;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2GetMSCReq);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
463*4882a593Smuzhiyun                        &status))
464*4882a593Smuzhiyun         return status;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun     status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc);
467*4882a593Smuzhiyun     if (status != Success)
468*4882a593Smuzhiyun         return status;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun     load_msc_reply(&rep, ust, msc, sbc);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun     return Success;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun static int
ProcDRI2WaitMSC(ClientPtr client)478*4882a593Smuzhiyun ProcDRI2WaitMSC(ClientPtr client)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun     REQUEST(xDRI2WaitMSCReq);
481*4882a593Smuzhiyun     DrawablePtr pDrawable;
482*4882a593Smuzhiyun     CARD64 target, divisor, remainder;
483*4882a593Smuzhiyun     int status;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun     /* FIXME: in restart case, client may be gone at this point */
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2WaitMSCReq);
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
490*4882a593Smuzhiyun                        &status))
491*4882a593Smuzhiyun         return status;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun     target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
494*4882a593Smuzhiyun     divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
495*4882a593Smuzhiyun     remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun     status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder);
498*4882a593Smuzhiyun     if (status != Success)
499*4882a593Smuzhiyun         return status;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun     return Success;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun int
ProcDRI2WaitMSCReply(ClientPtr client,CARD64 ust,CARD64 msc,CARD64 sbc)505*4882a593Smuzhiyun ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun     xDRI2MSCReply rep = {
508*4882a593Smuzhiyun         .type = X_Reply,
509*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
510*4882a593Smuzhiyun         .length = 0
511*4882a593Smuzhiyun     };
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun     load_msc_reply(&rep, ust, msc, sbc);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun     return Success;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun static int
ProcDRI2SwapInterval(ClientPtr client)521*4882a593Smuzhiyun ProcDRI2SwapInterval(ClientPtr client)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun     REQUEST(xDRI2SwapIntervalReq);
524*4882a593Smuzhiyun     DrawablePtr pDrawable;
525*4882a593Smuzhiyun     int status;
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun     /* FIXME: in restart case, client may be gone at this point */
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq);
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
532*4882a593Smuzhiyun                        &pDrawable, &status))
533*4882a593Smuzhiyun         return status;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun     DRI2SwapInterval(pDrawable, stuff->interval);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun     return Success;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun static int
ProcDRI2WaitSBC(ClientPtr client)541*4882a593Smuzhiyun ProcDRI2WaitSBC(ClientPtr client)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun     REQUEST(xDRI2WaitSBCReq);
544*4882a593Smuzhiyun     DrawablePtr pDrawable;
545*4882a593Smuzhiyun     CARD64 target;
546*4882a593Smuzhiyun     int status;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2WaitSBCReq);
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
551*4882a593Smuzhiyun                        &status))
552*4882a593Smuzhiyun         return status;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun     target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi);
555*4882a593Smuzhiyun     status = DRI2WaitSBC(client, pDrawable, target);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun     return status;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun static int
ProcDRI2GetParam(ClientPtr client)561*4882a593Smuzhiyun ProcDRI2GetParam(ClientPtr client)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun     REQUEST(xDRI2GetParamReq);
564*4882a593Smuzhiyun     xDRI2GetParamReply rep = {
565*4882a593Smuzhiyun         .type = X_Reply,
566*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
567*4882a593Smuzhiyun         .length = 0
568*4882a593Smuzhiyun     };
569*4882a593Smuzhiyun     DrawablePtr pDrawable;
570*4882a593Smuzhiyun     CARD64 value;
571*4882a593Smuzhiyun     int status;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDRI2GetParamReq);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun     if (!validDrawable(client, stuff->drawable, DixReadAccess,
576*4882a593Smuzhiyun                        &pDrawable, &status))
577*4882a593Smuzhiyun         return status;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun     status = DRI2GetParam(client, pDrawable, stuff->param,
580*4882a593Smuzhiyun                           &rep.is_param_recognized, &value);
581*4882a593Smuzhiyun     rep.value_hi = value >> 32;
582*4882a593Smuzhiyun     rep.value_lo = value & 0xffffffff;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun     if (status != Success)
585*4882a593Smuzhiyun         return status;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2GetParamReply), &rep);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun     return status;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun static int
ProcDRI2Dispatch(ClientPtr client)593*4882a593Smuzhiyun ProcDRI2Dispatch(ClientPtr client)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun     REQUEST(xReq);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun     switch (stuff->data) {
598*4882a593Smuzhiyun     case X_DRI2QueryVersion:
599*4882a593Smuzhiyun         return ProcDRI2QueryVersion(client);
600*4882a593Smuzhiyun     }
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun     if (!client->local)
603*4882a593Smuzhiyun         return BadRequest;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun     switch (stuff->data) {
606*4882a593Smuzhiyun     case X_DRI2Connect:
607*4882a593Smuzhiyun         return ProcDRI2Connect(client);
608*4882a593Smuzhiyun     case X_DRI2Authenticate:
609*4882a593Smuzhiyun         return ProcDRI2Authenticate(client);
610*4882a593Smuzhiyun     case X_DRI2CreateDrawable:
611*4882a593Smuzhiyun         return ProcDRI2CreateDrawable(client);
612*4882a593Smuzhiyun     case X_DRI2DestroyDrawable:
613*4882a593Smuzhiyun         return ProcDRI2DestroyDrawable(client);
614*4882a593Smuzhiyun     case X_DRI2GetBuffers:
615*4882a593Smuzhiyun         return ProcDRI2GetBuffers(client);
616*4882a593Smuzhiyun     case X_DRI2CopyRegion:
617*4882a593Smuzhiyun         return ProcDRI2CopyRegion(client);
618*4882a593Smuzhiyun     case X_DRI2GetBuffersWithFormat:
619*4882a593Smuzhiyun         return ProcDRI2GetBuffersWithFormat(client);
620*4882a593Smuzhiyun     case X_DRI2SwapBuffers:
621*4882a593Smuzhiyun         return ProcDRI2SwapBuffers(client);
622*4882a593Smuzhiyun     case X_DRI2GetMSC:
623*4882a593Smuzhiyun         return ProcDRI2GetMSC(client);
624*4882a593Smuzhiyun     case X_DRI2WaitMSC:
625*4882a593Smuzhiyun         return ProcDRI2WaitMSC(client);
626*4882a593Smuzhiyun     case X_DRI2WaitSBC:
627*4882a593Smuzhiyun         return ProcDRI2WaitSBC(client);
628*4882a593Smuzhiyun     case X_DRI2SwapInterval:
629*4882a593Smuzhiyun         return ProcDRI2SwapInterval(client);
630*4882a593Smuzhiyun     case X_DRI2GetParam:
631*4882a593Smuzhiyun         return ProcDRI2GetParam(client);
632*4882a593Smuzhiyun     default:
633*4882a593Smuzhiyun         return BadRequest;
634*4882a593Smuzhiyun     }
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun static int _X_COLD
SProcDRI2Connect(ClientPtr client)638*4882a593Smuzhiyun SProcDRI2Connect(ClientPtr client)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun     REQUEST(xDRI2ConnectReq);
641*4882a593Smuzhiyun     xDRI2ConnectReply rep = {
642*4882a593Smuzhiyun         .type = X_Reply,
643*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
644*4882a593Smuzhiyun         .length = 0,
645*4882a593Smuzhiyun         .driverNameLength = 0,
646*4882a593Smuzhiyun         .deviceNameLength = 0
647*4882a593Smuzhiyun     };
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun     /* If the client is swapped, it's not local.  Talk to the hand. */
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun     swaps(&stuff->length);
652*4882a593Smuzhiyun     if (sizeof(*stuff) / 4 != client->req_len)
653*4882a593Smuzhiyun         return BadLength;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun     swaps(&rep.sequenceNumber);
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun     WriteToClient(client, sizeof(xDRI2ConnectReply), &rep);
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun     return Success;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun static int _X_COLD
SProcDRI2Dispatch(ClientPtr client)663*4882a593Smuzhiyun SProcDRI2Dispatch(ClientPtr client)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun     REQUEST(xReq);
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun     /*
668*4882a593Smuzhiyun      * Only local clients are allowed DRI access, but remote clients
669*4882a593Smuzhiyun      * still need these requests to find out cleanly.
670*4882a593Smuzhiyun      */
671*4882a593Smuzhiyun     switch (stuff->data) {
672*4882a593Smuzhiyun     case X_DRI2QueryVersion:
673*4882a593Smuzhiyun         return ProcDRI2QueryVersion(client);
674*4882a593Smuzhiyun     case X_DRI2Connect:
675*4882a593Smuzhiyun         return SProcDRI2Connect(client);
676*4882a593Smuzhiyun     default:
677*4882a593Smuzhiyun         return BadRequest;
678*4882a593Smuzhiyun     }
679*4882a593Smuzhiyun }
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun void
DRI2ExtensionInit(void)682*4882a593Smuzhiyun DRI2ExtensionInit(void)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun     ExtensionEntry *dri2Extension;
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun #ifdef PANORAMIX
687*4882a593Smuzhiyun     if (!noPanoramiXExtension)
688*4882a593Smuzhiyun         return;
689*4882a593Smuzhiyun #endif
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun     dri2Extension = AddExtension(DRI2_NAME,
692*4882a593Smuzhiyun                                  DRI2NumberEvents,
693*4882a593Smuzhiyun                                  DRI2NumberErrors,
694*4882a593Smuzhiyun                                  ProcDRI2Dispatch,
695*4882a593Smuzhiyun                                  SProcDRI2Dispatch, NULL, StandardMinorOpcode);
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun     DRI2EventBase = dri2Extension->eventBase;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun     DRI2ModuleSetup();
700*4882a593Smuzhiyun }
701