xf86-video-ati: Branch 'master' - 4 commits

Alex Deucher agd5f at kemper.freedesktop.org
Thu Dec 4 23:51:48 PST 2008


 man/radeon.man                   |    6 +
 src/legacy_crtc.c                |    5 -
 src/radeon.h                     |    9 ++
 src/radeon_commonfuncs.c         |   88 +++++++++++++++++++++++---
 src/radeon_driver.c              |    1 
 src/radeon_exa.c                 |   27 +++++++
 src/radeon_exa_funcs.c           |   15 ++++
 src/radeon_exa_render.c          |   10 ++
 src/radeon_reg.h                 |   22 ++++++
 src/radeon_textured_video.c      |   25 ++++++-
 src/radeon_textured_videofuncs.c |  132 +++++++++++++++++++++++++++------------
 src/radeon_video.c               |   32 +++++++++
 src/radeon_video.h               |    6 +
 13 files changed, 323 insertions(+), 55 deletions(-)

New commits:
commit bae30856f2cb3884387ef347327af6ff00b75854
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Dec 5 08:15:59 2008 +0100

    Make VSync for EXA and Xv configurable

diff --git a/man/radeon.man b/man/radeon.man
index e18c820..b347001 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -516,6 +516,12 @@ This option allows you to disable int10 initialization.  Set this to
 False if you are experiencing a hang when initializing a secondary card.
 The default is
 .B on. 
+.BI "Option \*qEXAVSync\*q \*q" boolean \*q
+This option attempts to avoid tearing by stalling the engine until the display
+controller has passed the destination region.  It reduces tearing at the cost
+of performance.
+The default is
+.B off.
 
 .SH SEE ALSO
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff --git a/src/radeon.h b/src/radeon.h
index 051b765..8427e84 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -205,7 +205,8 @@ typedef enum {
     OPTION_TVSTD,
     OPTION_IGNORE_LID_STATUS,
     OPTION_DEFAULT_TVDAC_ADJ,
-    OPTION_INT10
+    OPTION_INT10,
+    OPTION_EXA_VSYNC
 } RADEONOpts;
 
 
@@ -601,6 +602,8 @@ struct radeon_accel_state {
     /* Size of tiles ... set to 65536x65536 if not tiling in that direction */
     Bool              src_tile_width;
     Bool              src_tile_height;
+
+    Bool              vsync;
 #endif
 
 #ifdef USE_XAA
@@ -942,11 +945,11 @@ extern Bool radeon_card_posted(ScrnInfoPtr pScrn);
 #ifdef XF86DRI
 extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn);
 extern void RADEONWaitForVLineCP(ScrnInfoPtr pScrn, PixmapPtr pPix,
-	int crtc, int start, int stop);
+	int crtc, int start, int stop, int enable);
 #endif
 extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
 extern void RADEONWaitForVLineMMIO(ScrnInfoPtr pScrn, PixmapPtr pPix,
-	int crtc, int start, int stop);
+	int crtc, int start, int stop, int enable);
 
 /* radeon_crtc.c */
 extern void radeon_crtc_dpms(xf86CrtcPtr crtc, int mode);
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index c2f3451..92e10d2 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -637,13 +637,16 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 
 /* inserts a wait for vline in the command stream */
 void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
-	int crtc, int start, int stop)
+	int crtc, int start, int stop, Bool enable)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
     xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     uint32_t offset;
     ACCEL_PREAMBLE();
 
+    if (!enable)
+	return;
+
     if ((crtc < 0) || (crtc > 1))
 	return;
 
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index a888436..843e9ff 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -192,6 +192,7 @@ static const OptionInfoRec RADEONOptions[] = {
     { OPTION_IGNORE_LID_STATUS, "IgnoreLidStatus", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_DEFAULT_TVDAC_ADJ, "DefaultTVDACAdj", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_INT10,             "Int10",           OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_EXA_VSYNC,         "EXAVSync",        OPTV_BOOLEAN, {0}, FALSE },
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index fe48701..55710ff 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -129,7 +129,7 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
 
     TRACE;
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2);
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2, info->accel_state->vsync);
 
     BEGIN_ACCEL(2);
     OUT_ACCEL_REG(RADEON_DST_Y_X, (y1 << 16) | x1);
@@ -230,7 +230,7 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
 	dstY += h - 1;
     }
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h);
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h, info->accel_state->vsync);
 
     BEGIN_ACCEL(3);
 
@@ -289,7 +289,7 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
 
 	RADEON_SWITCH_TO_2D();
 
