[Mesa-dev] [PATCH 07/21] r600g: rework scissor for r600-r700

Marek Olšák maraeo at gmail.com
Wed Feb 29 08:53:00 PST 2012


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.
---
 src/gallium/drivers/r600/r600_hw_context.c   |    9 ---
 src/gallium/drivers/r600/r600_pipe.c         |    3 +
 src/gallium/drivers/r600/r600_pipe.h         |    9 +++
 src/gallium/drivers/r600/r600_state.c        |   70 ++++++++++++--------------
 src/gallium/drivers/r600/r600_state_common.c |   25 +++++++++
 src/gallium/drivers/r600/r600d.h             |    2 +
 6 files changed, 72 insertions(+), 46 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
index 5a48b3d..9e99c7e 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 fe801ab..3f03f2a 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 62d8310..9550e9e 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 806d7dd..163469c 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 1df67dd..565af35 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 d54e00e..ec56ad0 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)
-- 
1.7.5.4



More information about the mesa-dev mailing list