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