summaryrefslogtreecommitdiffstats
path: root/src/glx
diff options
context:
space:
mode:
Diffstat (limited to 'src/glx')
-rw-r--r--src/glx/x11/XF86dri.c24
-rw-r--r--src/glx/x11/dri_glx.c2
-rw-r--r--src/glx/x11/glxclient.h7
-rw-r--r--src/glx/x11/glxcmds.c153
-rw-r--r--src/glx/x11/glxext.c76
-rw-r--r--src/glx/x11/glxhash.c6
-rw-r--r--src/glx/x11/xf86dristr.h5
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 {