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