Home | History | Annotate | Download | only in glx
      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 (at) valinux.com>
     32  *   Jens Owen <jens (at) tungstengraphics.com>
     33  *   Rickard E. (Rik) Faith <faith (at) 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 */
    627