summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorChristian König <[email protected]>2012-07-17 14:12:46 +0200
committerChristian König <[email protected]>2012-07-24 12:29:29 +0200
commit63636ae52aefc275115d1f3daac4e75285583485 (patch)
tree124ef1f0b00b84b18b55b55943eeb02a3225b296 /src/gallium/drivers
parentbf7302a6e1f3aed4518498e90e8261a2b1f6afd7 (diff)
radeonsi: move blender to new state handling
Signed-off-by: Christian König <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/radeonsi/evergreen_hw_context.c11
-rw-r--r--src/gallium/drivers/radeonsi/evergreen_state.c152
-rw-r--r--src/gallium/drivers/radeonsi/r600_blit.c2
-rw-r--r--src/gallium/drivers/radeonsi/r600_state_common.c27
-rw-r--r--src/gallium/drivers/radeonsi/radeonsi_pipe.h10
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c158
-rw-r--r--src/gallium/drivers/radeonsi/si_state.h9
7 files changed, 178 insertions, 191 deletions
diff --git a/src/gallium/drivers/radeonsi/evergreen_hw_context.c b/src/gallium/drivers/radeonsi/evergreen_hw_context.c
index 4cf6a9e5253..68d53d47104 100644
--- a/src/gallium/drivers/radeonsi/evergreen_hw_context.c
+++ b/src/gallium/drivers/radeonsi/evergreen_hw_context.c
@@ -184,21 +184,12 @@ static const struct r600_reg si_context_reg_list[] = {
{R_02870C_SPI_SHADER_POS_FORMAT, 0},
{R_028710_SPI_SHADER_Z_FORMAT, 0},
{R_028714_SPI_SHADER_COL_FORMAT, 0},
- {R_028780_CB_BLEND0_CONTROL, 0},
- {R_028784_CB_BLEND1_CONTROL, 0},
- {R_028788_CB_BLEND2_CONTROL, 0},
- {R_02878C_CB_BLEND3_CONTROL, 0},
- {R_028790_CB_BLEND4_CONTROL, 0},
- {R_028794_CB_BLEND5_CONTROL, 0},
- {R_028798_CB_BLEND6_CONTROL, 0},
- {R_02879C_CB_BLEND7_CONTROL, 0},
{R_0287D4_PA_CL_POINT_X_RAD, 0},
{R_0287D8_PA_CL_POINT_Y_RAD, 0},
{R_0287DC_PA_CL_POINT_SIZE, 0},
{R_0287E0_PA_CL_POINT_CULL_RAD, 0},
{R_028800_DB_DEPTH_CONTROL, 0},
{R_028804_DB_EQAA, 0},
- {R_028808_CB_COLOR_CONTROL, 0},
{R_02880C_DB_SHADER_CONTROL, 0},
{R_028810_PA_CL_CLIP_CNTL, 0},
{R_028814_PA_SU_SC_MODE_CNTL, 0},
@@ -284,8 +275,6 @@ static const struct r600_reg si_context_reg_list[] = {
{R_028C2C_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1, 0},
{R_028C30_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2, 0},
{R_028C34_PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3, 0},
- {R_028C38_PA_SC_AA_MASK_X0Y0_X1Y0, 0},
- {R_028C3C_PA_SC_AA_MASK_X0Y1_X1Y1, 0},
{GROUP_FORCE_NEW_BLOCK, 0},
{R_028C60_CB_COLOR0_BASE, REG_FLAG_NEED_BO},
{R_028C64_CB_COLOR0_PITCH, 0},
diff --git a/src/gallium/drivers/radeonsi/evergreen_state.c b/src/gallium/drivers/radeonsi/evergreen_state.c
index 9c45719c750..62f138a1404 100644
--- a/src/gallium/drivers/radeonsi/evergreen_state.c
+++ b/src/gallium/drivers/radeonsi/evergreen_state.c
@@ -45,76 +45,7 @@
#include "sid.h"
#include "r600_resource.h"
#include "radeonsi_pipe.h"
-
-static uint32_t si_translate_blend_function(int blend_func)
-{
- switch (blend_func) {
- case PIPE_BLEND_ADD:
- return V_028780_COMB_DST_PLUS_SRC;
- case PIPE_BLEND_SUBTRACT:
- return V_028780_COMB_SRC_MINUS_DST;
- case PIPE_BLEND_REVERSE_SUBTRACT:
- return V_028780_COMB_DST_MINUS_SRC;
- case PIPE_BLEND_MIN:
- return V_028780_COMB_MIN_DST_SRC;
- case PIPE_BLEND_MAX:
- return V_028780_COMB_MAX_DST_SRC;
- default:
- R600_ERR("Unknown blend function %d\n", blend_func);
- assert(0);
- break;
- }
- return 0;
-}
-
-static uint32_t si_translate_blend_factor(int blend_fact)
-{
- switch (blend_fact) {
- case PIPE_BLENDFACTOR_ONE:
- return V_028780_BLEND_ONE;
- case PIPE_BLENDFACTOR_SRC_COLOR:
- return V_028780_BLEND_SRC_COLOR;
- case PIPE_BLENDFACTOR_SRC_ALPHA:
- return V_028780_BLEND_SRC_ALPHA;
- case PIPE_BLENDFACTOR_DST_ALPHA:
- return V_028780_BLEND_DST_ALPHA;
- case PIPE_BLENDFACTOR_DST_COLOR:
- return V_028780_BLEND_DST_COLOR;
- case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
- return V_028780_BLEND_SRC_ALPHA_SATURATE;
- case PIPE_BLENDFACTOR_CONST_COLOR:
- return V_028780_BLEND_CONSTANT_COLOR;
- case PIPE_BLENDFACTOR_CONST_ALPHA:
- return V_028780_BLEND_CONSTANT_ALPHA;
- case PIPE_BLENDFACTOR_ZERO:
- return V_028780_BLEND_ZERO;
- case PIPE_BLENDFACTOR_INV_SRC_COLOR:
- return V_028780_BLEND_ONE_MINUS_SRC_COLOR;
- case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
- return V_028780_BLEND_ONE_MINUS_SRC_ALPHA;
- case PIPE_BLENDFACTOR_INV_DST_ALPHA:
- return V_028780_BLEND_ONE_MINUS_DST_ALPHA;
- case PIPE_BLENDFACTOR_INV_DST_COLOR:
- return V_028780_BLEND_ONE_MINUS_DST_COLOR;
- case PIPE_BLENDFACTOR_INV_CONST_COLOR:
- return V_028780_BLEND_ONE_MINUS_CONSTANT_COLOR;
- case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
- return V_028780_BLEND_ONE_MINUS_CONSTANT_ALPHA;
- case PIPE_BLENDFACTOR_SRC1_COLOR:
- return V_028780_BLEND_SRC1_COLOR;
- case PIPE_BLENDFACTOR_SRC1_ALPHA:
- return V_028780_BLEND_SRC1_ALPHA;
- case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
- return V_028780_BLEND_INV_SRC1_COLOR;
- case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
- return V_028780_BLEND_INV_SRC1_ALPHA;
- default:
- R600_ERR("Bad blend factor %d not supported!\n", blend_fact);
- assert(0);
- break;
- }
- return 0;
-}
+#include "si_state.h"
#if 0
static uint32_t r600_translate_stencil_op(int s_op)
@@ -852,83 +783,6 @@ static void evergreen_set_blend_color(struct pipe_context *ctx,
r600_context_pipe_state_set(rctx, rstate);
}
-static void *evergreen_create_blend_state(struct pipe_context *ctx,
- const struct pipe_blend_state *state)
-{
- 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, target_mask;
- /* FIXME there is more then 8 framebuffer */
- unsigned blend_cntl[8];
-
- if (blend == NULL) {
- return NULL;
- }
-
- rstate = &blend->rstate;
-
- rstate->id = R600_PIPE_STATE_BLEND;
-
- target_mask = 0;
- color_control = S_028808_MODE(V_028808_CB_NORMAL);
- if (state->logicop_enable) {
- color_control |= S_028808_ROP3(state->logicop_func | (state->logicop_func << 4));
- } else {
- color_control |= S_028808_ROP3(0xcc);
- }
- /* we pretend 8 buffer are used, CB_SHADER_MASK will disable unused one */
- if (state->independent_blend_enable) {
- for (int i = 0; i < 8; i++) {
- target_mask |= (state->rt[i].colormask << (4 * i));
- }
- } else {
- for (int i = 0; i < 8; i++) {
- target_mask |= (state->rt[0].colormask << (4 * i));
- }
- }
- blend->cb_target_mask = target_mask;
-
- r600_pipe_state_add_reg(rstate, R_028808_CB_COLOR_CONTROL,
- color_control, NULL, 0);
-
- r600_pipe_state_add_reg(rstate, R_028C38_PA_SC_AA_MASK_X0Y0_X1Y0, ~0, NULL, 0);
- r600_pipe_state_add_reg(rstate, R_028C3C_PA_SC_AA_MASK_X0Y1_X1Y1, ~0, NULL, 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;
-
- blend_cntl[i] = 0;
- if (!state->rt[j].blend_enable)
- continue;
-
- blend_cntl[i] |= S_028780_ENABLE(1);
- blend_cntl[i] |= S_028780_COLOR_COMB_FCN(si_translate_blend_function(eqRGB));
- blend_cntl[i] |= S_028780_COLOR_SRCBLEND(si_translate_blend_factor(srcRGB));
- blend_cntl[i] |= S_028780_COLOR_DESTBLEND(si_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(si_translate_blend_function(eqA));
- blend_cntl[i] |= S_028780_ALPHA_SRCBLEND(si_translate_blend_factor(srcA));
- blend_cntl[i] |= S_028780_ALPHA_DESTBLEND(si_translate_blend_factor(dstA));
- }
- }
- for (int i = 0; i < 8; i++) {
- r600_pipe_state_add_reg(rstate, R_028780_CB_BLEND0_CONTROL + i * 4, blend_cntl[i], NULL, 0);
- }
-
- return rstate;
-}
-
static void *evergreen_create_dsa_state(struct pipe_context *ctx,
const struct pipe_depth_stencil_alpha_state *state)
{
@@ -1880,7 +1734,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
void cayman_init_state_functions(struct r600_context *rctx)
{
- rctx->context.create_blend_state = evergreen_create_blend_state;
+ si_init_state_functions(rctx);
rctx->context.create_depth_stencil_alpha_state = evergreen_create_dsa_state;
rctx->context.create_fs_state = si_create_shader_state;
rctx->context.create_rasterizer_state = evergreen_create_rs_state;
@@ -1888,7 +1742,6 @@ void cayman_init_state_functions(struct r600_context *rctx)
rctx->context.create_sampler_view = evergreen_create_sampler_view;
rctx->context.create_vertex_elements_state = si_create_vertex_elements;
rctx->context.create_vs_state = si_create_shader_state;
- rctx->context.bind_blend_state = r600_bind_blend_state;
rctx->context.bind_depth_stencil_alpha_state = r600_bind_dsa_state;
rctx->context.bind_fragment_sampler_states = evergreen_bind_ps_sampler;
rctx->context.bind_fs_state = r600_bind_ps_shader;
@@ -1896,7 +1749,6 @@ void cayman_init_state_functions(struct r600_context *rctx)
rctx->context.bind_vertex_elements_state = r600_bind_vertex_elements;
rctx->context.bind_vertex_sampler_states = evergreen_bind_vs_sampler;
rctx->context.bind_vs_state = r600_bind_vs_shader;
- rctx->context.delete_blend_state = r600_delete_state;
rctx->context.delete_depth_stencil_alpha_state = r600_delete_state;
rctx->context.delete_fs_state = r600_delete_ps_shader;
rctx->context.delete_rasterizer_state = r600_delete_rs_state;
diff --git a/src/gallium/drivers/radeonsi/r600_blit.c b/src/gallium/drivers/radeonsi/r600_blit.c
index 1681b48b6f5..3b476bcee09 100644
--- a/src/gallium/drivers/radeonsi/r600_blit.c
+++ b/src/gallium/drivers/radeonsi/r600_blit.c
@@ -47,7 +47,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
r600_context_queries_suspend(rctx);
- util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]);
+ util_blitter_save_blend(rctx->blitter, rctx->queued.named.blend);
util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->states[R600_PIPE_STATE_DSA]);
if (rctx->states[R600_PIPE_STATE_STENCIL_REF]) {
util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref);
diff --git a/src/gallium/drivers/radeonsi/r600_state_common.c b/src/gallium/drivers/radeonsi/r600_state_common.c
index 18ba7a8e2b6..dd3382fb34d 100644
--- a/src/gallium/drivers/radeonsi/r600_state_common.c
+++ b/src/gallium/drivers/radeonsi/r600_state_common.c
@@ -33,6 +33,7 @@
#include "r600_hw_context_priv.h"
#include "radeonsi_pipe.h"
#include "sid.h"
+#include "si_state.h"
static void r600_emit_surface_sync(struct r600_context *rctx, struct r600_atom *atom)
{
@@ -119,22 +120,6 @@ static bool r600_conv_pipe_prim(unsigned pprim, unsigned *prim)
}
/* common state between evergreen and r600 */
-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_pipe_state *rstate;
-
- if (state == NULL)
- return;
- rstate = &blend->rstate;
- rctx->states[rstate->id] = rstate;
- rctx->cb_target_mask = blend->cb_target_mask;
- rctx->cb_color_control = blend->cb_color_control;
-
- r600_context_pipe_state_set(rctx, rstate);
-}
-
static void r600_set_stencil_ref(struct pipe_context *ctx,
const struct r600_stencil_ref *state)
{
@@ -685,6 +670,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
unsigned prim, mask, ls_mask = 0;
struct r600_block *dirty_block = NULL, *next_block = NULL;
struct r600_atom *state = NULL, *next_state = NULL;
+ struct si_state_blend *blend;
int i;
if ((!info.count && (info.indexed || !info.count_from_stream_output)) ||
@@ -696,6 +682,11 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
if (!rctx->ps_shader || !rctx->vs_shader)
return;
+ /* only temporary */
+ if (!rctx->queued.named.blend)
+ return;
+ blend = rctx->queued.named.blend;
+
si_update_derived_state(rctx);
r600_vertex_buffer_update(rctx);
@@ -745,7 +736,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
rctx->vgt.id = R600_PIPE_STATE_VGT;
rctx->vgt.nregs = 0;
r600_pipe_state_add_reg(&rctx->vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, NULL, 0);
- r600_pipe_state_add_reg(&rctx->vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, NULL, 0);
+ r600_pipe_state_add_reg(&rctx->vgt, R_028238_CB_TARGET_MASK, blend->cb_target_mask & mask, NULL, 0);
r600_pipe_state_add_reg(&rctx->vgt, R_028400_VGT_MAX_VTX_INDX, ~0, NULL, 0);
r600_pipe_state_add_reg(&rctx->vgt, R_028404_VGT_MIN_VTX_INDX, 0, NULL, 0);
r600_pipe_state_add_reg(&rctx->vgt, R_028408_VGT_INDX_OFFSET, info.index_bias, NULL, 0);
@@ -763,7 +754,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
rctx->vgt.nregs = 0;
r600_pipe_state_mod_reg(&rctx->vgt, prim);
- r600_pipe_state_mod_reg(&rctx->vgt, rctx->cb_target_mask & mask);
+ r600_pipe_state_mod_reg(&rctx->vgt, blend->cb_target_mask & mask);
r600_pipe_state_mod_reg(&rctx->vgt, ~0);
r600_pipe_state_mod_reg(&rctx->vgt, 0);
r600_pipe_state_mod_reg(&rctx->vgt, info.index_bias);
diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.h b/src/gallium/drivers/radeonsi/radeonsi_pipe.h
index 733afd9b4f0..df1b45b2f9e 100644
--- a/src/gallium/drivers/radeonsi/radeonsi_pipe.h
+++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.h
@@ -75,7 +75,6 @@ struct r600_atom_surface_sync {
};
enum r600_pipe_state_id {
- R600_PIPE_STATE_BLEND = 0,
R600_PIPE_STATE_BLEND_COLOR,
R600_PIPE_STATE_CONFIG,
R600_PIPE_STATE_SEAMLESS_CUBEMAP,
@@ -139,12 +138,6 @@ struct r600_pipe_rasterizer {
float offset_scale;
};
-struct r600_pipe_blend {
- struct r600_pipe_state rstate;
- unsigned cb_target_mask;
- unsigned cb_color_control;
-};
-
struct r600_pipe_dsa {
struct r600_pipe_state rstate;
unsigned alpha_ref;
@@ -243,8 +236,6 @@ struct r600_context {
struct r600_pipe_state *states[R600_PIPE_NSTATES];
struct r600_vertex_element *vertex_elements;
struct pipe_framebuffer_state framebuffer;
- unsigned cb_target_mask;
- unsigned cb_color_control;
unsigned pa_sc_line_stipple;
unsigned pa_su_sc_mode_cntl;
unsigned pa_cl_clip_cntl;
@@ -420,7 +411,6 @@ void *si_create_vertex_elements(struct pipe_context *ctx,
unsigned count,
const struct pipe_vertex_element *elements);
void r600_delete_vertex_element(struct pipe_context *ctx, void *state);
-void r600_bind_blend_state(struct pipe_context *ctx, void *state);
void r600_bind_dsa_state(struct pipe_context *ctx, void *state);
void r600_bind_rs_state(struct pipe_context *ctx, void *state);
void r600_delete_rs_state(struct pipe_context *ctx, void *state);
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 843403b6deb..8373f423685 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -22,7 +22,163 @@
*
* Authors:
* Christian König <[email protected]>
- *
*/
+#include "util/u_memory.h"
+#include "radeonsi_pipe.h"
#include "si_state.h"
+#include "sid.h"
+
+/*
+ * Blender functions
+ */
+
+static uint32_t si_translate_blend_function(int blend_func)
+{
+ switch (blend_func) {
+ case PIPE_BLEND_ADD:
+ return V_028780_COMB_DST_PLUS_SRC;
+ case PIPE_BLEND_SUBTRACT:
+ return V_028780_COMB_SRC_MINUS_DST;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return V_028780_COMB_DST_MINUS_SRC;
+ case PIPE_BLEND_MIN:
+ return V_028780_COMB_MIN_DST_SRC;
+ case PIPE_BLEND_MAX:
+ return V_028780_COMB_MAX_DST_SRC;
+ default:
+ R600_ERR("Unknown blend function %d\n", blend_func);
+ assert(0);
+ break;
+ }
+ return 0;
+}
+
+static uint32_t si_translate_blend_factor(int blend_fact)
+{
+ switch (blend_fact) {
+ case PIPE_BLENDFACTOR_ONE:
+ return V_028780_BLEND_ONE;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ return V_028780_BLEND_SRC_COLOR;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return V_028780_BLEND_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return V_028780_BLEND_DST_ALPHA;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ return V_028780_BLEND_DST_COLOR;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ return V_028780_BLEND_SRC_ALPHA_SATURATE;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ return V_028780_BLEND_CONSTANT_COLOR;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return V_028780_BLEND_CONSTANT_ALPHA;
+ case PIPE_BLENDFACTOR_ZERO:
+ return V_028780_BLEND_ZERO;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ return V_028780_BLEND_ONE_MINUS_SRC_COLOR;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ return V_028780_BLEND_ONE_MINUS_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ return V_028780_BLEND_ONE_MINUS_DST_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ return V_028780_BLEND_ONE_MINUS_DST_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ return V_028780_BLEND_ONE_MINUS_CONSTANT_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ return V_028780_BLEND_ONE_MINUS_CONSTANT_ALPHA;
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ return V_028780_BLEND_SRC1_COLOR;
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ return V_028780_BLEND_SRC1_ALPHA;
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ return V_028780_BLEND_INV_SRC1_COLOR;
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ return V_028780_BLEND_INV_SRC1_ALPHA;
+ default:
+ R600_ERR("Bad blend factor %d not supported!\n", blend_fact);
+ assert(0);
+ break;
+ }
+ return 0;
+}
+
+static void *si_create_blend_state(struct pipe_context *ctx,
+ const struct pipe_blend_state *state)
+{
+ struct si_state_blend *blend = CALLOC_STRUCT(si_state_blend);
+ struct si_pm4_state *pm4 = &blend->pm4;
+
+ uint32_t color_control;
+
+ if (blend == NULL)
+ return NULL;
+
+ color_control = S_028808_MODE(V_028808_CB_NORMAL);
+ if (state->logicop_enable) {
+ color_control |= S_028808_ROP3(state->logicop_func | (state->logicop_func << 4));
+ } else {
+ color_control |= S_028808_ROP3(0xcc);
+ }
+ si_pm4_set_reg(pm4, R_028808_CB_COLOR_CONTROL, color_control);
+
+ si_pm4_set_reg(pm4, R_028C38_PA_SC_AA_MASK_X0Y0_X1Y0, ~0);
+ si_pm4_set_reg(pm4, R_028C3C_PA_SC_AA_MASK_X0Y1_X1Y1, ~0);
+
+ blend->cb_target_mask = 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;
+
+ unsigned blend_cntl = 0;
+
+ /* we pretend 8 buffer are used, CB_SHADER_MASK will disable unused one */
+ blend->cb_target_mask |= state->rt[j].colormask << (4 * i);
+
+ if (!state->rt[j].blend_enable) {
+ si_pm4_set_reg(pm4, R_028780_CB_BLEND0_CONTROL + i * 4, blend_cntl);
+ continue;
+ }
+
+ blend_cntl |= S_028780_ENABLE(1);
+ blend_cntl |= S_028780_COLOR_COMB_FCN(si_translate_blend_function(eqRGB));
+ blend_cntl |= S_028780_COLOR_SRCBLEND(si_translate_blend_factor(srcRGB));
+ blend_cntl |= S_028780_COLOR_DESTBLEND(si_translate_blend_factor(dstRGB));
+
+ if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
+ blend_cntl |= S_028780_SEPARATE_ALPHA_BLEND(1);
+ blend_cntl |= S_028780_ALPHA_COMB_FCN(si_translate_blend_function(eqA));
+ blend_cntl |= S_028780_ALPHA_SRCBLEND(si_translate_blend_factor(srcA));
+ blend_cntl |= S_028780_ALPHA_DESTBLEND(si_translate_blend_factor(dstA));
+ }
+ si_pm4_set_reg(pm4, R_028780_CB_BLEND0_CONTROL + i * 4, blend_cntl);
+ }
+
+ return blend;
+}
+
+static void si_bind_blend_state(struct pipe_context *ctx, void *state)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ si_pm4_bind_state(rctx, blend, (struct si_state_blend *)state);
+}
+
+static void si_delete_blend_state(struct pipe_context *ctx, void *state)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ si_pm4_delete_state(rctx, blend, (struct si_state_blend *)state);
+}
+
+void si_init_state_functions(struct r600_context *rctx)
+{
+ rctx->context.create_blend_state = si_create_blend_state;
+ rctx->context.bind_blend_state = si_bind_blend_state;
+ rctx->context.delete_blend_state = si_delete_blend_state;
+}
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 697c8721359..ed880d6c916 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -29,8 +29,15 @@
#include "radeonsi_pm4.h"
+struct si_state_blend {
+ struct si_pm4_state pm4;
+ uint32_t cb_target_mask;
+ uint32_t cb_color_control;
+};
+
union si_state {
struct {
+ struct si_state_blend *blend;
} named;
struct si_pm4_state *array[0];
};
@@ -62,4 +69,6 @@ union si_state {
} \
} while(0);
+void si_init_state_functions(struct r600_context *rctx);
+
#endif