From 28453a25c7dd02b1591051c26c1c063c9f1928f4 Mon Sep 17 00:00:00 2001
From: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Date: Mon, 22 Nov 2010 04:11:07 +0100
Subject: [PATCH 3/4] ddx/ati: Add option "SwapbuffersWait" to control vsync of DRI2 swaps.

A new optional kms driver option "SwapbuffersWait" is defined
for xorg.conf, which defaults to "on". If "on", DRI2 bufferswaps
will be synchronized to vsync, otherwise not.

This currently only affects copy-swaps, not pageflipped swaps.
It also requires a swap_interval setting of zero by the OpenGL
client.

Ideally, we'd provide a way for dri2 to pass the current swap
interval to the ddx so we could change this dynamically.

Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
---
 man/radeon.man    |   11 +++++++++++
 src/radeon.h      |    6 +++++-
 src/radeon_dri2.c |    4 +++-
 src/radeon_kms.c  |    6 ++++++
 4 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/man/radeon.man b/man/radeon.man
index f442532..485c393 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -310,6 +310,17 @@ Color tiling will be automatically disabled in interlaced or doublescan screen m
 .br
 The default value is
 .B on.
+.TP
+.BI "Option \*qSwapbuffersWait\*q \*q" boolean \*q
+This option controls the behavior of glXSwapBuffers and glXCopySubBufferMESA
+calls by GL applications.  If enabled, the calls will avoid tearing by making
+sure the display scanline is outside of the area to be copied before the copy
+occurs.  If disabled, no scanline synchronization is performed, meaning tearing
+will likely occur.  Note that when enabled, this option can adversely affect
+the framerate of applications that render frames at less than refresh rate.
+.IP
+The default value is
+.B on.
 .TP 
 .BI "Option \*qIgnoreEDID\*q \*q" boolean \*q
 Do not use EDID data for mode validation.  DDC is still used
diff --git a/src/radeon.h b/src/radeon.h
index 8ace884..3ac6a47 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -224,7 +224,8 @@ typedef enum {
     OPTION_FORCE_LOW_POWER,
     OPTION_DYNAMIC_PM,
     OPTION_NEW_PLL,
-    OPTION_ZAPHOD_HEADS
+    OPTION_ZAPHOD_HEADS,
+    OPTION_SWAPBUFFERS_WAIT
 } RADEONOpts;
 
 
@@ -1073,6 +1074,9 @@ typedef struct {
     int               bicubic_offset;
     /* kms pageflipping */
     Bool allowPageFlip;
+
+    /* Perform vsync'ed SwapBuffers? */
+    Bool swapBuffersWait;
 } RADEONInfoRec, *RADEONInfoPtr;
 
 #define RADEONWaitForFifo(pScrn, entries)				\
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 69f8a48..c28017c 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -443,7 +443,9 @@ radeon_dri2_copy_region(DrawablePtr drawable,
     }
 
     vsync = info->accel_state->vsync;
-    info->accel_state->vsync = TRUE;
+
+    /* Driver option "SwapbuffersWait" defines if we vsync DRI2 copy-swaps. */ 
+    info->accel_state->vsync = info->swapBuffersWait;
 
     (*gc->ops->CopyArea)(src_drawable, dst_drawable, gc,
                          0, 0, drawable->width, drawable->height, 0, 0);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index dac1238..d66b05b 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -71,6 +71,7 @@ const OptionInfoRec RADEONOptions_KMS[] = {
     { OPTION_EXA_PIXMAPS,    "EXAPixmaps",	 OPTV_BOOLEAN,   {0}, FALSE },
     { OPTION_ZAPHOD_HEADS,   "ZaphodHeads",      OPTV_STRING,  {0}, FALSE },
     { OPTION_PAGE_FLIP,      "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
@@ -631,6 +632,11 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 		   "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis");
     }
 
+    info->swapBuffersWait = xf86ReturnOptValBool(info->Options,
+						 OPTION_SWAPBUFFERS_WAIT, TRUE);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "SwapBuffers wait for vsync: %sabled\n", info->swapBuffersWait ? "en" : "dis");
+
     if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
 	goto fail;
-- 
1.7.1.1

