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
 }