From: Chia-I Wu Date: Fri, 31 May 2013 08:11:38 +0000 (+0800) Subject: ilo: introduce blend CSO X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=eea1be2072a1c980871d80df71d3e39a67fdfb0a;p=mesa.git ilo: introduce blend CSO Introduce ilo_blend_cso and initialize it in create_blend_state(). This saves us from having to construct hardware blend states in draw_vbo(). --- diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c index 81cd6c22eaa..c94a0bbda24 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c @@ -669,12 +669,9 @@ gen6_pipeline_wm(struct ilo_3d_pipeline *p, DIRTY(RASTERIZER)) { const struct ilo_shader *fs = (ilo->fs)? ilo->fs->shader : NULL; const int num_samplers = ilo->sampler[PIPE_SHADER_FRAGMENT].count; - const bool dual_blend = - (!ilo->blend->state.logicop_enable && - ilo->blend->state.rt[0].blend_enable && - util_blend_state_is_dual(&ilo->blend->state, 0)); + const bool dual_blend = ilo->blend->dual_blend; const bool cc_may_kill = (ilo->dsa->state.alpha.enabled || - ilo->blend->state.alpha_to_coverage); + ilo->blend->alpha_to_coverage); if (fs) assert(!fs->pcb.clip_state_size); @@ -807,7 +804,7 @@ gen6_pipeline_state_cc(struct ilo_3d_pipeline *p, /* BLEND_STATE */ if (DIRTY(BLEND) || DIRTY(FRAMEBUFFER) || DIRTY(DEPTH_STENCIL_ALPHA)) { p->state.BLEND_STATE = p->gen6_BLEND_STATE(p->dev, - &ilo->blend->state, &ilo->fb, &ilo->dsa->state.alpha, p->cp); + ilo->blend, &ilo->fb, &ilo->dsa->state.alpha, p->cp); session->cc_state_blend_changed = true; } diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c index 33f5a759984..1ad19d2e675 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c @@ -463,7 +463,7 @@ gen7_pipeline_wm(struct ilo_3d_pipeline *p, DIRTY(RASTERIZER)) { const struct ilo_shader *fs = (ilo->fs)? ilo->fs->shader : NULL; const bool cc_may_kill = (ilo->dsa->state.alpha.enabled || - ilo->blend->state.alpha_to_coverage); + ilo->blend->alpha_to_coverage); if (fs) assert(!fs->pcb.clip_state_size); @@ -496,10 +496,7 @@ gen7_pipeline_wm(struct ilo_3d_pipeline *p, DIRTY(BLEND)) { const struct ilo_shader *fs = (ilo->fs)? ilo->fs->shader : NULL; const int num_samplers = ilo->sampler[PIPE_SHADER_FRAGMENT].count; - const bool dual_blend = - (!ilo->blend->state.logicop_enable && - ilo->blend->state.rt[0].blend_enable && - util_blend_state_is_dual(&ilo->blend->state, 0)); + const bool dual_blend = ilo->blend->dual_blend; if (fs) assert(!fs->pcb.clip_state_size); diff --git a/src/gallium/drivers/ilo/ilo_gpe.h b/src/gallium/drivers/ilo/ilo_gpe.h index 467a6b3a216..dc4e80eb97e 100644 --- a/src/gallium/drivers/ilo/ilo_gpe.h +++ b/src/gallium/drivers/ilo/ilo_gpe.h @@ -107,8 +107,23 @@ struct ilo_dsa_state { struct pipe_depth_stencil_alpha_state state; }; +struct ilo_blend_cso { + /* BLEND_STATE */ + uint32_t payload[2]; + + uint32_t dw_blend; + uint32_t dw_blend_dst_alpha_forced_one; + + uint32_t dw_logicop; + uint32_t dw_alpha_mod; +}; + struct ilo_blend_state { - struct pipe_blend_state state; + struct ilo_blend_cso cso[ILO_MAX_DRAW_BUFFERS]; + + bool independent_blend_enable; + bool dual_blend; + bool alpha_to_coverage; }; struct ilo_sampler_cso { @@ -191,6 +206,11 @@ void ilo_gpe_set_scissor_null(const struct ilo_dev_info *dev, struct ilo_scissor_state *scissor); +void +ilo_gpe_init_blend(const struct ilo_dev_info *dev, + const struct pipe_blend_state *state, + struct ilo_blend_state *blend); + void ilo_gpe_init_sampler_cso(const struct ilo_dev_info *dev, const struct pipe_sampler_state *state, diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.c b/src/gallium/drivers/ilo/ilo_gpe_gen6.c index 082392bdeea..dab964f36c1 100644 --- a/src/gallium/drivers/ilo/ilo_gpe_gen6.c +++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.c @@ -3229,9 +3229,141 @@ gen6_blend_factor_dst_alpha_forced_one(int factor) } } +static uint32_t +blend_get_rt_blend_enable(const struct ilo_dev_info *dev, + const struct pipe_rt_blend_state *rt, + bool dst_alpha_forced_one) +{ + int rgb_src, rgb_dst, a_src, a_dst; + uint32_t dw; + + if (!rt->blend_enable) + return 0; + + rgb_src = gen6_translate_pipe_blendfactor(rt->rgb_src_factor); + rgb_dst = gen6_translate_pipe_blendfactor(rt->rgb_dst_factor); + a_src = gen6_translate_pipe_blendfactor(rt->alpha_src_factor); + a_dst = gen6_translate_pipe_blendfactor(rt->alpha_dst_factor); + + if (dst_alpha_forced_one) { + rgb_src = gen6_blend_factor_dst_alpha_forced_one(rgb_src); + rgb_dst = gen6_blend_factor_dst_alpha_forced_one(rgb_dst); + a_src = gen6_blend_factor_dst_alpha_forced_one(a_src); + a_dst = gen6_blend_factor_dst_alpha_forced_one(a_dst); + } + + dw = 1 << 31 | + gen6_translate_pipe_blend(rt->alpha_func) << 26 | + a_src << 20 | + a_dst << 15 | + gen6_translate_pipe_blend(rt->rgb_func) << 11 | + rgb_src << 5 | + rgb_dst; + + if (rt->rgb_func != rt->alpha_func || + rgb_src != a_src || rgb_dst != a_dst) + dw |= 1 << 30; + + return dw; +} + +void +ilo_gpe_init_blend(const struct ilo_dev_info *dev, + const struct pipe_blend_state *state, + struct ilo_blend_state *blend) +{ + unsigned num_cso, i; + + ILO_GPE_VALID_GEN(dev, 6, 7); + + if (state->independent_blend_enable) { + num_cso = Elements(blend->cso); + } + else { + memset(blend->cso, 0, sizeof(blend->cso)); + num_cso = 1; + } + + blend->independent_blend_enable = state->independent_blend_enable; + blend->alpha_to_coverage = state->alpha_to_coverage; + blend->dual_blend = false; + + for (i = 0; i < num_cso; i++) { + const struct pipe_rt_blend_state *rt = &state->rt[i]; + struct ilo_blend_cso *cso = &blend->cso[i]; + bool dual_blend; + + cso->payload[0] = 0; + cso->payload[1] = BRW_RENDERTARGET_CLAMPRANGE_FORMAT << 2 | + 0x3; + + if (!(rt->colormask & PIPE_MASK_A)) + cso->payload[1] |= 1 << 27; + if (!(rt->colormask & PIPE_MASK_R)) + cso->payload[1] |= 1 << 26; + if (!(rt->colormask & PIPE_MASK_G)) + cso->payload[1] |= 1 << 25; + if (!(rt->colormask & PIPE_MASK_B)) + cso->payload[1] |= 1 << 24; + + if (state->dither) + cso->payload[1] |= 1 << 12; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 365: + * + * "Color Buffer Blending and Logic Ops must not be enabled + * simultaneously, or behavior is UNDEFINED." + * + * Since state->logicop_enable takes precedence over rt->blend_enable, + * no special care is needed. + */ + if (state->logicop_enable) { + cso->dw_logicop = 1 << 22 | + gen6_translate_pipe_logicop(state->logicop_func) << 18; + + cso->dw_blend = 0; + cso->dw_blend_dst_alpha_forced_one = 0; + + dual_blend = false; + } + else { + cso->dw_logicop = 0; + + cso->dw_blend = blend_get_rt_blend_enable(dev, rt, false); + cso->dw_blend_dst_alpha_forced_one = + blend_get_rt_blend_enable(dev, rt, true); + + dual_blend = (rt->blend_enable && + util_blend_state_is_dual(state, i)); + } + + cso->dw_alpha_mod = 0; + + if (state->alpha_to_coverage) { + cso->dw_alpha_mod |= 1 << 31; + + if (dev->gen >= ILO_GEN(7)) + cso->dw_alpha_mod |= 1 << 29; + } + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 378: + * + * "If Dual Source Blending is enabled, this bit (AlphaToOne Enable) + * must be disabled." + */ + if (state->alpha_to_one && !dual_blend) + cso->dw_alpha_mod |= 1 << 30; + + if (dual_blend) + blend->dual_blend = true; + } +} + static uint32_t gen6_emit_BLEND_STATE(const struct ilo_dev_info *dev, - const struct pipe_blend_state *blend, + const struct ilo_blend_state *blend, const struct ilo_fb_state *fb, const struct pipe_alpha_state *alpha, struct ilo_cp *cp) @@ -3239,7 +3371,7 @@ gen6_emit_BLEND_STATE(const struct ilo_dev_info *dev, const int state_align = 64 / 4; int state_len; uint32_t state_offset, *dw; - int num_targets, i; + unsigned num_targets, i; ILO_GPE_VALID_GEN(dev, 6, 7); @@ -3264,12 +3396,12 @@ gen6_emit_BLEND_STATE(const struct ilo_dev_info *dev, state_len, state_align, &state_offset); for (i = 0; i < num_targets; i++) { - const int target = (blend->independent_blend_enable) ? i : 0; - const struct pipe_rt_blend_state *rt = &blend->rt[target]; + const unsigned idx = (blend->independent_blend_enable) ? i : 0; + const struct ilo_blend_cso *cso = &blend->cso[idx]; const int num_samples = fb->num_samples; const struct util_format_description *format_desc = - (target < fb->state.nr_cbufs) ? - util_format_description(fb->state.cbufs[target]->format) : NULL; + (idx < fb->state.nr_cbufs) ? + util_format_description(fb->state.cbufs[idx]->format) : NULL; bool rt_is_unorm, rt_is_pure_integer, rt_dst_alpha_forced_one; rt_is_unorm = true; @@ -3306,56 +3438,27 @@ gen6_emit_BLEND_STATE(const struct ilo_dev_info *dev, } } - dw[0] = 0; - dw[1] = BRW_RENDERTARGET_CLAMPRANGE_FORMAT << 2 | 0x3; + dw[0] = cso->payload[0]; + dw[1] = cso->payload[1]; + + if (!rt_is_pure_integer) { + if (rt_dst_alpha_forced_one) + dw[0] |= cso->dw_blend_dst_alpha_forced_one; + else + dw[0] |= cso->dw_blend; + } /* * From the Sandy Bridge PRM, volume 2 part 1, page 365: * - * "* Color Buffer Blending and Logic Ops must not be enabled - * simultaneously, or behavior is UNDEFINED. - * - * * Logic Ops are only supported on *_UNORM surfaces (excluding - * _SRGB variants), otherwise Logic Ops must be DISABLED." + * "Logic Ops are only supported on *_UNORM surfaces (excluding + * _SRGB variants), otherwise Logic Ops must be DISABLED." * - * Since blend->logicop_enable takes precedence over rt->blend_enable, - * and logicop is ignored for non-UNORM color buffers, no special care + * Since logicop is ignored for non-UNORM color buffers, no special care * is needed. */ - if (blend->logicop_enable) { - if (rt_is_unorm) { - dw[1] |= 1 << 22 | - gen6_translate_pipe_logicop(blend->logicop_func) << 18; - } - } - else if (rt->blend_enable && !rt_is_pure_integer) { - int rgb_src, rgb_dst, a_src, a_dst; - - rgb_src = gen6_translate_pipe_blendfactor(rt->rgb_src_factor); - rgb_dst = gen6_translate_pipe_blendfactor(rt->rgb_dst_factor); - a_src = gen6_translate_pipe_blendfactor(rt->alpha_src_factor); - a_dst = gen6_translate_pipe_blendfactor(rt->alpha_dst_factor); - - if (rt_dst_alpha_forced_one) { - rgb_src = gen6_blend_factor_dst_alpha_forced_one(rgb_src); - rgb_dst = gen6_blend_factor_dst_alpha_forced_one(rgb_dst); - a_src = gen6_blend_factor_dst_alpha_forced_one(a_src); - a_dst = gen6_blend_factor_dst_alpha_forced_one(a_dst); - } - - dw[0] |= 1 << 31 | - gen6_translate_pipe_blend(rt->alpha_func) << 26 | - a_src << 20 | - a_dst << 15 | - gen6_translate_pipe_blend(rt->rgb_func) << 11 | - rgb_src << 5 | - rgb_dst; - - if (rt->rgb_func != rt->alpha_func || - rgb_src != a_src || - rgb_dst != a_dst) - dw[0] |= 1 << 30; - } + if (rt_is_unorm) + dw[1] |= cso->dw_logicop; /* * From the Sandy Bridge PRM, volume 2 part 1, page 356: @@ -3366,37 +3469,8 @@ gen6_emit_BLEND_STATE(const struct ilo_dev_info *dev, * There is no such limitation on GEN7, or for AlphaToOne. But GL * requires that anyway. */ - if (num_samples > 1) { - if (blend->alpha_to_coverage) - dw[1] |= 1 << 31; - - if (blend->alpha_to_one) { - const bool dual_blend = - (!blend->logicop_enable && rt->blend_enable && - util_blend_state_is_dual(blend, target)); - - /* - * From the Sandy Bridge PRM, volume 2 part 1, page 378: - * - * "If Dual Source Blending is enabled, this bit (AlphaToOne - * Enable) must be disabled." - */ - if (!dual_blend) - dw[1] |= 1 << 30; - } - - if (dev->gen >= ILO_GEN(7)) - dw[1] |= 1 << 29; - } - - if (!(rt->colormask & PIPE_MASK_A)) - dw[1] |= 1 << 27; - if (!(rt->colormask & PIPE_MASK_R)) - dw[1] |= 1 << 26; - if (!(rt->colormask & PIPE_MASK_G)) - dw[1] |= 1 << 25; - if (!(rt->colormask & PIPE_MASK_B)) - dw[1] |= 1 << 24; + if (num_samples > 1) + dw[1] |= cso->dw_alpha_mod; /* * From the Sandy Bridge PRM, volume 2 part 1, page 382: @@ -3409,9 +3483,6 @@ gen6_emit_BLEND_STATE(const struct ilo_dev_info *dev, gen6_translate_dsa_func(alpha->func) << 13; } - if (blend->dither) - dw[1] |= 1 << 12; - dw += 2; } diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.h b/src/gallium/drivers/ilo/ilo_gpe_gen6.h index bb09dc0ff94..16445a03d9f 100644 --- a/src/gallium/drivers/ilo/ilo_gpe_gen6.h +++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.h @@ -402,7 +402,7 @@ typedef uint32_t typedef uint32_t (*ilo_gpe_gen6_BLEND_STATE)(const struct ilo_dev_info *dev, - const struct pipe_blend_state *blend, + const struct ilo_blend_state *blend, const struct ilo_fb_state *fb, const struct pipe_alpha_state *alpha, struct ilo_cp *cp); diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index ab2a4e9ae10..c032e177673 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -156,12 +156,13 @@ static void * ilo_create_blend_state(struct pipe_context *pipe, const struct pipe_blend_state *state) { + struct ilo_context *ilo = ilo_context(pipe); struct ilo_blend_state *blend; blend = MALLOC_STRUCT(ilo_blend_state); assert(blend); - blend->state = *state; + ilo_gpe_init_blend(ilo->dev, state, blend); return blend; }