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