summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Nieminen <ext-pauli.nieminen@nokia.com>2010-10-25 14:36:33 +0300
committerPauli Nieminen <ext-pauli.nieminen@nokia.com>2011-02-04 16:40:13 +0200
commitb6400d98b602cccf946af53dc81aeff1d75114c0 (patch)
tree6fb7a8f496fd6d05607416bcf873b18a5bc73f93
parentea1ffd3e60bdcedbec5a6f28929f8677bf45d450 (diff)
DRI2: Free DRI2 drawable references in DRI2DestroyDrawable
If client calls DRI2CreateDrawable multiple times for same drawable DRI2 creates multiple references. Multiple references cause DRI2 send multiple invalidate events for same client. Problem is triggered because client side EGL implementation is using DRI2 directly. DRI2 code in server doesn't handle DRI2DestroyDrawable that leaks references. If client recreates rendering target EGL destroys and creates DRI2 drawable. In that case DRI2DestroyDrawable leaks DRI2 drawable references. To fix this memory leak/performance problem server has to free the reference when client requests for it. Signed-off-by: Pauli Nieminen <ext-pauli.nieminen@nokia.com> Reviewed-By: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
-rw-r--r--hw/xfree86/dri2/dri2.c31
-rw-r--r--hw/xfree86/dri2/dri2.h4
-rw-r--r--hw/xfree86/dri2/dri2ext.c2
3 files changed, 35 insertions, 2 deletions
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 39996f946..66d217cc8 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -211,6 +211,18 @@ DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id)
return NULL;
}
+static DRI2DrawableRefPtr
+DRI2LookupClientDrawableRef(DRI2DrawablePtr pPriv, ClientPtr client, XID id)
+{
+ DRI2DrawableRefPtr ref;
+
+ list_for_each_entry(ref, &pPriv->reference_list, link) {
+ if (CLIENT_ID(ref->dri2_id) == client->index && ref->id == id)
+ return ref;
+ }
+ return NULL;
+}
+
static int
DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id,
DRI2InvalidateProcPtr invalidate, void *priv)
@@ -258,6 +270,25 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
return Success;
}
+int
+DRI2DestroyDrawable(ClientPtr client, DrawablePtr pDraw, XID id)
+{
+ DRI2DrawableRefPtr ref;
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+
+ if (!pPriv)
+ return BadDrawable;
+
+ ref = DRI2LookupClientDrawableRef(pPriv, client, id);
+
+ if (!ref)
+ return BadDrawable;
+
+ FreeResourceByType(ref->dri2_id, dri2DrawableRes, FALSE);
+
+ return Success;
+}
+
static int DRI2DrawableGone(pointer p, XID id)
{
DRI2DrawablePtr pPriv = p;
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index fe0bf6ccb..dd63c3029 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -214,7 +214,9 @@ extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
DRI2InvalidateProcPtr invalidate,
void *priv);
-extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
+extern _X_EXPORT int DRI2DestroyDrawable(ClientPtr client,
+ DrawablePtr pDraw,
+ XID id);
extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffers(DrawablePtr pDraw,
int *width,
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 4e48e65b2..c7e6be1ce 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -200,7 +200,7 @@ ProcDRI2DestroyDrawable(ClientPtr client)
&pDrawable, &status))
return status;
- return Success;
+ return DRI2DestroyDrawable(client, pDrawable, stuff->drawable);
}