[Mesa-dev] [PATCH] radeonsi: Fix blending using destination alpha factor but non-alpha destination

Michel Dänzer michel at daenzer.net
Mon Feb 18 10:14:34 PST 2013


From: Michel Dänzer <michel.daenzer at amd.com>

11 more little piglits.

NOTE: This is a candidate for the 9.1 branch.

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---

Any ideas why this seems necessary with radeonsi but not with r600g?

 src/gallium/drivers/radeonsi/si_state.c | 116 +++++++++++++++++---------------
 src/gallium/drivers/radeonsi/si_state.h |   3 +-
 2 files changed, 61 insertions(+), 58 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index d20e3ff..144a29d 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -36,33 +36,6 @@
 #include "si_state.h"
 #include "sid.h"
 
-/*
- * inferred framebuffer and blender state
- */
-static void si_update_fb_blend_state(struct r600_context *rctx)
-{
-	struct si_pm4_state *pm4;
-	struct si_state_blend *blend = rctx->queued.named.blend;
-	uint32_t mask;
-
-	if (blend == NULL)
-		return;
-
-	pm4 = CALLOC_STRUCT(si_pm4_state);
-	if (pm4 == NULL)
-		return;
-
-	mask = (1ULL << ((unsigned)rctx->framebuffer.nr_cbufs * 4)) - 1;
-	mask &= blend->cb_target_mask;
-	si_pm4_set_reg(pm4, R_028238_CB_TARGET_MASK, mask);
-
-	si_pm4_set_state(rctx, fb_blend, pm4);
-}
-
-/*
- * Blender functions
- */
-
 static uint32_t si_translate_blend_function(int blend_func)
 {
 	switch (blend_func) {
@@ -84,7 +57,7 @@ static uint32_t si_translate_blend_function(int blend_func)
 	return 0;
 }
 
-static uint32_t si_translate_blend_factor(int blend_fact)
+static uint32_t si_translate_blend_factor(int blend_fact, bool dst_alpha)
 {
 	switch (blend_fact) {
 	case PIPE_BLENDFACTOR_ONE:
@@ -94,7 +67,7 @@ static uint32_t si_translate_blend_factor(int blend_fact)
 	case PIPE_BLENDFACTOR_SRC_ALPHA:
 		return V_028780_BLEND_SRC_ALPHA;
 	case PIPE_BLENDFACTOR_DST_ALPHA:
-		return V_028780_BLEND_DST_ALPHA;
+		return dst_alpha ? V_028780_BLEND_DST_ALPHA : V_028780_BLEND_ONE;
 	case PIPE_BLENDFACTOR_DST_COLOR:
 		return V_028780_BLEND_DST_COLOR;
 	case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
@@ -110,7 +83,7 @@ static uint32_t si_translate_blend_factor(int blend_fact)
 	case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
 		return V_028780_BLEND_ONE_MINUS_SRC_ALPHA;
 	case PIPE_BLENDFACTOR_INV_DST_ALPHA:
-		return V_028780_BLEND_ONE_MINUS_DST_ALPHA;
+		return dst_alpha ? V_028780_BLEND_ONE_MINUS_DST_ALPHA : V_028780_BLEND_ZERO;
 	case PIPE_BLENDFACTOR_INV_DST_COLOR:
 		return V_028780_BLEND_ONE_MINUS_DST_COLOR;
 	case PIPE_BLENDFACTOR_INV_CONST_COLOR:
@@ -133,30 +106,25 @@ static uint32_t si_translate_blend_factor(int blend_fact)
 	return 0;
 }
 
-static void *si_create_blend_state(struct pipe_context *ctx,
-				   const struct pipe_blend_state *state)
+/*
+ * inferred framebuffer and blender state
+ */
+static void si_update_fb_blend_state(struct r600_context *rctx)
 {
-	struct si_state_blend *blend = CALLOC_STRUCT(si_state_blend);
-	struct si_pm4_state *pm4 = &blend->pm4;
-
-	uint32_t color_control;
+	struct si_pm4_state *pm4;
+	struct si_state_blend *blend = rctx->queued.named.blend;
+	const struct pipe_blend_state *state;
+	uint32_t mask = 0;
 
 	if (blend == NULL)
-		return NULL;
-
-	color_control = S_028808_MODE(V_028808_CB_NORMAL);
-	if (state->logicop_enable) {
-		color_control |= S_028808_ROP3(state->logicop_func | (state->logicop_func << 4));
-	} else {
-		color_control |= S_028808_ROP3(0xcc);
-	}
-	si_pm4_set_reg(pm4, R_028808_CB_COLOR_CONTROL, color_control);
+		return;
 
-	si_pm4_set_reg(pm4, R_028C38_PA_SC_AA_MASK_X0Y0_X1Y0, ~0);
-	si_pm4_set_reg(pm4, R_028C3C_PA_SC_AA_MASK_X0Y1_X1Y1, ~0);
+	pm4 = CALLOC_STRUCT(si_pm4_state);
+	if (pm4 == NULL)
+		return;
 
-	blend->cb_target_mask = 0;
-	for (int i = 0; i < 8; i++) {
+	state = &blend->state;
+	for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) {
 		/* state->rt entries > 0 only written if independent blending */
 		const int j = state->independent_blend_enable ? i : 0;
 
@@ -166,31 +134,67 @@ static void *si_create_blend_state(struct pipe_context *ctx,
 		unsigned eqA = state->rt[j].alpha_func;
 		unsigned srcA = state->rt[j].alpha_src_factor;
 		unsigned dstA = state->rt[j].alpha_dst_factor;
-
+		const struct util_format_description *desc;
 		unsigned blend_cntl = 0;
+		bool dst_alpha;
 
-		/* we pretend 8 buffer are used, CB_SHADER_MASK will disable unused one */
-		blend->cb_target_mask |= state->rt[j].colormask << (4 * i);
+		mask |= state->rt[j].colormask << (4 * i);
 
 		if (!state->rt[j].blend_enable) {
 			si_pm4_set_reg(pm4, R_028780_CB_BLEND0_CONTROL + i * 4, blend_cntl);
 			continue;
 		}
 
+		desc = util_format_description(rctx->framebuffer.cbufs[i]->format);
+		dst_alpha = desc->swizzle[3] != PIPE_SWIZZLE_ONE;
+
 		blend_cntl |= S_028780_ENABLE(1);
 		blend_cntl |= S_028780_COLOR_COMB_FCN(si_translate_blend_function(eqRGB));
-		blend_cntl |= S_028780_COLOR_SRCBLEND(si_translate_blend_factor(srcRGB));
-		blend_cntl |= S_028780_COLOR_DESTBLEND(si_translate_blend_factor(dstRGB));
+		blend_cntl |= S_028780_COLOR_SRCBLEND(si_translate_blend_factor(srcRGB, dst_alpha));
+		blend_cntl |= S_028780_COLOR_DESTBLEND(si_translate_blend_factor(dstRGB, dst_alpha));
 
 		if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
 			blend_cntl |= S_028780_SEPARATE_ALPHA_BLEND(1);
 			blend_cntl |= S_028780_ALPHA_COMB_FCN(si_translate_blend_function(eqA));
-			blend_cntl |= S_028780_ALPHA_SRCBLEND(si_translate_blend_factor(srcA));
-			blend_cntl |= S_028780_ALPHA_DESTBLEND(si_translate_blend_factor(dstA));
+			blend_cntl |= S_028780_ALPHA_SRCBLEND(si_translate_blend_factor(srcA, dst_alpha));
+			blend_cntl |= S_028780_ALPHA_DESTBLEND(si_translate_blend_factor(dstA, dst_alpha));
 		}
 		si_pm4_set_reg(pm4, R_028780_CB_BLEND0_CONTROL + i * 4, blend_cntl);
 	}
 
+	si_pm4_set_reg(pm4, R_028238_CB_TARGET_MASK, mask);
+
+	si_pm4_set_state(rctx, fb_blend, pm4);
+}
+
+/*
+ * Blender functions
+ */
+
+static void *si_create_blend_state(struct pipe_context *ctx,
+				   const struct pipe_blend_state *state)
+{
+	struct si_state_blend *blend = CALLOC_STRUCT(si_state_blend);
+	struct si_pm4_state *pm4 = &blend->pm4;
+
+	uint32_t color_control;
+
+	if (blend == NULL)
+		return NULL;
+
+	color_control = S_028808_MODE(V_028808_CB_NORMAL);
+	if (state->logicop_enable) {
+		color_control |= S_028808_ROP3(state->logicop_func | (state->logicop_func << 4));
+	} else {
+		color_control |= S_028808_ROP3(0xcc);
+	}
+	si_pm4_set_reg(pm4, R_028808_CB_COLOR_CONTROL, color_control);
+
+	si_pm4_set_reg(pm4, R_028C38_PA_SC_AA_MASK_X0Y0_X1Y0, ~0);
+	si_pm4_set_reg(pm4, R_028C3C_PA_SC_AA_MASK_X0Y1_X1Y1, ~0);
+
+	memcpy(&blend->state, state, sizeof(blend->state));
+
 	return blend;
 }
 
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index c49b029..6bf8fef 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -31,8 +31,7 @@
 
 struct si_state_blend {
 	struct si_pm4_state	pm4;
-	uint32_t		cb_target_mask;
-	uint32_t		cb_color_control;
+	struct pipe_blend_state state;
 };
 
 struct si_state_viewport {
-- 
1.8.1.3



More information about the mesa-dev mailing list