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

Chris Wilson chris at chris-wilson.co.uk
Wed Jul 4 06:27:28 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.

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 7bb7c67..6206f04 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -112,6 +112,8 @@ typedef struct _DRI2Screen {
 
     HandleExposuresProcPtr HandleExposures;
 
+    DRI2AsyncSwapProcPtr AsyncSwap;
+
     ConfigNotifyProcPtr ConfigNotify;
 } DRI2ScreenRec;
 
@@ -876,6 +878,29 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
     return FALSE;
 }
 
+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,
@@ -907,23 +932,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) {
-        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);
-        return Success;
+	pPriv->swapsPending++;
+	if ((*ds->AsyncSwap)(client, pDraw,
+			     pDestBuffer, pSrcBuffer,
+			     func, data))
+	    DRI2InvalidateDrawable(pDraw);
+	return Success;
     }
 
     /*
@@ -1238,6 +1254,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
         cur_minor = 4;
     }
 
+    if (info->version >= 9) {
+	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 4fd0fbc..e888c54 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);
@@ -193,7 +199,7 @@ typedef int (*DRI2GetParamProcPtr) (ClientPtr client,
 /**
  * Version of the DRI2InfoRec structure defined in this header
  */
-#define DRI2INFOREC_VERSION 8
+#define DRI2INFOREC_VERSION 9
 
 typedef struct {
     unsigned int version;       /**< Version of this struct */
@@ -236,6 +242,20 @@ typedef struct {
     /* If this is NULL the AuthMagic callback is used */
     /* If this is non-NULL the AuthMagic callback is ignored */
     DRI2AuthMagic2ProcPtr AuthMagic2;
+
+    /* added in version 9 */
+
+    /* 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.10



More information about the xorg-devel mailing list