dri: attempt to actually refcount the __DRIDrawable
authorDave Airlie <airlied@redhat.com>
Thu, 16 Apr 2009 03:06:24 +0000 (13:06 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 16 Apr 2009 03:06:24 +0000 (13:06 +1000)
valgrind was showing a race between the drawable getting destroyed
by the X resource freeing code, and the context getting destroyed
later and freeing the drawable.

However I've no idea if some other combination of things could cause
this code to leak.

src/mesa/drivers/dri/common/dri_util.c

index 38c2e7b..0ec4adc 100644 (file)
@@ -37,6 +37,9 @@
 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
 #endif
 
+static void dri_get_drawable(__DRIdrawable *pdp);
+static void dri_put_drawable(__DRIdrawable *pdp);
+
 /**
  * This is just a token extension used to signal that the driver
  * supports setting a read drawable.
@@ -127,7 +130,7 @@ static int driUnbindContext(__DRIcontext *pcp)
        return GL_FALSE;
     }
 
-    pdp->refcount--;
+    dri_put_drawable(pdp);
 
     if (prp != pdp) {
         if (prp->refcount == 0) {
@@ -135,7 +138,7 @@ static int driUnbindContext(__DRIcontext *pcp)
            return GL_FALSE;
        }
 
-       prp->refcount--;
+       dri_put_drawable(prp);
     }
 
 
@@ -170,10 +173,10 @@ static int driBindContext(__DRIcontext *pcp,
        pcp->driReadablePriv = prp;
        if (pdp) {
            pdp->driContextPriv = pcp;
-           pdp->refcount++;
+           dri_get_drawable(pdp);
        }
        if ( prp && pdp != prp ) {
-           prp->refcount++;
+           dri_get_drawable(prp);
        }
     }
 
@@ -430,7 +433,7 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
 
     pdp->loaderPrivate = data;
     pdp->hHWDrawable = hwDrawable;
-    pdp->refcount = 0;
+    pdp->refcount = 1;
     pdp->pStamp = NULL;
     pdp->lastStamp = 0;
     pdp->index = 0;
@@ -483,12 +486,19 @@ dri2CreateNewDrawable(__DRIscreen *screen,
     return pdraw;
 }
 
-
-static void
-driDestroyDrawable(__DRIdrawable *pdp)
+static void dri_get_drawable(__DRIdrawable *pdp)
+{
+    pdp->refcount++;
+}
+       
+static void dri_put_drawable(__DRIdrawable *pdp)
 {
     __DRIscreenPrivate *psp;
 
+    pdp->refcount--;
+    if (pdp->refcount)
+       return;
+
     if (pdp) {
        psp = pdp->driScreenPriv;
         (*psp->DriverAPI.DestroyBuffer)(pdp);
@@ -504,6 +514,12 @@ driDestroyDrawable(__DRIdrawable *pdp)
     }
 }
 
+static void
+driDestroyDrawable(__DRIdrawable *pdp)
+{
+    dri_put_drawable(pdp);
+}
+
 /*@}*/