glx: Drop broken drawable garbage collection
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 27 Aug 2010 16:40:11 +0000 (12:40 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 8 Sep 2010 13:20:42 +0000 (09:20 -0400)
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
src/glx/dri2_glx.c
src/glx/dri_common.c
src/glx/dri_common.h
src/glx/dri_glx.c
src/glx/drisw_glx.c
src/glx/glxcmds.c
src/glx/glxcurrent.c
src/glx/indirect_glx.c

index d70ec5a3ecf82c5d7522075c9bef035870ea26e4..d4108986489fad1137ad901b6371d93b93589f3e 100644 (file)
@@ -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;
 }
 
index ff48c79c272e12a85834b5eba87c62fab80741da..e38a40ce53dab2a3dd4c471aed537e1e3713460a 100644 (file)
@@ -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 *
index a7fb4c642442652d22a4b067ab5aa3251f0ad0a3..5fb5255416b48dabae8ac6382f248ed6908bc3d6 100644 (file)
@@ -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 */
index 846a905a88037fa56214c78ea4f08c12ae8ead21..13b5ae471d13b84da9110cfde2e222c25e1666be 100644 (file)
@@ -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, ...);
index 43a2aa495a71dfde04c225c24eea881017ee3e49..42b263c6377b090ff7fac055195fe93fecc6f868 100644 (file)
@@ -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 = {
index c5b179157b3edaf2f423a39a889c2bf42411335b..237ce1761765b60d8b92baeafe1e31a6fdec1cd0 100644 (file)
@@ -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 = {
index 9575156080121b6fbc53c78cdd9564beba7c637d..4f7e84ef5f9c16782510289b047f32e6969500f3 100644 (file)
@@ -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
  *
index 98f66c22898203f88009683c75e6f5c795e4c0a1..710985b02c1a696bea14d27bb5a7e6c14a4e0661 100644 (file)
@@ -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();
    }
index 61ceed3d438081510dd94811e6a4ee889732a632..1870edee37137d243356a770018dce61abee9040 100644 (file)
@@ -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.