-	FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), y, y + h);
+	FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), y, y + h, info->accel_state->vsync);
 
 	while ((buf = RADEONHostDataBlit(pScrn,
 					 cpp, w, dst_pitch_off, &buf_pitch,
@@ -612,6 +612,12 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
 #endif
     info->accel_state->exa->maxY = 8192;
 
+    if (xf86ReturnOptValBool(info->Options, OPTION_EXA_VSYNC, FALSE)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA VSync enabled\n");
+	info->accel_state->vsync = TRUE;
+    } else
+	info->accel_state->vsync = FALSE;
+
     RADEONEngineInit(pScrn);
 
     if (!exaDriverInit(pScreen, info->accel_state->exa)) {
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 4b918c4..b5f0197 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -1997,7 +1997,7 @@ static void FUNC_NAME(RadeonCompositeTile)(PixmapPtr pDst,
     else
 	vtx_count = 4;
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h);
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h, info->accel_state->vsync);
 
 #ifdef ACCEL_CP
     if (info->ChipFamily < CHIP_FAMILY_R200) {
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index cf6999c..7712344 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -381,11 +381,21 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] =
 
 static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] =
 {
+    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
+    {0, 0, 0, NULL}
+};
+
+#define NUM_ATTRIBUTES_R300 2
+
+static XF86AttributeRec Attributes_r300[NUM_ATTRIBUTES_R300+1] =
+{
     {XvSettable | XvGettable, 0, 2, "XV_BICUBIC"},
+    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
     {0, 0, 0, NULL}
 };
 
 static Atom xvBicubic;
+static Atom xvVSync;
 
 #define NUM_IMAGES 4
 
@@ -410,6 +420,8 @@ RADEONGetTexPortAttribute(ScrnInfoPtr  pScrn,
 
     if (attribute == xvBicubic)
 	*value = pPriv->bicubic_state;
+    else if (attribute == xvVSync)
+	*value = pPriv->vsync;
     else
 	return BadMatch;
 
@@ -429,6 +441,8 @@ RADEONSetTexPortAttribute(ScrnInfoPtr  pScrn,
 
     if (attribute == xvBicubic)
 	pPriv->bicubic_state = ClipValue (value, 0, 2);
+    else if (attribute == xvVSync)
+	pPriv->vsync = ClipValue (value, 0, 1);
     else
 	return BadMatch;
 
@@ -451,6 +465,7 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
 	return NULL;
 
     xvBicubic         = MAKE_ATOM("XV_BICUBIC");
+    xvVSync           = MAKE_ATOM("XV_VSYNC");
 
     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
     adapt->flags = 0;
@@ -468,8 +483,13 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
     pPortPriv =
 	(RADEONPortPrivPtr)(&adapt->pPortPrivates[num_texture_ports]);
 
-    adapt->pAttributes = Attributes;
-    adapt->nAttributes = NUM_ATTRIBUTES;
+    if (IS_R300_3D || IS_R500_3D) {
+	adapt->pAttributes = Attributes_r300;
+	adapt->nAttributes = NUM_ATTRIBUTES_R300;
+    } else {
+	adapt->pAttributes = Attributes;
+	adapt->nAttributes = NUM_ATTRIBUTES;
+    }
     adapt->pImages = Images;
     adapt->nImages = NUM_IMAGES;
     adapt->PutVideo = NULL;
@@ -492,6 +512,7 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
 	pPriv->currentBuffer = 0;
 	pPriv->doubleBuffer = 0;
 	pPriv->bicubic_state = BICUBIC_AUTO;
+	pPriv->vsync = TRUE;
 
 	/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
 	REGION_NULL(pScreen, &pPriv->clip);
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 0638751..e324fd9 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1521,7 +1521,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 							   pPriv->drw_y + pPriv->dst_h,
 							   pPriv->desired_crtc),
 				  pPriv->drw_y,
-				  pPriv->drw_y + pPriv->dst_h);
+				  pPriv->drw_y + pPriv->dst_h,
+				  pPriv->vsync);
 
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
diff --git a/src/radeon_video.h b/src/radeon_video.h
index 7c4151f..7f1891e 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -115,6 +115,7 @@ typedef struct {
     int src_w, src_h, dst_w, dst_h;
     int w, h;
     int drw_x, drw_y;
+    int vsync;
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
 int
commit 33638d9e388b330e2f4eb4debd05ba09924cf176
Author: Pierre Ossman <pierre at ossman.eu>
Date:   Thu Dec 4 23:29:31 2008 +0100

    Optimise RADEONWaitForVLine
    
    Only avoid the vlines we are rendering to, instead of the entire
    screen. This way we don't stall the card for longer than we
    absolutely have to.
    
    EXA calls fixed by Alex Deucher.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index bbd0c0a..4e2395f 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -511,11 +511,6 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 	else
 	    OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
 		   0);
-
-	OUTREG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
-	       (((0) << AVIVO_D1MODE_VLINE_START_SHIFT) |
-		((mode->VDisplay) << AVIVO_D1MODE_VLINE_END_SHIFT) |
-		AVIVO_D1MODE_VLINE_INV));
     }
 
     atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags);
diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
index 751b5ef..5ed14d4 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -133,8 +133,6 @@ RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
     OUTREG(RADEON_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
     OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
 
-    OUTREG(RADEON_CRTC_GUI_TRIG_VLINE,  restore->crtc_gui_trig_vline);
-
     if (IS_R300_VARIANT)
 	OUTREG(R300_CRTC_TILE_X0_Y0,    restore->crtc_tile_x0_y0);
     OUTREG(RADEON_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
@@ -179,8 +177,6 @@ RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
     OUTREG(RADEON_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
     OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
 
-    OUTREG(RADEON_CRTC2_GUI_TRIG_VLINE,  restore->crtc2_gui_trig_vline);
-
     OUTREG(RADEON_FP_H2_SYNC_STRT_WID,   restore->fp_h2_sync_strt_wid);
     OUTREG(RADEON_FP_V2_SYNC_STRT_WID,   restore->fp_v2_sync_strt_wid);
 
@@ -522,8 +518,6 @@ RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
     save->crtc_v_total_disp    = INREG(RADEON_CRTC_V_TOTAL_DISP);
     save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID);
 
-    save->crtc_gui_trig_vline  = INREG(RADEON_CRTC_GUI_TRIG_VLINE);
-
     save->crtc_offset          = INREG(RADEON_CRTC_OFFSET);
     save->crtc_offset_cntl     = INREG(RADEON_CRTC_OFFSET_CNTL);
     save->crtc_pitch           = INREG(RADEON_CRTC_PITCH);
@@ -560,8 +554,6 @@ RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
     save->crtc2_v_total_disp    = INREG(RADEON_CRTC2_V_TOTAL_DISP);
     save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
 
-    save->crtc2_gui_trig_vline  = INREG(RADEON_CRTC2_GUI_TRIG_VLINE);
-
     save->crtc2_offset          = INREG(RADEON_CRTC2_OFFSET);
     save->crtc2_offset_cntl     = INREG(RADEON_CRTC2_OFFSET_CNTL);
     save->crtc2_pitch           = INREG(RADEON_CRTC2_PITCH);
@@ -955,10 +947,6 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
 			 (pScrn->bitsPerPixel * 8));
     save->crtc_pitch |= save->crtc_pitch << 16;
 
-    save->crtc_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
-				 (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
-				 RADEON_CRTC_GUI_TRIG_VLINE_INV);
-
     if (info->IsDellServer) {
 	save->dac2_cntl = info->SavedReg->dac2_cntl;
 	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl;
@@ -1150,10 +1138,6 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
 			  ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8);
     save->crtc2_pitch |= save->crtc2_pitch << 16;
 
-    save->crtc2_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
-				  (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
-				  RADEON_CRTC_GUI_TRIG_VLINE_INV);
-
     /* check to see if TV DAC is enabled for another crtc and keep it enabled */
     if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON)
 	save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
