From bf69ce37f0dcbb479078ee676d5100ac63e20750 Mon Sep 17 00:00:00 2001 From: =?utf8?q?St=C3=A9phane=20Marchesin?= Date: Wed, 15 Jun 2011 15:09:12 -0700 Subject: [PATCH] glx: implement drawable refcounting. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Stéphane Marchesin Reviewed-by: Adam Jackson --- src/glx/dri2_glx.c | 5 ++--- src/glx/dri_common.c | 26 +++++++++++++++++++------- src/glx/dri_glx.c | 6 ++++-- src/glx/drisw_glx.c | 6 ++++-- src/glx/glxclient.h | 1 + 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(); } -- 2.30.2