diff options
author | Marek Olšák <maraeo@gmail.com> | 2012-10-05 02:45:29 +0200 |
---|---|---|
committer | Marek Olšák <maraeo@gmail.com> | 2012-10-10 00:16:32 +0200 |
commit | faaba52aedf9807ced2ddfccc4133589a7bacd5f (patch) | |
tree | 0ea3c1c03ffa3538f9a0504d7b164fde4e95500e | |
parent | eb65fefa4bd5e9a6f08ec599b95f9d63d11c15fa (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 <jglisse@redhat.com>
-rw-r--r-- | src/gallium/drivers/r600/evergreen_hw_context.c | 20 | ||||
-rw-r--r-- | src/gallium/drivers/r600/evergreen_state.c | 87 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_blit.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_hw_context.c | 19 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_hw_context_priv.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 41 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state.c | 121 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 60 |
9 files changed, 182 insertions, 176 deletions
diff --git a/src/gallium/drivers/r600/evergreen_hw_context.c b/src/gallium/drivers/r600/evergreen_hw_context.c index 666b18c94f..547f4f57d3 100644 --- a/src/gallium/drivers/r600/evergreen_hw_context.c +++ b/src/gallium/drivers/r600/evergreen_hw_context.c @@ -95,17 +95,8 @@ static const struct r600_reg evergreen_context_reg_list[] = { {R_0286E0_SPI_BARYC_CNTL, 0, 0}, {R_0286E4_SPI_PS_IN_CONTROL_2, 0, 0}, {R_0286E8_SPI_COMPUTE_INPUT_CNTL, 0, 0}, - {R_028780_CB_BLEND0_CONTROL, 0, 0}, - {R_028784_CB_BLEND1_CONTROL, 0, 0}, - {R_028788_CB_BLEND2_CONTROL, 0, 0}, - {R_02878C_CB_BLEND3_CONTROL, 0, 0}, - {R_028790_CB_BLEND4_CONTROL, 0, 0}, - {R_028794_CB_BLEND5_CONTROL, 0, 0}, - {R_028798_CB_BLEND6_CONTROL, 0, 0}, - {R_02879C_CB_BLEND7_CONTROL, 0, 0}, {R_028800_DB_DEPTH_CONTROL, 0, 0}, {R_02880C_DB_SHADER_CONTROL, 0, 0}, - {R_028808_CB_COLOR_CONTROL, 0, 0}, {R_028814_PA_SU_SC_MODE_CNTL, 0, 0}, {R_028840_SQ_PGM_START_PS, REG_FLAG_NEED_BO, 0}, {R_028844_SQ_PGM_RESOURCES_PS, 0, 0}, @@ -120,7 +111,6 @@ static const struct r600_reg evergreen_context_reg_list[] = { {R_028A48_PA_SC_MODE_CNTL_0, 0, 0}, {R_028ABC_DB_HTILE_SURFACE, 0, 0}, {R_028B54_VGT_SHADER_STAGES_EN, 0, 0}, - {R_028B70_DB_ALPHA_TO_MASK, 0, 0}, {R_028B78_PA_SU_POLY_OFFSET_DB_FMT_CNTL, 0, 0}, {R_028B7C_PA_SU_POLY_OFFSET_CLAMP, 0, 0}, {R_028B80_PA_SU_POLY_OFFSET_FRONT_SCALE, 0, 0}, @@ -191,16 +181,7 @@ static const struct r600_reg cayman_context_reg_list[] = { {R_0286E0_SPI_BARYC_CNTL, 0, 0}, {R_0286E4_SPI_PS_IN_CONTROL_2, 0, 0}, {R_0286E8_SPI_COMPUTE_INPUT_CNTL, 0, 0}, - {R_028780_CB_BLEND0_CONTROL, 0, 0}, - {R_028784_CB_BLEND1_CONTROL, 0, 0}, - {R_028788_CB_BLEND2_CONTROL, 0, 0}, - {R_02878C_CB_BLEND3_CONTROL, 0, 0}, - {R_028790_CB_BLEND4_CONTROL, 0, 0}, - {R_028794_CB_BLEND5_CONTROL, 0, 0}, - {R_028798_CB_BLEND6_CONTROL, 0, 0}, - {R_02879C_CB_BLEND7_CONTROL, 0, 0}, {R_028800_DB_DEPTH_CONTROL, 0, 0}, - {R_028808_CB_COLOR_CONTROL, 0, 0}, {R_02880C_DB_SHADER_CONTROL, 0, 0}, {R_028814_PA_SU_SC_MODE_CNTL, 0, 0}, {R_028838_SQ_DYN_GPR_RESOURCE_LIMIT_1, 0, 0}, @@ -226,7 +207,6 @@ static const struct r600_reg cayman_context_reg_list[] = { {R_028A48_PA_SC_MODE_CNTL_0, 0, 0}, {R_028ABC_DB_HTILE_SURFACE, 0, 0}, {R_028B54_VGT_SHADER_STAGES_EN, 0, 0}, - {R_028B70_DB_ALPHA_TO_MASK, 0, 0}, {R_028B78_PA_SU_POLY_OFFSET_DB_FMT_CNTL, 0, 0}, {R_028B7C_PA_SU_POLY_OFFSET_CLAMP, 0, 0}, {R_028B80_PA_SU_POLY_OFFSET_FRONT_SCALE, 0, 0}, diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index a3b76d958d..9aef66bfc2 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) diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 062f6d9b22..a88cb5e4bb 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -68,7 +68,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op util_blitter_save_viewport(rctx->blitter, &rctx->viewport.state); util_blitter_save_scissor(rctx->blitter, &rctx->scissor); util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader); - util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]); + util_blitter_save_blend(rctx->blitter, rctx->blend_state.cso); util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->states[R600_PIPE_STATE_DSA]); util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref.pipe_state); util_blitter_save_sample_mask(rctx->blitter, rctx->sample_mask.sample_mask); diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index c457f35f20..b3f0fbadf2 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -177,12 +177,6 @@ int r600_context_add_block(struct r600_context *ctx, const struct r600_reg *reg, continue; } - /* ignore regs not on R600 on R600 */ - if ((reg[i].flags & REG_FLAG_NOT_R600) && ctx->family == CHIP_R600) { - n = 1; - continue; - } - /* register that need relocation are in their own group */ /* find number of consecutive registers */ n = 0; @@ -227,20 +221,10 @@ static const struct r600_reg r600_config_reg_list[] = { static const struct r600_reg r600_context_reg_list[] = { {R_028A4C_PA_SC_MODE_CNTL, 0, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, - {R_028780_CB_BLEND0_CONTROL, REG_FLAG_NOT_R600, 0}, - {R_028784_CB_BLEND1_CONTROL, REG_FLAG_NOT_R600, 0}, - {R_028788_CB_BLEND2_CONTROL, REG_FLAG_NOT_R600, 0}, - {R_02878C_CB_BLEND3_CONTROL, REG_FLAG_NOT_R600, 0}, - {R_028790_CB_BLEND4_CONTROL, REG_FLAG_NOT_R600, 0}, - {R_028794_CB_BLEND5_CONTROL, REG_FLAG_NOT_R600, 0}, - {R_028798_CB_BLEND6_CONTROL, REG_FLAG_NOT_R600, 0}, - {R_02879C_CB_BLEND7_CONTROL, REG_FLAG_NOT_R600, 0}, {R_028800_DB_DEPTH_CONTROL, 0, 0}, - {R_028804_CB_BLEND_CONTROL, 0, 0}, {R_02880C_DB_SHADER_CONTROL, 0, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_028D24_DB_HTILE_SURFACE, 0, 0}, - {R_028D44_DB_ALPHA_TO_MASK, 0, 0}, {R_028250_PA_SC_VPORT_SCISSOR_0_TL, 0, 0}, {R_028254_PA_SC_VPORT_SCISSOR_0_BR, 0, 0}, {R_0286D4_SPI_INTERP_CONTROL_0, 0, 0}, @@ -891,6 +875,9 @@ void r600_begin_new_cs(struct r600_context *ctx) ctx->stencil_ref.atom.dirty = true; ctx->viewport.atom.dirty = true; + if (ctx->blend_state.cso) + ctx->blend_state.atom.dirty = true; + if (ctx->chip_class <= R700) { ctx->seamless_cube_map.atom.dirty = true; } diff --git a/src/gallium/drivers/r600/r600_hw_context_priv.h b/src/gallium/drivers/r600/r600_hw_context_priv.h index 85fd74dce9..c59a9abf3f 100644 --- a/src/gallium/drivers/r600/r600_hw_context_priv.h +++ b/src/gallium/drivers/r600/r600_hw_context_priv.h @@ -35,7 +35,6 @@ /* these flags are used in register flags and added into block flags */ #define REG_FLAG_NEED_BO 1 #define REG_FLAG_DIRTY_ALWAYS 2 -#define REG_FLAG_NOT_R600 8 #define REG_FLAG_ENABLE_ALWAYS 16 #define REG_FLAG_FLUSH_CHANGE 64 diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 70cfe1408f..35fa9d49f1 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -159,9 +159,6 @@ static void r600_destroy_context(struct pipe_context *context) pipe_resource_reference((struct pipe_resource**)&rctx->dummy_cmask, NULL); pipe_resource_reference((struct pipe_resource**)&rctx->dummy_fmask, NULL); - if (rctx->no_blend) { - rctx->context.delete_blend_state(&rctx->context, rctx->no_blend); - } if (rctx->dummy_pixel_shader) { rctx->context.delete_fs_state(&rctx->context, rctx->dummy_pixel_shader); } @@ -204,7 +201,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void { struct r600_context *rctx = CALLOC_STRUCT(r600_context); struct r600_screen* rscreen = (struct r600_screen *)screen; - struct pipe_blend_state no_blend = {}; if (rctx == NULL) return NULL; @@ -311,9 +307,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void TGSI_INTERPOLATE_CONSTANT); rctx->context.bind_fs_state(&rctx->context, rctx->dummy_pixel_shader); - no_blend.rt[0].colormask = 0xF; - rctx->no_blend = rctx->context.create_blend_state(&rctx->context, &no_blend); - return &rctx->context; fail: diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index c6e0241483..449c785421 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -35,7 +35,7 @@ #include "r600_resource.h" #include "evergreen_compute.h" -#define R600_NUM_ATOMS 29 +#define R600_NUM_ATOMS 30 #define R600_MAX_CONST_BUFFERS 2 #define R600_MAX_CONST_BUFFER_SIZE 4096 @@ -161,7 +161,6 @@ struct r600_viewport_state { }; enum r600_pipe_state_id { - R600_PIPE_STATE_BLEND = 0, R600_PIPE_STATE_SCISSOR, R600_PIPE_STATE_RASTERIZER, R600_PIPE_STATE_DSA, @@ -223,10 +222,12 @@ struct r600_pipe_rasterizer { bool multisample_enable; }; -struct r600_pipe_blend { - struct r600_pipe_state rstate; +struct r600_blend_state { + struct r600_command_buffer buffer; + struct r600_command_buffer buffer_no_blend; unsigned cb_target_mask; unsigned cb_color_control; + unsigned cb_color_control_no_blend; bool dual_src_blend; bool alpha_to_one; }; @@ -359,6 +360,14 @@ struct r600_vertexbuf_state uint32_t dirty_mask; }; +/* CSO (constant state object, in other words, immutable state). */ +struct r600_cso_state +{ + struct r600_atom atom; + void *cso; /* e.g. r600_blend_state */ + struct r600_command_buffer *cb; +}; + struct r600_context { struct pipe_context context; struct blitter_context *blitter; @@ -409,6 +418,7 @@ struct r600_context { struct r600_command_buffer start_compute_cs_cmd; /* Register states. */ struct r600_alphatest_state alphatest_state; + struct r600_cso_state blend_state; struct r600_blend_color blend_color; struct r600_cb_misc_state cb_misc_state; struct r600_clip_misc_state clip_misc_state; @@ -431,13 +441,7 @@ struct r600_context { struct r600_vertexbuf_state cs_vertex_buffer_state; /******************************/ - /* current external blend state (from state tracker) */ - struct r600_pipe_blend *blend; - /* state with disabled blending - used internally with blend_override */ - struct r600_pipe_blend *no_blend; - - /* 1 - override current blend state with no_blend, 0 - use external state */ - unsigned blend_override; + bool force_blend_disable; struct radeon_winsys_cs *cs; @@ -518,6 +522,20 @@ static INLINE void r600_emit_atom(struct r600_context *rctx, struct r600_atom *a atom->dirty = false; } +static INLINE void r600_set_cso_state(struct r600_cso_state *state, void *cso) +{ + state->cso = cso; + state->atom.dirty = cso != NULL; +} + +static INLINE void r600_set_cso_state_with_cb(struct r600_cso_state *state, void *cso, + struct r600_command_buffer *cb) +{ + state->cb = cb; + state->atom.num_dw = cb->num_dw; + r600_set_cso_state(state, cso); +} + /* evergreen_state.c */ struct pipe_sampler_view * evergreen_create_sampler_view_custom(struct pipe_context *ctx, @@ -644,6 +662,7 @@ void r600_translate_index_buffer(struct r600_context *r600, /* r600_state_common.c */ void r600_init_common_state_functions(struct r600_context *rctx); +void r600_emit_cso_state(struct r600_context *rctx, struct r600_atom *atom); void r600_emit_alphatest_state(struct r600_context *rctx, struct r600_atom *atom); void r600_emit_blend_color(struct r600_context *rctx, struct r600_atom *atom); void r600_emit_vgt_state(struct r600_context *rctx, struct r600_atom *atom); diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 9a6b9f1486..98b45816d7 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -692,21 +692,49 @@ void r600_polygon_offset_update(struct r600_context *rctx) } } +static uint32_t r600_get_blend_control(const struct pipe_blend_state *state, unsigned i) +{ + int j = state->independent_blend_enable ? i : 0; + + unsigned eqRGB = state->rt[j].rgb_func; + unsigned srcRGB = state->rt[j].rgb_src_factor; + unsigned dstRGB = state->rt[j].rgb_dst_factor; + + 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; + + if (!state->rt[j].blend_enable) + return 0; + + bc |= S_028804_COLOR_COMB_FCN(r600_translate_blend_function(eqRGB)); + bc |= S_028804_COLOR_SRCBLEND(r600_translate_blend_factor(srcRGB)); + bc |= S_028804_COLOR_DESTBLEND(r600_translate_blend_factor(dstRGB)); + + if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) { + bc |= S_028804_SEPARATE_ALPHA_BLEND(1); + bc |= S_028804_ALPHA_COMB_FCN(r600_translate_blend_function(eqA)); + bc |= S_028804_ALPHA_SRCBLEND(r600_translate_blend_factor(srcA)); + bc |= S_028804_ALPHA_DESTBLEND(r600_translate_blend_factor(dstA)); + } + return bc; +} + static void *r600_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 = 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); /* R600 does not support per-MRT blends */ if (rctx->family > CHIP_R600) @@ -739,56 +767,42 @@ static void *r600_create_blend_state_mode(struct pipe_context *ctx, else color_control |= S_028808_SPECIAL_OP(V_028808_DISABLE); - blend->cb_target_mask = target_mask; - blend->cb_color_control = color_control; /* only MRT0 has dual src blend */ blend->dual_src_blend = util_blend_state_is_dual(state, 0); - 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; - - unsigned eqRGB = state->rt[j].rgb_func; - unsigned srcRGB = state->rt[j].rgb_src_factor; - unsigned dstRGB = state->rt[j].rgb_dst_factor; - - 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; - - if (!state->rt[j].blend_enable) - continue; - - bc |= S_028804_COLOR_COMB_FCN(r600_translate_blend_function(eqRGB)); - bc |= S_028804_COLOR_SRCBLEND(r600_translate_blend_factor(srcRGB)); - bc |= S_028804_COLOR_DESTBLEND(r600_translate_blend_factor(dstRGB)); - - if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) { - bc |= S_028804_SEPARATE_ALPHA_BLEND(1); - bc |= S_028804_ALPHA_COMB_FCN(r600_translate_blend_function(eqA)); - bc |= S_028804_ALPHA_SRCBLEND(r600_translate_blend_factor(srcA)); - bc |= S_028804_ALPHA_DESTBLEND(r600_translate_blend_factor(dstA)); - } + blend->cb_target_mask = target_mask; + blend->cb_color_control = color_control; + blend->cb_color_control_no_blend = color_control & C_028808_TARGET_BLEND_ENABLE; + blend->alpha_to_one = state->alpha_to_one; + + r600_store_context_reg(&blend->buffer, R_028D44_DB_ALPHA_TO_MASK, + S_028D44_ALPHA_TO_MASK_ENABLE(state->alpha_to_coverage) | + S_028D44_ALPHA_TO_MASK_OFFSET0(2) | + S_028D44_ALPHA_TO_MASK_OFFSET1(2) | + S_028D44_ALPHA_TO_MASK_OFFSET2(2) | + S_028D44_ALPHA_TO_MASK_OFFSET3(2)); - /* R600 does not support per-MRT blends */ - if (rctx->family > CHIP_R600) - r600_pipe_state_add_reg(rstate, R_028780_CB_BLEND0_CONTROL + i * 4, bc); - if (i == 0) - r600_pipe_state_add_reg(rstate, R_028804_CB_BLEND_CONTROL, bc); + /* Copy over the registers set so far into buffer_no_blend. */ + memcpy(blend->buffer_no_blend.buf, blend->buffer.buf, blend->buffer.num_dw * 4); + blend->buffer_no_blend.num_dw = blend->buffer.num_dw; + + /* Only add blend registers if blending is enabled. */ + if (!G_028808_TARGET_BLEND_ENABLE(color_control)) { + return blend; } - r600_pipe_state_add_reg(rstate, R_028D44_DB_ALPHA_TO_MASK, - S_028D44_ALPHA_TO_MASK_ENABLE(state->alpha_to_coverage) | - S_028D44_ALPHA_TO_MASK_OFFSET0(2) | - S_028D44_ALPHA_TO_MASK_OFFSET1(2) | - S_028D44_ALPHA_TO_MASK_OFFSET2(2) | - S_028D44_ALPHA_TO_MASK_OFFSET3(2)); + /* The first R600 does not support per-MRT blends */ + r600_store_context_reg(&blend->buffer, R_028804_CB_BLEND_CONTROL, + r600_get_blend_control(state, 0)); - blend->alpha_to_one = state->alpha_to_one; - return rstate; + if (rctx->family > CHIP_R600) { + r600_store_context_reg_seq(&blend->buffer, R_028780_CB_BLEND0_CONTROL, 8); + for (int i = 0; i < 8; i++) { + r600_store_value(&blend->buffer, r600_get_blend_control(state, i)); + } + } + return blend; } - static void *r600_create_blend_state(struct pipe_context *ctx, const struct pipe_blend_state *state) { @@ -2151,6 +2165,7 @@ void r600_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++, r600_emit_cb_misc_state, 7); 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++, r600_emit_clip_state, 26); @@ -2731,7 +2746,6 @@ void r600_fetch_shader(struct pipe_context *ctx, void *r600_create_resolve_blend(struct r600_context *rctx) { struct pipe_blend_state blend; - struct r600_pipe_state *rstate; unsigned i; memset(&blend, 0, sizeof(blend)); @@ -2746,32 +2760,27 @@ void *r600_create_resolve_blend(struct r600_context *rctx) blend.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; } - rstate = r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_RESOLVE_BOX); - return rstate; + return r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_RESOLVE_BOX); } void *r700_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 = r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_RESOLVE_BOX); - return rstate; + return r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_RESOLVE_BOX); } void *r600_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 = r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_EXPAND_SAMPLES); - return rstate; + return r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_EXPAND_SAMPLES); } void *r600_create_db_flush_dsa(struct r600_context *rctx) diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 4e336b1b99..5ba043087f 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -60,6 +60,11 @@ void r600_init_atom(struct r600_context *rctx, atom->dirty = false; } +void r600_emit_cso_state(struct r600_context *rctx, struct r600_atom *atom) +{ + r600_emit_command_buffer(rctx->cs, ((struct r600_cso_state*)atom)->cb); +} + void r600_emit_alphatest_state(struct r600_context *rctx, struct r600_atom *atom) { struct radeon_winsys_cs *cs = rctx->cs; @@ -113,22 +118,31 @@ static unsigned r600_conv_pipe_prim(unsigned prim) /* common state between evergreen and r600 */ static void r600_bind_blend_state_internal(struct r600_context *rctx, - struct r600_pipe_blend *blend) + struct r600_blend_state *blend, bool blend_disable) { - struct r600_pipe_state *rstate; + unsigned color_control; bool update_cb = false; - rstate = &blend->rstate; - rctx->states[rstate->id] = rstate; - r600_context_pipe_state_set(rctx, rstate); + rctx->alpha_to_one = blend->alpha_to_one; + rctx->dual_src_blend = blend->dual_src_blend; + + if (!blend_disable) { + r600_set_cso_state_with_cb(&rctx->blend_state, blend, &blend->buffer); + color_control = blend->cb_color_control; + } else { + /* Blending is disabled. */ + r600_set_cso_state_with_cb(&rctx->blend_state, blend, &blend->buffer_no_blend); + color_control = blend->cb_color_control_no_blend; + } + /* Update derived states. */ if (rctx->cb_misc_state.blend_colormask != blend->cb_target_mask) { rctx->cb_misc_state.blend_colormask = blend->cb_target_mask; update_cb = true; } if (rctx->chip_class <= R700 && - rctx->cb_misc_state.cb_color_control != blend->cb_color_control) { - rctx->cb_misc_state.cb_color_control = blend->cb_color_control; + rctx->cb_misc_state.cb_color_control != color_control) { + rctx->cb_misc_state.cb_color_control = color_control; update_cb = true; } if (rctx->cb_misc_state.dual_src_blend != blend->dual_src_blend) { @@ -143,17 +157,12 @@ static void r600_bind_blend_state_internal(struct r600_context *rctx, static void r600_bind_blend_state(struct pipe_context *ctx, void *state) { struct r600_context *rctx = (struct r600_context *)ctx; - struct r600_pipe_blend *blend = (struct r600_pipe_blend *)state; + struct r600_blend_state *blend = (struct r600_blend_state *)state; if (blend == NULL) return; - rctx->blend = blend; - rctx->alpha_to_one = blend->alpha_to_one; - rctx->dual_src_blend = blend->dual_src_blend; - - if (!rctx->blend_override) - r600_bind_blend_state_internal(rctx, blend); + r600_bind_blend_state_internal(rctx, blend, rctx->force_blend_disable); } static void r600_set_blend_color(struct pipe_context *ctx, @@ -459,6 +468,15 @@ static void r600_delete_sampler_state(struct pipe_context *ctx, void *state) free(state); } +static void r600_delete_blend_state(struct pipe_context *ctx, void *state) +{ + struct r600_blend_state *blend = (struct r600_blend_state*)state; + + r600_release_command_buffer(&blend->buffer); + r600_release_command_buffer(&blend->buffer_no_blend); + FREE(blend); +} + static void r600_delete_state(struct pipe_context *ctx, void *state) { struct r600_context *rctx = (struct r600_context *)ctx; @@ -1076,7 +1094,8 @@ static void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask static void r600_update_derived_state(struct r600_context *rctx) { struct pipe_context * ctx = (struct pipe_context*)rctx; - unsigned ps_dirty = 0, blend_override; + unsigned ps_dirty = 0; + bool blend_disable; if (!rctx->blitter->running) { unsigned i; @@ -1110,13 +1129,14 @@ static void r600_update_derived_state(struct r600_context *rctx) if (ps_dirty) r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate); - blend_override = (rctx->dual_src_blend && + blend_disable = (rctx->dual_src_blend && rctx->ps_shader->current->nr_ps_color_outputs < 2); - if (blend_override != rctx->blend_override) { - rctx->blend_override = blend_override; + if (blend_disable != rctx->force_blend_disable) { + rctx->force_blend_disable = blend_disable; r600_bind_blend_state_internal(rctx, - blend_override ? rctx->no_blend : rctx->blend); + rctx->blend_state.cso, + blend_disable); } if (rctx->chip_class >= EVERGREEN) { @@ -1553,7 +1573,7 @@ void r600_init_common_state_functions(struct r600_context *rctx) rctx->context.bind_vertex_elements_state = r600_bind_vertex_elements; rctx->context.bind_vertex_sampler_states = r600_bind_vs_sampler_states; rctx->context.bind_vs_state = r600_bind_vs_state; - rctx->context.delete_blend_state = r600_delete_state; + rctx->context.delete_blend_state = r600_delete_blend_state; rctx->context.delete_depth_stencil_alpha_state = r600_delete_state; rctx->context.delete_fs_state = r600_delete_ps_state; rctx->context.delete_rasterizer_state = r600_delete_rs_state; |