diff --git a/src/radeon.h b/src/radeon.h
index 826ffe3..051b765 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -941,10 +941,12 @@ extern Bool radeon_card_posted(ScrnInfoPtr pScrn);
 /* radeon_commonfuncs.c */
 #ifdef XF86DRI
 extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn);
-extern void RADEONWaitForVLineCP(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc);
+extern void RADEONWaitForVLineCP(ScrnInfoPtr pScrn, PixmapPtr pPix,
+	int crtc, int start, int stop);
 #endif
 extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
-extern void RADEONWaitForVLineMMIO(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc);
+extern void RADEONWaitForVLineMMIO(ScrnInfoPtr pScrn, PixmapPtr pPix,
+	int crtc, int start, int stop);
 
 /* radeon_crtc.c */
 extern void radeon_crtc_dpms(xf86CrtcPtr crtc, int mode);
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 7f32acd..c2f3451 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -636,7 +636,8 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 }
 
 /* inserts a wait for vline in the command stream */
-void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc)
+void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
+	int crtc, int start, int stop)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
     xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -646,6 +647,9 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc)
     if ((crtc < 0) || (crtc > 1))
 	return;
 
+    if (stop < start)
+	return;
+
     if (!xf86_config->crtc[crtc]->enabled)
 	return;
 
@@ -657,16 +661,45 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc)
 	offset = pPix->devPrivate.ptr - info->FB;
 
     /* if drawing to front buffer */
-    if (offset == 0) {
-	BEGIN_ACCEL(1);
+    if (offset != 0)
+	return;
+
+    start = max(start, 0);
+    stop = max(stop, xf86_config->crtc[crtc]->mode.VDisplay);
+
+    if (start > xf86_config->crtc[crtc]->mode.VDisplay)
+	return;
+
+    BEGIN_ACCEL(2);
+
+    if (IS_AVIVO_VARIANT) {
+	RADEONCrtcPrivatePtr radeon_crtc = xf86_config->crtc[crtc]->driver_private;
+
+	OUT_ACCEL_REG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
+		      ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+		       (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
+		       AVIVO_D1MODE_VLINE_INV));
+    } else {
 	if (crtc == 0)
-	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
-					      RADEON_ENG_DISPLAY_SELECT_CRTC0));
+	    OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE,
+			  ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+			   (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+			   RADEON_CRTC_GUI_TRIG_VLINE_INV));
 	else
-	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
-					      RADEON_ENG_DISPLAY_SELECT_CRTC1));
-	FINISH_ACCEL();
+	    OUT_ACCEL_REG(RADEON_CRTC2_GUI_TRIG_VLINE,
+			  ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+			   (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+			   RADEON_CRTC_GUI_TRIG_VLINE_INV));
     }
+
+    if (crtc == 0)
+	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
+					  RADEON_ENG_DISPLAY_SELECT_CRTC0));
+    else
+	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
+					  RADEON_ENG_DISPLAY_SELECT_CRTC1));
+
+    FINISH_ACCEL();
 }
 
 /* MMIO:
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 76d6c41..fe48701 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -117,8 +117,6 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
     FINISH_ACCEL();
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix));
-
     return TRUE;
 }
 
@@ -131,6 +129,8 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
 
     TRACE;
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2);
+
     BEGIN_ACCEL(2);
     OUT_ACCEL_REG(RADEON_DST_Y_X, (y1 << 16) | x1);
     OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1));
@@ -207,8 +207,6 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
     FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset,
 				   datatype, rop, planemask);
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
-
     return TRUE;
 }
 
@@ -232,6 +230,8 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
 	dstY += h - 1;
     }
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h);
+
     BEGIN_ACCEL(3);
 
     OUT_ACCEL_REG(RADEON_SRC_Y_X,	   (srcY << 16) | srcX);
@@ -289,7 +289,7 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
 
 	RADEON_SWITCH_TO_2D();
 
-	FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+	FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), y, y + h);
 
 	while ((buf = RADEONHostDataBlit(pScrn,
 					 cpp, w, dst_pitch_off, &buf_pitch,
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 5d3f737..4b918c4 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -624,8 +624,6 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl);
     FINISH_ACCEL();
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
-
     return TRUE;
 }
 
@@ -932,8 +930,6 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl);
     FINISH_ACCEL();
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
-
     return TRUE;
 }
 
@@ -1889,8 +1885,6 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 4);
     FINISH_ACCEL();
 
-    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
-
     return TRUE;
 }
 
@@ -2003,6 +1997,8 @@ static void FUNC_NAME(RadeonCompositeTile)(PixmapPtr pDst,
     else
 	vtx_count = 4;
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst), dstY, dstY + h);
+
 #ifdef ACCEL_CP
     if (info->ChipFamily < CHIP_FAMILY_R200) {
 	BEGIN_RING(3 * vtx_count + 3);
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 313daa6..8c6845f 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -442,7 +442,6 @@ typedef struct {
     uint32_t          crtc_h_sync_strt_wid;
     uint32_t          crtc_v_total_disp;
     uint32_t          crtc_v_sync_strt_wid;
-    uint32_t          crtc_gui_trig_vline;
     uint32_t          crtc_offset;
     uint32_t          crtc_offset_cntl;
     uint32_t          crtc_pitch;
@@ -464,7 +463,6 @@ typedef struct {
     uint32_t          crtc2_h_sync_strt_wid;
     uint32_t          crtc2_v_total_disp;
     uint32_t          crtc2_v_sync_strt_wid;
-    uint32_t          crtc2_gui_trig_vline;
     uint32_t          crtc2_offset;
     uint32_t          crtc2_offset_cntl;
     uint32_t          crtc2_pitch;
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index ddf2df6..0638751 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1519,7 +1519,9 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 							   pPriv->drw_x + pPriv->dst_w,
 							   pPriv->drw_y,
 							   pPriv->drw_y + pPriv->dst_h,
-							   pPriv->desired_crtc));
+							   pPriv->desired_crtc),
+				  pPriv->drw_y,
+				  pPriv->drw_y + pPriv->dst_h);
 
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
commit d1690f5cc096e2f735c8b407c370a1c1cd7a8afc
Author: Pierre Ossman <pierre at ossman.eu>
Date:   Wed Dec 3 21:49:37 2008 +0100

    Improve tearing avoidance for Xvideo in two steps
    
    - Fix up VLINE handling to trigger whenever scanout is outside the
      visible area.
    
    - Render the video as a scissored triangle as R300+ cannot render a
      quad in a single pass.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 620bc8d..bbd0c0a 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -513,8 +513,9 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 		   0);
 
 	OUTREG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
-	       ((0 << AVIVO_D1MODE_VLINE_START_SHIFT) |
-		(mode->VDisplay << AVIVO_D1MODE_VLINE_END_SHIFT)));
+	       (((0) << AVIVO_D1MODE_VLINE_START_SHIFT) |
+		((mode->VDisplay) << AVIVO_D1MODE_VLINE_END_SHIFT) |
+		AVIVO_D1MODE_VLINE_INV));
     }
 
     atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags);
diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
index 2e7063c..751b5ef 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -956,7 +956,8 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
     save->crtc_pitch |= save->crtc_pitch << 16;
 
     save->crtc_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
-				 (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT));
+				 (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+				 RADEON_CRTC_GUI_TRIG_VLINE_INV);
 
     if (info->IsDellServer) {
 	save->dac2_cntl = info->SavedReg->dac2_cntl;
@@ -1150,7 +1151,8 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
     save->crtc2_pitch |= save->crtc2_pitch << 16;
 
     save->crtc2_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
-				  (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT));
+				  (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+				  RADEON_CRTC_GUI_TRIG_VLINE_INV);
 
     /* check to see if TV DAC is enabled for another crtc and keep it enabled */
     if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON)
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 556dba3..7f32acd 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -548,13 +548,8 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
 	FINISH_ACCEL();
 
