[PATCH] dri2: Send out event when auxillary buffers are invalidated

Kristian Høgsberg krh at bitplanet.net
Tue May 11 07:52:18 PDT 2010


This lets the DRI2 clients rely on the server to notify them when they
need to get new buffers.  Without this, OpenGL clients poll the server
in glViewport() which can be a performance problems and also isn't
completely correct behaviour.

We bump the DRI2 protocol minor to indicate the availability of the
event, which the DRI2 clients can use to avoid polling.  This speeds up
various piglit and oglc test cases as well as real applications.

Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
---

This is an upated version of Franciscos original patch that uses the new
DRI2DrawableRef structs for keeping track of clients and their callback
data.  The semantics is a little different in that as long as a client
holds a reference to a window, we'll send it invalidate events.

 configure.ac              |    2 +-
 glx/glxdri2.c             |   23 +++++++++++++++-
 hw/xfree86/dri2/dri2.c    |   64 ++++++++++++++++++++++++++++++++++++++++-----
 hw/xfree86/dri2/dri2.h    |    9 +++++-
 hw/xfree86/dri2/dri2ext.c |   19 ++++++++++++-
 5 files changed, 106 insertions(+), 11 deletions(-)

diff --git a/configure.ac b/configure.ac
index 6110d8c..a25b1f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -781,7 +781,7 @@ RECORDPROTO="recordproto >= 1.13.99.1"
 SCRNSAVERPROTO="scrnsaverproto >= 1.1"
 RESOURCEPROTO="resourceproto"
 DRIPROTO="xf86driproto >= 2.1.0"
-DRI2PROTO="dri2proto >= 2.2"
+DRI2PROTO="dri2proto >= 2.3"
 XINERAMAPROTO="xineramaproto"
 BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
 XCALIBRATEPROTO="xcalibrateproto"
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index bad4516..99949d0 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -429,6 +429,17 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
     return &context->base;
 }
 
+static void
+__glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv)
+{
+#if __DRI2_FLUSH_VERSION >= 3
+    __GLXDRIdrawable *private = priv;
+    __GLXDRIscreen *screen = private->screen;
+
+    (*screen->flush->invalidate)(private->driDrawable);
+#endif
+}
+
 static __GLXdrawable *
 __glXDRIscreenCreateDrawable(ClientPtr client,
 			     __GLXscreen *screen,
@@ -459,7 +470,8 @@ __glXDRIscreenCreateDrawable(ClientPtr client,
     private->base.waitGL	= __glXDRIdrawableWaitGL;
     private->base.waitX		= __glXDRIdrawableWaitX;
 
-    if (DRI2CreateDrawable(client, pDraw, drawId)) {
+    if (DRI2CreateDrawable(client, pDraw, drawId,
+			   __glXDRIinvalidateBuffers, private)) {
 	    xfree(private);
 	    return NULL;
     }
@@ -573,9 +585,18 @@ static const __DRIdri2LoaderExtension loaderExtension = {
     dri2GetBuffersWithFormat,
 };
 
+#ifdef __DRI_USE_INVALIDATE
+static const __DRIuseInvalidateExtension dri2UseInvalidate = {
+   { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION }
+};
+#endif
+
 static const __DRIextension *loader_extensions[] = {
     &systemTimeExtension.base,
     &loaderExtension.base,
+#ifdef __DRI_USE_INVALIDATE
+    &dri2UseInvalidate,
+#endif
     NULL
 };
 
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 143163d..3ac9f7d 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -96,6 +96,8 @@ typedef struct _DRI2Screen {
     DRI2ScheduleWaitMSCProcPtr	 ScheduleWaitMSC;
 
     HandleExposuresProcPtr       HandleExposures;
+
+    ConfigNotifyProcPtr		 ConfigNotify;
 } DRI2ScreenRec;
 
 static DRI2ScreenPtr
@@ -165,9 +167,11 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
 }
 
 typedef struct DRI2DrawableRefRec {
-    XID id;
-    XID dri2_id;
-    struct list link;
+    XID		  id;
+    XID		  dri2_id;
+    DRI2InvalidateProcPtr	invalidate;
+    void	 *priv;
+    struct list	  link;
 } DRI2DrawableRefRec, *DRI2DrawableRefPtr;
 
 static DRI2DrawableRefPtr
@@ -184,7 +188,8 @@ DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id)
 }
 
 static int
-DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id)
+DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id,
+		   DRI2InvalidateProcPtr invalidate, void *priv)
 {
     DRI2DrawableRefPtr ref;
 
@@ -200,13 +205,16 @@ DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id)
 
     ref->id = id;
     ref->dri2_id = dri2_id; 
+    ref->invalidate = invalidate;
+    ref->priv = priv;
     list_add(&ref->link, &pPriv->reference_list);
 
     return Success;
 }
 
 int
-DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id)
+DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
+		   DRI2InvalidateProcPtr invalidate, void *priv)
 {
     DRI2DrawablePtr pPriv;
     XID dri2_id;
@@ -219,7 +227,7 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id)
 	return BadAlloc;
     
     dri2_id = FakeClientID(client->index);
-    rc = DRI2AddDrawableRef(pPriv, id, dri2_id);
+    rc = DRI2AddDrawableRef(pPriv, id, dri2_id, invalidate, priv);
     if (rc != Success)
 	return rc;
 
@@ -456,6 +464,19 @@ DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
 			  out_count, TRUE);
 }
 
+static void
+DRI2InvalidateDrawable(DrawablePtr pDraw)
+{
+    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+    DRI2DrawableRefPtr ref;
+
+    if (!pPriv)
+        return;
+
+    list_for_each_entry(ref, &pPriv->reference_list, link)
+	ref->invalidate(pDraw, ref->priv);
+}
+
 /*
  * In the direct rendered case, we throttle the clients that have more
  * than their share of outstanding swaps (and thus busy buffers) when a
@@ -766,6 +787,8 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
      */
     *swap_target = pPriv->swap_count + pPriv->swapsPending;
 
+    DRI2InvalidateDrawable(pDraw);
+
     return Success;
 }
 
@@ -916,6 +939,30 @@ DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic)
     return TRUE;
 }
 
+static void
+DRI2ConfigNotify(WindowPtr pWin, int x, int y, int w, int h, int bw,
+		 WindowPtr pSib)
+{
+    DrawablePtr pDraw = (DrawablePtr)pWin;
+    ScreenPtr pScreen = pDraw->pScreen;
+    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+    DRI2DrawablePtr dd = DRI2GetDrawable(pDraw);
+
+    if (ds->ConfigNotify) {
+	pScreen->ConfigNotify = ds->ConfigNotify;
+
+	(*pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib);
+
+	ds->ConfigNotify = pScreen->ConfigNotify;
+	pScreen->ConfigNotify = DRI2ConfigNotify;
+    }
+
+    if (!dd || (dd->width == w && dd->height == h))
+	return;
+
+    DRI2InvalidateDrawable(pDraw);
+}
+
 Bool
 DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
 {
@@ -953,7 +1000,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
 	ds->ScheduleSwap = info->ScheduleSwap;
 	ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
 	ds->GetMSC = info->GetMSC;
-	cur_minor = 2;
+	cur_minor = 3;
     } else {
 	cur_minor = 1;
     }
@@ -984,6 +1031,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
 
     dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
 
+    ds->ConfigNotify = pScreen->ConfigNotify;
+    pScreen->ConfigNotify = DRI2ConfigNotify;
+
     xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
     for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) {
 	if (i < ds->numDrivers && ds->driverNames[i]) {
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 5415a0b..be44bdd 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -152,6 +152,10 @@ typedef int		(*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
 						      CARD64 target_msc,
 						      CARD64 divisor,
 						      CARD64 remainder);
+
+typedef void		(*DRI2InvalidateProcPtr)(DrawablePtr pDraw,
+						 void *data);
+
 /**
  * Version of the DRI2InfoRec structure defined in this header
  */
@@ -199,7 +203,10 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
 extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
 
 extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
-					DrawablePtr pDraw, XID id);
+					DrawablePtr pDraw,
+					XID id,
+					DRI2InvalidateProcPtr invalidate,
+					void *priv);
 
 extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
 
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 58eaa10..9419326 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -154,6 +154,22 @@ ProcDRI2Authenticate(ClientPtr client)
     return client->noClientException;
 }
 
+static void
+DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv)
+{
+    xDRI2InvalidateBuffers event;
+    ClientPtr client = priv;
+
+    if (client->clientGone)
+	return;
+
+    event.type = DRI2EventBase + DRI2_InvalidateBuffers;
+    event.sequenceNumber = client->sequence;
+    event.drawable = pDraw->id;
+
+    WriteEventsToClient(client, 1, (xEvent *)&event);
+}
+
 static int
 ProcDRI2CreateDrawable(ClientPtr client)
 {
@@ -167,7 +183,8 @@ ProcDRI2CreateDrawable(ClientPtr client)
 		       &pDrawable, &status))
 	return status;
 
-    status = DRI2CreateDrawable(client, pDrawable, stuff->drawable);
+    status = DRI2CreateDrawable(client, pDrawable, stuff->drawable,
+				DRI2InvalidateBuffersEvent, client);
     if (status != Success)
 	return status;
 
-- 
1.7.0.1



More information about the xorg-devel mailing list