glx: implement drawable refcounting.
authorStéphane Marchesin <marcheu@chromium.org>
Wed, 15 Jun 2011 22:09:12 +0000 (15:09 -0700)
committerStéphane Marchesin <marcheu@chromium.org>
Fri, 17 Jun 2011 18:20:19 +0000 (11:20 -0700)
The current dri context unbind logic will leak drawables until the process
dies (they will then get released by the GEM code). There are two ways to fix
this: either always call driReleaseDrawables every time we unbind a context
(but that costs us round trips to the X server at getbuffers() time) or
implement proper drawable refcounting. This patch implements the latter.

Signed-off-by: Antoine Labour <piman@chromium.org>
Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-by: Adam Jackson <ajax@redhat.com>
src/glx/dri2_glx.c
src/glx/dri_common.c
src/glx/dri_glx.c
src/glx/drisw_glx.c
src/glx/glxclient.h
src/glx/glxcurrent.c

index 506754c..e7c18ff 100644 (file)
@@ -143,6 +143,8 @@ dri2_bind_context(struct glx_context *context, struct glx_context *old,
    pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw);
    pread = (struct dri2_drawable *) driFetchDrawable(context, read);
 
+   driReleaseDrawables(&pcp->base);
+
    if (pdraw == NULL || pread == NULL)
       return GLXBadDrawable;
 
@@ -170,9 +172,6 @@ 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);
-
-   if (context == new)
-      driReleaseDrawables(&pcp->base);
 }
 
 static struct glx_context *
index 06a73e4..bac0c9e 100644 (file)
@@ -369,8 +369,10 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
    if (priv->drawHash == NULL)
       return NULL;
 
-   if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0)
+   if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
+      pdraw->refcount ++;
       return pdraw;
+   }
 
    pdraw = psc->driScreen->createDrawable(psc, glxDrawable,
                                           glxDrawable, gc->config);
@@ -378,6 +380,7 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
       (*pdraw->destroyDrawable) (pdraw);
       return NULL;
    }
+   pdraw->refcount = 1;
 
    return pdraw;
 }
@@ -394,19 +397,28 @@ driReleaseDrawables(struct glx_context *gc)
    if (__glxHashLookup(priv->drawHash,
                       gc->currentDrawable, (void *) &pdraw) == 0) {
       if (pdraw->drawable == pdraw->xDrawable) {
-        (*pdraw->destroyDrawable)(pdraw);
-        __glxHashDelete(priv->drawHash, gc->currentDrawable);
+        pdraw->refcount --;
+        if (pdraw->refcount == 0) {
+           (*pdraw->destroyDrawable)(pdraw);
+           __glxHashDelete(priv->drawHash, gc->currentDrawable);
+        }
       }
    }
 
-   if (gc->currentDrawable != gc->currentReadable &&
-       __glxHashLookup(priv->drawHash,
+   if (__glxHashLookup(priv->drawHash,
                       gc->currentReadable, (void *) &pdraw) == 0) {
       if (pdraw->drawable == pdraw->xDrawable) {
-        (*pdraw->destroyDrawable)(pdraw);
-        __glxHashDelete(priv->drawHash, gc->currentReadable);
+        pdraw->refcount --;
+        if (pdraw->refcount == 0) {
+           (*pdraw->destroyDrawable)(pdraw);
+           __glxHashDelete(priv->drawHash, gc->currentReadable);
+        }
       }
    }
+
+   gc->currentDrawable = None;
+   gc->currentReadable = None;
+
 }
 
 #endif /* GLX_DIRECT_RENDERING */
index ff027dc..d59784c 100644 (file)
@@ -503,6 +503,8 @@ dri_destroy_context(struct glx_context * context)
    struct dri_context *pcp = (struct dri_context *) context;
    struct dri_screen *psc = (struct dri_screen *) context->psc;
 
+   driReleaseDrawables(&pcp->base);
+
    if (context->xid)
       glx_send_destroy_context(psc->base.dpy, context->xid);
 
@@ -526,6 +528,8 @@ dri_bind_context(struct glx_context *context, struct glx_context *old,
    pdraw = (struct dri_drawable *) driFetchDrawable(context, draw);
    pread = (struct dri_drawable *) driFetchDrawable(context, read);
 
+   driReleaseDrawables(&pcp->base);
+
    if (pdraw == NULL || pread == NULL)
       return GLXBadDrawable;
 
@@ -543,8 +547,6 @@ 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 2eaa3c5..0075695 100644 (file)
@@ -242,6 +242,8 @@ drisw_destroy_context(struct glx_context *context)
    struct drisw_context *pcp = (struct drisw_context *) context;
    struct drisw_screen *psc = (struct drisw_screen *) context->psc;
 
+   driReleaseDrawables(&pcp->base);
+
    if (context->xid)
       glx_send_destroy_context(psc->base.dpy, context->xid);
 
@@ -264,6 +266,8 @@ drisw_bind_context(struct glx_context *context, struct glx_context *old,
    pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
    pread = (struct drisw_drawable *) driFetchDrawable(context, read);
 
+   driReleaseDrawables(&pcp->base);
+
    if (pdraw == NULL || pread == NULL)
       return GLXBadDrawable;
 
@@ -281,8 +285,6 @@ 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 fa2e2d3..88a6edd 100644 (file)
@@ -138,6 +138,7 @@ struct __GLXDRIdrawableRec
    GLenum textureTarget;
    GLenum textureFormat;        /* EXT_texture_from_pixmap support */
    unsigned long eventMask;
+   int refcount;
 };
 
 /*
index 064fd71..9eb7d5a 100644 (file)
@@ -255,8 +255,6 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
       if (--oldGC->thread_refcount == 0) {
         oldGC->vtable->unbind(oldGC, gc);
         oldGC->currentDpy = 0;
-        oldGC->currentDrawable = None;
-        oldGC->currentReadable = None;
 
         if (oldGC->xid == None && oldGC != gc) {
            /* We are switching away from a context that was
@@ -268,13 +266,15 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
    }
 
    if (gc) {
-      if (gc->thread_refcount++ == 0) {
-        gc->currentDpy = dpy;
-        gc->currentDrawable = draw;
-        gc->currentReadable = read;
-      }
+      if (gc->thread_refcount == 0)
+         gc->currentDpy = dpy;
       __glXSetCurrentContext(gc);
       ret = gc->vtable->bind(gc, oldGC, draw, read);
+      if (gc->thread_refcount == 0) {
+         gc->currentDrawable = draw;
+         gc->currentReadable = read;
+      }
+      gc->thread_refcount++;
    } else {
       __glXSetCurrentContextNull();
    }