-	BEGIN_ACCEL(7);
+	BEGIN_ACCEL(5);
 	OUT_ACCEL_REG(R300_SC_EDGERULE, 0xA5294A5);
-	OUT_ACCEL_REG(R300_SC_SCISSOR0, ((0 << R300_SCISSOR_X_SHIFT) |
-					 (0 << R300_SCISSOR_Y_SHIFT)));
-	OUT_ACCEL_REG(R300_SC_SCISSOR1, ((8191 << R300_SCISSOR_X_SHIFT) |
-					 (8191 << R300_SCISSOR_Y_SHIFT)));
-
 	if (IS_R300_3D) {
 	    /* clip has offset 1440 */
 	    OUT_ACCEL_REG(R300_SC_CLIP_0_A, ((1088 << R300_CLIP_X_SHIFT) |
@@ -575,7 +570,7 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	       (info->ChipFamily == CHIP_FAMILY_RS300) ||
 	       (info->ChipFamily == CHIP_FAMILY_R200)) {
 
-	BEGIN_ACCEL(7);
+	BEGIN_ACCEL(6);
 	if (info->ChipFamily == CHIP_FAMILY_RS300) {
 	    OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS);
 	} else {
@@ -584,7 +579,6 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	OUT_ACCEL_REG(R200_PP_CNTL_X, 0);
 	OUT_ACCEL_REG(R200_PP_TXMULTI_CTL_0, 0);
 	OUT_ACCEL_REG(R200_SE_VTX_STATE_CNTL, 0);
-	OUT_ACCEL_REG(R200_RE_CNTL, 0x0);
 	OUT_ACCEL_REG(R200_SE_VTE_CNTL, 0);
 	OUT_ACCEL_REG(R200_SE_VAP_CNTL, R200_VAP_FORCE_W_TO_ONE |
 	    R200_VAP_VF_MAX_VTX_NUM);
@@ -602,6 +596,15 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 				       RADEON_ROUND_MODE_ROUND |
 				       RADEON_ROUND_PREC_4TH_PIX));
 	FINISH_ACCEL();
+
+	BEGIN_ACCEL(4);
+	OUT_ACCEL_REG(R200_RE_SCISSOR_TL_0, ((0 << R200_SCISSOR_X_SHIFT) |
+					     (0 << R200_SCISSOR_Y_SHIFT)));
+	OUT_ACCEL_REG(R200_RE_SCISSOR_BR_0, ((2047 << R200_SCISSOR_X_SHIFT) |
+					     (2047 << R200_SCISSOR_Y_SHIFT)));
+	OUT_ACCEL_REG(R200_RE_AUX_SCISSOR_CNTL, R200_SCISSOR_ENABLE_0);
+	OUT_ACCEL_REG(R200_RE_CNTL, R200_SCISSOR_ENABLE);
+	FINISH_ACCEL();
     } else {
 	BEGIN_ACCEL(2);
 	if ((info->ChipFamily == CHIP_FAMILY_RADEON) ||
@@ -657,10 +660,10 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc)
     if (offset == 0) {
 	BEGIN_ACCEL(1);
 	if (crtc == 0)
-	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE |
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
 					      RADEON_ENG_DISPLAY_SELECT_CRTC0));
 	else
-	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE |
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
 					      RADEON_ENG_DISPLAY_SELECT_CRTC1));
 	FINISH_ACCEL();
     }
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 895958c..5d3f737 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -1864,6 +1864,14 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	FINISH_ACCEL();
     }
 
