summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r600
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r600')
-rw-r--r--src/gallium/drivers/r600/evergreen_hw_context.c20
-rw-r--r--src/gallium/drivers/r600/evergreen_state.c87
-rw-r--r--src/gallium/drivers/r600/r600_blit.c2
-rw-r--r--src/gallium/drivers/r600/r600_hw_context.c19
-rw-r--r--src/gallium/drivers/r600/r600_hw_context_priv.h1
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c7
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h41
-rw-r--r--src/gallium/drivers/r600/r600_state.c121
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c60
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;