From: Marek Olšák Date: Sun, 26 Feb 2012 12:17:53 +0000 (+0100) Subject: r600g: rework scissor for r600-r700 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aacd653834264b70a2537aff7914762b39f0683f;p=mesa.git r600g: rework scissor for r600-r700 We must use VPORT_SCISSOR, because that's the only one we can use for multiple scissor rectangles in ARB_viewport_array. R700 can use the VPORT_SCISSOR_ENABLE bit, but R600 doesn't have that and must emit a 8192x8192 rectangle if scissor is disabled. This commit also cleanups magic numbers in create_rs_state. Reviewed-by: Alex Deucher Reviewed-by: Christian König --- diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index 5a48b3d9634..9e99c7ee54f 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -378,15 +378,6 @@ static const struct r600_reg r600_context_reg_list[] = { {R_028034_PA_SC_SCREEN_SCISSOR_BR, 0, 0}, {R_028204_PA_SC_WINDOW_SCISSOR_TL, 0, 0}, {R_028208_PA_SC_WINDOW_SCISSOR_BR, 0, 0}, - {R_02820C_PA_SC_CLIPRECT_RULE, 0, 0}, - {R_028210_PA_SC_CLIPRECT_0_TL, 0, 0}, - {R_028214_PA_SC_CLIPRECT_0_BR, 0, 0}, - {R_028218_PA_SC_CLIPRECT_1_TL, 0, 0}, - {R_02821C_PA_SC_CLIPRECT_1_BR, 0, 0}, - {R_028220_PA_SC_CLIPRECT_2_TL, 0, 0}, - {R_028224_PA_SC_CLIPRECT_2_BR, 0, 0}, - {R_028228_PA_SC_CLIPRECT_3_TL, 0, 0}, - {R_02822C_PA_SC_CLIPRECT_3_BR, 0, 0}, {R_028240_PA_SC_GENERIC_SCISSOR_TL, 0, 0}, {R_028244_PA_SC_GENERIC_SCISSOR_BR, 0, 0}, {R_028250_PA_SC_VPORT_SCISSOR_0_TL, 0, 0}, diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index fe801aba19f..3f03f2aba82 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -310,6 +310,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void r600_get_backend_mask(rctx); /* this emits commands and must be last */ + if (rctx->chip_class == R600) + r600_set_max_scissor(rctx); + return &rctx->context; fail: diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 62d831086fc..9550e9e0bae 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -152,6 +152,7 @@ struct r600_pipe_rasterizer { unsigned pa_cl_clip_cntl; float offset_units; float offset_scale; + bool scissor_enable; }; struct r600_pipe_blend { @@ -336,6 +337,11 @@ struct r600_context { struct r600_so_target *so_targets[PIPE_MAX_SO_BUFFERS]; boolean streamout_start; unsigned streamout_append_bitmask; + + /* There is no scissor enable bit on r6xx, so we must use a workaround. + * These track the current scissor state. */ + bool scissor_enable; + struct pipe_scissor_state scissor_state; }; static INLINE void r600_emit_atom(struct r600_context *rctx, struct r600_atom *atom) @@ -420,6 +426,8 @@ int r600_find_vs_semantic_index(struct r600_shader *vs, struct r600_shader *ps, int id); /* r600_state.c */ +void r600_set_scissor_state(struct r600_context *rctx, + const struct pipe_scissor_state *state); void r600_update_sampler_states(struct r600_context *rctx); void r600_init_state_functions(struct r600_context *rctx); void r600_init_atom_start_cs(struct r600_context *rctx); @@ -474,6 +482,7 @@ void r600_bind_blend_state(struct pipe_context *ctx, void *state); void r600_set_blend_color(struct pipe_context *ctx, const struct pipe_blend_color *state); void r600_bind_dsa_state(struct pipe_context *ctx, void *state); +void r600_set_max_scissor(struct r600_context *rctx); void r600_bind_rs_state(struct pipe_context *ctx, void *state); void r600_delete_rs_state(struct pipe_context *ctx, void *state); void r600_sampler_view_destroy(struct pipe_context *ctx, diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 806d7dd4b35..163469c0c64 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -772,7 +772,6 @@ static void *r600_create_rs_state(struct pipe_context *ctx, struct r600_pipe_state *rstate; unsigned tmp; unsigned prov_vtx = 1, polygon_dual_mode; - unsigned clip_rule; unsigned sc_mode_cntl; float psize_min, psize_max; @@ -800,7 +799,6 @@ static void *r600_create_rs_state(struct pipe_context *ctx, S_028810_ZCLIP_FAR_DISABLE(!state->depth_clip) | S_028810_DX_LINEAR_ATTR_CLIP_ENA(1); - clip_rule = state->scissor ? 0xAAAA : 0xFFFF; /* offset */ rs->offset_units = state->offset_units; rs->offset_scale = state->offset_scale * 12.0f; @@ -840,10 +838,18 @@ static void *r600_create_rs_state(struct pipe_context *ctx, tmp = (unsigned)state->line_width * 8; r600_pipe_state_add_reg(rstate, R_028A08_PA_SU_LINE_CNTL, S_028A08_WIDTH(tmp), NULL, 0); - if (rctx->chip_class >= R700) - sc_mode_cntl = 0x514002; - else - sc_mode_cntl = 0x4102; + if (rctx->chip_class >= R700) { + sc_mode_cntl = + S_028A4C_FORCE_EOV_CNTDWN_ENABLE(1) | + S_028A4C_FORCE_EOV_REZ_ENABLE(1) | + S_028A4C_R700_ZMM_LINE_OFFSET(1) | + S_028A4C_R700_VPORT_SCISSOR_ENABLE(state->scissor); + } else { + sc_mode_cntl = + S_028A4C_WALK_ALIGN8_PRIM_FITS_ST(1) | + S_028A4C_FORCE_EOV_CNTDWN_ENABLE(1); + rs->scissor_enable = state->scissor; + } sc_mode_cntl |= S_028A4C_LINE_STIPPLE_ENABLE(state->line_stipple_enable); r600_pipe_state_add_reg(rstate, R_028A4C_PA_SC_MODE_CNTL, sc_mode_cntl, @@ -854,7 +860,6 @@ static void *r600_create_rs_state(struct pipe_context *ctx, NULL, 0); r600_pipe_state_add_reg(rstate, R_028DFC_PA_SU_POLY_OFFSET_CLAMP, fui(state->offset_clamp), NULL, 0); - r600_pipe_state_add_reg(rstate, R_02820C_PA_SC_CLIPRECT_RULE, clip_rule, NULL, 0); r600_pipe_state_add_reg(rstate, R_028814_PA_SU_SC_MODE_CNTL, S_028814_PROVOKING_VTX_LAST(prov_vtx) | S_028814_CULL_FRONT(state->rasterizer_discard || (state->cull_face & PIPE_FACE_FRONT) ? 1 : 0) | @@ -1254,10 +1259,9 @@ static void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask { } -static void r600_set_scissor_state(struct pipe_context *ctx, - const struct pipe_scissor_state *state) +void r600_set_scissor_state(struct r600_context *rctx, + const struct pipe_scissor_state *state) { - struct r600_context *rctx = (struct r600_context *)ctx; struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state); uint32_t tl, br; @@ -1268,28 +1272,10 @@ static void r600_set_scissor_state(struct pipe_context *ctx, tl = S_028240_TL_X(state->minx) | S_028240_TL_Y(state->miny) | S_028240_WINDOW_OFFSET_DISABLE(1); br = S_028244_BR_X(state->maxx) | S_028244_BR_Y(state->maxy); r600_pipe_state_add_reg(rstate, - R_028210_PA_SC_CLIPRECT_0_TL, tl, - NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028214_PA_SC_CLIPRECT_0_BR, br, - NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028218_PA_SC_CLIPRECT_1_TL, tl, - NULL, 0); - r600_pipe_state_add_reg(rstate, - R_02821C_PA_SC_CLIPRECT_1_BR, br, - NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028220_PA_SC_CLIPRECT_2_TL, tl, - NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028224_PA_SC_CLIPRECT_2_BR, br, - NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028228_PA_SC_CLIPRECT_3_TL, tl, + R_028250_PA_SC_VPORT_SCISSOR_0_TL, tl, NULL, 0); r600_pipe_state_add_reg(rstate, - R_02822C_PA_SC_CLIPRECT_3_BR, br, + R_028254_PA_SC_VPORT_SCISSOR_0_BR, br, NULL, 0); free(rctx->states[R600_PIPE_STATE_SCISSOR]); @@ -1297,6 +1283,21 @@ static void r600_set_scissor_state(struct pipe_context *ctx, r600_context_pipe_state_set(rctx, rstate); } +static void r600_pipe_set_scissor_state(struct pipe_context *ctx, + const struct pipe_scissor_state *state) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + + if (rctx->chip_class == R600) { + rctx->scissor_state = *state; + + if (!rctx->scissor_enable) + return; + } + + r600_set_scissor_state(rctx, state); +} + static void r600_set_viewport_state(struct pipe_context *ctx, const struct pipe_viewport_state *state) { @@ -1621,12 +1622,6 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, r600_pipe_state_add_reg(rstate, R_028244_PA_SC_GENERIC_SCISSOR_BR, br, NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028250_PA_SC_VPORT_SCISSOR_0_TL, tl, - NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028254_PA_SC_VPORT_SCISSOR_0_BR, br, - NULL, 0); r600_pipe_state_add_reg(rstate, R_0287A0_CB_SHADER_CONTROL, shader_control, NULL, 0); @@ -1704,7 +1699,7 @@ void r600_init_state_functions(struct r600_context *rctx) rctx->context.set_framebuffer_state = r600_set_framebuffer_state; rctx->context.set_polygon_stipple = r600_set_polygon_stipple; rctx->context.set_sample_mask = r600_set_sample_mask; - rctx->context.set_scissor_state = r600_set_scissor_state; + rctx->context.set_scissor_state = r600_pipe_set_scissor_state; rctx->context.set_stencil_ref = r600_set_pipe_stencil_ref; rctx->context.set_vertex_buffers = r600_set_vertex_buffers; rctx->context.set_index_buffer = r600_set_index_buffer; @@ -2059,6 +2054,7 @@ void r600_init_atom_start_cs(struct r600_context *rctx) } r600_store_context_reg(cb, R_028200_PA_SC_WINDOW_OFFSET, 0); + r600_store_context_reg(cb, R_02820C_PA_SC_CLIPRECT_RULE, 0xFFFF); if (rctx->chip_class >= R700) { r600_store_context_reg(cb, R_028230_PA_SC_EDGERULE, 0xAAAAAAAA); diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 1df67dde0c1..565af35c7e5 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -269,6 +269,18 @@ void r600_bind_dsa_state(struct pipe_context *ctx, void *state) } } +void r600_set_max_scissor(struct r600_context *rctx) +{ + /* Set a scissor state such that it doesn't do anything. */ + struct pipe_scissor_state scissor; + scissor.minx = 0; + scissor.miny = 0; + scissor.maxx = 8192; + scissor.maxy = 8192; + + r600_set_scissor_state(rctx, &scissor); +} + void r600_bind_rs_state(struct pipe_context *ctx, void *state) { struct r600_pipe_rasterizer *rs = (struct r600_pipe_rasterizer *)state; @@ -292,6 +304,19 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state) } else { r600_polygon_offset_update(rctx); } + + /* Workaround for a missing scissor enable on r600. */ + if (rctx->chip_class == R600) { + if (rs->scissor_enable != rctx->scissor_enable) { + rctx->scissor_enable = rs->scissor_enable; + + if (rs->scissor_enable) { + r600_set_scissor_state(rctx, &rctx->scissor_state); + } else { + r600_set_max_scissor(rctx); + } + } + } } void r600_delete_rs_state(struct pipe_context *ctx, void *state) diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h index d54e00eb19d..ec56ad027c4 100644 --- a/src/gallium/drivers/r600/r600d.h +++ b/src/gallium/drivers/r600/r600d.h @@ -3132,6 +3132,8 @@ #define S_028A4C_PS_ITER_SAMPLE(x) (((x) & 0x1) << 17) #define G_028A4C_PS_ITER_SAMPLE(x) (((x) >> 17) & 0x1) #define C_028A4C_PS_ITER_SAMPLE 0xFFFDFFFF +#define S_028A4C_R700_ZMM_LINE_OFFSET(x) (((x) & 0x1) << 20) +#define S_028A4C_R700_VPORT_SCISSOR_ENABLE(x) (((x) & 0x1) << 22) #define R_028A84_VGT_PRIMITIVEID_EN 0x028A84 #define S_028A84_PRIMITIVEID_EN(x) (((x) & 0x1) << 0) #define G_028A84_PRIMITIVEID_EN(x) (((x) >> 0) & 0x1)