summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStéphane Marchesin <marcheu@chromium.org>2011-06-15 15:09:12 -0700
committerStéphane Marchesin <marcheu@chromium.org>2011-06-17 11:20:19 -0700
commitbf69ce37f0dcbb479078ee676d5100ac63e20750 (patch)
treecfb0bf5deb989d947503e2bbeddde5aa5080fb62
parent8173471fc25f4c768cab54fa840fd4c53d1c3c0f (diff)
downloadexternal_mesa3d-bf69ce37f0dcbb479078ee676d5100ac63e20750.zip
external_mesa3d-bf69ce37f0dcbb479078ee676d5100ac63e20750.tar.gz
external_mesa3d-bf69ce37f0dcbb479078ee676d5100ac63e20750.tar.bz2
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 <piman@chromium.org> Signed-off-by: Stéphane Marchesin <marcheu@chromium.org> Reviewed-by: Adam Jackson <ajax@redhat.com>
-rw-r--r--src/glx/dri2_glx.c5
-rw-r--r--src/glx/dri_common.c26
-rw-r--r--src/glx/dri_glx.c6
-rw-r--r--src/glx/drisw_glx.c6
-rw-r--r--src/glx/glxclient.h1
-rw-r--r--src/glx/glxcurrent.c14
6 files changed, 37 insertions, 21 deletions
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index 506754c..e7c18ff 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 06a73e4..bac0c9e 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 ff027dc..d59784c 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 2eaa3c5..0075695 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 fa2e2d3..88a6edd 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 064fd71..9eb7d5a 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();
}