Mesa: add drawable refcounting.
Backport of 122a57f86877c35904e94703d76f9022bb02b96b. This avoids
a driver-side leak which manifests in Chrome in the GPU process.
BUG=chromium:85082
TEST=Manual
Change-Id: I1a6cab758395c9400a85eeabe2867002acfc86a2
Reviewed-on: http://gerrit.chromium.org/gerrit/2946
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Tested-by: David Reveman <reveman@chromium.org>
Reviewed-by: Zelidrag Hornung <zelidrag@chromium.org>
diff --git a/media-libs/mesa/files/7.10-glx-implement-drawable-refcounting.patch b/media-libs/mesa/files/7.10-glx-implement-drawable-refcounting.patch
new file mode 100644
index 0000000..5cfba5d
--- /dev/null
+++ b/media-libs/mesa/files/7.10-glx-implement-drawable-refcounting.patch
@@ -0,0 +1,175 @@
+diff -paur mesa-7.10.2/src/glx/dri2_glx.c mesa-7.10.2.work/src/glx/dri2_glx.c
+--- mesa-7.10.2/src/glx/dri2_glx.c 2011-04-06 13:41:43.000000000 -0700
++++ mesa-7.10.2.work/src/glx/dri2_glx.c 2011-06-16 20:54:42.294798000 -0700
+@@ -143,6 +143,8 @@ dri2_bind_context(struct glx_context *co
+ 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 *
+ 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 -paur mesa-7.10.2/src/glx/dri_common.c mesa-7.10.2.work/src/glx/dri_common.c
+--- mesa-7.10.2/src/glx/dri_common.c 2011-04-06 13:41:43.000000000 -0700
++++ mesa-7.10.2.work/src/glx/dri_common.c 2011-06-16 20:54:42.302797000 -0700
+@@ -367,8 +367,10 @@ driFetchDrawable(struct glx_context *gc,
+ 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);
+@@ -376,6 +378,7 @@ driFetchDrawable(struct glx_context *gc,
+ (*pdraw->destroyDrawable) (pdraw);
+ return NULL;
+ }
++ pdraw->refcount = 1;
+
+ return pdraw;
+ }
+@@ -392,19 +395,28 @@ driReleaseDrawables(struct glx_context *
+ 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 -paur mesa-7.10.2/src/glx/dri_glx.c mesa-7.10.2.work/src/glx/dri_glx.c
+--- mesa-7.10.2/src/glx/dri_glx.c 2011-04-06 13:41:43.000000000 -0700
++++ mesa-7.10.2.work/src/glx/dri_glx.c 2011-06-16 20:54:42.305804000 -0700
+@@ -503,6 +503,8 @@ dri_destroy_context(struct glx_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 *con
+ 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 *c
+ 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 -paur mesa-7.10.2/src/glx/drisw_glx.c mesa-7.10.2.work/src/glx/drisw_glx.c
+--- mesa-7.10.2/src/glx/drisw_glx.c 2011-04-06 13:41:43.000000000 -0700
++++ mesa-7.10.2.work/src/glx/drisw_glx.c 2011-06-16 20:54:42.312797000 -0700
+@@ -244,6 +244,8 @@ drisw_destroy_context(struct glx_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);
+
+@@ -266,6 +268,8 @@ drisw_bind_context(struct glx_context *c
+ pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
+ pread = (struct drisw_drawable *) driFetchDrawable(context, read);
+
++ driReleaseDrawables(&pcp->base);
++
+ if (pdraw == NULL || pread == NULL)
+ return GLXBadDrawable;
+
+@@ -283,8 +287,6 @@ drisw_unbind_context(struct glx_context
+ 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 -paur mesa-7.10.2/src/glx/glxclient.h mesa-7.10.2.work/src/glx/glxclient.h
+--- mesa-7.10.2/src/glx/glxclient.h 2011-04-06 13:41:43.000000000 -0700
++++ mesa-7.10.2.work/src/glx/glxclient.h 2011-06-16 20:54:42.316797000 -0700
+@@ -138,6 +138,7 @@ struct __GLXDRIdrawableRec
+ GLenum textureTarget;
+ GLenum textureFormat; /* EXT_texture_from_pixmap support */
+ unsigned long eventMask;
++ int refcount;
+ };
+
+ /*
+diff -paur mesa-7.10.2/src/glx/glxcurrent.c mesa-7.10.2.work/src/glx/glxcurrent.c
+--- mesa-7.10.2/src/glx/glxcurrent.c 2011-04-06 13:41:43.000000000 -0700
++++ mesa-7.10.2.work/src/glx/glxcurrent.c 2011-06-16 20:57:36.183701000 -0700
+@@ -249,18 +249,16 @@ MakeContextCurrent(Display * dpy, GLXDra
+ if (oldGC != &dummyContext) {
+ oldGC->vtable->unbind(oldGC, gc);
+ oldGC->currentDpy = 0;
+- oldGC->currentDrawable = None;
+- oldGC->currentReadable = None;
+ oldGC->thread_id = 0;
+ }
+
+ if (gc) {
+ gc->currentDpy = dpy;
+- gc->currentDrawable = draw;
+- gc->currentReadable = read;
+ gc->thread_id = _glthread_GetID();
+ __glXSetCurrentContext(gc);
+ ret = gc->vtable->bind(gc, oldGC, draw, read);
++ gc->currentDrawable = draw;
++ gc->currentReadable = read;
+ } else {
+ __glXSetCurrentContextNull();
+ }
diff --git a/media-libs/mesa/mesa-7.10-r1.ebuild b/media-libs/mesa/mesa-7.10-r2.ebuild
similarity index 98%
rename from media-libs/mesa/mesa-7.10-r1.ebuild
rename to media-libs/mesa/mesa-7.10-r2.ebuild
index e0918fd..615610a 100644
--- a/media-libs/mesa/mesa-7.10-r1.ebuild
+++ b/media-libs/mesa/mesa-7.10-r2.ebuild
@@ -131,6 +131,7 @@
base_src_prepare
epatch "${FILESDIR}"/${PV}-glxmakecurrent.patch
+ epatch "${FILESDIR}"/${PV}-glx-implement-drawable-refcounting.patch
eautoreconf
}