+    /* Clear out scissoring */
+    BEGIN_ACCEL(2);
+    OUT_ACCEL_REG(R300_SC_SCISSOR0, ((0 << R300_SCISSOR_X_SHIFT) |
+				     (0 << R300_SCISSOR_Y_SHIFT)));
+    OUT_ACCEL_REG(R300_SC_SCISSOR1, ((8191 << R300_SCISSOR_X_SHIFT) |
+				     (8191 << R300_SCISSOR_Y_SHIFT)));
+    FINISH_ACCEL();
+
     BEGIN_ACCEL(3);
 
     OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index bcb83ea..92bbccc 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -2290,6 +2290,14 @@
 #       define R200_VTX_STQ3_D3D		0x00400000
 #       define R200_VTX_STQ4_D3D		0x01000000
 #       define R200_VTX_STQ5_D3D		0x04000000
+#define R200_RE_SCISSOR_TL_0			0x1cd8
+#define R200_RE_SCISSOR_BR_0			0x1cdc
+#define R200_RE_SCISSOR_TL_1			0x1ce0
+#define R200_RE_SCISSOR_BR_1			0x1ce4
+#define R200_RE_SCISSOR_TL_2			0x1ce8
+#define R200_RE_SCISSOR_BR_2			0x1cec
+#       define R200_SCISSOR_X_SHIFT		0
+#       define R200_SCISSOR_Y_SHIFT		16
 #define RADEON_SE_CNTL_STATUS               0x2140
 #       define RADEON_VC_NO_SWAP            (0 << 0)
 #       define RADEON_VC_16BIT_SWAP         (1 << 0)
@@ -2589,6 +2597,13 @@
 #       define R200_VC_NO_SWAP			(0 << 0)
 #       define R200_VC_16BIT_SWAP		(1 << 0)
 #       define R200_VC_32BIT_SWAP		(2 << 0)
+#define R200_RE_AUX_SCISSOR_CNTL		0x26f0
+#       define R200_EXCLUSIVE_SCISSOR_0		0x01000000
+#       define R200_EXCLUSIVE_SCISSOR_1		0x02000000
+#       define R200_EXCLUSIVE_SCISSOR_2		0x04000000
+#       define R200_SCISSOR_ENABLE_0		0x10000000
+#       define R200_SCISSOR_ENABLE_1		0x20000000
+#       define R200_SCISSOR_ENABLE_2		0x40000000
 #define R200_PP_TXFILTER_0			0x2c00 
 #define R200_PP_TXFILTER_1			0x2c20
 #define R200_PP_TXFILTER_2			0x2c40
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index edd322b..ddf2df6 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1475,6 +1475,44 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	}
     }
 
+    /*
+     * Rendering of the actual polygon is done in two different
+     * ways depending on chip generation:
+     *
+     * < R300:
+     *
+     *     These chips can render a rectangle in one pass, so
+     *     handling is pretty straight-forward.
+     *
+     * >= R300:
+     *
+     *     These chips can accept a quad, but will render it as
+     *     two triangles which results in a diagonal tear. Instead
+     *     We render a single, large triangle and use the scissor
+     *     functionality to restrict it to the desired rectangle.
+     */
+
+    if (IS_R300_3D || IS_R500_3D) {
+	/*
+	 * Set up the scissor area to that of the output size.
+	 */
+
+	BEGIN_ACCEL(2);
+	if (IS_R300_3D) {
+	    /* R300 has an offset */
+	    OUT_ACCEL_REG(R300_SC_SCISSOR0, (((pPriv->drw_x + 1088) << R300_SCISSOR_X_SHIFT) |
+					     ((pPriv->drw_y + 1088) << R300_SCISSOR_Y_SHIFT)));
+	    OUT_ACCEL_REG(R300_SC_SCISSOR1, (((pPriv->drw_x + pPriv->dst_w + 1088 - 1) << R300_SCISSOR_X_SHIFT) |
+					     ((pPriv->drw_y + pPriv->dst_h + 1088 - 1) << R300_SCISSOR_Y_SHIFT)));
+	} else {
+	    OUT_ACCEL_REG(R300_SC_SCISSOR0, (((pPriv->drw_x) << R300_SCISSOR_X_SHIFT) |
+					     ((pPriv->drw_y) << R300_SCISSOR_Y_SHIFT)));
+	    OUT_ACCEL_REG(R300_SC_SCISSOR1, (((pPriv->drw_x + pPriv->dst_w - 1) << R300_SCISSOR_X_SHIFT) |
+					     ((pPriv->drw_y + pPriv->dst_h - 1) << R300_SCISSOR_Y_SHIFT)));
+	}
+	FINISH_ACCEL();
+    }
+
     FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
 				  radeon_covering_crtc_num(pScrn,
 							   pPriv->drw_x,
@@ -1486,7 +1524,6 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
-	xPointFixed srcTopLeft, srcTopRight, srcBottomLeft, srcBottomRight;
 	dstX = pBox->x1 + dstxoff;
 	dstY = pBox->y1 + dstyoff;
 	dstw = pBox->x2 - pBox->x1;
@@ -1500,16 +1537,6 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
 	srch = (pPriv->src_h * dsth) / pPriv->dst_h;
 
-	srcTopLeft.x     = IntToxFixed(srcX);
-	srcTopLeft.y     = IntToxFixed(srcY);
-	srcTopRight.x    = IntToxFixed(srcX + srcw);
-	srcTopRight.y    = IntToxFixed(srcY);
-	srcBottomLeft.x  = IntToxFixed(srcX);
-	srcBottomLeft.y  = IntToxFixed(srcY + srch);
-	srcBottomRight.x = IntToxFixed(srcX + srcw);
-	srcBottomRight.y = IntToxFixed(srcY + srch);
-
-
 #if 0
 	ErrorF("dst: %d, %d, %d, %d\n", dstX, dstY, dstw, dsth);
 	ErrorF("src: %d, %d, %d, %d\n", srcX, srcY, srcw, srch);
@@ -1528,12 +1555,12 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
 		     (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 	} else if (IS_R300_3D || IS_R500_3D) {
-		BEGIN_RING(4 * vtx_count + 4);
-		OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-				    4 * vtx_count));
-		OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
-			 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
-			 (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	    BEGIN_RING(3 * vtx_count + 4);
+	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
+				3 * vtx_count));
+	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST |
+		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+		     (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 	} else {
 	    BEGIN_RING(3 * vtx_count + 2);
 	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
@@ -1544,7 +1571,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	}
 #else /* ACCEL_CP */
 	if (IS_R300_3D || IS_R500_3D)
