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

Chris Wilson chris at chris-wilson.co.uk
Tue Jul 10 01:21:51 PDT 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.

v3: Time for another rebase.
v4: Rebase on top of Prime.

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>
Reviewed-by: Simon Farnsworth <simon.farnsworth at onelan.co.uk>
Reviewed-by: Jesse Barnes <jbarnes at virtuousgeek.org>
---
 hw/xfree86/dri2/dri2.c |   54 ++++++++++++++++++++++++++++++++++--------------
 hw/xfree86/dri2/dri2.h |   22 +++++++++++++++++++-
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 2ea0c33..8dae0ae 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -130,6 +130,8 @@ typedef struct _DRI2Screen {
 
     HandleExposuresProcPtr HandleExposures;
 
+    DRI2AsyncSwapProcPtr AsyncSwap;
+
     ConfigNotifyProcPtr ConfigNotify;
     DRI2CreateBuffer2ProcPtr CreateBuffer2;
     DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
@@ -1044,6 +1046,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,
@@ -1075,23 +1100,14 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
         return BadDrawable;
     }
 
-    /* Old DDX or no swap interval, just blit */
+    /* Old DDX or no swap interval, just perform an immediate swap */
     if (!ds->ScheduleSwap || !pPriv->swap_interval || pPriv->prime_id) {
-        BoxRec box;
-        RegionRec region;
-
-        box.x1 = 0;
-        box.y1 = 0;
-        box.x2 = pDraw->width;
-        box.y2 = pDraw->height;
-        RegionInit(&region, &box, 0);
-
-        pPriv->swapsPending++;
-
-        dri2_copy_region(pDraw, &region, pDestBuffer, pSrcBuffer);
-        DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
-                         func, data);
-        return Success;
+	pPriv->swapsPending++;
+	if ((*ds->AsyncSwap)(client, pDraw,
+			     pDestBuffer, pSrcBuffer,
+			     func, data))
+	    DRI2InvalidateDrawable(pDraw);
+	return Success;
     }
 
     /*
@@ -1477,6 +1493,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
         ds->CopyRegion2 = info->CopyRegion2;
     }
 
+    if (info->version >= 10) {
+	ds->AsyncSwap = info->AsyncSwap;
+    }
+    if (ds->AsyncSwap == NULL)
+	ds->AsyncSwap = DRI2AsyncSwapBuffers;
+
     /*
      * if the driver doesn't provide an AuthMagic function or the info struct
      * version is too low, call through LegacyAuthMagic
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index da7825e..ba1f000 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -101,6 +101,12 @@ typedef int (*DRI2ScheduleSwapProcPtr) (ClientPtr client,
                                         CARD64 divisor,
                                         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);
@@ -205,7 +211,7 @@ typedef int (*DRI2GetParamProcPtr) (ClientPtr client,
 /**
  * Version of the DRI2InfoRec structure defined in this header
  */
-#define DRI2INFOREC_VERSION 9
+#define DRI2INFOREC_VERSION 10
 
 typedef struct {
     unsigned int version;       /**< Version of this struct */
@@ -252,6 +258,20 @@ typedef struct {
     DRI2CreateBuffer2ProcPtr CreateBuffer2;
     DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
     DRI2CopyRegion2ProcPtr CopyRegion2;
+
+    /* added in version 10 */
+
+    /* 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 Bool DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info);
-- 
1.7.10



More information about the xorg-devel mailing list