Mesa (master): glx: Drop broken drawable garbage collection

Kristian Høgsberg krh at kemper.freedesktop.org
Wed Sep 8 14:18:12 UTC 2010


Module: Mesa
Branch: master
Commit: 16887d042a917fa4773e4d853f50051b54e9948c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=16887d042a917fa4773e4d853f50051b54e9948c

Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Fri Aug 27 12:40:11 2010 -0400

glx: Drop broken drawable garbage collection

Doesn't work for pixmaps, was looking up the GLX XID and was never thread
safe.  Instead, just destroy the client side structures when the
drawable is no long current for a context.

---

 src/glx/dri2.c         |    8 +++++++
 src/glx/dri2_glx.c     |    4 +-
 src/glx/dri_common.c   |   25 ++++++++++++++++++++++++
 src/glx/dri_common.h   |    3 ++
 src/glx/dri_glx.c      |    4 +-
 src/glx/drisw_glx.c    |    4 +-
 src/glx/glxcmds.c      |   50 ------------------------------------------------
 src/glx/glxcurrent.c   |    6 ++--
 src/glx/indirect_glx.c |    3 ++
 9 files changed, 48 insertions(+), 59 deletions(-)

diff --git a/src/glx/dri2.c b/src/glx/dri2.c
index d70ec5a..d410898 100644
--- a/src/glx/dri2.c
+++ b/src/glx/dri2.c
@@ -175,6 +175,14 @@ DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
 	err->minorCode == X_DRI2CopyRegion)
 	return True;
 
+    /* If the X drawable was destroyed before the GLX drawable, the
+     * DRI2 drawble will be gone by the time we call
+     * DRI2DestroyDrawable.  So just ignore BadDrawable here. */
+    if (err->majorCode == codes->major_opcode &&
+	err->errorCode == BadDrawable &&
+	err->minorCode == X_DRI2DestroyDrawable)
+	return True;
+
     return False;
 }
 
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index ff48c79..e38a40c 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -124,8 +124,6 @@ dri2_destroy_context(struct glx_context *context)
    if (context->extensions)
       XFree((char *) context->extensions);
 
-   GarbageCollectDRIDrawables(context->psc);
-
    (*psc->core->destroyContext) (pcp->driContext);
 
    Xfree(pcp);
@@ -159,6 +157,8 @@ dri2_unbind_context(struct glx_context *context, struct glx_context *new)
    struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
 
    (*psc->core->unbindContext) (pcp->driContext);
+
+   driReleaseDrawables(&pcp->base);
 }
 
 static struct glx_context *
diff --git a/src/glx/dri_common.c b/src/glx/dri_common.c
index a7fb4c6..5fb5255 100644
--- a/src/glx/dri_common.c
+++ b/src/glx/dri_common.c
@@ -380,4 +380,29 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
    return pdraw;
 }
 
+_X_HIDDEN void
+driReleaseDrawables(struct glx_context *gc)
+{
+   struct glx_display *const priv = __glXInitialize(gc->psc->dpy);
+   __GLXDRIdrawable *pdraw;
+
+   if (priv == NULL)
+      return;
+
+   if (__glxHashLookup(priv->drawHash,
+		       gc->currentDrawable, (void *) &pdraw) == 0) {
+      if (pdraw->drawable == pdraw->xDrawable)
+	 (*pdraw->destroyDrawable)(pdraw);
+      __glxHashDelete(priv->drawHash, gc->currentDrawable);
+   }
+
+   if (gc->currentDrawable != gc->currentReadable &&
+       __glxHashLookup(priv->drawHash,
+		       gc->currentReadable, (void *) &pdraw) == 0) {
+      if (pdraw->drawable == pdraw->xDrawable)
+	 (*pdraw->destroyDrawable)(pdraw);
+      __glxHashDelete(priv->drawHash, gc->currentReadable);
+   }
+}
+
 #endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/dri_common.h b/src/glx/dri_common.h
index 846a905..13b5ae4 100644
--- a/src/glx/dri_common.h
+++ b/src/glx/dri_common.h
@@ -55,6 +55,9 @@ extern void driDestroyConfigs(const __DRIconfig **configs);
 extern __GLXDRIdrawable *
 driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable);
 
+extern void
+driReleaseDrawables(struct glx_context *gc);
+
 extern const __DRIsystemTimeExtension systemTimeExtension;
 
 extern void InfoMessageF(const char *f, ...);
diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c
index 43a2aa4..42b263c 100644
--- a/src/glx/dri_glx.c
+++ b/src/glx/dri_glx.c
@@ -509,8 +509,6 @@ dri_destroy_context(struct glx_context * context)
    if (context->extensions)
       XFree((char *) context->extensions);
 
-   GarbageCollectDRIDrawables(context->psc);
-
    (*psc->core->destroyContext) (pcp->driContext);
 
    XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
