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 /src/glx/dri_common.c | |
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]>
Diffstat (limited to 'src/glx/dri_common.c')
-rw-r--r-- | src/glx/dri_common.c | 26 |
1 files changed, 19 insertions, 7 deletions
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 */ |