diff options
Diffstat (limited to 'src/gallium/drivers/r600')
-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 666b18c94fc..547f4f57d3e 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 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) diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 062f6d9b227..a88cb5e4bba 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 c457f35f20e..b3f0fbadf2d 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 85fd74dce92..c59a9abf3f9 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 70cfe1408f3..35fa9d49f1a 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 c6e02414830..449c785421f 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 9a6b9f14865..98b45816d73 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 4e336b1b991..5ba043087f8 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; |