diff options
-rw-r--r-- | src/gallium/drivers/radeon/r600_pipe_common.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/r600_viewport.c | 64 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/r600d_common.h | 1 |
3 files changed, 50 insertions, 17 deletions
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index ad41028e32b..88879b7b8f0 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -636,6 +636,8 @@ void r600_init_screen_texture_functions(struct r600_common_screen *rscreen); void r600_init_context_texture_functions(struct r600_common_context *rctx); /* r600_viewport.c */ +void evergreen_apply_scissor_bug_workaround(struct r600_common_context *rctx, + struct pipe_scissor_state *scissor); void r600_set_scissor_enable(struct r600_common_context *rctx, bool enable); void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx, struct tgsi_shader_info *info); diff --git a/src/gallium/drivers/radeon/r600_viewport.c b/src/gallium/drivers/radeon/r600_viewport.c index 32563767656..4901ba07977 100644 --- a/src/gallium/drivers/radeon/r600_viewport.c +++ b/src/gallium/drivers/radeon/r600_viewport.c @@ -24,6 +24,8 @@ #include "r600_cs.h" #include "tgsi/tgsi_scan.h" +#define GET_MAX_SCISSOR(rctx) (rctx->chip_class >= EVERGREEN ? 16384 : 8192) + static void r600_set_scissor_states(struct pipe_context *ctx, unsigned start_slot, unsigned num_scissors, @@ -42,7 +44,8 @@ static void r600_set_scissor_states(struct pipe_context *ctx, rctx->set_atom_dirty(rctx, &rctx->scissors.atom, true); } -static void r600_get_scissor_from_viewport(const struct pipe_viewport_state *vp, +static void r600_get_scissor_from_viewport(struct r600_common_context *rctx, + const struct pipe_viewport_state *vp, struct r600_signed_scissor *scissor) { int tmp; @@ -57,7 +60,7 @@ static void r600_get_scissor_from_viewport(const struct pipe_viewport_state *vp, if (scissor->minx == -1 && scissor->miny == -1 && scissor->maxx == 1 && scissor->maxy == 1) { scissor->minx = scissor->miny = 0; - scissor->maxx = scissor->maxy = 16384; + scissor->maxx = scissor->maxy = GET_MAX_SCISSOR(rctx); } /* Handle inverted viewports. */ @@ -73,13 +76,15 @@ static void r600_get_scissor_from_viewport(const struct pipe_viewport_state *vp, } } -static void r600_clamp_scissor(struct pipe_scissor_state *out, +static void r600_clamp_scissor(struct r600_common_context *rctx, + struct pipe_scissor_state *out, struct r600_signed_scissor *scissor) { - out->minx = CLAMP(scissor->minx, 0, 16384); - out->miny = CLAMP(scissor->miny, 0, 16384); - out->maxx = CLAMP(scissor->maxx, 0, 16384); - out->maxy = CLAMP(scissor->maxy, 0, 16384); + unsigned max_scissor = GET_MAX_SCISSOR(rctx); + out->minx = CLAMP(scissor->minx, 0, max_scissor); + out->miny = CLAMP(scissor->miny, 0, max_scissor); + out->maxx = CLAMP(scissor->maxx, 0, max_scissor); + out->maxy = CLAMP(scissor->maxy, 0, max_scissor); } static void r600_clip_scissor(struct pipe_scissor_state *out, @@ -100,7 +105,23 @@ static void r600_scissor_make_union(struct r600_signed_scissor *out, out->maxy = MAX2(out->maxy, in->maxy); } -static void r600_emit_one_scissor(struct radeon_winsys_cs *cs, +void evergreen_apply_scissor_bug_workaround(struct r600_common_context *rctx, + struct pipe_scissor_state *scissor) +{ + if (rctx->chip_class == EVERGREEN || rctx->chip_class == CAYMAN) { + if (scissor->maxx == 0) + scissor->minx = 1; + if (scissor->maxy == 0) + scissor->miny = 1; + + if (rctx->chip_class == CAYMAN && + scissor->maxx == 1 && scissor->maxy == 1) + scissor->maxx = 2; + } +} + +static void r600_emit_one_scissor(struct r600_common_context *rctx, + struct radeon_winsys_cs *cs, struct r600_signed_scissor *vp_scissor, struct pipe_scissor_state *scissor) { @@ -109,11 +130,13 @@ static void r600_emit_one_scissor(struct radeon_winsys_cs *cs, /* Since the guard band disables clipping, we have to clip per-pixel * using a scissor. */ - r600_clamp_scissor(&final, vp_scissor); + r600_clamp_scissor(rctx, &final, vp_scissor); if (scissor) r600_clip_scissor(&final, scissor); + evergreen_apply_scissor_bug_workaround(rctx, &final); + radeon_emit(cs, S_028250_TL_X(final.minx) | S_028250_TL_Y(final.miny) | S_028250_WINDOW_OFFSET_DISABLE(1)); @@ -122,7 +145,7 @@ static void r600_emit_one_scissor(struct radeon_winsys_cs *cs, } /* the range is [-MAX, MAX] */ -#define R600_MAX_VIEWPORT_RANGE 32768 +#define GET_MAX_VIEWPORT_RANGE(rctx) (rctx->chip_class >= EVERGREEN ? 32768 : 16384) static void r600_emit_guardband(struct r600_common_context *rctx, struct r600_signed_scissor *vp_as_scissor) @@ -152,7 +175,7 @@ static void r600_emit_guardband(struct r600_common_context *rctx, * * Use a limit one pixel smaller to allow for some precision error. */ - max_range = R600_MAX_VIEWPORT_RANGE - 1; + max_range = GET_MAX_VIEWPORT_RANGE(rctx) - 1; left = (-max_range - vp.translate[0]) / vp.scale[0]; right = ( max_range - vp.translate[0]) / vp.scale[0]; top = (-max_range - vp.translate[1]) / vp.scale[1]; @@ -164,7 +187,11 @@ static void r600_emit_guardband(struct r600_common_context *rctx, guardband_y = MIN2(-top, bottom); /* If any of the GB registers is updated, all of them must be updated. */ - radeon_set_context_reg_seq(cs, CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ, 4); + if (rctx->chip_class >= CAYMAN) + radeon_set_context_reg_seq(cs, CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ, 4); + else + radeon_set_context_reg_seq(cs, R600_R_028C0C_PA_CL_GB_VERT_CLIP_ADJ, 4); + radeon_emit(cs, fui(guardband_y)); /* R_028BE8_PA_CL_GB_VERT_CLIP_ADJ */ radeon_emit(cs, fui(1.0)); /* R_028BEC_PA_CL_GB_VERT_DISC_ADJ */ radeon_emit(cs, fui(guardband_x)); /* R_028BF0_PA_CL_GB_HORZ_CLIP_ADJ */ @@ -188,7 +215,7 @@ static void r600_emit_scissors(struct r600_common_context *rctx, struct r600_ato return; radeon_set_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL, 2); - r600_emit_one_scissor(cs, vp, scissor_enabled ? &states[0] : NULL); + r600_emit_one_scissor(rctx, cs, vp, scissor_enabled ? &states[0] : NULL); r600_emit_guardband(rctx, vp); rctx->scissors.dirty_mask &= ~1; /* clear one bit */ return; @@ -208,8 +235,8 @@ static void r600_emit_scissors(struct r600_common_context *rctx, struct r600_ato radeon_set_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL + start * 4 * 2, count * 2); for (i = start; i < start+count; i++) { - r600_emit_one_scissor(cs, &rctx->viewports.as_scissor[i], - scissor_enabled ? &states[i] : NULL); + r600_emit_one_scissor(rctx, cs, &rctx->viewports.as_scissor[i], + scissor_enabled ? &states[i] : NULL); } } r600_emit_guardband(rctx, &max_vp_scissor); @@ -228,8 +255,8 @@ static void r600_set_viewport_states(struct pipe_context *ctx, unsigned index = start_slot + i; rctx->viewports.states[index] = state[i]; - r600_get_scissor_from_viewport(&state[i], - &rctx->viewports.as_scissor[index]); + r600_get_scissor_from_viewport(rctx, &state[i], + &rctx->viewports.as_scissor[index]); } rctx->viewports.dirty_mask |= ((1 << num_viewports) - 1) << start_slot; @@ -315,6 +342,9 @@ void r600_init_viewport_functions(struct r600_common_context *rctx) rctx->scissors.atom.emit = r600_emit_scissors; rctx->viewports.atom.emit = r600_emit_viewports; + rctx->scissors.atom.num_dw = (2 + 16 * 2) + 6; + rctx->viewports.atom.num_dw = 2 + 16 * 6; + rctx->b.set_scissor_states = r600_set_scissor_states; rctx->b.set_viewport_states = r600_set_viewport_states; } diff --git a/src/gallium/drivers/radeon/r600d_common.h b/src/gallium/drivers/radeon/r600d_common.h index 045dd8ac77e..c8cb5e217e8 100644 --- a/src/gallium/drivers/radeon/r600d_common.h +++ b/src/gallium/drivers/radeon/r600d_common.h @@ -220,6 +220,7 @@ /*CIK+*/ #define R_0300FC_CP_STRMOUT_CNTL 0x0300FC +#define R600_R_028C0C_PA_CL_GB_VERT_CLIP_ADJ 0x028C0C #define CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ 0x28be8 #define R_02843C_PA_CL_VPORT_XSCALE 0x02843C |