-	    BEGIN_ACCEL(2 + vtx_count * 4);
+	    BEGIN_ACCEL(2 + vtx_count * 3);
 	else
 	    BEGIN_ACCEL(1 + vtx_count * 3);
 
@@ -1554,9 +1581,9 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 					      RADEON_VF_RADEON_MODE |
 					      (3 << RADEON_VF_NUM_VERTICES_SHIFT)));
 	else if (IS_R300_3D || IS_R500_3D)
-	    OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
+	    OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_LIST |
 					      RADEON_VF_PRIM_WALK_DATA |
-					      (4 << RADEON_VF_NUM_VERTICES_SHIFT)));
+					      (3 << RADEON_VF_NUM_VERTICES_SHIFT)));
 	else
 	    OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_RECTANGLE_LIST |
 					      RADEON_VF_PRIM_WALK_DATA |
@@ -1564,29 +1591,43 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
 #endif
 	if (pPriv->bicubic_enabled) {
-		VTX_OUT_FILTER((float)dstX,                       (float)dstY,
-		xFixedToFloat(srcTopLeft.x) / info->accel_state->texW[0],      xFixedToFloat(srcTopLeft.y) / info->accel_state->texH[0],
-		xFixedToFloat(srcTopLeft.x) + 0.5,                xFixedToFloat(srcTopLeft.y) + 0.5);
-		VTX_OUT_FILTER((float)dstX,                       (float)(dstY + dsth),
-		xFixedToFloat(srcBottomLeft.x) / info->accel_state->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->accel_state->texH[0],
-		xFixedToFloat(srcBottomLeft.x) + 0.5,             xFixedToFloat(srcBottomLeft.y) + 0.5);
-		VTX_OUT_FILTER((float)(dstX + dstw),              (float)(dstY + dsth),
-		xFixedToFloat(srcBottomRight.x) / info->accel_state->texW[0],  xFixedToFloat(srcBottomRight.y) / info->accel_state->texH[0],
-		xFixedToFloat(srcBottomRight.x) + 0.5,            xFixedToFloat(srcBottomRight.y) + 0.5);
-		VTX_OUT_FILTER((float)(dstX + dstw),              (float)dstY,
-		xFixedToFloat(srcTopRight.x) / info->accel_state->texW[0],     xFixedToFloat(srcTopRight.y) / info->accel_state->texH[0],
-		xFixedToFloat(srcTopRight.x) + 0.5,               xFixedToFloat(srcTopRight.y) + 0.5);
+		/*
+		 * This code is only executed on >= R200, so we don't
+		 * have to deal with the legacy handling.
+		 */
+		VTX_OUT_FILTER((float)dstX,                                    (float)dstY,
+			(float)srcX / info->accel_state->texW[0],              (float)srcY / info->accel_state->texH[0],
+			(float)srcX + 0.5,                                     (float)srcY + 0.5);
+		VTX_OUT_FILTER((float)dstX,                                    (float)(dstY + dsth * 2),
+			(float)srcX / info->accel_state->texW[0],              (float)(srcY + srch * 2) / info->accel_state->texH[0],
+			(float)srcX + 0.5,                                     (float)(srcY + srch * 2) + 0.5);
+		VTX_OUT_FILTER((float)(dstX + dstw * 2),                       (float)dstY,
+			(float)(srcX + srcw * 2) / info->accel_state->texW[0], (float)srcY / info->accel_state->texH[0],
+			(float)(srcX + srcw * 2) + 0.5,                        (float)srcY + 0.5);
 	} else {
 		if (IS_R300_3D || IS_R500_3D) {
-			VTX_OUT((float)dstX,                              (float)dstY,
-			xFixedToFloat(srcTopLeft.x) / info->accel_state->texW[0],      xFixedToFloat(srcTopLeft.y) / info->accel_state->texH[0]);
+			/*
+			 * Render a big, scissored triangle. This means
+			 * doubling the triangle size and adjusting
+			 * texture coordinates.
+			 */
+			VTX_OUT((float)dstX,                                           (float)dstY,
+				(float)srcX / info->accel_state->texW[0],              (float)srcY / info->accel_state->texH[0]);
+			VTX_OUT((float)dstX,                                           (float)(dstY + dsth * 2),
+				(float)srcX / info->accel_state->texW[0],              (float)(srcY + srch * 2) / info->accel_state->texH[0]);
+			VTX_OUT((float)(dstX + dstw * 2),                              (float)dstY,
+				(float)(srcX + srcw * 2) / info->accel_state->texW[0], (float)srcY / info->accel_state->texH[0]);
+		} else {
+			/*
+			 * Just render a quad (using three coords).
+			 */
+			VTX_OUT((float)dstX,                                       (float)(dstY + dsth),
+				(float)srcX / info->accel_state->texW[0],          (float)(srcY + srch) / info->accel_state->texH[0]);
+			VTX_OUT((float)(dstX + dstw),                              (float)(dstY + dsth),
+				(float)(srcX + srcw) / info->accel_state->texW[0], (float)(srcY + srch) / info->accel_state->texH[0]);
+			VTX_OUT((float)(dstX + dstw),                              (float)dstY,
+				(float)(srcX + srcw) / info->accel_state->texW[0], (float)srcY / info->accel_state->texH[0]);
 		}
-		VTX_OUT((float)dstX,                              (float)(dstY + dsth),
-		xFixedToFloat(srcBottomLeft.x) / info->accel_state->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->accel_state->texH[0]);
-		VTX_OUT((float)(dstX + dstw),                     (float)(dstY + dsth),
-		xFixedToFloat(srcBottomRight.x) / info->accel_state->texW[0],  xFixedToFloat(srcBottomRight.y) / info->accel_state->texH[0]);
-		VTX_OUT((float)(dstX + dstw),                     (float)dstY,
-		xFixedToFloat(srcTopRight.x) / info->accel_state->texW[0],     xFixedToFloat(srcTopRight.y) / info->accel_state->texH[0]);
 	}
 
 	if (IS_R300_3D || IS_R500_3D)
