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 pi...@chromium.org
Signed-off-by: Stéphane Marchesin marc...@chromium.org
---
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 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;
+