diff options
author | Stéphane Marchesin <[email protected]> | 2011-06-15 15:09:12 -0700 |
---|---|---|
committer | Stéphane Marchesin <[email protected]> | 2011-06-17 11:20:19 -0700 |
commit | bf69ce37f0dcbb479078ee676d5100ac63e20750 (patch) | |
tree | cfb0bf5deb989d947503e2bbeddde5aa5080fb62 | |
parent | 8173471fc25f4c768cab54fa840fd4c53d1c3c0f (diff) |
glx: implement drawable refcounting.
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 <[email protected]>
Signed-off-by: Stéphane Marchesin <[email protected]>
Reviewed-by: Adam Jackson <[email protected]>
-rw-r--r-- | src/glx/dri2_glx.c | 5 | ||||
-rw-r--r-- | src/glx/dri_common.c | 26 | ||||
-rw-r--r-- | src/glx/dri_glx.c | 6 | ||||
-rw-r--r-- | src/glx/drisw_glx.c | 6 | ||||
-rw-r--r-- | src/glx/glxclient.h | 1 | ||||
-rw-r--r-- | src/glx/glxcurrent.c | 14 |
6 files changed, 37 insertions, 21 deletions
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index 506754ccc1f..e7c18ffe1eb 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -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 * diff --git a/src/glx/dri_common.c b/src/glx/dri_common.c index 06a73e4a6b2..bac0c9e5911 100644 --- a/src/glx/dri_common.c +++ b/src/glx/dri_common.c @@ -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 */ diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c index ff027dc9e9c..d59784c6a4f 100644 --- a/src/glx/dri_glx.c +++ b/src/glx/dri_glx.c @@ -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 = { diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c index 2eaa3c59348..00756959320 100644 --- a/src/glx/drisw_glx.c +++ b/src/glx/drisw_glx.c @@ -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 = { diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h index fa2e2d360ca..88a6edd097c 100644 --- a/src/glx/glxclient.h +++ b/src/glx/glxclient.h @@ -138,6 +138,7 @@ struct __GLXDRIdrawableRec GLenum textureTarget; GLenum textureFormat; /* EXT_texture_from_pixmap support */ unsigned long eventMask; + int refcount; }; /* diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c index 064fd71ae6e..9eb7d5ac546 100644 --- a/src/glx/glxcurrent.c +++ b/src/glx/glxcurrent.c @@ -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(); } |