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