1 /* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */
2 /**************************************************************************
3 
4 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5 Copyright 2000 VA Linux Systems, Inc.
6 All Rights Reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sub license, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15 
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial portions
18 of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 
28 **************************************************************************/
29 
30 /*
31  * Authors:
32  *   Kevin E. Martin <martin@valinux.com>
33  *   Jens Owen <jens@tungstengraphics.com>
34  *   Rickard E. (Rik) Faith <faith@valinux.com>
35  *
36  */
37 
38 /* THIS IS NOT AN X CONSORTIUM STANDARD */
39 
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43 
44 #include <X11/Xlibint.h>
45 #include <X11/extensions/Xext.h>
46 #include <X11/extensions/extutil.h>
47 #include <stdint.h>
48 #include "xf86dristr.h"
49 
50 static XExtensionInfo _xf86dri_info_data;
51 static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
52 static char xf86dri_extension_name[] = XF86DRINAME;
53 
54 #define uniDRICheckExtension(dpy,i,val) \
55   XextCheckExtension (dpy, i, xf86dri_extension_name, val)
56 
57 /*****************************************************************************
58  *                                                                           *
59  *			   private utility routines                          *
60  *                                                                           *
61  *****************************************************************************/
62 
63 static int close_display(Display * dpy, XExtCodes * extCodes);
64 static /* const */ XExtensionHooks xf86dri_extension_hooks = {
65     NULL,			       /* create_gc */
66     NULL,			       /* copy_gc */
67     NULL,			       /* flush_gc */
68     NULL,			       /* free_gc */
69     NULL,			       /* create_font */
70     NULL,			       /* free_font */
71     close_display,		       /* close_display */
72     NULL,			       /* wire_to_event */
73     NULL,			       /* event_to_wire */
74     NULL,			       /* error */
75     NULL,			       /* error_string */
76 };
77 
78 static
79 XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info,
80     xf86dri_extension_name, &xf86dri_extension_hooks, 0, NULL)
81 
82     static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info)
83 
84 /*****************************************************************************
85  *                                                                           *
86  *		    public XFree86-DRI Extension routines                    *
87  *                                                                           *
88  *****************************************************************************/
89 #if 0
90 #include <stdio.h>
91 #define TRACE(msg)  fprintf(stderr,"uniDRI%s\n", msg);
92 #else
93 #define TRACE(msg)
94 #endif
95     Bool uniDRIQueryExtension(dpy, event_basep, error_basep)
96     Display *dpy;
97     int *event_basep, *error_basep;
98 {
99     XExtDisplayInfo *info = find_display(dpy);
100 
101     TRACE("QueryExtension...");
102     if (XextHasExtension(info)) {
103 	*event_basep = info->codes->first_event;
104 	*error_basep = info->codes->first_error;
105 	TRACE("QueryExtension... return True");
106 	return True;
107     } else {
108 	TRACE("QueryExtension... return False");
109 	return False;
110     }
111 }
112 
113 Bool
uniDRIQueryVersion(dpy,majorVersion,minorVersion,patchVersion)114 uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
115     Display *dpy;
116     int *majorVersion;
117     int *minorVersion;
118     int *patchVersion;
119 {
120     XExtDisplayInfo *info = find_display(dpy);
121     xXF86DRIQueryVersionReply rep;
122     xXF86DRIQueryVersionReq *req;
123 
124     TRACE("QueryVersion...");
125     uniDRICheckExtension(dpy, info, False);
126 
127     LockDisplay(dpy);
128     GetReq(XF86DRIQueryVersion, req);
129     req->reqType = info->codes->major_opcode;
130     req->driReqType = X_XF86DRIQueryVersion;
131     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
132 	UnlockDisplay(dpy);
133 	SyncHandle();
134 	TRACE("QueryVersion... return False");
135 	return False;
136     }
137     *majorVersion = rep.majorVersion;
138     *minorVersion = rep.minorVersion;
139     *patchVersion = rep.patchVersion;
140     UnlockDisplay(dpy);
141     SyncHandle();
142     TRACE("QueryVersion... return True");
143     return True;
144 }
145 
146 Bool
uniDRIQueryDirectRenderingCapable(dpy,screen,isCapable)147 uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
148     Display *dpy;
149     int screen;
150     Bool *isCapable;
151 {
152     XExtDisplayInfo *info = find_display(dpy);
153     xXF86DRIQueryDirectRenderingCapableReply rep;
154     xXF86DRIQueryDirectRenderingCapableReq *req;
155 
156     TRACE("QueryDirectRenderingCapable...");
157     uniDRICheckExtension(dpy, info, False);
158 
159     LockDisplay(dpy);
160     GetReq(XF86DRIQueryDirectRenderingCapable, req);
161     req->reqType = info->codes->major_opcode;
162     req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
163     req->screen = screen;
164     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
165 	UnlockDisplay(dpy);
166 	SyncHandle();
167 	TRACE("QueryDirectRenderingCapable... return False");
168 	return False;
169     }
170     *isCapable = rep.isCapable;
171     UnlockDisplay(dpy);
172     SyncHandle();
173     TRACE("QueryDirectRenderingCapable... return True");
174     return True;
175 }
176 
177 Bool
uniDRIOpenConnection(dpy,screen,hSAREA,busIdString)178 uniDRIOpenConnection(dpy, screen, hSAREA, busIdString)
179     Display *dpy;
180     int screen;
181     drm_handle_t *hSAREA;
182     char **busIdString;
183 {
184     XExtDisplayInfo *info = find_display(dpy);
185     xXF86DRIOpenConnectionReply rep;
186     xXF86DRIOpenConnectionReq *req;
187 
188     TRACE("OpenConnection...");
189     uniDRICheckExtension(dpy, info, False);
190 
191     LockDisplay(dpy);
192     GetReq(XF86DRIOpenConnection, req);
193     req->reqType = info->codes->major_opcode;
194     req->driReqType = X_XF86DRIOpenConnection;
195     req->screen = screen;
196     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
197 	UnlockDisplay(dpy);
198 	SyncHandle();
199 	TRACE("OpenConnection... return False");
200 	return False;
201     }
202 
203     *hSAREA = rep.hSAREALow;
204 #ifdef LONG64
205     if (sizeof(drm_handle_t) == 8) {
206 	*hSAREA |= ((unsigned long)rep.hSAREAHigh) << 32;
207     }
208 #endif
209     if (rep.length) {
210 	if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
211 	    _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3));
212 	    UnlockDisplay(dpy);
213 	    SyncHandle();
214 	    TRACE("OpenConnection... return False");
215 	    return False;
216 	}
217 	_XReadPad(dpy, *busIdString, rep.busIdStringLength);
218     } else {
219 	*busIdString = NULL;
220     }
221     UnlockDisplay(dpy);
222     SyncHandle();
223     TRACE("OpenConnection... return True");
224     return True;
225 }
226 
227 Bool
uniDRIAuthConnection(dpy,screen,magic)228 uniDRIAuthConnection(dpy, screen, magic)
229     Display *dpy;
230     int screen;
231     drm_magic_t magic;
232 {
233     XExtDisplayInfo *info = find_display(dpy);
234     xXF86DRIAuthConnectionReq *req;
235     xXF86DRIAuthConnectionReply rep;
236 
237     TRACE("AuthConnection...");
238     uniDRICheckExtension(dpy, info, False);
239 
240     LockDisplay(dpy);
241     GetReq(XF86DRIAuthConnection, req);
242     req->reqType = info->codes->major_opcode;
243     req->driReqType = X_XF86DRIAuthConnection;
244     req->screen = screen;
245     req->magic = magic;
246     rep.authenticated = 0;
247     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) {
248 	UnlockDisplay(dpy);
249 	SyncHandle();
250 	TRACE("AuthConnection... return False");
251 	return False;
252     }
253     UnlockDisplay(dpy);
254     SyncHandle();
255     TRACE("AuthConnection... return True");
256     return True;
257 }
258 
259 Bool
uniDRICloseConnection(dpy,screen)260 uniDRICloseConnection(dpy, screen)
261     Display *dpy;
262     int screen;
263 {
264     XExtDisplayInfo *info = find_display(dpy);
265     xXF86DRICloseConnectionReq *req;
266 
267     TRACE("CloseConnection...");
268 
269     uniDRICheckExtension(dpy, info, False);
270 
271     LockDisplay(dpy);
272     GetReq(XF86DRICloseConnection, req);
273     req->reqType = info->codes->major_opcode;
274     req->driReqType = X_XF86DRICloseConnection;
275     req->screen = screen;
276     UnlockDisplay(dpy);
277     SyncHandle();
278     TRACE("CloseConnection... return True");
279     return True;
280 }
281 
282 Bool
uniDRIGetClientDriverName(dpy,screen,ddxDriverMajorVersion,ddxDriverMinorVersion,ddxDriverPatchVersion,clientDriverName)283 uniDRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
284     ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
285     Display *dpy;
286     int screen;
287     int *ddxDriverMajorVersion;
288     int *ddxDriverMinorVersion;
289     int *ddxDriverPatchVersion;
290     char **clientDriverName;
291 {
292     XExtDisplayInfo *info = find_display(dpy);
293     xXF86DRIGetClientDriverNameReply rep;
294     xXF86DRIGetClientDriverNameReq *req;
295 
296     TRACE("GetClientDriverName...");
297     uniDRICheckExtension(dpy, info, False);
298 
299     LockDisplay(dpy);
300     GetReq(XF86DRIGetClientDriverName, req);
301     req->reqType = info->codes->major_opcode;
302     req->driReqType = X_XF86DRIGetClientDriverName;
303     req->screen = screen;
304     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
305 	UnlockDisplay(dpy);
306 	SyncHandle();
307 	TRACE("GetClientDriverName... return False");
308 	return False;
309     }
310 
311     *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
312     *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
313     *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
314 
315     if (rep.length) {
316 	if (!(*clientDriverName =
317 		(char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
318 	    _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3));
319 	    UnlockDisplay(dpy);
320 	    SyncHandle();
321 	    TRACE("GetClientDriverName... return False");
322 	    return False;
323 	}
324 	_XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
325     } else {
326 	*clientDriverName = NULL;
327     }
328     UnlockDisplay(dpy);
329     SyncHandle();
330     TRACE("GetClientDriverName... return True");
331     return True;
332 }
333 
334 Bool
uniDRICreateContextWithConfig(dpy,screen,configID,context,hHWContext)335 uniDRICreateContextWithConfig(dpy, screen, configID, context, hHWContext)
336     Display *dpy;
337     int screen;
338     int configID;
339     XID *context;
340     drm_context_t *hHWContext;
341 {
342     XExtDisplayInfo *info = find_display(dpy);
343     xXF86DRICreateContextReply rep;
344     xXF86DRICreateContextReq *req;
345 
346     TRACE("CreateContext...");
347     uniDRICheckExtension(dpy, info, False);
348 
349     LockDisplay(dpy);
350     GetReq(XF86DRICreateContext, req);
351     req->reqType = info->codes->major_opcode;
352     req->driReqType = X_XF86DRICreateContext;
353     req->visual = configID;
354     req->screen = screen;
355     *context = XAllocID(dpy);
356     req->context = *context;
357     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
358 	UnlockDisplay(dpy);
359 	SyncHandle();
360 	TRACE("CreateContext... return False");
361 	return False;
362     }
363     *hHWContext = rep.hHWContext;
364     UnlockDisplay(dpy);
365     SyncHandle();
366     TRACE("CreateContext... return True");
367     return True;
368 }
369 
370 Bool
uniDRICreateContext(dpy,screen,visual,context,hHWContext)371 uniDRICreateContext(dpy, screen, visual, context, hHWContext)
372     Display *dpy;
373     int screen;
374     Visual *visual;
375     XID *context;
376     drm_context_t *hHWContext;
377 {
378     return uniDRICreateContextWithConfig(dpy, screen, visual->visualid,
379 	context, hHWContext);
380 }
381 
382 Bool
uniDRIDestroyContext(Display * ndpy,int screen,XID context)383 uniDRIDestroyContext(Display * ndpy, int screen, XID context)
384 {
385     Display *const dpy = (Display *) ndpy;
386     XExtDisplayInfo *info = find_display(dpy);
387     xXF86DRIDestroyContextReq *req;
388 
389     TRACE("DestroyContext...");
390     uniDRICheckExtension(dpy, info, False);
391 
392     LockDisplay(dpy);
393     GetReq(XF86DRIDestroyContext, req);
394     req->reqType = info->codes->major_opcode;
395     req->driReqType = X_XF86DRIDestroyContext;
396     req->screen = screen;
397     req->context = context;
398     UnlockDisplay(dpy);
399     SyncHandle();
400     TRACE("DestroyContext... return True");
401     return True;
402 }
403 
404 Bool
uniDRICreateDrawable(Display * ndpy,int screen,Drawable drawable,drm_drawable_t * hHWDrawable)405 uniDRICreateDrawable(Display * ndpy, int screen,
406     Drawable drawable, drm_drawable_t * hHWDrawable)
407 {
408     Display *const dpy = (Display *) ndpy;
409     XExtDisplayInfo *info = find_display(dpy);
410     xXF86DRICreateDrawableReply rep;
411     xXF86DRICreateDrawableReq *req;
412 
413     TRACE("CreateDrawable...");
414     uniDRICheckExtension(dpy, info, False);
415 
416     LockDisplay(dpy);
417     GetReq(XF86DRICreateDrawable, req);
418     req->reqType = info->codes->major_opcode;
419     req->driReqType = X_XF86DRICreateDrawable;
420     req->screen = screen;
421     req->drawable = drawable;
422     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
423 	UnlockDisplay(dpy);
424 	SyncHandle();
425 	TRACE("CreateDrawable... return False");
426 	return False;
427     }
428     *hHWDrawable = rep.hHWDrawable;
429     UnlockDisplay(dpy);
430     SyncHandle();
431     TRACE("CreateDrawable... return True");
432     return True;
433 }
434 
435 Bool
uniDRIDestroyDrawable(Display * ndpy,int screen,Drawable drawable)436 uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable)
437 {
438     Display *const dpy = (Display *) ndpy;
439     XExtDisplayInfo *info = find_display(dpy);
440     xXF86DRIDestroyDrawableReq *req;
441 
442     TRACE("DestroyDrawable...");
443     uniDRICheckExtension(dpy, info, False);
444 
445     LockDisplay(dpy);
446     GetReq(XF86DRIDestroyDrawable, req);
447     req->reqType = info->codes->major_opcode;
448     req->driReqType = X_XF86DRIDestroyDrawable;
449     req->screen = screen;
450     req->drawable = drawable;
451     UnlockDisplay(dpy);
452     SyncHandle();
453     TRACE("DestroyDrawable... return True");
454     return True;
455 }
456 
457 Bool
uniDRIGetDrawableInfo(Display * dpy,int screen,Drawable drawable,unsigned int * index,unsigned int * stamp,int * X,int * Y,int * W,int * H,int * numClipRects,drm_clip_rect_t ** pClipRects,int * backX,int * backY,int * numBackClipRects,drm_clip_rect_t ** pBackClipRects)458 uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable,
459     unsigned int *index, unsigned int *stamp,
460     int *X, int *Y, int *W, int *H,
461     int *numClipRects, drm_clip_rect_t ** pClipRects,
462     int *backX, int *backY,
463     int *numBackClipRects, drm_clip_rect_t ** pBackClipRects)
464 {
465     XExtDisplayInfo *info = find_display(dpy);
466     xXF86DRIGetDrawableInfoReply rep;
467     xXF86DRIGetDrawableInfoReq *req;
468     int total_rects;
469 
470     TRACE("GetDrawableInfo...");
471     uniDRICheckExtension(dpy, info, False);
472 
473     LockDisplay(dpy);
474     GetReq(XF86DRIGetDrawableInfo, req);
475     req->reqType = info->codes->major_opcode;
476     req->driReqType = X_XF86DRIGetDrawableInfo;
477     req->screen = screen;
478     req->drawable = drawable;
479 
480     if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) {
481 	UnlockDisplay(dpy);
482 	SyncHandle();
483 	TRACE("GetDrawableInfo... return False");
484 	return False;
485     }
486     *index = rep.drawableTableIndex;
487     *stamp = rep.drawableTableStamp;
488     *X = (int)rep.drawableX;
489     *Y = (int)rep.drawableY;
490     *W = (int)rep.drawableWidth;
491     *H = (int)rep.drawableHeight;
492     *numClipRects = rep.numClipRects;
493     total_rects = *numClipRects;
494 
495     *backX = rep.backX;
496     *backY = rep.backY;
497     *numBackClipRects = rep.numBackClipRects;
498     total_rects += *numBackClipRects;
499 
500 #if 0
501     /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
502      * backwards compatibility (Because of the >> 2 shift) but the fix
503      * enables multi-threaded apps to work.
504      */
505     if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
506 			SIZEOF(xGenericReply) +
507 			total_rects * sizeof(drm_clip_rect_t)) +
508 		    3) & ~3) >> 2)) {
509 	_XEatData(dpy, rep.length);
510 	UnlockDisplay(dpy);
511 	SyncHandle();
512 	TRACE("GetDrawableInfo... return False");
513 	return False;
514     }
515 #endif
516 
517     if (*numClipRects) {
518 	int len = sizeof(drm_clip_rect_t) * (*numClipRects);
519 
520 	*pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
521 	if (*pClipRects)
522 	    _XRead(dpy, (char *)*pClipRects, len);
523     } else {
524 	*pClipRects = NULL;
525     }
526 
527     if (*numBackClipRects) {
528 	int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
529 
530 	*pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
531 	if (*pBackClipRects)
532 	    _XRead(dpy, (char *)*pBackClipRects, len);
533     } else {
534 	*pBackClipRects = NULL;
535     }
536 
537     UnlockDisplay(dpy);
538     SyncHandle();
539     TRACE("GetDrawableInfo... return True");
540     return True;
541 }
542 
543 Bool
uniDRIGetDeviceInfo(dpy,screen,hFrameBuffer,fbOrigin,fbSize,fbStride,devPrivateSize,pDevPrivate)544 uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer,
545     fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
546     Display *dpy;
547     int screen;
548     drm_handle_t *hFrameBuffer;
549     int *fbOrigin;
550     int *fbSize;
551     int *fbStride;
552     int *devPrivateSize;
553     void **pDevPrivate;
554 {
555     XExtDisplayInfo *info = find_display(dpy);
556     xXF86DRIGetDeviceInfoReply rep;
557     xXF86DRIGetDeviceInfoReq *req;
558 
559     TRACE("GetDeviceInfo...");
560     uniDRICheckExtension(dpy, info, False);
561 
562     LockDisplay(dpy);
563     GetReq(XF86DRIGetDeviceInfo, req);
564     req->reqType = info->codes->major_opcode;
565     req->driReqType = X_XF86DRIGetDeviceInfo;
566     req->screen = screen;
567     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
568 	UnlockDisplay(dpy);
569 	SyncHandle();
570 	TRACE("GetDeviceInfo... return False");
571 	return False;
572     }
573 
574     *hFrameBuffer = rep.hFrameBufferLow;
575 #ifdef LONG64
576     if (sizeof(drm_handle_t) == 8) {
577 	*hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32;
578     }
579 #endif
580 
581     *fbOrigin = rep.framebufferOrigin;
582     *fbSize = rep.framebufferSize;
583     *fbStride = rep.framebufferStride;
584     *devPrivateSize = rep.devPrivateSize;
585 
586     if (rep.length) {
587 	if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
588 	    _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3));
589 	    UnlockDisplay(dpy);
590 	    SyncHandle();
591 	    TRACE("GetDeviceInfo... return False");
592 	    return False;
593 	}
594 	_XRead(dpy, (char *)*pDevPrivate, rep.devPrivateSize);
595     } else {
596 	*pDevPrivate = NULL;
597     }
598 
599     UnlockDisplay(dpy);
600     SyncHandle();
601     TRACE("GetDeviceInfo... return True");
602     return True;
603 }
604