1706f2543Smrg/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */
2706f2543Smrg/**************************************************************************
3706f2543Smrg
4706f2543SmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5706f2543SmrgCopyright 2000 VA Linux Systems, Inc.
6706f2543SmrgAll Rights Reserved.
7706f2543Smrg
8706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a
9706f2543Smrgcopy of this software and associated documentation files (the
10706f2543Smrg"Software"), to deal in the Software without restriction, including
11706f2543Smrgwithout limitation the rights to use, copy, modify, merge, publish,
12706f2543Smrgdistribute, sub license, and/or sell copies of the Software, and to
13706f2543Smrgpermit persons to whom the Software is furnished to do so, subject to
14706f2543Smrgthe following conditions:
15706f2543Smrg
16706f2543SmrgThe above copyright notice and this permission notice (including the
17706f2543Smrgnext paragraph) shall be included in all copies or substantial portions
18706f2543Smrgof the Software.
19706f2543Smrg
20706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23706f2543SmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24706f2543SmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25706f2543SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26706f2543SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27706f2543Smrg
28706f2543Smrg**************************************************************************/
29706f2543Smrg
30706f2543Smrg/*
31706f2543Smrg * Authors:
32706f2543Smrg *   Kevin E. Martin <martin@valinux.com>
33706f2543Smrg *   Jens Owen <jens@tungstengraphics.com>
34706f2543Smrg *   Rickard E. (Rik) Faith <faith@valinux.com>
35706f2543Smrg *
36706f2543Smrg */
37706f2543Smrg
38706f2543Smrg/*
39706f2543Smrg * This file has been copied from the mesa source tree and a little bit
40706f2543Smrg * modified by:
41706f2543Smrg *
42706f2543Smrg * Dodji Seketeli <dodji@openedhand.com>
43706f2543Smrg */
44706f2543Smrg
45706f2543Smrg#ifdef HAVE_CONFIG_H
46706f2543Smrg#include <kdrive-config.h>
47706f2543Smrg#endif
48706f2543Smrg/*
49706f2543Smrg * including some server headers (like kdrive-config.h)
50706f2543Smrg * might define the macro _XSERVER64
51706f2543Smrg * on 64 bits machines. That macro must _NOT_ be defined for Xlib
52706f2543Smrg * client code, otherwise bad things happen.
53706f2543Smrg * So let's undef that macro if necessary.
54706f2543Smrg */
55706f2543Smrg#ifdef _XSERVER64
56706f2543Smrg#undef _XSERVER64
57706f2543Smrg#endif
58706f2543Smrg
59706f2543Smrg/* THIS IS NOT AN X CONSORTIUM STANDARD */
60706f2543Smrg
61706f2543Smrg#include <X11/Xlibint.h>
62706f2543Smrg#include <X11/extensions/Xext.h>
63706f2543Smrg#include <X11/extensions/extutil.h>
64706f2543Smrg#include <GL/glx.h>
65706f2543Smrg#include "xf86dri.h"
66706f2543Smrg#include <X11/dri/xf86driproto.h>
67706f2543Smrg
68706f2543Smrgstatic XExtensionInfo _xf86dri_info_data;
69706f2543Smrgstatic XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
70706f2543Smrgstatic char xf86dri_extension_name[] = XF86DRINAME;
71706f2543Smrg
72706f2543Smrg#define XF86DRICheckExtension(dpy,i,val) \
73706f2543Smrg  XextCheckExtension (dpy, i, xf86dri_extension_name, val)
74706f2543Smrg
75706f2543Smrg/*****************************************************************************
76706f2543Smrg *                                                                           *
77706f2543Smrg *			   private utility routines                          *
78706f2543Smrg *                                                                           *
79706f2543Smrg *****************************************************************************/
80706f2543Smrg
81706f2543Smrgstatic int close_display(Display *dpy, XExtCodes *extCodes);
82706f2543Smrgstatic /* const */ XExtensionHooks xf86dri_extension_hooks = {
83706f2543Smrg    NULL,				/* create_gc */
84706f2543Smrg    NULL,				/* copy_gc */
85706f2543Smrg    NULL,				/* flush_gc */
86706f2543Smrg    NULL,				/* free_gc */
87706f2543Smrg    NULL,				/* create_font */
88706f2543Smrg    NULL,				/* free_font */
89706f2543Smrg    close_display,			/* close_display */
90706f2543Smrg    NULL,				/* wire_to_event */
91706f2543Smrg    NULL,				/* event_to_wire */
92706f2543Smrg    NULL,				/* error */
93706f2543Smrg    NULL,				/* error_string */
94706f2543Smrg};
95706f2543Smrg
96706f2543Smrgstatic XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info,
97706f2543Smrg				   xf86dri_extension_name,
98706f2543Smrg				   &xf86dri_extension_hooks,
99706f2543Smrg				   0, NULL)
100706f2543Smrg
101706f2543Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info)
102706f2543Smrg
103706f2543Smrg
104706f2543Smrg/*****************************************************************************
105706f2543Smrg *                                                                           *
106706f2543Smrg *		    public XFree86-DRI Extension routines                    *
107706f2543Smrg *                                                                           *
108706f2543Smrg *****************************************************************************/
109706f2543Smrg
110706f2543Smrg#if 0
111706f2543Smrg#include <stdio.h>
112706f2543Smrg#define TRACE(msg)  fprintf(stderr,"XF86DRI%s\n", msg);
113706f2543Smrg#else
114706f2543Smrg#define TRACE(msg)
115706f2543Smrg#endif
116706f2543Smrg
117706f2543SmrgBool XF86DRIOpenFullScreen(Display *dpy, int screen, Drawable drawable);
118706f2543SmrgBool XF86DRICloseFullScreen(Display *dpy, int screen, Drawable drawable);
119706f2543Smrg
120706f2543SmrgBool XF86DRIQueryExtension (Display *dpy, int *event_basep, int *error_basep)
121706f2543Smrg{
122706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
123706f2543Smrg
124706f2543Smrg    TRACE("QueryExtension...");
125706f2543Smrg    if (XextHasExtension(info)) {
126706f2543Smrg	*event_basep = info->codes->first_event;
127706f2543Smrg	*error_basep = info->codes->first_error;
128706f2543Smrg        TRACE("QueryExtension... return True");
129706f2543Smrg	return True;
130706f2543Smrg    } else {
131706f2543Smrg        TRACE("QueryExtension... return False");
132706f2543Smrg	return False;
133706f2543Smrg    }
134706f2543Smrg}
135706f2543Smrg
136706f2543SmrgBool XF86DRIQueryVersion(Display *dpy, int *majorVersion, int *minorVersion,
137706f2543Smrg                         int *patchVersion)
138706f2543Smrg{
139706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
140706f2543Smrg    xXF86DRIQueryVersionReply rep;
141706f2543Smrg    xXF86DRIQueryVersionReq *req;
142706f2543Smrg
143706f2543Smrg    TRACE("QueryVersion...");
144706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
145706f2543Smrg
146706f2543Smrg    LockDisplay(dpy);
147706f2543Smrg    GetReq(XF86DRIQueryVersion, req);
148706f2543Smrg    req->reqType = info->codes->major_opcode;
149706f2543Smrg    req->driReqType = X_XF86DRIQueryVersion;
150706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
151706f2543Smrg	UnlockDisplay(dpy);
152706f2543Smrg	SyncHandle();
153706f2543Smrg        TRACE("QueryVersion... return False");
154706f2543Smrg	return False;
155706f2543Smrg    }
156706f2543Smrg    *majorVersion = rep.majorVersion;
157706f2543Smrg    *minorVersion = rep.minorVersion;
158706f2543Smrg    *patchVersion = rep.patchVersion;
159706f2543Smrg    UnlockDisplay(dpy);
160706f2543Smrg    SyncHandle();
161706f2543Smrg    TRACE("QueryVersion... return True");
162706f2543Smrg    return True;
163706f2543Smrg}
164706f2543Smrg
165706f2543SmrgBool
166706f2543SmrgXF86DRIQueryDirectRenderingCapable (Display *dpy, int screen, Bool *isCapable)
167706f2543Smrg{
168706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
169706f2543Smrg    xXF86DRIQueryDirectRenderingCapableReply rep;
170706f2543Smrg    xXF86DRIQueryDirectRenderingCapableReq *req;
171706f2543Smrg
172706f2543Smrg    TRACE("QueryDirectRenderingCapable...");
173706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
174706f2543Smrg
175706f2543Smrg    LockDisplay(dpy);
176706f2543Smrg    GetReq(XF86DRIQueryDirectRenderingCapable, req);
177706f2543Smrg    req->reqType = info->codes->major_opcode;
178706f2543Smrg    req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
179706f2543Smrg    req->screen = screen;
180706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
181706f2543Smrg        UnlockDisplay(dpy);
182706f2543Smrg        SyncHandle();
183706f2543Smrg        TRACE("QueryDirectRenderingCapable... return False");
184706f2543Smrg        return False;
185706f2543Smrg    }
186706f2543Smrg    *isCapable = rep.isCapable;
187706f2543Smrg    UnlockDisplay(dpy);
188706f2543Smrg    SyncHandle();
189706f2543Smrg    TRACE("QueryDirectRenderingCapable... return True");
190706f2543Smrg    return True;
191706f2543Smrg}
192706f2543Smrg
193706f2543SmrgBool
194706f2543SmrgXF86DRIOpenConnection (Display *dpy, int screen,
195706f2543Smrg                       drm_handle_t *hSAREA,
196706f2543Smrg                       char **busIdString)
197706f2543Smrg{
198706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
199706f2543Smrg    xXF86DRIOpenConnectionReply rep;
200706f2543Smrg    xXF86DRIOpenConnectionReq *req;
201706f2543Smrg
202706f2543Smrg    TRACE("OpenConnection...");
203706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
204706f2543Smrg
205706f2543Smrg    LockDisplay(dpy);
206706f2543Smrg    GetReq(XF86DRIOpenConnection, req);
207706f2543Smrg    req->reqType = info->codes->major_opcode;
208706f2543Smrg    req->driReqType = X_XF86DRIOpenConnection;
209706f2543Smrg    req->screen = screen;
210706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
211706f2543Smrg        UnlockDisplay(dpy);
212706f2543Smrg        SyncHandle();
213706f2543Smrg        TRACE("OpenConnection... return False");
214706f2543Smrg        return False;
215706f2543Smrg    }
216706f2543Smrg
217706f2543Smrg    *hSAREA = rep.hSAREALow;
218706f2543Smrg    if (sizeof(drm_handle_t) == 8) {
219706f2543Smrg        int shift = 32; /* var to prevent warning on next line */
220706f2543Smrg        *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
221706f2543Smrg    }
222706f2543Smrg
223706f2543Smrg    if (rep.length) {
224706f2543Smrg        if (!(*busIdString = (char *)calloc(rep.busIdStringLength + 1, 1))) {
225706f2543Smrg            _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
226706f2543Smrg            UnlockDisplay(dpy);
227706f2543Smrg            SyncHandle();
228706f2543Smrg            TRACE("OpenConnection... return False");
229706f2543Smrg            return False;
230706f2543Smrg        }
231706f2543Smrg        _XReadPad(dpy, *busIdString, rep.busIdStringLength);
232706f2543Smrg    } else {
233706f2543Smrg        *busIdString = NULL;
234706f2543Smrg    }
235706f2543Smrg    UnlockDisplay(dpy);
236706f2543Smrg    SyncHandle();
237706f2543Smrg    TRACE("OpenConnection... return True");
238706f2543Smrg    return True;
239706f2543Smrg}
240706f2543Smrg
241706f2543SmrgBool XF86DRIAuthConnection(Display *dpy, int screen, drm_magic_t magic)
242706f2543Smrg{
243706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
244706f2543Smrg    xXF86DRIAuthConnectionReq *req;
245706f2543Smrg    xXF86DRIAuthConnectionReply rep;
246706f2543Smrg
247706f2543Smrg    TRACE("AuthConnection...");
248706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
249706f2543Smrg
250706f2543Smrg    LockDisplay(dpy);
251706f2543Smrg    GetReq(XF86DRIAuthConnection, req);
252706f2543Smrg    req->reqType = info->codes->major_opcode;
253706f2543Smrg    req->driReqType = X_XF86DRIAuthConnection;
254706f2543Smrg    req->screen = screen;
255706f2543Smrg    req->magic = magic;
256706f2543Smrg    rep.authenticated = 0;
257706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
258706f2543Smrg	UnlockDisplay(dpy);
259706f2543Smrg	SyncHandle();
260706f2543Smrg        TRACE("AuthConnection... return False");
261706f2543Smrg	return False;
262706f2543Smrg    }
263706f2543Smrg    UnlockDisplay(dpy);
264706f2543Smrg    SyncHandle();
265706f2543Smrg    TRACE("AuthConnection... return True");
266706f2543Smrg    return True;
267706f2543Smrg}
268706f2543Smrg
269706f2543SmrgBool XF86DRICloseConnection(Display *dpy, int screen)
270706f2543Smrg{
271706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
272706f2543Smrg    xXF86DRICloseConnectionReq *req;
273706f2543Smrg
274706f2543Smrg    TRACE("CloseConnection...");
275706f2543Smrg
276706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
277706f2543Smrg
278706f2543Smrg    LockDisplay(dpy);
279706f2543Smrg    GetReq(XF86DRICloseConnection, req);
280706f2543Smrg    req->reqType = info->codes->major_opcode;
281706f2543Smrg    req->driReqType = X_XF86DRICloseConnection;
282706f2543Smrg    req->screen = screen;
283706f2543Smrg    UnlockDisplay(dpy);
284706f2543Smrg    SyncHandle();
285706f2543Smrg    TRACE("CloseConnection... return True");
286706f2543Smrg    return True;
287706f2543Smrg}
288706f2543Smrg
289706f2543SmrgBool XF86DRIGetClientDriverName(Display *dpy, int screen,
290706f2543Smrg                                int *ddxDriverMajorVersion,
291706f2543Smrg	                        int *ddxDriverMinorVersion,
292706f2543Smrg                                int *ddxDriverPatchVersion,
293706f2543Smrg                                char **clientDriverName)
294706f2543Smrg{
295706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
296706f2543Smrg    xXF86DRIGetClientDriverNameReply rep;
297706f2543Smrg    xXF86DRIGetClientDriverNameReq *req;
298706f2543Smrg
299706f2543Smrg    TRACE("GetClientDriverName...");
300706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
301706f2543Smrg
302706f2543Smrg    LockDisplay(dpy);
303706f2543Smrg    GetReq(XF86DRIGetClientDriverName, req);
304706f2543Smrg    req->reqType = info->codes->major_opcode;
305706f2543Smrg    req->driReqType = X_XF86DRIGetClientDriverName;
306706f2543Smrg    req->screen = screen;
307706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
308706f2543Smrg	UnlockDisplay(dpy);
309706f2543Smrg	SyncHandle();
310706f2543Smrg        TRACE("GetClientDriverName... return False");
311706f2543Smrg	return False;
312706f2543Smrg    }
313706f2543Smrg
314706f2543Smrg    *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
315706f2543Smrg    *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
316706f2543Smrg    *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
317706f2543Smrg
318706f2543Smrg    if (rep.length) {
319706f2543Smrg        if (!(*clientDriverName = (char *)calloc(rep.clientDriverNameLength + 1, 1))) {
320706f2543Smrg            _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
321706f2543Smrg            UnlockDisplay(dpy);
322706f2543Smrg            SyncHandle();
323706f2543Smrg            TRACE("GetClientDriverName... return False");
324706f2543Smrg            return False;
325706f2543Smrg        }
326706f2543Smrg	_XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
327706f2543Smrg    } else {
328706f2543Smrg        *clientDriverName = NULL;
329706f2543Smrg    }
330706f2543Smrg    UnlockDisplay(dpy);
331706f2543Smrg    SyncHandle();
332706f2543Smrg    TRACE("GetClientDriverName... return True");
333706f2543Smrg    return True;
334706f2543Smrg}
335706f2543Smrg
336706f2543SmrgBool XF86DRICreateContextWithConfig(Display *dpy, int screen, int configID,
337706f2543Smrg                                    XID *context, drm_context_t *hHWContext)
338706f2543Smrg{
339706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
340706f2543Smrg    xXF86DRICreateContextReply rep;
341706f2543Smrg    xXF86DRICreateContextReq *req;
342706f2543Smrg
343706f2543Smrg    TRACE("CreateContext...");
344706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
345706f2543Smrg
346706f2543Smrg    LockDisplay(dpy);
347706f2543Smrg    GetReq(XF86DRICreateContext, req);
348706f2543Smrg    req->reqType = info->codes->major_opcode;
349706f2543Smrg    req->driReqType = X_XF86DRICreateContext;
350706f2543Smrg    req->visual = configID;
351706f2543Smrg    req->screen = screen;
352706f2543Smrg    *context = XAllocID(dpy);
353706f2543Smrg    req->context = *context;
354706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
355706f2543Smrg	UnlockDisplay(dpy);
356706f2543Smrg	SyncHandle();
357706f2543Smrg        TRACE("CreateContext... return False");
358706f2543Smrg	return False;
359706f2543Smrg    }
360706f2543Smrg    *hHWContext = rep.hHWContext;
361706f2543Smrg    UnlockDisplay(dpy);
362706f2543Smrg    SyncHandle();
363706f2543Smrg    TRACE("CreateContext... return True");
364706f2543Smrg    return True;
365706f2543Smrg}
366706f2543Smrg
367706f2543SmrgBool XF86DRICreateContext(Display *dpy, int screen, Visual *visual,
368706f2543Smrg                          XID *context, drm_context_t *hHWContext)
369706f2543Smrg{
370706f2543Smrg    return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid,
371706f2543Smrg					   context, hHWContext );
372706f2543Smrg}
373706f2543Smrg
374706f2543SmrgGLboolean XF86DRIDestroyContext( Display *dpy, int screen, XID context)
375706f2543Smrg{
376706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
377706f2543Smrg    xXF86DRIDestroyContextReq *req;
378706f2543Smrg
379706f2543Smrg    TRACE("DestroyContext...");
380706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
381706f2543Smrg
382706f2543Smrg    LockDisplay(dpy);
383706f2543Smrg    GetReq(XF86DRIDestroyContext, req);
384706f2543Smrg    req->reqType = info->codes->major_opcode;
385706f2543Smrg    req->driReqType = X_XF86DRIDestroyContext;
386706f2543Smrg    req->screen = screen;
387706f2543Smrg    req->context = context;
388706f2543Smrg    UnlockDisplay(dpy);
389706f2543Smrg    SyncHandle();
390706f2543Smrg    TRACE("DestroyContext... return True");
391706f2543Smrg    return True;
392706f2543Smrg}
393706f2543Smrg
394706f2543SmrgGLboolean
395706f2543SmrgXF86DRICreateDrawable (Display *dpy, int screen,
396706f2543Smrg                       XID drawable, drm_drawable_t * hHWDrawable)
397706f2543Smrg{
398706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
399706f2543Smrg    xXF86DRICreateDrawableReply rep;
400706f2543Smrg    xXF86DRICreateDrawableReq *req;
401706f2543Smrg
402706f2543Smrg    TRACE("CreateDrawable...");
403706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
404706f2543Smrg
405706f2543Smrg    LockDisplay(dpy);
406706f2543Smrg    GetReq(XF86DRICreateDrawable, req);
407706f2543Smrg    req->reqType = info->codes->major_opcode;
408706f2543Smrg    req->driReqType = X_XF86DRICreateDrawable;
409706f2543Smrg    req->screen = screen;
410706f2543Smrg    req->drawable = drawable;
411706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
412706f2543Smrg	UnlockDisplay(dpy);
413706f2543Smrg	SyncHandle();
414706f2543Smrg        TRACE("CreateDrawable... return False");
415706f2543Smrg	return False;
416706f2543Smrg    }
417706f2543Smrg    *hHWDrawable = rep.hHWDrawable;
418706f2543Smrg    UnlockDisplay(dpy);
419706f2543Smrg    SyncHandle();
420706f2543Smrg    TRACE("CreateDrawable... return True");
421706f2543Smrg    return True;
422706f2543Smrg}
423706f2543Smrg
424706f2543Smrgstatic int noopErrorHandler(Display *dpy, XErrorEvent *xerr)
425706f2543Smrg{
426706f2543Smrg    return 0;
427706f2543Smrg}
428706f2543Smrg
429706f2543SmrgGLboolean XF86DRIDestroyDrawable( Display *dpy, int screen,
430706f2543Smrg    XID drawable )
431706f2543Smrg{
432706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
433706f2543Smrg    xXF86DRIDestroyDrawableReq *req;
434706f2543Smrg    int (*oldXErrorHandler)(Display *, XErrorEvent *);
435706f2543Smrg
436706f2543Smrg    TRACE("DestroyDrawable...");
437706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
438706f2543Smrg
439706f2543Smrg    /* This is called from the DRI driver, which used call it like this
440706f2543Smrg     *
441706f2543Smrg     *   if (windowExists(drawable))
442706f2543Smrg     *     destroyDrawable(drawable);
443706f2543Smrg     *
444706f2543Smrg     * which is a textbook race condition - the window may disappear
445706f2543Smrg     * from the server between checking for its existance and
446706f2543Smrg     * destroying it.  Instead we change the semantics of
447706f2543Smrg     * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
448706f2543Smrg     * the windows is gone, by wrapping the destroy call in an error
449706f2543Smrg     * handler. */
450706f2543Smrg
451706f2543Smrg    XSync(dpy, GL_FALSE);
452706f2543Smrg    oldXErrorHandler = XSetErrorHandler(noopErrorHandler);
453706f2543Smrg
454706f2543Smrg    LockDisplay(dpy);
455706f2543Smrg    GetReq(XF86DRIDestroyDrawable, req);
456706f2543Smrg    req->reqType = info->codes->major_opcode;
457706f2543Smrg    req->driReqType = X_XF86DRIDestroyDrawable;
458706f2543Smrg    req->screen = screen;
459706f2543Smrg    req->drawable = drawable;
460706f2543Smrg    UnlockDisplay(dpy);
461706f2543Smrg    SyncHandle();
462706f2543Smrg
463706f2543Smrg    XSetErrorHandler(oldXErrorHandler);
464706f2543Smrg
465706f2543Smrg    TRACE("DestroyDrawable... return True");
466706f2543Smrg    return True;
467706f2543Smrg}
468706f2543Smrg
469706f2543SmrgBool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
470706f2543Smrg    unsigned int* index, unsigned int* stamp,
471706f2543Smrg    int* X, int* Y, int* W, int* H,
472706f2543Smrg    int* numClipRects, drm_clip_rect_t ** pClipRects,
473706f2543Smrg    int* backX, int* backY,
474706f2543Smrg    int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
475706f2543Smrg{
476706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
477706f2543Smrg    xXF86DRIGetDrawableInfoReply rep;
478706f2543Smrg    xXF86DRIGetDrawableInfoReq *req=NULL;
479706f2543Smrg    int total_rects;
480706f2543Smrg
481706f2543Smrg    TRACE("GetDrawableInfo...");
482706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
483706f2543Smrg
484706f2543Smrg    LockDisplay(dpy);
485706f2543Smrg    GetReq(XF86DRIGetDrawableInfo, req);
486706f2543Smrg    req->reqType = info->codes->major_opcode;
487706f2543Smrg    req->driReqType = X_XF86DRIGetDrawableInfo;
488706f2543Smrg    req->screen = screen;
489706f2543Smrg    req->drawable = drawable;
490706f2543Smrg
491706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 1, xFalse))
492706f2543Smrg    {
493706f2543Smrg	UnlockDisplay(dpy);
494706f2543Smrg	SyncHandle();
495706f2543Smrg        TRACE("GetDrawableInfo... return False");
496706f2543Smrg	return False;
497706f2543Smrg    }
498706f2543Smrg    *index = rep.drawableTableIndex;
499706f2543Smrg    *stamp = rep.drawableTableStamp;
500706f2543Smrg    *X = (int)rep.drawableX;
501706f2543Smrg    *Y = (int)rep.drawableY;
502706f2543Smrg    *W = (int)rep.drawableWidth;
503706f2543Smrg    *H = (int)rep.drawableHeight;
504706f2543Smrg    *numClipRects = rep.numClipRects;
505706f2543Smrg    total_rects = *numClipRects;
506706f2543Smrg
507706f2543Smrg    *backX = rep.backX;
508706f2543Smrg    *backY = rep.backY;
509706f2543Smrg    *numBackClipRects = rep.numBackClipRects;
510706f2543Smrg    total_rects += *numBackClipRects;
511706f2543Smrg
512706f2543Smrg#if 0
513706f2543Smrg    /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
514706f2543Smrg     * backwards compatibility (Because of the >> 2 shift) but the fix
515706f2543Smrg     * enables multi-threaded apps to work.
516706f2543Smrg     */
517706f2543Smrg    if (rep.length !=  ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
518706f2543Smrg		       SIZEOF(xGenericReply) +
519706f2543Smrg		       total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
520706f2543Smrg        _XEatData(dpy, rep.length);
521706f2543Smrg	UnlockDisplay(dpy);
522706f2543Smrg	SyncHandle();
523706f2543Smrg        TRACE("GetDrawableInfo... return False");
524706f2543Smrg        return False;
525706f2543Smrg    }
526706f2543Smrg#endif
527706f2543Smrg
528706f2543Smrg    if (*numClipRects) {
529706f2543Smrg       int len = sizeof(drm_clip_rect_t) * (*numClipRects);
530706f2543Smrg
531706f2543Smrg       *pClipRects = (drm_clip_rect_t *)calloc(len, 1);
532706f2543Smrg       if (*pClipRects)
533706f2543Smrg	  _XRead(dpy, (char*)*pClipRects, len);
534706f2543Smrg    } else {
535706f2543Smrg        *pClipRects = NULL;
536706f2543Smrg    }
537706f2543Smrg
538706f2543Smrg    if (*numBackClipRects) {
539706f2543Smrg       int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
540706f2543Smrg
541706f2543Smrg       *pBackClipRects = (drm_clip_rect_t *)calloc(len, 1);
542706f2543Smrg       if (*pBackClipRects)
543706f2543Smrg	  _XRead(dpy, (char*)*pBackClipRects, len);
544706f2543Smrg    } else {
545706f2543Smrg        *pBackClipRects = NULL;
546706f2543Smrg    }
547706f2543Smrg
548706f2543Smrg    UnlockDisplay(dpy);
549706f2543Smrg    SyncHandle();
550706f2543Smrg    TRACE("GetDrawableInfo... return True");
551706f2543Smrg    return True;
552706f2543Smrg}
553706f2543Smrg
554706f2543SmrgBool
555706f2543SmrgXF86DRIGetDeviceInfo (Display *dpy, int screen, drm_handle_t *hFrameBuffer,
556706f2543Smrg                      int *fbOrigin, int *fbSize, int *fbStride,
557706f2543Smrg                      int *devPrivateSize, void **pDevPrivate)
558706f2543Smrg{
559706f2543Smrg    XExtDisplayInfo *info = find_display (dpy);
560706f2543Smrg    xXF86DRIGetDeviceInfoReply rep;
561706f2543Smrg    xXF86DRIGetDeviceInfoReq *req;
562706f2543Smrg
563706f2543Smrg    TRACE("GetDeviceInfo...");
564706f2543Smrg    XF86DRICheckExtension (dpy, info, False);
565706f2543Smrg
566706f2543Smrg    LockDisplay(dpy);
567706f2543Smrg    GetReq(XF86DRIGetDeviceInfo, req);
568706f2543Smrg    req->reqType = info->codes->major_opcode;
569706f2543Smrg    req->driReqType = X_XF86DRIGetDeviceInfo;
570706f2543Smrg    req->screen = screen;
571706f2543Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
572706f2543Smrg	UnlockDisplay(dpy);
573706f2543Smrg	SyncHandle();
574706f2543Smrg        TRACE("GetDeviceInfo... return False");
575706f2543Smrg	return False;
576706f2543Smrg    }
577706f2543Smrg
578706f2543Smrg    *hFrameBuffer = rep.hFrameBufferLow;
579706f2543Smrg    if (sizeof(drm_handle_t) == 8) {
580706f2543Smrg       int shift = 32; /* var to prevent warning on next line */
581706f2543Smrg       *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
582706f2543Smrg    }
583706f2543Smrg
584706f2543Smrg    *fbOrigin = rep.framebufferOrigin;
585706f2543Smrg    *fbSize = rep.framebufferSize;
586706f2543Smrg    *fbStride = rep.framebufferStride;
587706f2543Smrg    *devPrivateSize = rep.devPrivateSize;
588706f2543Smrg
589706f2543Smrg    if (rep.length) {
590706f2543Smrg        if (!(*pDevPrivate = (void *)calloc(rep.devPrivateSize, 1))) {
591706f2543Smrg            _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
592706f2543Smrg            UnlockDisplay(dpy);
593706f2543Smrg            SyncHandle();
594706f2543Smrg            TRACE("GetDeviceInfo... return False");
595706f2543Smrg            return False;
596706f2543Smrg        }
597706f2543Smrg	_XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
598706f2543Smrg    } else {
599706f2543Smrg        *pDevPrivate = NULL;
600706f2543Smrg    }
601706f2543Smrg
602706f2543Smrg    UnlockDisplay(dpy);
603706f2543Smrg    SyncHandle();
604706f2543Smrg    TRACE("GetDeviceInfo... return True");
605706f2543Smrg    return True;
606706f2543Smrg}
607706f2543Smrg
608706f2543SmrgBool
609706f2543SmrgXF86DRIOpenFullScreen(Display *dpy, int screen, Drawable drawable)
610706f2543Smrg{
611706f2543Smrg    /* This function and the underlying X protocol are deprecated.
612706f2543Smrg     */
613706f2543Smrg    (void) dpy;
614706f2543Smrg    (void) screen;
615706f2543Smrg    (void) drawable;
616706f2543Smrg    return False;
617706f2543Smrg}
618706f2543Smrg
619706f2543SmrgBool
620706f2543SmrgXF86DRICloseFullScreen(Display *dpy, int screen, Drawable drawable)
621706f2543Smrg{
622706f2543Smrg    /* This function and the underlying X protocol are deprecated.
623706f2543Smrg     */
624706f2543Smrg    (void) dpy;
625706f2543Smrg    (void) screen;
626706f2543Smrg    (void) drawable;
627706f2543Smrg    return True;
628706f2543Smrg}
629