commit 4d98acbca2e630056bf56cdcd0e23007fded2ced
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Jul 16 03:14:06 2008 -0400

    First pass at tear-free accel
    
    if the dest pixmap is the front buffer, stall the pipe
    until the vline is outside the active area.
    For EXA, pick crtc based on the larger mode area;
    ideally we'd have one pixmap per crtc.
    For Xv, use dst window area to determine crtc.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 4e2395f..620bc8d 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -511,6 +511,10 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 	else
 	    OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
 		   0);
+
+	OUTREG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
+	       ((0 << AVIVO_D1MODE_VLINE_START_SHIFT) |
+		(mode->VDisplay << AVIVO_D1MODE_VLINE_END_SHIFT)));
     }
 
     atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags);
diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
index 75ab6c8..2e7063c 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -133,8 +133,10 @@ RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
     OUTREG(RADEON_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
     OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
 
+    OUTREG(RADEON_CRTC_GUI_TRIG_VLINE,  restore->crtc_gui_trig_vline);
+
     if (IS_R300_VARIANT)
-	OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0);
+	OUTREG(R300_CRTC_TILE_X0_Y0,    restore->crtc_tile_x0_y0);
     OUTREG(RADEON_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
     OUTREG(RADEON_CRTC_OFFSET,          restore->crtc_offset);
 
@@ -177,11 +179,13 @@ RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
     OUTREG(RADEON_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
     OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
 
+    OUTREG(RADEON_CRTC2_GUI_TRIG_VLINE,  restore->crtc2_gui_trig_vline);
+
     OUTREG(RADEON_FP_H2_SYNC_STRT_WID,   restore->fp_h2_sync_strt_wid);
     OUTREG(RADEON_FP_V2_SYNC_STRT_WID,   restore->fp_v2_sync_strt_wid);
 
     if (IS_R300_VARIANT)
-	OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0);
+	OUTREG(R300_CRTC2_TILE_X0_Y0,    restore->crtc2_tile_x0_y0);
     OUTREG(RADEON_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
     OUTREG(RADEON_CRTC2_OFFSET,          restore->crtc2_offset);
 
@@ -518,6 +522,8 @@ RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
     save->crtc_v_total_disp    = INREG(RADEON_CRTC_V_TOTAL_DISP);
     save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID);
 
+    save->crtc_gui_trig_vline  = INREG(RADEON_CRTC_GUI_TRIG_VLINE);
+
     save->crtc_offset          = INREG(RADEON_CRTC_OFFSET);
     save->crtc_offset_cntl     = INREG(RADEON_CRTC_OFFSET_CNTL);
     save->crtc_pitch           = INREG(RADEON_CRTC_PITCH);
@@ -553,6 +559,9 @@ RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
     save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
     save->crtc2_v_total_disp    = INREG(RADEON_CRTC2_V_TOTAL_DISP);
     save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+    save->crtc2_gui_trig_vline  = INREG(RADEON_CRTC2_GUI_TRIG_VLINE);
+
     save->crtc2_offset          = INREG(RADEON_CRTC2_OFFSET);
     save->crtc2_offset_cntl     = INREG(RADEON_CRTC2_OFFSET_CNTL);
     save->crtc2_pitch           = INREG(RADEON_CRTC2_PITCH);
@@ -946,6 +955,9 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
 			 (pScrn->bitsPerPixel * 8));
     save->crtc_pitch |= save->crtc_pitch << 16;
 
+    save->crtc_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+				 (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT));
+
     if (info->IsDellServer) {
 	save->dac2_cntl = info->SavedReg->dac2_cntl;
 	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl;
@@ -1137,6 +1149,9 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
 			  ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8);
     save->crtc2_pitch |= save->crtc2_pitch << 16;
 
+    save->crtc2_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+				  (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT));
+
     /* check to see if TV DAC is enabled for another crtc and keep it enabled */
     if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON)
 	save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
diff --git a/src/radeon.h b/src/radeon.h
index 86cee4b..826ffe3 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -941,8 +941,10 @@ extern Bool radeon_card_posted(ScrnInfoPtr pScrn);
 /* radeon_commonfuncs.c */
 #ifdef XF86DRI
 extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn);
+extern void RADEONWaitForVLineCP(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc);
 #endif
 extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
+extern void RADEONWaitForVLineMMIO(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc);
 
 /* radeon_crtc.c */
 extern void radeon_crtc_dpms(xf86CrtcPtr crtc, int mode);
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index c7d42bc..556dba3 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -632,6 +632,39 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 
 }
 
+/* inserts a wait for vline in the command stream */
+void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    uint32_t offset;
+    ACCEL_PREAMBLE();
+
+    if ((crtc < 0) || (crtc > 1))
+	return;
+
+    if (!xf86_config->crtc[crtc]->enabled)
+	return;
+
+#ifdef USE_EXA
+    if (info->useEXA)
+	offset = exaGetPixmapOffset(pPix);
+    else
+#endif
+	offset = pPix->devPrivate.ptr - info->FB;
+
+    /* if drawing to front buffer */
+    if (offset == 0) {
+	BEGIN_ACCEL(1);
+	if (crtc == 0)
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE |
+					      RADEON_ENG_DISPLAY_SELECT_CRTC0));
+	else
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE |
+					      RADEON_ENG_DISPLAY_SELECT_CRTC1));
+	FINISH_ACCEL();
+    }
+}
 
 /* MMIO:
  *
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 04c097b..c4bc1bb 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -192,6 +192,33 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
 	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
 }
 
+/*
+ * Used for vblank render stalling.
+ * Ideally we'd have one pixmap per crtc.
+ * syncing per-blit is unrealistic so,
+ * we sync to whichever crtc has a larger area.
+ */
+int RADEONBiggerCrtcArea(PixmapPtr pPix)
+{
+    ScrnInfoPtr pScrn =  xf86Screens[pPix->drawable.pScreen->myNum];
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int c, crtc_num = -1, area = 0;
+
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (!crtc->enabled)
+	    continue;
+
+	if ((crtc->mode.HDisplay * crtc->mode.VDisplay) > area) {
+	    area = crtc->mode.HDisplay * crtc->mode.VDisplay;
+	    crtc_num = c;
+	}
+    }
+
+    return crtc_num;
+}
+
 #if X_BYTE_ORDER == X_BIG_ENDIAN
 
 static unsigned long swapper_surfaces[3];
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 62224d0..76d6c41 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -117,6 +117,8 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
     FINISH_ACCEL();
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix));
+
     return TRUE;
 }
 
