diff options
Diffstat (limited to 'src/glx')
-rw-r--r-- | src/glx/x11/XF86dri.c | 24 | ||||
-rw-r--r-- | src/glx/x11/dri_glx.c | 2 | ||||
-rw-r--r-- | src/glx/x11/glxclient.h | 7 | ||||
-rw-r--r-- | src/glx/x11/glxcmds.c | 153 | ||||
-rw-r--r-- | src/glx/x11/glxext.c | 76 | ||||
-rw-r--r-- | src/glx/x11/glxhash.c | 6 | ||||
-rw-r--r-- | src/glx/x11/xf86dristr.h | 5 |
7 files changed, 179 insertions, 94 deletions
diff --git a/src/glx/x11/XF86dri.c b/src/glx/x11/XF86dri.c index 8909a047721..721bb3e65ac 100644 --- a/src/glx/x11/XF86dri.c +++ b/src/glx/x11/XF86dri.c @@ -427,16 +427,37 @@ PUBLIC GLboolean XF86DRICreateDrawable( __DRInativeDisplay * ndpy, int screen, return True; } +static int noopErrorHandler(Display *dpy, XErrorEvent *xerr) +{ + return 0; +} + PUBLIC GLboolean XF86DRIDestroyDrawable( __DRInativeDisplay * ndpy, int screen, __DRIid drawable ) { Display * const dpy = (Display *) ndpy; XExtDisplayInfo *info = find_display (dpy); xXF86DRIDestroyDrawableReq *req; + int (*oldXErrorHandler)(Display *, XErrorEvent *); TRACE("DestroyDrawable..."); XF86DRICheckExtension (dpy, info, False); + /* This is called from the DRI driver, which used call it like this + * + * if (windowExists(drawable)) + * destroyDrawable(drawable); + * + * which is a textbook race condition - the window may disappear + * from the server between checking for its existance and + * destroying it. Instead we change the semantics of + * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if + * the windows is gone, by wrapping the destroy call in an error + * handler. */ + + XSync(dpy, GL_FALSE); + oldXErrorHandler = XSetErrorHandler(noopErrorHandler); + LockDisplay(dpy); GetReq(XF86DRIDestroyDrawable, req); req->reqType = info->codes->major_opcode; @@ -445,6 +466,9 @@ PUBLIC GLboolean XF86DRIDestroyDrawable( __DRInativeDisplay * ndpy, int screen, req->drawable = drawable; UnlockDisplay(dpy); SyncHandle(); + + XSetErrorHandler(oldXErrorHandler); + TRACE("DestroyDrawable... return True"); return True; } diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index 5cf9923979a..d68addaa9f4 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -171,7 +171,7 @@ ExtractDir(int index, const char *paths, int dirLen, char *dir) * \todo * Create a macro or something so that this is automatically updated. */ -static const char createNewScreenName[] = "__driCreateNewScreen_20050727"; +static const char createNewScreenName[] = "__driCreateNewScreen_20070105"; /** diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index 477566cc464..3dbdc306da3 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -60,6 +60,7 @@ #include "GL/internal/glcore.h" #include "glapitable.h" #include "glxextensions.h" +#include "glxhash.h" #if defined( USE_XTHREADS ) # include <X11/Xthreads.h> #elif defined( PTHREADS ) @@ -349,6 +350,11 @@ struct __GLXcontextRec { * Per context direct rendering interface functions and data. */ __DRIcontext driContext; + + /** + * Pointer to the mode used to create this context. + */ + const __GLcontextModes * mode; #endif /** @@ -456,6 +462,7 @@ typedef struct __GLXscreenConfigsRec { * Per screen direct rendering interface functions and data. */ __DRIscreen driScreen; + __glxHashTable *drawHash; #endif /** diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index f52b71ffcd2..09514937269 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -61,41 +61,92 @@ static const char __glXGLXClientVersion[] = "1.4"; /****************************************************************************/ + +#ifdef GLX_DIRECT_RENDERING + +static Bool windowExistsFlag; +static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr) +{ + if (xerr->error_code == BadWindow) { + windowExistsFlag = GL_FALSE; + } + return 0; +} + +/** + * Find drawables in the local hash that have been destroyed on the + * server. + * + * \param dpy Display to destroy drawables for + * \param screen Screen number to destroy drawables for + */ +static void GarbageCollectDRIDrawables(Display *dpy, int screen) +{ + __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + __GLXscreenConfigs *sc; + __DRIid draw; + __DRIdrawable *pdraw; + XWindowAttributes xwa; + int (*oldXErrorHandler)(Display *, XErrorEvent *); + + if (priv == NULL || priv->driDisplay.private == NULL) + return; + + /* Set no-op error handler so Xlib doesn't bail out if the windows + * has alreay been destroyed on the server. */ + XSync(dpy, GL_FALSE); + oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler); + + sc = &priv->screenConfigs[screen]; + if (__glxHashFirst(sc->drawHash, &draw, (void *)&pdraw) == 1) { + do { + windowExistsFlag = GL_TRUE; + XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */ + if (!windowExistsFlag) { + /* Destroy the local drawable data, if the drawable no + longer exists in the Xserver */ + (*pdraw->destroyDrawable)(dpy, pdraw->private); + Xfree(pdraw); + } + } while (__glxHashNext(sc->drawHash, &draw, (void *)&pdraw) == 1); + } + + XSetErrorHandler(oldXErrorHandler); +} + /** * Get the __DRIdrawable for the drawable associated with a GLXContext * * \param dpy The display associated with \c drawable. * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved. + * \param scrn_num If non-NULL, the drawables screen is stored there * \returns A pointer to the context's __DRIdrawable on success, or NULL if * the drawable is not associated with a direct-rendering context. */ - -#ifdef GLX_DIRECT_RENDERING static __DRIdrawable * GetDRIDrawable( Display *dpy, GLXDrawable drawable, int * const scrn_num ) { __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + __DRIdrawable * const pdraw; + const unsigned screen_count = ScreenCount(dpy); + unsigned i; + __GLXscreenConfigs *sc; - if ( (priv != NULL) && (priv->driDisplay.private != NULL) ) { - const unsigned screen_count = ScreenCount(dpy); - unsigned i; - - for ( i = 0 ; i < screen_count ; i++ ) { - __DRIscreen * const psc = &priv->screenConfigs[i].driScreen; - __DRIdrawable * const pdraw = (psc->private != NULL) - ? (*psc->getDrawable)(dpy, drawable, psc->private) : NULL; - - if ( pdraw != NULL ) { - if ( scrn_num != NULL ) { - *scrn_num = i; - } - return pdraw; - } + if (priv == NULL || priv->driDisplay.private == NULL) + return NULL; + + for (i = 0; i < screen_count; i++) { + sc = &priv->screenConfigs[i]; + if (__glxHashLookup(sc->drawHash, drawable, (void *) &pdraw) == 0) { + if (scrn_num != NULL) + *scrn_num = i; + return pdraw; } } return NULL; } + #endif @@ -359,7 +410,7 @@ CreateContext(Display *dpy, XVisualInfo *vis, gc->screen = mode->screen; gc->vid = mode->visualID; gc->fbconfigID = mode->fbconfigID; - gc->driContext.mode = mode; + gc->mode = mode; } } } @@ -473,6 +524,7 @@ DestroyContext(Display *dpy, GLXContext gc) gc->driContext.private); gc->driContext.private = NULL; } + GarbageCollectDRIDrawables(dpy, gc->screen); } #endif @@ -1730,9 +1782,7 @@ static int __glXSwapIntervalMESA(unsigned int interval) if ( (psc != NULL) && (psc->driScreen.private != NULL) && __glXExtensionBitIsEnabled( psc, MESA_swap_control_bit ) ) { __DRIdrawable * const pdraw = - (*psc->driScreen.getDrawable)(gc->currentDpy, - gc->currentDrawable, - psc->driScreen.private); + GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); if ( pdraw != NULL ) { pdraw->swap_interval = interval; return 0; @@ -1759,9 +1809,7 @@ static int __glXGetSwapIntervalMESA(void) if ( (psc != NULL) && (psc->driScreen.private != NULL) && __glXExtensionBitIsEnabled( psc, MESA_swap_control_bit ) ) { __DRIdrawable * const pdraw = - (*psc->driScreen.getDrawable)(gc->currentDpy, - gc->currentDrawable, - psc->driScreen.private); + GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); if ( pdraw != NULL ) { return pdraw->swap_interval; } @@ -1919,9 +1967,7 @@ static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count if ( __glXExtensionBitIsEnabled( psc, SGI_video_sync_bit ) && psc->driScreen.private ) { __DRIdrawable * const pdraw = - (*psc->driScreen.getDrawable)(gc->currentDpy, - gc->currentDrawable, - psc->driScreen.private); + GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); if ( (pdraw != NULL) && (pdraw->waitForMSC != NULL) ) { int ret; int64_t msc; @@ -2140,11 +2186,10 @@ Bool __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, int i; - GetDRIDrawable( dpy, drawable, & screen_num ); - if ( (screen_num != -1) - && XF86VidModeQueryVersion( dpy, & i, & i ) - && XF86VidModeGetModeLine( dpy, screen_num, & dot_clock, - & mode_line ) ) { + if (GetDRIDrawable( dpy, drawable, & screen_num) != NULL + && XF86VidModeQueryVersion( dpy, & i, & i ) + && XF86VidModeGetModeLine( dpy, screen_num, & dot_clock, + & mode_line ) ) { unsigned n = dot_clock * 1000; unsigned d = mode_line.vtotal * mode_line.htotal; @@ -2889,50 +2934,6 @@ int __glXGetInternalVersion(void) } - -static Bool windowExistsFlag; - -static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr) -{ - if (xerr->error_code == BadWindow) { - windowExistsFlag = GL_FALSE; - } - return 0; -} - -/** - * Determine if a window associated with a \c GLXDrawable exists on the - * X-server. This function is not used internally by libGL. It is provided - * as a utility function for DRI drivers. - * Drivers should not call this function directly. They should instead use - * \c glXGetProcAddress to obtain a pointer to the function. - * - * \param dpy Display associated with the drawable to be queried. - * \param draw \c GLXDrawable to test. - * - * \returns \c GL_TRUE if a window exists that is associated with \c draw, - * otherwise \c GL_FALSE is returned. - * - * \warning This function is not currently thread-safe. - * - * \sa glXGetProcAddress - * - * \since Internal API version 20021128. - */ -Bool __glXWindowExists(Display *dpy, GLXDrawable draw) -{ - XWindowAttributes xwa; - int (*oldXErrorHandler)(Display *, XErrorEvent *); - - XSync(dpy, GL_FALSE); - windowExistsFlag = GL_TRUE; - oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler); - XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */ - XSetErrorHandler(oldXErrorHandler); - return windowExistsFlag; -} - - /** * Get the unadjusted system time (UST). Currently, the UST is measured in * microseconds since Epoc. The actual resolution of the UST may vary from diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c index 8fe10338a80..7f0428c0a99 100644 --- a/src/glx/x11/glxext.c +++ b/src/glx/x11/glxext.c @@ -61,6 +61,7 @@ #include <inttypes.h> #include <sys/mman.h> #include "xf86dri.h" +#include "xf86drm.h" #include "sarea.h" #include "dri_glx.h" #endif @@ -366,6 +367,7 @@ static void FreeScreenConfigs(__GLXdisplayPrivate *priv) (*psc->driScreen.destroyScreen)(priv->dpy, i, psc->driScreen.private); psc->driScreen.private = NULL; + __glxHashDestroy(psc->drawHash); #endif } XFree((char*) priv->screenConfigs); @@ -781,7 +783,6 @@ static const __DRIinterfaceMethods interface_methods = { _gl_context_modes_destroy, __glXFindDRIScreen, - __glXWindowExists, XF86DRICreateContextWithConfig, XF86DRIDestroyContext, @@ -816,7 +817,7 @@ static const __DRIinterfaceMethods interface_methods = { * returned by the client-side driver. */ static void * -CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, +CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, __DRIdisplay * driDpy, PFNCREATENEWSCREENFUNC createNewScreen) { @@ -937,13 +938,12 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, if ( status == 0 ) { __GLcontextModes * driver_modes = NULL; - __GLXscreenConfigs *configs = psc->screenConfigs; err_msg = "InitDriver"; err_extra = NULL; psp = (*createNewScreen)(dpy, scrn, - psc, - configs->configs, + &psc->driScreen, + psc->configs, & ddx_version, & dri_version, & drm_version, @@ -954,7 +954,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, & interface_methods, & driver_modes ); - filter_modes( & configs->configs, + filter_modes( & psc->configs, driver_modes ); _gl_context_modes_destroy( driver_modes ); } @@ -1169,6 +1169,14 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv) UnlockDisplay(dpy); #ifdef GLX_DIRECT_RENDERING + /* Create drawable hash */ + psc->drawHash = __glxHashCreate(); + if ( psc->drawHash == NULL ) { + SyncHandle(); + FreeScreenConfigs(priv); + return GL_FALSE; + } + /* Initialize per screen dynamic client GLX extensions */ psc->ext_list_first_time = GL_TRUE; /* Initialize the direct rendering per screen data and functions */ @@ -1181,7 +1189,7 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv) psc->driScreen.screenConfigs = (void *)psc; psc->driScreen.private = - CallCreateNewScreen(dpy, i, & psc->driScreen, + CallCreateNewScreen(dpy, i, psc, & priv->driDisplay, priv->driDisplay.createNewScreen[i] ); } @@ -1617,20 +1625,64 @@ static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode, #ifdef GLX_DIRECT_RENDERING +static __DRIdrawable * +FetchDRIDrawable( Display *dpy, GLXDrawable drawable, GLXContext gc) +{ + __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + __DRIdrawable *pdraw; + __GLXscreenConfigs *sc; + void *empty_attribute_list = NULL; + + if (priv == NULL || priv->driDisplay.private == NULL) + return NULL; + + sc = &priv->screenConfigs[gc->screen]; + if (__glxHashLookup(sc->drawHash, drawable, (void *) &pdraw) == 0) + return pdraw; + + /* Allocate a new drawable */ + pdraw = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable)); + if (!pdraw) + return NULL; + + /* Create a new drawable */ + pdraw->private = + (*sc->driScreen.createNewDrawable)(dpy, + gc->mode, + drawable, pdraw, + GLX_WINDOW_BIT, + empty_attribute_list); + + if (!pdraw->private) { + /* ERROR!!! */ + Xfree(pdraw); + return NULL; + } + + if (__glxHashInsert(sc->drawHash, drawable, pdraw)) { + (*pdraw->destroyDrawable)(dpy, pdraw->private); + Xfree(pdraw); + return NULL; + } + + return pdraw; +} + static Bool BindContextWrapper( Display *dpy, GLXContext gc, GLXDrawable draw, GLXDrawable read ) { - return (*gc->driContext.bindContext)(dpy, gc->screen, draw, read, + __DRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc); + __DRIdrawable *pread = FetchDRIDrawable(dpy, read, gc); + + return (*gc->driContext.bindContext)(dpy, gc->screen, pdraw, pread, & gc->driContext); } static Bool UnbindContextWrapper( GLXContext gc ) { - return (*gc->driContext.unbindContext)(gc->currentDpy, gc->screen, - gc->currentDrawable, - gc->currentReadable, - & gc->driContext ); + return (*gc->driContext.unbindContext)(gc->currentDpy, gc->screen, + &gc->driContext ); } #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/glxhash.c b/src/glx/x11/glxhash.c index f722cbaf389..1b284c5f451 100644 --- a/src/glx/x11/glxhash.c +++ b/src/glx/x11/glxhash.c @@ -1,4 +1,6 @@ -/* xf86drmHash.c -- Small hash table support for integer -> integer mapping +/* glxhash.c -- Small hash table support for integer -> integer mapping + * Taken from libdrm. + * * Created: Sun Apr 18 09:35:45 1999 by faith@precisioninsight.com * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. @@ -25,8 +27,6 @@ * * Authors: Rickard E. (Rik) Faith <faith@valinux.com> * - * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmHash.c,v 1.4 2001/03/21 18:08:54 dawes Exp $ - * * DESCRIPTION * * This file contains a straightforward implementation of a fixed-sized diff --git a/src/glx/x11/xf86dristr.h b/src/glx/x11/xf86dristr.h index ac05b183b3c..7e8bc557d3e 100644 --- a/src/glx/x11/xf86dristr.h +++ b/src/glx/x11/xf86dristr.h @@ -50,9 +50,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 4.0.0: Original * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02 * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02 + * 5.0.0: Drop XIDs from DRI interface. */ -#define XF86DRI_MAJOR_VERSION 4 -#define XF86DRI_MINOR_VERSION 1 +#define XF86DRI_MAJOR_VERSION 5 +#define XF86DRI_MINOR_VERSION 0 #define XF86DRI_PATCH_VERSION 0 typedef struct _XF86DRIQueryVersion { |