summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r600/evergreen_state.c
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2012-10-05 02:45:29 +0200
committerMarek Olšák <[email protected]>2012-10-10 00:16:32 +0200
commitfaaba52aedf9807ced2ddfccc4133589a7bacd5f (patch)
tree0ea3c1c03ffa3538f9a0504d7b164fde4e95500e /src/gallium/drivers/r600/evergreen_state.c
parenteb65fefa4bd5e9a6f08ec599b95f9d63d11c15fa (diff)
r600g: atomize blend state
This is not so trivial, because we disable blending if the dual src blending is turned on and the number of color outputs is less than 2. I decided to create 2 command buffers in the blend state object and just switch between them when needed, because there are other states unrelated to blending (like the color mask) and those shouldn't be changed (the old code had it wrong). Reviewed-by: Jerome Glisse <[email protected]>
Diffstat (limited to 'src/gallium/drivers/r600/evergreen_state.c')
-rw-r--r--src/gallium/drivers/r600/evergreen_state.c87
1 files changed, 43 insertions, 44 deletions
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index a3b76d958d4..9aef66bfc28 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -683,22 +683,16 @@ boolean evergreen_is_format_supported(struct pipe_screen *screen,
static void *evergreen_create_blend_state_mode(struct pipe_context *ctx,
const struct pipe_blend_state *state, int mode)
{
- struct r600_context *rctx = (struct r600_context *)ctx;
- struct r600_pipe_blend *blend = CALLOC_STRUCT(r600_pipe_blend);
- struct r600_pipe_state *rstate;
- uint32_t color_control = 0, target_mask;
- /* XXX there is more then 8 framebuffer */
- unsigned blend_cntl[8];
+ uint32_t color_control = 0, target_mask = 0;
+ struct r600_blend_state *blend = CALLOC_STRUCT(r600_blend_state);
- if (blend == NULL) {
+ if (!blend) {
return NULL;
}
- rstate = &blend->rstate;
-
- rstate->id = R600_PIPE_STATE_BLEND;
+ r600_init_command_buffer(&blend->buffer, 20);
+ r600_init_command_buffer(&blend->buffer_no_blend, 20);
- target_mask = 0;
if (state->logicop_enable) {
color_control |= (state->logicop_func << 16) | (state->logicop_func << 20);
} else {
@@ -714,17 +708,32 @@ static void *evergreen_create_blend_state_mode(struct pipe_context *ctx,
target_mask |= (state->rt[0].colormask << (4 * i));
}
}
+
+ /* only have dual source on MRT0 */
+ blend->dual_src_blend = util_blend_state_is_dual(state, 0);
blend->cb_target_mask = target_mask;
+ blend->alpha_to_one = state->alpha_to_one;
if (target_mask)
color_control |= S_028808_MODE(mode);
else
color_control |= S_028808_MODE(V_028808_CB_DISABLE);
- r600_pipe_state_add_reg(rstate, R_028808_CB_COLOR_CONTROL,
- color_control);
- /* only have dual source on MRT0 */
- blend->dual_src_blend = util_blend_state_is_dual(state, 0);
+
+ r600_store_context_reg(&blend->buffer, R_028808_CB_COLOR_CONTROL, color_control);
+ r600_store_context_reg(&blend->buffer, R_028B70_DB_ALPHA_TO_MASK,
+ S_028B70_ALPHA_TO_MASK_ENABLE(state->alpha_to_coverage) |
+ S_028B70_ALPHA_TO_MASK_OFFSET0(2) |
+ S_028B70_ALPHA_TO_MASK_OFFSET1(2) |
+ S_028B70_ALPHA_TO_MASK_OFFSET2(2) |
+ S_028B70_ALPHA_TO_MASK_OFFSET3(2));
+ r600_store_context_reg_seq(&blend->buffer, R_028780_CB_BLEND0_CONTROL, 8);
+
+ /* Copy over the dwords set so far into buffer_no_blend.
+ * Only the CB_BLENDi_CONTROL registers must be set after this. */
+ memcpy(blend->buffer_no_blend.buf, blend->buffer.buf, blend->buffer.num_dw * 4);
+ blend->buffer_no_blend.num_dw = blend->buffer.num_dw;
+
for (int i = 0; i < 8; i++) {
/* state->rt entries > 0 only written if independent blending */
const int j = state->independent_blend_enable ? i : 0;
@@ -735,36 +744,29 @@ static void *evergreen_create_blend_state_mode(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;
+ uint32_t bc = 0;
- blend_cntl[i] = 0;
- if (!state->rt[j].blend_enable)
+ r600_store_value(&blend->buffer_no_blend, 0);
+
+ if (!state->rt[j].blend_enable) {
+ r600_store_value(&blend->buffer, 0);
continue;
+ }
- blend_cntl[i] |= S_028780_BLEND_CONTROL_ENABLE(1);
- blend_cntl[i] |= S_028780_COLOR_COMB_FCN(r600_translate_blend_function(eqRGB));
- blend_cntl[i] |= S_028780_COLOR_SRCBLEND(r600_translate_blend_factor(srcRGB));
- blend_cntl[i] |= S_028780_COLOR_DESTBLEND(r600_translate_blend_factor(dstRGB));
+ bc |= S_028780_BLEND_CONTROL_ENABLE(1);
+ bc |= S_028780_COLOR_COMB_FCN(r600_translate_blend_function(eqRGB));
+ bc |= S_028780_COLOR_SRCBLEND(r600_translate_blend_factor(srcRGB));
+ bc |= S_028780_COLOR_DESTBLEND(r600_translate_blend_factor(dstRGB));
if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
- blend_cntl[i] |= S_028780_SEPARATE_ALPHA_BLEND(1);
- blend_cntl[i] |= S_028780_ALPHA_COMB_FCN(r600_translate_blend_function(eqA));
- blend_cntl[i] |= S_028780_ALPHA_SRCBLEND(r600_translate_blend_factor(srcA));
- blend_cntl[i] |= S_028780_ALPHA_DESTBLEND(r600_translate_blend_factor(dstA));
+ bc |= S_028780_SEPARATE_ALPHA_BLEND(1);
+ bc |= S_028780_ALPHA_COMB_FCN(r600_translate_blend_function(eqA));
+ bc |= S_028780_ALPHA_SRCBLEND(r600_translate_blend_factor(srcA));
+ bc |= S_028780_ALPHA_DESTBLEND(r600_translate_blend_factor(dstA));
}
+ r600_store_value(&blend->buffer, bc);
}
- for (int i = 0; i < 8; i++) {
- r600_pipe_state_add_reg(rstate, R_028780_CB_BLEND0_CONTROL + i * 4, blend_cntl[i]);
- }
-
- r600_pipe_state_add_reg(rstate, R_028B70_DB_ALPHA_TO_MASK,
- S_028B70_ALPHA_TO_MASK_ENABLE(state->alpha_to_coverage) |
- S_028B70_ALPHA_TO_MASK_OFFSET0(2) |
- S_028B70_ALPHA_TO_MASK_OFFSET1(2) |
- S_028B70_ALPHA_TO_MASK_OFFSET2(2) |
- S_028B70_ALPHA_TO_MASK_OFFSET3(2));
-
- blend->alpha_to_one = state->alpha_to_one;
- return rstate;
+ return blend;
}
static void *evergreen_create_blend_state(struct pipe_context *ctx,
@@ -2351,6 +2353,7 @@ void evergreen_init_state_functions(struct r600_context *rctx)
r600_init_atom(rctx, &rctx->alphatest_state.atom, id++, r600_emit_alphatest_state, 6);
r600_init_atom(rctx, &rctx->blend_color.atom, id++, r600_emit_blend_color, 6);
+ r600_init_atom(rctx, &rctx->blend_state.atom, id++, r600_emit_cso_state, 0);
r600_init_atom(rctx, &rctx->cb_misc_state.atom, id++, evergreen_emit_cb_misc_state, 4);
r600_init_atom(rctx, &rctx->clip_misc_state.atom, id++, r600_emit_clip_misc_state, 6);
r600_init_atom(rctx, &rctx->clip_state.atom, id++, evergreen_emit_clip_state, 26);
@@ -3335,25 +3338,21 @@ void evergreen_fetch_shader(struct pipe_context *ctx,
void *evergreen_create_resolve_blend(struct r600_context *rctx)
{
struct pipe_blend_state blend;
- struct r600_pipe_state *rstate;
memset(&blend, 0, sizeof(blend));
blend.independent_blend_enable = true;
blend.rt[0].colormask = 0xf;
- rstate = evergreen_create_blend_state_mode(&rctx->context, &blend, V_028808_CB_RESOLVE);
- return rstate;
+ return evergreen_create_blend_state_mode(&rctx->context, &blend, V_028808_CB_RESOLVE);
}
void *evergreen_create_decompress_blend(struct r600_context *rctx)
{
struct pipe_blend_state blend;
- struct r600_pipe_state *rstate;
memset(&blend, 0, sizeof(blend));
blend.independent_blend_enable = true;
blend.rt[0].colormask = 0xf;
- rstate = evergreen_create_blend_state_mode(&rctx->context, &blend, V_028808_CB_DECOMPRESS);
- return rstate;
+ return evergreen_create_blend_state_mode(&rctx->context, &blend, V_028808_CB_DECOMPRESS);
}
void *evergreen_create_db_flush_dsa(struct r600_context *rctx)