[Mesa-dev] [PATCH 5/7] r600g: handle NULL colorbuffers correctly on Evergreen

Marek Olšák maraeo at gmail.com
Wed Jan 8 09:23:18 PST 2014


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/drivers/r600/evergreen_state.c | 59 ++++++++++++++++++------------
 src/gallium/drivers/r600/r600_blit.c       | 23 ++++++++++--
 2 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index d5c1792..77e3c95 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -1721,11 +1721,8 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
 
 	if (rctx->framebuffer.state.nr_cbufs) {
 		rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE | R600_CONTEXT_FLUSH_AND_INV;
-		rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV_CB;
-
-		if (rctx->framebuffer.state.cbufs[0]->texture->nr_samples > 1) {
-			rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV_CB_META;
-		}
+		rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV_CB |
+				 R600_CONTEXT_FLUSH_AND_INV_CB_META;
 	}
 	if (rctx->framebuffer.state.zsbuf) {
 		rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE | R600_CONTEXT_FLUSH_AND_INV;
@@ -1741,19 +1738,16 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
 
 	/* Colorbuffers. */
 	rctx->framebuffer.export_16bpc = state->nr_cbufs != 0;
-	rctx->framebuffer.cb0_is_integer = state->nr_cbufs &&
+	rctx->framebuffer.cb0_is_integer = state->nr_cbufs && state->cbufs[0] &&
 					   util_format_is_pure_integer(state->cbufs[0]->format);
 	rctx->framebuffer.compressed_cb_mask = 0;
-
-	if (state->nr_cbufs)
-		rctx->framebuffer.nr_samples = state->cbufs[0]->texture->nr_samples;
-	else if (state->zsbuf)
-		rctx->framebuffer.nr_samples = state->zsbuf->texture->nr_samples;
-	else
-		rctx->framebuffer.nr_samples = 0;
+	rctx->framebuffer.nr_samples = util_framebuffer_get_num_samples(state);
 
 	for (i = 0; i < state->nr_cbufs; i++) {
 		surf = (struct r600_surface*)state->cbufs[i];
+		if (!surf)
+			continue;
+
 		rtex = (struct r600_texture*)surf->base.texture;
 
 		r600_context_add_resource_size(ctx, state->cbufs[i]->texture);
@@ -1774,13 +1768,21 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
 	/* Update alpha-test state dependencies.
 	 * Alpha-test is done on the first colorbuffer only. */
 	if (state->nr_cbufs) {
+		bool alphatest_bypass = false;
+		bool export_16bpc = true;
+
 		surf = (struct r600_surface*)state->cbufs[0];
-		if (rctx->alphatest_state.bypass != surf->alphatest_bypass) {
-			rctx->alphatest_state.bypass = surf->alphatest_bypass;
+		if (surf) {
+			alphatest_bypass = surf->alphatest_bypass;
+			export_16bpc = surf->export_16bpc;
+		}
+
+		if (rctx->alphatest_state.bypass != alphatest_bypass) {
+			rctx->alphatest_state.bypass = alphatest_bypass;
 			rctx->alphatest_state.atom.dirty = true;
 		}
-		if (rctx->alphatest_state.cb0_export_16bpc != surf->export_16bpc) {
-			rctx->alphatest_state.cb0_export_16bpc = surf->export_16bpc;
+		if (rctx->alphatest_state.cb0_export_16bpc != export_16bpc) {
+			rctx->alphatest_state.cb0_export_16bpc = export_16bpc;
 			rctx->alphatest_state.atom.dirty = true;
 		}
 	}
@@ -2181,12 +2183,21 @@ static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r
 	/* Colorbuffers. */
 	for (i = 0; i < nr_cbufs; i++) {
 		struct r600_surface *cb = (struct r600_surface*)state->cbufs[i];
-		struct r600_texture *tex = (struct r600_texture *)cb->base.texture;
-		unsigned reloc = r600_context_bo_reloc(&rctx->b,
-						       &rctx->b.rings.gfx,
-						       (struct r600_resource*)cb->base.texture,
-						       RADEON_USAGE_READWRITE);
-		unsigned cmask_reloc = 0;
+		struct r600_texture *tex;
+		unsigned reloc, cmask_reloc;
+
+		if (!cb) {
+			r600_write_context_reg(cs, R_028C70_CB_COLOR0_INFO + i * 0x3C,
+					       S_028C70_FORMAT(V_028C70_COLOR_INVALID));
+			continue;
+		}
+
+		tex = (struct r600_texture *)cb->base.texture;
+		reloc = r600_context_bo_reloc(&rctx->b,
+					      &rctx->b.rings.gfx,
+					      (struct r600_resource*)cb->base.texture,
+					      RADEON_USAGE_READWRITE);
+
 		if (tex->cmask_buffer && tex->cmask_buffer != &tex->resource) {
 			cmask_reloc = r600_context_bo_reloc(&rctx->b, &rctx->b.rings.gfx,
 				tex->cmask_buffer, RADEON_USAGE_READWRITE);
@@ -2227,7 +2238,7 @@ static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r
 		radeon_emit(cs, reloc);
 	}
 	/* set CB_COLOR1_INFO for possible dual-src blending */
-	if (i == 1) {
+	if (i == 1 && state->cbufs[0]) {
 		r600_write_context_reg(cs, R_028C70_CB_COLOR0_INFO + 1 * 0x3C,
 				       ((struct r600_surface*)state->cbufs[0])->cb_color_info);
 
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index 7e29cc5..2b86138 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -439,9 +439,14 @@ static bool can_fast_clear_color(struct pipe_context *ctx)
 	}
 
 	for (i = 0; i < fb->nr_cbufs; i++) {
-		struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture;
+		struct r600_texture *tex;
+
+		if (!fb->cbufs[i])
+			continue;
+
+		tex = (struct r600_texture *)fb->cbufs[i]->texture;
 
-		/* 128-bit formats are unuspported */
+		/* 128-bit formats are unusupported */
 		if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) {
 			return false;
 		}
@@ -484,7 +489,12 @@ static void r600_clear(struct pipe_context *ctx, unsigned buffers,
 		int i;
 
 		for (i = 0; i < fb->nr_cbufs; i++) {
-			struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture;
+			struct r600_texture *tex;
+
+			if (!fb->cbufs[i])
+				continue;
+
+			tex = (struct r600_texture *)fb->cbufs[i]->texture;
 
 			evergreen_set_clear_color(fb->cbufs[i], color);
 			r600_clear_buffer(ctx, &tex->cmask_buffer->b.b,
@@ -502,7 +512,12 @@ static void r600_clear(struct pipe_context *ctx, unsigned buffers,
 
 		/* cannot use fast clear, make sure to disable expansion */
 		for (i = 0; i < fb->nr_cbufs; i++) {
-			struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture;
+			struct r600_texture *tex;
+
+			if (!fb->cbufs[i])
+				continue;
+
+			tex = (struct r600_texture *)fb->cbufs[i]->texture;
 			if (tex->fmask.size == 0)
 			    tex->dirty_level_mask &= ~(1 << fb->cbufs[i]->u.tex.level);
 		}
-- 
1.8.3.2



More information about the mesa-dev mailing list