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