@@ -545,6 +543,8 @@ dri_unbind_context(struct glx_context *context, struct glx_context *new)
    struct dri_screen *psc = (struct dri_screen *) pcp->base.psc;
 
    (*psc->core->unbindContext) (pcp->driContext);
+
+   driReleaseDrawables(&pcp->base);
 }
 
 static const struct glx_context_vtable dri_context_vtable = {
diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c
index c5b1791..237ce17 100644
--- a/src/glx/drisw_glx.c
+++ b/src/glx/drisw_glx.c
@@ -250,8 +250,6 @@ drisw_destroy_context(struct glx_context *context)
    if (context->extensions)
       XFree((char *) context->extensions);
 
-   GarbageCollectDRIDrawables(context->psc);
-
    (*psc->core->destroyContext) (pcp->driContext);
 
    Xfree(pcp);
@@ -285,6 +283,8 @@ drisw_unbind_context(struct glx_context *context, struct glx_context *new)
    struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
 
    (*psc->core->unbindContext) (pcp->driContext);
+
+   driReleaseDrawables(&pcp->base);
 }
 
 static const struct glx_context_vtable drisw_context_vtable = {
diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c
index 9575156..4f7e84e 100644
--- a/src/glx/glxcmds.c
+++ b/src/glx/glxcmds.c
@@ -63,56 +63,6 @@ static const char __glXGLXClientVersion[] = "1.4";
 
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
 
-static Bool windowExistsFlag;
-static int
-windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr)
-{
-   (void) dpy;
-
-   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
- */
-_X_HIDDEN void
-GarbageCollectDRIDrawables(struct glx_screen * sc)
-{
-   XID draw;
-   __GLXDRIdrawable *pdraw;
-   struct glx_display *priv = sc->display;
-   XWindowAttributes xwa;
-   int (*oldXErrorHandler) (Display *, XErrorEvent *);
-
-   /* Set no-op error handler so Xlib doesn't bail out if the windows
-    * has alreay been destroyed on the server. */
-   XSync(priv->dpy, GL_FALSE);
-   oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
-
-   if (__glxHashFirst(priv->drawHash, &draw, (void *) &pdraw) == 1) {
-      do {
-         windowExistsFlag = GL_TRUE;
-         XGetWindowAttributes(priv->dpy, draw, &xwa); /* dummy request */
-         if (!windowExistsFlag) {
-            /* Destroy the local drawable data, if the drawable no
-               longer exists in the Xserver */
-            (*pdraw->destroyDrawable) (pdraw);
-            __glxHashDelete(priv->drawHash, draw);
-         }
-      } while (__glxHashNext(priv->drawHash, &draw, (void *) &pdraw) == 1);
-   }
-
-   XSync(priv->dpy, GL_FALSE);
-   XSetErrorHandler(oldXErrorHandler);
-}
-
 /**
  * Get the __DRIdrawable for the drawable associated with a GLXContext
  *
diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c
index 98f66c2..710985b 100644
--- a/src/glx/glxcurrent.c
+++ b/src/glx/glxcurrent.c
@@ -242,13 +242,13 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
       return False;
    }
 
-   if (oldGC != &dummyContext && oldGC != gc) {
+   if (oldGC != &dummyContext) {
       oldGC->vtable->unbind(oldGC, gc);
       oldGC->currentDpy = 0;
       oldGC->currentDrawable = None;
       oldGC->currentReadable = None;
       oldGC->thread_id = 0;
-      if (oldGC->xid == None)
+      if (oldGC->xid == None && oldGC != gc)
 	 /* We are switching away from a context that was
 	  * previously destroyed, so we need to free the memory
 	  * for the old handle.
@@ -257,12 +257,12 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
    }
 
    if (gc) {
-      ret = gc->vtable->bind(gc, oldGC, draw, read);
       gc->currentDpy = dpy;
       gc->currentDrawable = draw;
       gc->currentReadable = read;
       gc->thread_id = _glthread_GetID();
       __glXSetCurrentContext(gc);
+      ret = gc->vtable->bind(gc, oldGC, draw, read);
    } else {
       __glXSetCurrentContextNull();
    }
diff --git a/src/glx/indirect_glx.c b/src/glx/indirect_glx.c
index 61ceed3..1870ede 100644
--- a/src/glx/indirect_glx.c
+++ b/src/glx/indirect_glx.c
@@ -168,6 +168,9 @@ indirect_unbind_context(struct glx_context *gc, struct glx_context *new)
    int opcode = __glXSetupForCommand(dpy);
    xGLXMakeCurrentReply reply;
 
+   if (gc == new)
+      return;
+   
    /* We are either switching to no context, away from a indirect
     * context to a direct context or from one dpy to another and have
     * to send a request to the dpy to unbind the previous context.




More information about the mesa-commit mailing list