[PATCH v2 2/2] dri2: Only add a drawable reference per client

Pauli Nieminen ext-pauli.nieminen at nokia.com
Mon Nov 1 04:22:26 PDT 2010

Registering only one reference per client avoids invalidate event storm
for misbehaving client that calls DRI2CreateDrawable multiple times for
same drawable. Each DRI2CreateDrawable creates a new reference.
Invalidating drawable then send an event for each reference. This will
result client receives multiple events.

This patch is split out from DRI2DestroyDrawable. I originally tough
this would be required for destroy but revisiting the patch made me
understand that this is not required.

Signed-off-by: Pauli Nieminen <ext-pauli.nieminen at nokia.com>

dri2 specification:
"Note that the server is only required to warn the client once
about this condition, until the client takes care of bringing
them back up-to-date with another GetBuffers request."

But if this is not wanted functionality in server then I will be happy
to drop this patch.

 hw/xfree86/dri2/dri2.c |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 75af3ea..410cdde 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -193,6 +193,7 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
 typedef struct DRI2DrawableRefRec {
     XID		  id;
     XID		  dri2_id;
+    int		  refcnt;
     DRI2InvalidateProcPtr	invalidate;
     void	 *priv;
     struct list	  link;
@@ -229,6 +230,7 @@ DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id,
     ref->id = id;
     ref->dri2_id = dri2_id; 
+    ref->refcnt = 1;
     ref->invalidate = invalidate;
     ref->priv = priv;
     list_add(&ref->link, &pPriv->reference_list);
@@ -253,6 +255,7 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
 		   DRI2InvalidateProcPtr invalidate, void *priv)
     DRI2DrawablePtr pPriv;
+    DRI2DrawableRefPtr ref;
     XID dri2_id;
     int rc;
@@ -261,6 +264,11 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
 	pPriv = DRI2AllocateDrawable(pDraw);
     if (pPriv == NULL)
 	return BadAlloc;
+    ref = DRI2FindClientDrawableRef(client, pPriv);
+    if (ref) {
+	    ref->refcnt++;
+	    return Success;
+    }
     dri2_id = FakeClientID(client->index);
     rc = DRI2AddDrawableRef(pPriv, id, dri2_id, invalidate, priv);
@@ -284,7 +292,8 @@ DRI2DestroyDrawable(ClientPtr client, DrawablePtr pDraw, XID id)
     if (!ref)
 	return BadDrawable;
-    FreeResourceByType(ref->dri2_id, dri2DrawableRes, FALSE);
+    if (--ref->refcnt == 0)
+	FreeResourceByType(ref->dri2_id, dri2DrawableRes, FALSE);
     return Success;

More information about the xorg-devel mailing list