diff options
| author | Alex Deucher <alexdeucher@gmail.com> | 2008-12-22 02:18:43 -0500 |
|---|---|---|
| committer | Alex Deucher <alexdeucher@gmail.com> | 2008-12-22 02:18:43 -0500 |
| commit | d01a609a2b07da4ca0f182e79459432584ec61f6 (patch) | |
| tree | ec77645fcf74c3b55cbc0215cd4090d0f760a3d2 | |
| parent | 4d009d14c9c72f6e1bc8100ec8d9b8037ee4e514 (diff) | |
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.
| -rw-r--r-- | src/radeon_textured_videofuncs.c | 155 |
1 files changed, 117 insertions, 38 deletions
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c index 410430c0..2fe852da 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) |
