[PATCH v3 05/11] dri2: Keep DRI2Drawable resource allocated until creator frees it

Pauli ext-pauli.nieminen at nokia.com
Wed Feb 16 02:21:39 PST 2011


From: Pauli Nieminen <ext-pauli.nieminen at nokia.com>

EGLImage requires that image siblings stay valid until all of them has
been freed. Base EGLImage is only required for creating new siblings.

http://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt

To keep DRI2Drawable until all siblings has been destroyed we need to
extent life time of DRI2Drawable beyond the Drawable.

We can keep the fake dri2 resource allocated. DRI2 can then searched
for fake resource  if client tries to use DRI2Drawable after Drawable was
destroyed.

v3:
* Hide DRI2 details behind DRI2DrawableGetType

Signed-off-by: Pauli Nieminen <ext-pauli.nieminen at nokia.com>
---
 hw/xfree86/dri2/dri2.c    |   48 +++++++++++++++++++++++++++++++++-----------
 hw/xfree86/dri2/dri2.h    |   10 +++++++++
 hw/xfree86/dri2/dri2ext.c |   12 ++++------
 3 files changed, 51 insertions(+), 19 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index b628a40..c9fd74f 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -149,6 +149,13 @@ DRI2DrawableGetScreen(DRI2DrawablePtr pPriv)
     return pPriv->dri2_screen->screen;
 }
 
+unsigned char
+DRI2DrawableGetType(DRI2DrawablePtr pPriv)
+{
+    /* If drawable is NULL type was DRAWABLE_WINDOW */
+    return pPriv->drawable ? pPriv->drawable->type : DRAWABLE_WINDOW;
+}
+
 static unsigned long
 DRI2DrawableSerial(DrawablePtr pDraw)
 {
@@ -243,6 +250,26 @@ DRI2LookupClientDrawableRef(DRI2DrawablePtr pPriv, ClientPtr client, XID id)
     return NULL;
 }
 
+static Bool
+DRI2MatchDrawableRef(pointer data, XID fake_id, pointer cdata)
+{
+    DRI2DrawablePtr pPriv = data;
+    XID id = (XID)(uintptr_t)cdata;
+    DRI2DrawableRefPtr ref = DRI2LookupDrawableRef(pPriv, id);
+    return ref != NULL;
+}
+
+int
+DRI2LookupDrawableComplex(ClientPtr client, XID id, DRI2DrawablePtr *pPriv)
+{
+    DRI2DrawablePtr tmp = LookupClientResourceComplex(client, dri2DrawableRes,
+	    DRI2MatchDrawableRef, (pointer)(uintptr_t)id);
+    if (!tmp)
+	return BadDrawable;
+    *pPriv = tmp;
+    return Success;
+}
+
 static int
 DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id,
 		   DRI2InvalidateProcPtr invalidate, void *priv)
@@ -312,9 +339,7 @@ static int DRI2DrawableGone(pointer p, XID id)
     DRI2DrawablePtr pPriv = p;
     DRI2ScreenPtr   ds = pPriv->dri2_screen;
     DRI2DrawableRefPtr ref, next;
-    WindowPtr pWin;
-    PixmapPtr pPixmap;
-    DrawablePtr pDraw;
+    DrawablePtr pDraw = pPriv->drawable;
     int i;
 
     list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) {
@@ -329,11 +354,10 @@ static int DRI2DrawableGone(pointer p, XID id)
 	    break;
 	}
 
-	if (ref->id == id) {
-	    pPriv->refcnt--;
-	    list_del(&ref->link);
-	    FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE);
-	    free(ref);
+	if (ref->id == id && pDraw && pDraw->type == DRAWABLE_WINDOW) {
+	    WindowPtr pWin = (WindowPtr) pDraw;
+	    dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
+	    pPriv->drawable = NULL;
 	}
     }
 
@@ -348,11 +372,11 @@ static int DRI2DrawableGone(pointer p, XID id)
 
     pDraw = pPriv->drawable;
 
-    if (pDraw->type == DRAWABLE_WINDOW) {
-	pWin = (WindowPtr) pDraw;
+    if (pDraw && pDraw->type == DRAWABLE_WINDOW) {
+	WindowPtr pWin = (WindowPtr) pDraw;
 	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
-    } else {
-	pPixmap = (PixmapPtr) pDraw;
+    } else if (pDraw) {
+	PixmapPtr pPixmap = (PixmapPtr) pDraw;
 	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
 	pDraw->pScreen->DestroyPixmap(pPixmap);
     }
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 3dec65e..88171be 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -342,4 +342,14 @@ extern _X_EXPORT ScreenPtr DRI2DrawableGetScreen(DRI2DrawablePtr pPriv);
  * \return Valid DRI2DrawablePtr if DRI2Drawable exists. Otherwise NULL.
  */
 extern _X_EXPORT DRI2DrawablePtr DRI2GetDrawable(DrawablePtr pDraw);
+
+/**
+ * \param pPriv DRI2 private drawable
+ * \return Drawable type
+ */
+extern _X_EXPORT unsigned char DRI2DrawableGetType(DRI2DrawablePtr pPriv);
+
+extern _X_EXPORT int DRI2LookupDrawableComplex(ClientPtr client,
+                                               XID id,
+                                               DRI2DrawablePtr *pPriv);
 #endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index a8c5c50..587228b 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -66,10 +66,8 @@ validDRI2Drawable(ClientPtr client, XID id, Mask access,
 
     rc = dixLookupResourceByType((pointer*)&pTmp, id, dri2DrawableRes, client, access);
 
-    if (rc == BadValue) {
-	*status = BadDrawable;
-	return FALSE;
-    }
+    if (rc == BadValue)
+	rc = DRI2LookupDrawableComplex(client, id, &pTmp);
     *status = rc;
     if (rc != Success)
 	return FALSE;
@@ -238,12 +236,12 @@ send_buffers_reply(ClientPtr client, DRI2DrawablePtr pPriv,
     xDRI2GetBuffersReply rep;
     int skip = 0;
     int i;
-    DrawablePtr pDrawable = DRI2DrawableGetDrawable(pPriv);
+    unsigned char type = DRI2DrawableGetType(pPriv);
 
     if (buffers == NULL)
 	    return BadAlloc;
 
-    if (pDrawable->type == DRAWABLE_WINDOW) {
+    if (type == DRAWABLE_WINDOW) {
 	for (i = 0; i < count; i++) {
 	    /* Do not send the real front buffer of a window to the client.
 	     */
@@ -267,7 +265,7 @@ send_buffers_reply(ClientPtr client, DRI2DrawablePtr pPriv,
 
 	/* Do not send the real front buffer of a window to the client.
 	 */
-	if (pDrawable->type == DRAWABLE_WINDOW
+	if (type == DRAWABLE_WINDOW
 	    && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
 	    continue;
 	}
-- 
1.7.0.4



More information about the xorg-devel mailing list