xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/dri/xf86dri.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /**************************************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4*4882a593Smuzhiyun Copyright 2000 VA Linux Systems, Inc.
5*4882a593Smuzhiyun All Rights Reserved.
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun Permission is hereby granted, free of charge, to any person obtaining a
8*4882a593Smuzhiyun copy of this software and associated documentation files (the
9*4882a593Smuzhiyun "Software"), to deal in the Software without restriction, including
10*4882a593Smuzhiyun without limitation the rights to use, copy, modify, merge, publish,
11*4882a593Smuzhiyun distribute, sub license, and/or sell copies of the Software, and to
12*4882a593Smuzhiyun permit persons to whom the Software is furnished to do so, subject to
13*4882a593Smuzhiyun the following conditions:
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun The above copyright notice and this permission notice (including the
16*4882a593Smuzhiyun next paragraph) shall be included in all copies or substantial portions
17*4882a593Smuzhiyun of the Software.
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20*4882a593Smuzhiyun OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21*4882a593Smuzhiyun MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22*4882a593Smuzhiyun IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23*4882a593Smuzhiyun ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24*4882a593Smuzhiyun TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25*4882a593Smuzhiyun SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun **************************************************************************/
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun  * Authors:
31*4882a593Smuzhiyun  *   Kevin E. Martin <martin@valinux.com>
32*4882a593Smuzhiyun  *   Jens Owen <jens@tungstengraphics.com>
33*4882a593Smuzhiyun  *   Rickard E. (Rik) Faith <faith@valinux.com>
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  */
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
38*4882a593Smuzhiyun #include <xorg-config.h>
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include <string.h>
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #include "xf86.h"
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #include <X11/X.h>
46*4882a593Smuzhiyun #include <X11/Xproto.h>
47*4882a593Smuzhiyun #include "misc.h"
48*4882a593Smuzhiyun #include "dixstruct.h"
49*4882a593Smuzhiyun #include "extnsionst.h"
50*4882a593Smuzhiyun #include "extinit.h"
51*4882a593Smuzhiyun #include "colormapst.h"
52*4882a593Smuzhiyun #include "cursorstr.h"
53*4882a593Smuzhiyun #include "scrnintstr.h"
54*4882a593Smuzhiyun #include "servermd.h"
55*4882a593Smuzhiyun #define _XF86DRI_SERVER_
56*4882a593Smuzhiyun #include <X11/dri/xf86driproto.h>
57*4882a593Smuzhiyun #include "swaprep.h"
58*4882a593Smuzhiyun #include "xf86str.h"
59*4882a593Smuzhiyun #include "dri.h"
60*4882a593Smuzhiyun #include "sarea.h"
61*4882a593Smuzhiyun #include "dristruct.h"
62*4882a593Smuzhiyun #include "xf86drm.h"
63*4882a593Smuzhiyun #include "protocol-versions.h"
64*4882a593Smuzhiyun #include "xf86Extensions.h"
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static int DRIErrorBase;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun static void XF86DRIResetProc(ExtensionEntry *extEntry);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static unsigned char DRIReqCode = 0;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun /*ARGSUSED*/
73*4882a593Smuzhiyun static void
XF86DRIResetProc(ExtensionEntry * extEntry)74*4882a593Smuzhiyun XF86DRIResetProc(ExtensionEntry *extEntry)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun     DRIReset();
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun static int
ProcXF86DRIQueryVersion(register ClientPtr client)80*4882a593Smuzhiyun ProcXF86DRIQueryVersion(register ClientPtr client)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun     xXF86DRIQueryVersionReply rep = {
83*4882a593Smuzhiyun         .type = X_Reply,
84*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
85*4882a593Smuzhiyun         .length = 0,
86*4882a593Smuzhiyun         .majorVersion = SERVER_XF86DRI_MAJOR_VERSION,
87*4882a593Smuzhiyun         .minorVersion = SERVER_XF86DRI_MINOR_VERSION,
88*4882a593Smuzhiyun         .patchVersion = SERVER_XF86DRI_PATCH_VERSION
89*4882a593Smuzhiyun     };
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq);
92*4882a593Smuzhiyun     if (client->swapped) {
93*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
94*4882a593Smuzhiyun         swapl(&rep.length);
95*4882a593Smuzhiyun         swaps(&rep.majorVersion);
96*4882a593Smuzhiyun         swaps(&rep.minorVersion);
97*4882a593Smuzhiyun         swapl(&rep.patchVersion);
98*4882a593Smuzhiyun     }
99*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), &rep);
100*4882a593Smuzhiyun     return Success;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun static int
ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)104*4882a593Smuzhiyun ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun     xXF86DRIQueryDirectRenderingCapableReply rep;
107*4882a593Smuzhiyun     Bool isCapable;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun     REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
110*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
111*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
112*4882a593Smuzhiyun         client->errorValue = stuff->screen;
113*4882a593Smuzhiyun         return BadValue;
114*4882a593Smuzhiyun     }
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun     if (!DRIQueryDirectRenderingCapable(screenInfo.screens[stuff->screen],
117*4882a593Smuzhiyun                                         &isCapable)) {
118*4882a593Smuzhiyun         return BadValue;
119*4882a593Smuzhiyun     }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun     if (!client->local || client->swapped)
122*4882a593Smuzhiyun         isCapable = 0;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     rep = (xXF86DRIQueryDirectRenderingCapableReply) {
125*4882a593Smuzhiyun         .type = X_Reply,
126*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
127*4882a593Smuzhiyun         .length = 0,
128*4882a593Smuzhiyun         .isCapable = isCapable
129*4882a593Smuzhiyun     };
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     if (client->swapped) {
132*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
133*4882a593Smuzhiyun         swapl(&rep.length);
134*4882a593Smuzhiyun     }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun     WriteToClient(client,
137*4882a593Smuzhiyun                   sizeof(xXF86DRIQueryDirectRenderingCapableReply),
138*4882a593Smuzhiyun                   &rep);
139*4882a593Smuzhiyun     return Success;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun static int
ProcXF86DRIOpenConnection(register ClientPtr client)143*4882a593Smuzhiyun ProcXF86DRIOpenConnection(register ClientPtr client)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun     xXF86DRIOpenConnectionReply rep;
146*4882a593Smuzhiyun     drm_handle_t hSAREA;
147*4882a593Smuzhiyun     char *busIdString;
148*4882a593Smuzhiyun     CARD32 busIdStringLength = 0;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun     REQUEST(xXF86DRIOpenConnectionReq);
151*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq);
152*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
153*4882a593Smuzhiyun         client->errorValue = stuff->screen;
154*4882a593Smuzhiyun         return BadValue;
155*4882a593Smuzhiyun     }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun     if (!DRIOpenConnection(screenInfo.screens[stuff->screen],
158*4882a593Smuzhiyun                            &hSAREA, &busIdString)) {
159*4882a593Smuzhiyun         return BadValue;
160*4882a593Smuzhiyun     }
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun     if (busIdString)
163*4882a593Smuzhiyun         busIdStringLength = strlen(busIdString);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun     rep = (xXF86DRIOpenConnectionReply) {
166*4882a593Smuzhiyun         .type = X_Reply,
167*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
168*4882a593Smuzhiyun         .length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) -
169*4882a593Smuzhiyun                                  SIZEOF(xGenericReply) +
170*4882a593Smuzhiyun                                  pad_to_int32(busIdStringLength)),
171*4882a593Smuzhiyun         .busIdStringLength = busIdStringLength,
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun         .hSAREALow = (CARD32) (hSAREA & 0xffffffff),
174*4882a593Smuzhiyun #if defined(LONG64) && !defined(__linux__)
175*4882a593Smuzhiyun         .hSAREAHigh = (CARD32) (hSAREA >> 32),
176*4882a593Smuzhiyun #else
177*4882a593Smuzhiyun         .hSAREAHigh = 0
178*4882a593Smuzhiyun #endif
179*4882a593Smuzhiyun     };
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), &rep);
182*4882a593Smuzhiyun     if (busIdStringLength)
183*4882a593Smuzhiyun         WriteToClient(client, busIdStringLength, busIdString);
184*4882a593Smuzhiyun     return Success;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun static int
ProcXF86DRIAuthConnection(register ClientPtr client)188*4882a593Smuzhiyun ProcXF86DRIAuthConnection(register ClientPtr client)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun     xXF86DRIAuthConnectionReply rep = {
191*4882a593Smuzhiyun         .type = X_Reply,
192*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
193*4882a593Smuzhiyun         .length = 0,
194*4882a593Smuzhiyun         .authenticated = 1
195*4882a593Smuzhiyun     };
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun     REQUEST(xXF86DRIAuthConnectionReq);
198*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq);
199*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
200*4882a593Smuzhiyun         client->errorValue = stuff->screen;
201*4882a593Smuzhiyun         return BadValue;
202*4882a593Smuzhiyun     }
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun     if (!DRIAuthConnection(screenInfo.screens[stuff->screen], stuff->magic)) {
205*4882a593Smuzhiyun         ErrorF("Failed to authenticate %lu\n", (unsigned long) stuff->magic);
206*4882a593Smuzhiyun         rep.authenticated = 0;
207*4882a593Smuzhiyun     }
208*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), &rep);
209*4882a593Smuzhiyun     return Success;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun static int
ProcXF86DRICloseConnection(register ClientPtr client)213*4882a593Smuzhiyun ProcXF86DRICloseConnection(register ClientPtr client)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun     REQUEST(xXF86DRICloseConnectionReq);
216*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq);
217*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
218*4882a593Smuzhiyun         client->errorValue = stuff->screen;
219*4882a593Smuzhiyun         return BadValue;
220*4882a593Smuzhiyun     }
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun     DRICloseConnection(screenInfo.screens[stuff->screen]);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun     return Success;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun static int
ProcXF86DRIGetClientDriverName(register ClientPtr client)228*4882a593Smuzhiyun ProcXF86DRIGetClientDriverName(register ClientPtr client)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun     xXF86DRIGetClientDriverNameReply rep = {
231*4882a593Smuzhiyun         .type = X_Reply,
232*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
233*4882a593Smuzhiyun         .clientDriverNameLength = 0
234*4882a593Smuzhiyun     };
235*4882a593Smuzhiyun     char *clientDriverName;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     REQUEST(xXF86DRIGetClientDriverNameReq);
238*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq);
239*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
240*4882a593Smuzhiyun         client->errorValue = stuff->screen;
241*4882a593Smuzhiyun         return BadValue;
242*4882a593Smuzhiyun     }
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun     DRIGetClientDriverName(screenInfo.screens[stuff->screen],
245*4882a593Smuzhiyun                            (int *) &rep.ddxDriverMajorVersion,
246*4882a593Smuzhiyun                            (int *) &rep.ddxDriverMinorVersion,
247*4882a593Smuzhiyun                            (int *) &rep.ddxDriverPatchVersion,
248*4882a593Smuzhiyun                            &clientDriverName);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun     if (clientDriverName)
251*4882a593Smuzhiyun         rep.clientDriverNameLength = strlen(clientDriverName);
252*4882a593Smuzhiyun     rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) -
253*4882a593Smuzhiyun                                 SIZEOF(xGenericReply) +
254*4882a593Smuzhiyun                                 pad_to_int32(rep.clientDriverNameLength));
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRIGetClientDriverNameReply), &rep);
257*4882a593Smuzhiyun     if (rep.clientDriverNameLength)
258*4882a593Smuzhiyun         WriteToClient(client, rep.clientDriverNameLength, clientDriverName);
259*4882a593Smuzhiyun     return Success;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun static int
ProcXF86DRICreateContext(register ClientPtr client)263*4882a593Smuzhiyun ProcXF86DRICreateContext(register ClientPtr client)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun     xXF86DRICreateContextReply rep = {
266*4882a593Smuzhiyun         .type = X_Reply,
267*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
268*4882a593Smuzhiyun         .length = 0
269*4882a593Smuzhiyun     };
270*4882a593Smuzhiyun     ScreenPtr pScreen;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     REQUEST(xXF86DRICreateContextReq);
273*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRICreateContextReq);
274*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
275*4882a593Smuzhiyun         client->errorValue = stuff->screen;
276*4882a593Smuzhiyun         return BadValue;
277*4882a593Smuzhiyun     }
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun     pScreen = screenInfo.screens[stuff->screen];
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun     if (!DRICreateContext(pScreen,
282*4882a593Smuzhiyun                           NULL,
283*4882a593Smuzhiyun                           stuff->context, (drm_context_t *) &rep.hHWContext)) {
284*4882a593Smuzhiyun         return BadValue;
285*4882a593Smuzhiyun     }
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRICreateContextReply), &rep);
288*4882a593Smuzhiyun     return Success;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun static int
ProcXF86DRIDestroyContext(register ClientPtr client)292*4882a593Smuzhiyun ProcXF86DRIDestroyContext(register ClientPtr client)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun     REQUEST(xXF86DRIDestroyContextReq);
295*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq);
296*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
297*4882a593Smuzhiyun         client->errorValue = stuff->screen;
298*4882a593Smuzhiyun         return BadValue;
299*4882a593Smuzhiyun     }
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     if (!DRIDestroyContext(screenInfo.screens[stuff->screen], stuff->context)) {
302*4882a593Smuzhiyun         return BadValue;
303*4882a593Smuzhiyun     }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     return Success;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun static int
ProcXF86DRICreateDrawable(ClientPtr client)309*4882a593Smuzhiyun ProcXF86DRICreateDrawable(ClientPtr client)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun     xXF86DRICreateDrawableReply rep = {
312*4882a593Smuzhiyun         .type = X_Reply,
313*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
314*4882a593Smuzhiyun         .length = 0
315*4882a593Smuzhiyun     };
316*4882a593Smuzhiyun     DrawablePtr pDrawable;
317*4882a593Smuzhiyun     int rc;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun     REQUEST(xXF86DRICreateDrawableReq);
320*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq);
321*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
322*4882a593Smuzhiyun         client->errorValue = stuff->screen;
323*4882a593Smuzhiyun         return BadValue;
324*4882a593Smuzhiyun     }
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun     rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
327*4882a593Smuzhiyun                            DixReadAccess);
328*4882a593Smuzhiyun     if (rc != Success)
329*4882a593Smuzhiyun         return rc;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun     if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client,
332*4882a593Smuzhiyun                            pDrawable, (drm_drawable_t *) &rep.hHWDrawable)) {
333*4882a593Smuzhiyun         return BadValue;
334*4882a593Smuzhiyun     }
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), &rep);
337*4882a593Smuzhiyun     return Success;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun static int
ProcXF86DRIDestroyDrawable(register ClientPtr client)341*4882a593Smuzhiyun ProcXF86DRIDestroyDrawable(register ClientPtr client)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun     REQUEST(xXF86DRIDestroyDrawableReq);
344*4882a593Smuzhiyun     DrawablePtr pDrawable;
345*4882a593Smuzhiyun     int rc;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
350*4882a593Smuzhiyun         client->errorValue = stuff->screen;
351*4882a593Smuzhiyun         return BadValue;
352*4882a593Smuzhiyun     }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun     rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
355*4882a593Smuzhiyun                            DixReadAccess);
356*4882a593Smuzhiyun     if (rc != Success)
357*4882a593Smuzhiyun         return rc;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun     if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client,
360*4882a593Smuzhiyun                             pDrawable)) {
361*4882a593Smuzhiyun         return BadValue;
362*4882a593Smuzhiyun     }
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun     return Success;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun static int
ProcXF86DRIGetDrawableInfo(register ClientPtr client)368*4882a593Smuzhiyun ProcXF86DRIGetDrawableInfo(register ClientPtr client)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun     xXF86DRIGetDrawableInfoReply rep = {
371*4882a593Smuzhiyun         .type = X_Reply,
372*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
373*4882a593Smuzhiyun         .length = 0
374*4882a593Smuzhiyun     };
375*4882a593Smuzhiyun     DrawablePtr pDrawable;
376*4882a593Smuzhiyun     int X, Y, W, H;
377*4882a593Smuzhiyun     drm_clip_rect_t *pClipRects, *pClippedRects;
378*4882a593Smuzhiyun     drm_clip_rect_t *pBackClipRects;
379*4882a593Smuzhiyun     int backX, backY, rc;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun     REQUEST(xXF86DRIGetDrawableInfoReq);
382*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq);
383*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
384*4882a593Smuzhiyun         client->errorValue = stuff->screen;
385*4882a593Smuzhiyun         return BadValue;
386*4882a593Smuzhiyun     }
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun     rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
389*4882a593Smuzhiyun                            DixReadAccess);
390*4882a593Smuzhiyun     if (rc != Success)
391*4882a593Smuzhiyun         return rc;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     if (!DRIGetDrawableInfo(screenInfo.screens[stuff->screen],
394*4882a593Smuzhiyun                             pDrawable,
395*4882a593Smuzhiyun                             (unsigned int *) &rep.drawableTableIndex,
396*4882a593Smuzhiyun                             (unsigned int *) &rep.drawableTableStamp,
397*4882a593Smuzhiyun                             (int *) &X,
398*4882a593Smuzhiyun                             (int *) &Y,
399*4882a593Smuzhiyun                             (int *) &W,
400*4882a593Smuzhiyun                             (int *) &H,
401*4882a593Smuzhiyun                             (int *) &rep.numClipRects,
402*4882a593Smuzhiyun                             &pClipRects,
403*4882a593Smuzhiyun                             &backX,
404*4882a593Smuzhiyun                             &backY,
405*4882a593Smuzhiyun                             (int *) &rep.numBackClipRects, &pBackClipRects)) {
406*4882a593Smuzhiyun         return BadValue;
407*4882a593Smuzhiyun     }
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun     rep.drawableX = X;
410*4882a593Smuzhiyun     rep.drawableY = Y;
411*4882a593Smuzhiyun     rep.drawableWidth = W;
412*4882a593Smuzhiyun     rep.drawableHeight = H;
413*4882a593Smuzhiyun     rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - SIZEOF(xGenericReply));
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun     rep.backX = backX;
416*4882a593Smuzhiyun     rep.backY = backY;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun     if (rep.numBackClipRects)
419*4882a593Smuzhiyun         rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun     pClippedRects = pClipRects;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun     if (rep.numClipRects) {
424*4882a593Smuzhiyun         /* Clip cliprects to screen dimensions (redirected windows) */
425*4882a593Smuzhiyun         pClippedRects = xallocarray(rep.numClipRects, sizeof(drm_clip_rect_t));
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun         if (pClippedRects) {
428*4882a593Smuzhiyun             ScreenPtr pScreen = screenInfo.screens[stuff->screen];
429*4882a593Smuzhiyun             int i, j;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun             for (i = 0, j = 0; i < rep.numClipRects; i++) {
432*4882a593Smuzhiyun                 pClippedRects[j].x1 = max(pClipRects[i].x1, 0);
433*4882a593Smuzhiyun                 pClippedRects[j].y1 = max(pClipRects[i].y1, 0);
434*4882a593Smuzhiyun                 pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width);
435*4882a593Smuzhiyun                 pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun                 if (pClippedRects[j].x1 < pClippedRects[j].x2 &&
438*4882a593Smuzhiyun                     pClippedRects[j].y1 < pClippedRects[j].y2) {
439*4882a593Smuzhiyun                     j++;
440*4882a593Smuzhiyun                 }
441*4882a593Smuzhiyun             }
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun             rep.numClipRects = j;
444*4882a593Smuzhiyun         }
445*4882a593Smuzhiyun         else {
446*4882a593Smuzhiyun             rep.numClipRects = 0;
447*4882a593Smuzhiyun         }
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun         rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects;
450*4882a593Smuzhiyun     }
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun     rep.length = bytes_to_int32(rep.length);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), &rep);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun     if (rep.numClipRects) {
457*4882a593Smuzhiyun         WriteToClient(client,
458*4882a593Smuzhiyun                       sizeof(drm_clip_rect_t) * rep.numClipRects,
459*4882a593Smuzhiyun                       pClippedRects);
460*4882a593Smuzhiyun         free(pClippedRects);
461*4882a593Smuzhiyun     }
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun     if (rep.numBackClipRects) {
464*4882a593Smuzhiyun         WriteToClient(client,
465*4882a593Smuzhiyun                       sizeof(drm_clip_rect_t) * rep.numBackClipRects,
466*4882a593Smuzhiyun                       pBackClipRects);
467*4882a593Smuzhiyun     }
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun     return Success;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun static int
ProcXF86DRIGetDeviceInfo(register ClientPtr client)473*4882a593Smuzhiyun ProcXF86DRIGetDeviceInfo(register ClientPtr client)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun     xXF86DRIGetDeviceInfoReply rep = {
476*4882a593Smuzhiyun         .type = X_Reply,
477*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
478*4882a593Smuzhiyun         .length = 0
479*4882a593Smuzhiyun     };
480*4882a593Smuzhiyun     drm_handle_t hFrameBuffer;
481*4882a593Smuzhiyun     void *pDevPrivate;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun     REQUEST(xXF86DRIGetDeviceInfoReq);
484*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq);
485*4882a593Smuzhiyun     if (stuff->screen >= screenInfo.numScreens) {
486*4882a593Smuzhiyun         client->errorValue = stuff->screen;
487*4882a593Smuzhiyun         return BadValue;
488*4882a593Smuzhiyun     }
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun     if (!DRIGetDeviceInfo(screenInfo.screens[stuff->screen],
491*4882a593Smuzhiyun                           &hFrameBuffer,
492*4882a593Smuzhiyun                           (int *) &rep.framebufferOrigin,
493*4882a593Smuzhiyun                           (int *) &rep.framebufferSize,
494*4882a593Smuzhiyun                           (int *) &rep.framebufferStride,
495*4882a593Smuzhiyun                           (int *) &rep.devPrivateSize, &pDevPrivate)) {
496*4882a593Smuzhiyun         return BadValue;
497*4882a593Smuzhiyun     }
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun     rep.hFrameBufferLow = (CARD32) (hFrameBuffer & 0xffffffff);
500*4882a593Smuzhiyun #if defined(LONG64) && !defined(__linux__)
501*4882a593Smuzhiyun     rep.hFrameBufferHigh = (CARD32) (hFrameBuffer >> 32);
502*4882a593Smuzhiyun #else
503*4882a593Smuzhiyun     rep.hFrameBufferHigh = 0;
504*4882a593Smuzhiyun #endif
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun     if (rep.devPrivateSize) {
507*4882a593Smuzhiyun         rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) -
508*4882a593Smuzhiyun                                     SIZEOF(xGenericReply) +
509*4882a593Smuzhiyun                                     pad_to_int32(rep.devPrivateSize));
510*4882a593Smuzhiyun     }
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun     WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), &rep);
513*4882a593Smuzhiyun     if (rep.length) {
514*4882a593Smuzhiyun         WriteToClient(client, rep.devPrivateSize, pDevPrivate);
515*4882a593Smuzhiyun     }
516*4882a593Smuzhiyun     return Success;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun static int
ProcXF86DRIDispatch(register ClientPtr client)520*4882a593Smuzhiyun ProcXF86DRIDispatch(register ClientPtr client)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun     REQUEST(xReq);
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun     switch (stuff->data) {
525*4882a593Smuzhiyun     case X_XF86DRIQueryVersion:
526*4882a593Smuzhiyun         return ProcXF86DRIQueryVersion(client);
527*4882a593Smuzhiyun     case X_XF86DRIQueryDirectRenderingCapable:
528*4882a593Smuzhiyun         return ProcXF86DRIQueryDirectRenderingCapable(client);
529*4882a593Smuzhiyun     }
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun     if (!client->local)
532*4882a593Smuzhiyun         return DRIErrorBase + XF86DRIClientNotLocal;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun     switch (stuff->data) {
535*4882a593Smuzhiyun     case X_XF86DRIOpenConnection:
536*4882a593Smuzhiyun         return ProcXF86DRIOpenConnection(client);
537*4882a593Smuzhiyun     case X_XF86DRICloseConnection:
538*4882a593Smuzhiyun         return ProcXF86DRICloseConnection(client);
539*4882a593Smuzhiyun     case X_XF86DRIGetClientDriverName:
540*4882a593Smuzhiyun         return ProcXF86DRIGetClientDriverName(client);
541*4882a593Smuzhiyun     case X_XF86DRICreateContext:
542*4882a593Smuzhiyun         return ProcXF86DRICreateContext(client);
543*4882a593Smuzhiyun     case X_XF86DRIDestroyContext:
544*4882a593Smuzhiyun         return ProcXF86DRIDestroyContext(client);
545*4882a593Smuzhiyun     case X_XF86DRICreateDrawable:
546*4882a593Smuzhiyun         return ProcXF86DRICreateDrawable(client);
547*4882a593Smuzhiyun     case X_XF86DRIDestroyDrawable:
548*4882a593Smuzhiyun         return ProcXF86DRIDestroyDrawable(client);
549*4882a593Smuzhiyun     case X_XF86DRIGetDrawableInfo:
550*4882a593Smuzhiyun         return ProcXF86DRIGetDrawableInfo(client);
551*4882a593Smuzhiyun     case X_XF86DRIGetDeviceInfo:
552*4882a593Smuzhiyun         return ProcXF86DRIGetDeviceInfo(client);
553*4882a593Smuzhiyun     case X_XF86DRIAuthConnection:
554*4882a593Smuzhiyun         return ProcXF86DRIAuthConnection(client);
555*4882a593Smuzhiyun         /* {Open,Close}FullScreen are deprecated now */
556*4882a593Smuzhiyun     default:
557*4882a593Smuzhiyun         return BadRequest;
558*4882a593Smuzhiyun     }
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun static int _X_COLD
SProcXF86DRIQueryVersion(register ClientPtr client)562*4882a593Smuzhiyun SProcXF86DRIQueryVersion(register ClientPtr client)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun     REQUEST(xXF86DRIQueryVersionReq);
565*4882a593Smuzhiyun     swaps(&stuff->length);
566*4882a593Smuzhiyun     return ProcXF86DRIQueryVersion(client);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun static int _X_COLD
SProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)570*4882a593Smuzhiyun SProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun     REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
573*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
574*4882a593Smuzhiyun     swaps(&stuff->length);
575*4882a593Smuzhiyun     swapl(&stuff->screen);
576*4882a593Smuzhiyun     return ProcXF86DRIQueryDirectRenderingCapable(client);
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun static int _X_COLD
SProcXF86DRIDispatch(register ClientPtr client)580*4882a593Smuzhiyun SProcXF86DRIDispatch(register ClientPtr client)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun     REQUEST(xReq);
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun     /*
585*4882a593Smuzhiyun      * Only local clients are allowed DRI access, but remote clients still need
586*4882a593Smuzhiyun      * these requests to find out cleanly.
587*4882a593Smuzhiyun      */
588*4882a593Smuzhiyun     switch (stuff->data) {
589*4882a593Smuzhiyun     case X_XF86DRIQueryVersion:
590*4882a593Smuzhiyun         return SProcXF86DRIQueryVersion(client);
591*4882a593Smuzhiyun     case X_XF86DRIQueryDirectRenderingCapable:
592*4882a593Smuzhiyun         return SProcXF86DRIQueryDirectRenderingCapable(client);
593*4882a593Smuzhiyun     default:
594*4882a593Smuzhiyun         return DRIErrorBase + XF86DRIClientNotLocal;
595*4882a593Smuzhiyun     }
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun void
XFree86DRIExtensionInit(void)599*4882a593Smuzhiyun XFree86DRIExtensionInit(void)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun     ExtensionEntry *extEntry;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun     if (DRIExtensionInit() &&
604*4882a593Smuzhiyun         (extEntry = AddExtension(XF86DRINAME,
605*4882a593Smuzhiyun                                  XF86DRINumberEvents,
606*4882a593Smuzhiyun                                  XF86DRINumberErrors,
607*4882a593Smuzhiyun                                  ProcXF86DRIDispatch,
608*4882a593Smuzhiyun                                  SProcXF86DRIDispatch,
609*4882a593Smuzhiyun                                  XF86DRIResetProc, StandardMinorOpcode))) {
610*4882a593Smuzhiyun         DRIReqCode = (unsigned char) extEntry->base;
611*4882a593Smuzhiyun         DRIErrorBase = extEntry->errorBase;
612*4882a593Smuzhiyun     }
613*4882a593Smuzhiyun }
614