Skip to content

Instantly share code, notes, and snippets.

@dsd
Last active August 29, 2015 13:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dsd/6f2984f87f972f62d53e to your computer and use it in GitHub Desktop.
Save dsd/6f2984f87f972f62d53e to your computer and use it in GitHub Desktop.
xserver patch to handle Mali's incorrect spew of DRI2CreateDrawable requests
The state of the DRI2CreateDrawable request is a little unclear.
dri2proto.txt states that it was dropped in version 1.99.2, but
actually this must still be called exactly once for each drawable
before GetBuffers and friends can be called, because it is the only
way that the internal DRI2DrawableRec structure will be allocated.
Mali fails to obey this unwritten rule and instead calls CreateDrawable
before each and every GetBuffers request. That causes a new dri2_id and
internal reference to be created every time. When we then come to
invalidate the drawable after GetBuffers+SwapBuffers for frame N, we end
up generating N invalidate events from DRI2InvalidateDrawable. Things
quickly get out of hand.
Fix this by detecting the fact that we're being called from
the DRI2CreateDrawable request context (i.e. caller does not get to
learn about the assigned dri2_id). In that case, just ensure that
we have allocated the relevant internal DRI2 private data, and return.
Signed-off-by: Daniel Drake <drake@endlessm.com>
---
hw/xfree86/dri2/dri2.c | 7 +++++++
1 file changed, 7 insertions(+)
Index: xorg-server-1.13.3/hw/xfree86/dri2/dri2.c
===================================================================
--- xorg-server-1.13.3.orig/hw/xfree86/dri2/dri2.c 2014-02-25 10:37:59.002464709 -0600
+++ xorg-server-1.13.3/hw/xfree86/dri2/dri2.c 2014-02-25 11:38:29.229158820 -0600
@@ -101,6 +101,7 @@
int swap_limit; /* for N-buffering */
unsigned long serialNumber;
Bool needInvalidate;
+ Bool client_created;
int prime_id;
PixmapPtr prime_slave_pixmap;
PixmapPtr redirectpixmap;
@@ -215,6 +216,7 @@
if (pPriv == NULL)
return NULL;
+ pPriv->client_created = FALSE;
pPriv->dri2_screen = ds;
pPriv->drawable = pDraw;
pPriv->width = pDraw->width;
@@ -343,6 +345,15 @@
int rc;
pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv && dri2_id_out == NULL && pPriv->client_created) {
+ /* We already allocated a DRI2Drawable for this drawable, the client
+ * has called into this function (so will receive invalidate events)
+ * and now we're being called by the client again (we know this because
+ * the caller doesn't care about the dri2_id). This means we don't need
+ * to allocate another one, we have nothing else to do. */
+ pPriv->prime_id = dri2_client->prime_id;
+ return Success;
+ }
if (pPriv == NULL)
pPriv = DRI2AllocateDrawable(pDraw);
if (pPriv == NULL)
@@ -357,6 +368,11 @@
if (dri2_id_out)
*dri2_id_out = dri2_id;
+ else {
+ /* The client has called in for the first time, it will now receive
+ * invalidate events. Record this for later. */
+ pPriv->client_created = TRUE;
+ }
return Success;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment