[PATCH] dri2: Pass AsyncSwap [swap_interval=0] requests to the drivers

Chris Wilson chris at chris-wilson.co.uk
Tue Feb 21 01:55:43 PST 2012


Currently, the midlayer dri2 code intercepts swap_interval=0 (ala
vblank_mode=0) SwapBuffers and converts it to a CopyRegion request.
This prevents the backend from doing anything meaningful in this case
and typically ends up being vsync'ed since the drivers cannot distinguish
it from a regular CopyRegion request.

v2: Only invalidate the drawable on the behest of the backend, so that
existing behaviour of not invalidating for async blit copies is
preserved, suggested by Simon Farnsworh. And rebase for the intervening
12 months since v1.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Jesse Barnes <jbarnes at virtuousgeek.org>
Cc: Kristian Høgsberg <krh at bitplanet.net>
Cc: Ville Syrjälä <ville.syrjala at nokia.com>
Cc: Dave Airlie <airlied at redhat.com>
Cc: Michel Dänzer <michel at daenzer.net>
Cc: Simon Farnsworth <simon.farnsworth at onelan.co.uk>
---
 hw/xfree86/dri2/dri2.c |   46 +++++++++++++++++++++++++++++++++-------------
 hw/xfree86/dri2/dri2.h |   22 +++++++++++++++++++++-
 2 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 5cc9068..05b7cb3 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -98,6 +98,7 @@ typedef struct _DRI2Screen {
     DRI2CreateBufferProcPtr	 CreateBuffer;
     DRI2DestroyBufferProcPtr	 DestroyBuffer;
     DRI2CopyRegionProcPtr	 CopyRegion;
+    DRI2AsyncSwapProcPtr	 AsyncSwap;
     DRI2ScheduleSwapProcPtr	 ScheduleSwap;
     DRI2GetMSCProcPtr		 GetMSC;
     DRI2ScheduleWaitMSCProcPtr	 ScheduleWaitMSC;
@@ -843,6 +844,29 @@ DRI2InvalidateWalk(WindowPtr pWin, pointer data)
     return WT_WALKCHILDREN;
 }
 
+static Bool
+DRI2AsyncSwapBuffers(ClientPtr client,
+		     DrawablePtr pDraw,
+		     DRI2BufferPtr pDestBuffer,
+		     DRI2BufferPtr pSrcBuffer,
+		     DRI2SwapEventPtr func, void *data)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+    BoxRec box;
+    RegionRec region;
+
+    box.x1 = 0;
+    box.y1 = 0;
+    box.x2 = pDraw->width;
+    box.y2 = pDraw->height;
+    RegionInit(&region, &box, 0);
+
+    (*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
+    DRI2SwapComplete(client, pDraw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
+
+    return FALSE;
+}
+
 int
 DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
 		CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
@@ -876,20 +900,11 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
 
     /* Old DDX or no swap interval, just blit */
     if (!ds->ScheduleSwap || !pPriv->swap_interval) {
-	BoxRec box;
-	RegionRec region;
-
-	box.x1 = 0;
-	box.y1 = 0;
-	box.x2 = pDraw->width;
-	box.y2 = pDraw->height;
-	RegionInit(&region, &box, 0);
-
 	pPriv->swapsPending++;
-
-	(*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
-	DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
-			 func, data);
+	if ((*ds->AsyncSwap)(client, pDraw,
+			     pDestBuffer, pSrcBuffer,
+			     func, data))
+	    DRI2InvalidateDrawable(pDraw);
 	return Success;
     }
 
@@ -1202,6 +1217,11 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
 	ds->SwapLimitValidate = info->SwapLimitValidate;
     }
 
+    ds->AsyncSwap = DRI2AsyncSwapBuffers;
+    if (info->version >= 7) {
+	ds->AsyncSwap = info->AsyncSwap;
+    }
+
     /*
      * if the driver doesn't provide an AuthMagic function or the info struct
      * version is too low, it relies on the old method (using libdrm) or fail
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index a67e35f..6395edd 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -104,6 +104,12 @@ typedef int		(*DRI2ScheduleSwapProcPtr)(ClientPtr client,
 						   CARD64 remainder,
 						   DRI2SwapEventPtr func,
 						   void *data);
+typedef Bool		(*DRI2AsyncSwapProcPtr)(ClientPtr client,
+						DrawablePtr pDraw,
+						DRI2BufferPtr pDestBuffer,
+						DRI2BufferPtr pSrcBuffer,
+						DRI2SwapEventPtr func,
+						void *data);
 typedef DRI2BufferPtr	(*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
 						   unsigned int attachment,
 						   unsigned int format);
@@ -185,7 +191,7 @@ typedef Bool		(*DRI2SwapLimitValidateProcPtr)(DrawablePtr pDraw,
 /**
  * Version of the DRI2InfoRec structure defined in this header
  */
-#define DRI2INFOREC_VERSION 6
+#define DRI2INFOREC_VERSION 7
 
 typedef struct {
     unsigned int version;	/**< Version of this struct */
@@ -218,6 +224,20 @@ typedef struct {
 
     DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
     DRI2SwapLimitValidateProcPtr SwapLimitValidate;
+
+    /* added in version 7 */
+
+    /* Used when the client requests swap_interval=0, i.e. swap immediately
+     * with no throttling. Whether to tear or not is left up to the driver.
+     *
+     * A return value of TRUE indicates that a buffer exchange occurred and
+     * that the DRI2 drawable requires invalidation (i.e. for the updated
+     * attachment names to be propagated back to the client.) A return value
+     * of FALSE implies that the back buffer was just copied onto the front,
+     * and that no invalidation is required as the buffer attachments remain
+     * the same.
+     */
+    DRI2AsyncSwapProcPtr	AsyncSwap;
 }  DRI2InfoRec, *DRI2InfoPtr;
 
 extern _X_EXPORT int DRI2EventBase;
-- 
1.7.9



More information about the xorg-devel mailing list