xf86-video-ati: Branch 'master'

Alex Deucher agd5f at kemper.freedesktop.org
Sun Dec 21 23:21:13 PST 2008


 src/radeon_textured_videofuncs.c |  155 +++++++++++++++++++++++++++++----------
 1 file changed, 117 insertions(+), 38 deletions(-)

New commits:
commit d01a609a2b07da4ca0f182e79459432584ec61f6
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Dec 22 02:18:43 2008 -0500

    R3xx-R5xx: better fix for xv primitive tearing issues
    
    R5xx:      always use single clipped triangle
    R3xx/R4xx: use single clipped triangle up to guardband limit,
    	   then use quad.

diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 410430c..2fe852d 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1486,16 +1486,30 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 				  pPriv->drw_y + pPriv->dst_h,
 				  pPriv->vsync);
 
-    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();
+    /*
+     * 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.
+     *     Due to guardband limits on r3xx/r4xx, we can only use
+     *     the single triangle up to 2880 pixels; above that we
+     *     render as a quad.
+     */
 
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
+	Bool use_quad = FALSE;
 	dstX = pBox->x1 + dstxoff;
 	dstY = pBox->y1 + dstyoff;
 	dstw = pBox->x2 - pBox->x1;
@@ -1514,6 +1528,28 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	ErrorF("src: %d, %d, %d, %d\n", srcX, srcY, srcw, srch);
 #endif
 
+	if (IS_R300_3D || IS_R500_3D) {
+	    if (IS_R300_3D && ((dstw > 1440) || (dsth > 1440)))
+		use_quad = TRUE;
+	    /*
+	     * 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, (((dstX + 1088) << R300_SCISSOR_X_SHIFT) |
+						 ((dstY + 1088) << R300_SCISSOR_Y_SHIFT)));
+		OUT_ACCEL_REG(R300_SC_SCISSOR1, (((dstX + dstw + 1088 - 1) << R300_SCISSOR_X_SHIFT) |
+						 ((dstY + dsth + 1088 - 1) << R300_SCISSOR_Y_SHIFT)));
+	    } else {
+		OUT_ACCEL_REG(R300_SC_SCISSOR0, (((dstX) << R300_SCISSOR_X_SHIFT) |
+						 ((dstY) << R300_SCISSOR_Y_SHIFT)));
+		OUT_ACCEL_REG(R300_SC_SCISSOR1, (((dstX + dstw - 1) << R300_SCISSOR_X_SHIFT) |
+						 ((dstY + dsth - 1) << R300_SCISSOR_Y_SHIFT)));
+	    }
+	    FINISH_ACCEL();
+	}
+
 #ifdef ACCEL_CP
 	if (info->ChipFamily < CHIP_FAMILY_R200) {
 	    BEGIN_RING(3 * vtx_count + 3);
@@ -1527,12 +1563,21 @@ 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));
+	    if (use_quad) {
+		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));
+	    } else {
+		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,
@@ -1542,9 +1587,12 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		     (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 	}
 #else /* ACCEL_CP */
-	if (IS_R300_3D || IS_R500_3D)
-	    BEGIN_ACCEL(2 + vtx_count * 4);
-	else
+	if (IS_R300_3D || IS_R500_3D) {
+	    if (use_quad)
+		BEGIN_ACCEL(2 + vtx_count * 4);
+	    else
+		BEGIN_ACCEL(2 + vtx_count * 3);
+	} else
 	    BEGIN_ACCEL(1 + vtx_count * 3);
 
 	if (info->ChipFamily < CHIP_FAMILY_R200)
@@ -1552,11 +1600,16 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 					      RADEON_VF_PRIM_WALK_DATA |
 					      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 |
-					      RADEON_VF_PRIM_WALK_DATA |
-					      (4 << RADEON_VF_NUM_VERTICES_SHIFT)));
-	else
+	else if (IS_R300_3D || IS_R500_3D) {
+	    if (use_quad)
+		OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
+						  RADEON_VF_PRIM_WALK_DATA |
+						  (4 << RADEON_VF_NUM_VERTICES_SHIFT)));
+	    else
+		OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_LIST |
+						  RADEON_VF_PRIM_WALK_DATA |
+						  (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 |
 					      (3 << RADEON_VF_NUM_VERTICES_SHIFT)));
@@ -1567,6 +1620,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		 * This code is only executed on >= R300, so we don't
 		 * have to deal with the legacy handling.
 		 */
+	    if (use_quad) {
 		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);
@@ -1579,27 +1633,52 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		VTX_OUT_FILTER((float)(dstX + dstw),                              (float)dstY,
 			       (float)(srcX + srcw) / info->accel_state->texW[0], (float)srcY / info->accel_state->texH[0],
 			       (float)(srcX + srcw) + 0.5,                        (float)srcY + 0.5);
+	    } else {
+		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,
-				(float)srcX / info->accel_state->texW[0],              (float)srcY / info->accel_state->texH[0]);
-			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]);
+	    if (IS_R300_3D || IS_R500_3D) {
+		if (use_quad) {
+		    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),
+			    (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]);
 		} else {
-			/*
-			 * Just render a rect (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]);
+		    /*
+		     * 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 rect (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]);
+	    }
 	}
 
 	if (IS_R300_3D || IS_R500_3D)


More information about the xorg-commit mailing list