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