@@ -205,6 +207,8 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
     FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset,
 				   datatype, rop, planemask);
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
     return TRUE;
 }
 
@@ -264,7 +268,7 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
     unsigned int   hpass;
     uint32_t	   buf_pitch, dst_pitch_off;
 #endif
-#if X_BYTE_ORDER == X_BIG_ENDIAN 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
     unsigned char *RADEONMMIO = info->MMIO;
     unsigned int swapper = info->ModeReg->surface_cntl &
 	    ~(RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP |
@@ -284,6 +288,9 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
 	ACCEL_PREAMBLE();
 
 	RADEON_SWITCH_TO_2D();
+
+	FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
 	while ((buf = RADEONHostDataBlit(pScrn,
 					 cpp, w, dst_pitch_off, &buf_pitch,
 					 x, &y, (unsigned int*)&h, &hpass)) != 0) {
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index a74abb6..895958c 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -624,6 +624,8 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl);
     FINISH_ACCEL();
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
     return TRUE;
 }
 
@@ -930,6 +932,8 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl);
     FINISH_ACCEL();
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
     return TRUE;
 }
 
@@ -1877,6 +1881,8 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 4);
     FINISH_ACCEL();
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
     return TRUE;
 }
 
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 8c6845f..313daa6 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -442,6 +442,7 @@ typedef struct {
     uint32_t          crtc_h_sync_strt_wid;
     uint32_t          crtc_v_total_disp;
     uint32_t          crtc_v_sync_strt_wid;
+    uint32_t          crtc_gui_trig_vline;
     uint32_t          crtc_offset;
     uint32_t          crtc_offset_cntl;
     uint32_t          crtc_pitch;
@@ -463,6 +464,7 @@ typedef struct {
     uint32_t          crtc2_h_sync_strt_wid;
     uint32_t          crtc2_v_total_disp;
     uint32_t          crtc2_v_sync_strt_wid;
+    uint32_t          crtc2_gui_trig_vline;
     uint32_t          crtc2_offset;
     uint32_t          crtc2_offset_cntl;
     uint32_t          crtc2_pitch;
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 672d1b5..bcb83ea 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -401,6 +401,9 @@
 #       define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4)
 #       define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5)
 #define RADEON_CRTC_GUI_TRIG_VLINE          0x0218
+#       define RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT  0
+#       define RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT    16
+#       define RADEON_CRTC_GUI_TRIG_VLINE_INV          (1 << 15)
 #define RADEON_CRTC_H_SYNC_STRT_WID         0x0204
 #       define RADEON_CRTC_H_SYNC_STRT_PIX        (0x07  <<  0)
 #       define RADEON_CRTC_H_SYNC_STRT_CHAR       (0x3ff <<  3)
@@ -3619,6 +3622,10 @@
 #define AVIVO_D1MODE_DATA_FORMAT                0x6528
 #       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
 #define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652c
+#define AVIVO_D1MODE_VLINE_START_END            0x6538
+#       define AVIVO_D1MODE_VLINE_START_SHIFT   0
+#       define AVIVO_D1MODE_VLINE_END_SHIFT     16
+#       define AVIVO_D1MODE_VLINE_INV           (1 << 31)
 #define AVIVO_D1MODE_VIEWPORT_START             0x6580
 #define AVIVO_D1MODE_VIEWPORT_SIZE              0x6584
 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6588
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 86532b5..edd322b 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1475,6 +1475,14 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	}
     }
 
+    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
+				  radeon_covering_crtc_num(pScrn,
+							   pPriv->drw_x,
+							   pPriv->drw_x + pPriv->dst_w,
+							   pPriv->drw_y,
+							   pPriv->drw_y + pPriv->dst_h,
+							   pPriv->desired_crtc));
+
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
diff --git a/src/radeon_video.c b/src/radeon_video.c
index 6249cea..423ea28 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -105,7 +105,6 @@ static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode;
 #define GET_PORT_PRIVATE(pScrn) \
    (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
 
-#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER
 static void
 radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
 {
@@ -136,6 +135,37 @@ radeon_box_area(BoxPtr box)
     return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
 }
 
+int
+radeon_covering_crtc_num(ScrnInfoPtr pScrn,
+			 int x1, int x2, int y1, int y2,
+			 xf86CrtcPtr desired)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			coverage, best_coverage;
+    int			c, best_crtc = 0;
+    BoxRec		box, crtc_box, cover_box;
+
+    box.x1 = x1;
+    box.x2 = x2;
+    box.y1 = y1;
+    box.y2 = y2;
+    best_coverage = 0;
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+	radeon_crtc_box(crtc, &crtc_box);
+	radeon_box_intersect(&cover_box, &crtc_box, &box);
+	coverage = radeon_box_area(&cover_box);
+	if (coverage && crtc == desired) {
+	    return c;
+	} else if (coverage > best_coverage) {
+	    best_crtc = c;
+	    best_coverage = coverage;
+	}
+    }
+    return best_crtc;
+}
+
+#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER
 static xf86CrtcPtr
 radeon_covering_crtc(ScrnInfoPtr pScrn,
 		     BoxPtr	box,
diff --git a/src/radeon_video.h b/src/radeon_video.h
index 448377b..7c4151f 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -117,6 +117,11 @@ typedef struct {
     int drw_x, drw_y;
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
+int
+radeon_covering_crtc_num(ScrnInfoPtr pScrn,
+                         int x1, int x2, int y1, int y2,
+                         xf86CrtcPtr desired);
+
 void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
 void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
 


More information about the xorg-commit mailing list