dw[1] = dw1;
}
+static inline void
+gen8_3DSTATE_PS_BLEND(struct ilo_builder *builder,
+ const struct ilo_blend_state *blend,
+ const struct ilo_fb_state *fb,
+ const struct ilo_dsa_state *dsa)
+{
+ const uint8_t cmd_len = 2;
+ uint32_t dw1, *dw;
+
+ ILO_DEV_ASSERT(builder->dev, 8, 8);
+
+ dw1 = 0;
+ if (blend->alpha_to_coverage && fb->num_samples > 1)
+ dw1 |= GEN8_PS_BLEND_DW1_ALPHA_TO_COVERAGE;
+
+ if (fb->state.nr_cbufs && fb->state.cbufs[0]) {
+ const struct ilo_fb_blend_caps *caps = &fb->blend_caps[0];
+
+ dw1 |= GEN8_PS_BLEND_DW1_WRITABLE_RT;
+ if (caps->can_blend) {
+ if (caps->dst_alpha_forced_one)
+ dw1 |= blend->dw_ps_blend_dst_alpha_forced_one;
+ else
+ dw1 |= blend->dw_ps_blend;
+ }
+
+ if (caps->can_alpha_test)
+ dw1 |= dsa->dw_ps_blend_alpha;
+ } else {
+ dw1 |= dsa->dw_ps_blend_alpha;
+ }
+
+ ilo_builder_batch_pointer(builder, cmd_len, &dw);
+
+ dw[0] = GEN8_RENDER_CMD(3D, 3DSTATE_PS_BLEND) | (cmd_len - 2);
+ dw[1] = dw1;
+}
+
static inline void
gen6_3DSTATE_CONSTANT_PS(struct ilo_builder *builder,
const uint32_t *bufs, const int *sizes,
assert(num_targets <= 8);
if (!num_targets) {
- if (!dsa->dw_alpha)
+ if (!dsa->dw_blend_alpha)
return 0;
/* to be able to reference alpha func */
num_targets = 1;
dw[1] |= blend->dw_logicop;
if (caps->can_alpha_test)
- dw[1] |= dsa->dw_alpha;
+ dw[1] |= dsa->dw_blend_alpha;
} else {
dw[1] |= GEN6_RT_DW1_WRITE_DISABLE_A |
GEN6_RT_DW1_WRITE_DISABLE_R |
GEN6_RT_DW1_WRITE_DISABLE_G |
GEN6_RT_DW1_WRITE_DISABLE_B |
- dsa->dw_alpha;
+ dsa->dw_blend_alpha;
}
/*
return state_offset;
}
+static inline uint32_t
+gen8_BLEND_STATE(struct ilo_builder *builder,
+ const struct ilo_blend_state *blend,
+ const struct ilo_fb_state *fb,
+ const struct ilo_dsa_state *dsa)
+{
+ const int state_align = 64;
+ int state_len;
+ uint32_t state_offset, *dw;
+ unsigned i;
+
+ ILO_DEV_ASSERT(builder->dev, 8, 8);
+
+ assert(fb->state.nr_cbufs <= 8);
+
+ /* may need to reference alpha func even when there is no color buffer */
+ if (!fb->state.nr_cbufs && !dsa->dw_blend_alpha)
+ return 0;
+
+ state_len = 1 + 2 * fb->state.nr_cbufs;
+
+ state_offset = ilo_builder_dynamic_pointer(builder,
+ ILO_BUILDER_ITEM_BLEND, state_align, state_len, &dw);
+
+ dw[0] = blend->dw_shared;
+ if (fb->num_samples > 1)
+ dw[0] |= blend->dw_alpha_mod;
+ if (!fb->state.nr_cbufs || fb->blend_caps[0].can_alpha_test)
+ dw[0] |= dsa->dw_blend_alpha;
+ dw++;
+
+ for (i = 0; i < fb->state.nr_cbufs; i++) {
+ const struct ilo_fb_blend_caps *caps = &fb->blend_caps[i];
+ const struct ilo_blend_cso *cso = &blend->cso[i];
+
+ dw[0] = cso->payload[0];
+ dw[1] = cso->payload[1];
+
+ if (fb->state.cbufs[i]) {
+ if (caps->can_blend) {
+ if (caps->dst_alpha_forced_one)
+ dw[0] |= cso->dw_blend_dst_alpha_forced_one;
+ else
+ dw[0] |= cso->dw_blend;
+ }
+
+ if (caps->can_logicop)
+ dw[1] |= blend->dw_logicop;
+ } else {
+ dw[0] |= GEN8_RT_DW0_WRITE_DISABLE_A |
+ GEN8_RT_DW0_WRITE_DISABLE_R |
+ GEN8_RT_DW0_WRITE_DISABLE_G |
+ GEN8_RT_DW0_WRITE_DISABLE_B;
+ }
+
+ dw += 2;
+ }
+
+ return state_offset;
+}
+
#endif /* ILO_BUILDER_3D_BOTTOM_H */
return dw;
}
+static uint32_t
+blend_get_rt_blend_enable_gen8(const struct ilo_dev_info *dev,
+ const struct pipe_rt_blend_state *rt,
+ bool dst_alpha_forced_one,
+ bool *independent_alpha)
+{
+ int rgb_src, rgb_dst, a_src, a_dst;
+ uint32_t dw;
+
+ ILO_DEV_ASSERT(dev, 8, 8);
+
+ if (!rt->blend_enable) {
+ *independent_alpha = false;
+ 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 = GEN8_RT_DW0_BLEND_ENABLE |
+ rgb_src << 26 |
+ rgb_dst << 21 |
+ gen6_translate_pipe_blend(rt->rgb_func) << 18 |
+ a_src << 13 |
+ a_dst << 8 |
+ gen6_translate_pipe_blend(rt->alpha_func) << 5;
+
+ *independent_alpha = (rt->rgb_func != rt->alpha_func ||
+ rgb_src != a_src ||
+ rgb_dst != a_dst);
+
+ return dw;
+}
+
static void
blend_init_cso_gen6(const struct ilo_dev_info *dev,
const struct pipe_blend_state *state,
}
}
+static bool
+blend_init_cso_gen8(const struct ilo_dev_info *dev,
+ const struct pipe_blend_state *state,
+ struct ilo_blend_state *blend,
+ unsigned index)
+{
+ const struct pipe_rt_blend_state *rt = &state->rt[index];
+ struct ilo_blend_cso *cso = &blend->cso[index];
+ bool independent_alpha = false;
+
+ ILO_DEV_ASSERT(dev, 8, 8);
+
+ cso->payload[0] = 0;
+ cso->payload[1] = GEN8_RT_DW1_COLORCLAMP_RTFORMAT |
+ GEN8_RT_DW1_PRE_BLEND_CLAMP |
+ GEN8_RT_DW1_POST_BLEND_CLAMP;
+
+ if (!(rt->colormask & PIPE_MASK_A))
+ cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_A;
+ if (!(rt->colormask & PIPE_MASK_R))
+ cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_R;
+ if (!(rt->colormask & PIPE_MASK_G))
+ cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_G;
+ if (!(rt->colormask & PIPE_MASK_B))
+ cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_B;
+
+ if (state->logicop_enable) {
+ cso->dw_blend = 0;
+ cso->dw_blend_dst_alpha_forced_one = 0;
+ } else {
+ bool tmp[2];
+
+ cso->dw_blend = blend_get_rt_blend_enable_gen8(dev, rt, false, &tmp[0]);
+ cso->dw_blend_dst_alpha_forced_one =
+ blend_get_rt_blend_enable_gen8(dev, rt, true, &tmp[1]);
+
+ if (tmp[0] || tmp[1])
+ independent_alpha = true;
+ }
+
+ return independent_alpha;
+}
+
static uint32_t
blend_get_logicop_enable_gen6(const struct ilo_dev_info *dev,
const struct pipe_blend_state *state)
gen6_translate_pipe_logicop(state->logicop_func) << 18;
}
+static uint32_t
+blend_get_logicop_enable_gen8(const struct ilo_dev_info *dev,
+ const struct pipe_blend_state *state)
+{
+ ILO_DEV_ASSERT(dev, 8, 8);
+
+ if (!state->logicop_enable)
+ return 0;
+
+ return GEN8_RT_DW1_LOGICOP_ENABLE |
+ gen6_translate_pipe_logicop(state->logicop_func) << 27;
+}
+
static uint32_t
blend_get_alpha_mod_gen6(const struct ilo_dev_info *dev,
const struct pipe_blend_state *state,
return dw;
}
+static uint32_t
+blend_get_alpha_mod_gen8(const struct ilo_dev_info *dev,
+ const struct pipe_blend_state *state,
+ bool dual_blend)
+{
+ uint32_t dw = 0;
+
+ ILO_DEV_ASSERT(dev, 8, 8);
+
+ if (state->alpha_to_coverage) {
+ dw |= GEN8_BLEND_DW0_ALPHA_TO_COVERAGE |
+ GEN8_BLEND_DW0_ALPHA_TO_COVERAGE_DITHER;
+ }
+
+ if (state->alpha_to_one && !dual_blend)
+ dw |= GEN8_BLEND_DW0_ALPHA_TO_ONE;
+
+ return dw;
+}
+
+static uint32_t
+blend_get_ps_blend_gen8(const struct ilo_dev_info *dev, uint32_t rt_dw0)
+{
+ int rgb_src, rgb_dst, a_src, a_dst;
+ uint32_t dw;
+
+ ILO_DEV_ASSERT(dev, 8, 8);
+
+ if (!(rt_dw0 & GEN8_RT_DW0_BLEND_ENABLE))
+ return 0;
+
+ a_src = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_SRC_ALPHA_FACTOR);
+ a_dst = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_DST_ALPHA_FACTOR);
+ rgb_src = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_SRC_COLOR_FACTOR);
+ rgb_dst = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_DST_COLOR_FACTOR);
+
+ dw = GEN8_PS_BLEND_DW1_BLEND_ENABLE;
+ dw |= GEN_SHIFT32(a_src, GEN8_PS_BLEND_DW1_SRC_ALPHA_FACTOR);
+ dw |= GEN_SHIFT32(a_dst, GEN8_PS_BLEND_DW1_DST_ALPHA_FACTOR);
+ dw |= GEN_SHIFT32(rgb_src, GEN8_PS_BLEND_DW1_SRC_COLOR_FACTOR);
+ dw |= GEN_SHIFT32(rgb_dst, GEN8_PS_BLEND_DW1_DST_COLOR_FACTOR);
+
+ if (a_src != rgb_src || a_dst != rgb_dst)
+ dw |= GEN8_PS_BLEND_DW1_INDEPENDENT_ALPHA_ENABLE;
+
+ return dw;
+}
+
void
ilo_gpe_init_blend(const struct ilo_dev_info *dev,
const struct pipe_blend_state *state,
{
unsigned i;
- ILO_DEV_ASSERT(dev, 6, 7.5);
+ ILO_DEV_ASSERT(dev, 6, 8);
blend->dual_blend = (util_blend_state_is_dual(state, 0) &&
state->rt[0].blend_enable &&
!state->logicop_enable);
blend->alpha_to_coverage = state->alpha_to_coverage;
- blend->dw_alpha_mod =
- blend_get_alpha_mod_gen6(dev, state, blend->dual_blend);
- blend->dw_logicop = blend_get_logicop_enable_gen6(dev, state);
- blend->dw_shared = (state->dither) ? GEN6_RT_DW1_DITHER_ENABLE : 0;
-
- blend_init_cso_gen6(dev, state, blend, 0);
- if (state->independent_blend_enable) {
- for (i = 1; i < Elements(blend->cso); i++)
- blend_init_cso_gen6(dev, state, blend, i);
+ if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+ bool independent_alpha;
+
+ blend->dw_alpha_mod =
+ blend_get_alpha_mod_gen8(dev, state, blend->dual_blend);
+ blend->dw_logicop = blend_get_logicop_enable_gen8(dev, state);
+ blend->dw_shared = (state->dither) ? GEN8_BLEND_DW0_DITHER_ENABLE : 0;
+
+ independent_alpha = blend_init_cso_gen8(dev, state, blend, 0);
+ if (independent_alpha)
+ blend->dw_shared |= GEN8_BLEND_DW0_INDEPENDENT_ALPHA_ENABLE;
+
+ blend->dw_ps_blend = blend_get_ps_blend_gen8(dev,
+ blend->cso[0].dw_blend);
+ blend->dw_ps_blend_dst_alpha_forced_one = blend_get_ps_blend_gen8(dev,
+ blend->cso[0].dw_blend_dst_alpha_forced_one);
+
+ if (state->independent_blend_enable) {
+ for (i = 1; i < Elements(blend->cso); i++) {
+ independent_alpha = blend_init_cso_gen8(dev, state, blend, i);
+ if (independent_alpha)
+ blend->dw_shared |= GEN8_BLEND_DW0_INDEPENDENT_ALPHA_ENABLE;
+ }
+ } else {
+ for (i = 1; i < Elements(blend->cso); i++)
+ blend->cso[i] = blend->cso[0];
+ }
} else {
- for (i = 1; i < Elements(blend->cso); i++)
- blend->cso[i] = blend->cso[0];
+ blend->dw_alpha_mod =
+ blend_get_alpha_mod_gen6(dev, state, blend->dual_blend);
+ blend->dw_logicop = blend_get_logicop_enable_gen6(dev, state);
+ blend->dw_shared = (state->dither) ? GEN6_RT_DW1_DITHER_ENABLE : 0;
+
+ blend->dw_ps_blend = 0;
+ blend->dw_ps_blend_dst_alpha_forced_one = 0;
+
+ blend_init_cso_gen6(dev, state, blend, 0);
+ if (state->independent_blend_enable) {
+ for (i = 1; i < Elements(blend->cso); i++)
+ blend_init_cso_gen6(dev, state, blend, i);
+ } else {
+ for (i = 1; i < Elements(blend->cso); i++)
+ blend->cso[i] = blend->cso[0];
+ }
}
}
state->stencil[1].valuemask << 8 |
state->stencil[1].writemask;
- dsa->dw_alpha = dsa_get_alpha_enable_gen6(dev, &state->alpha);
+ dsa->dw_blend_alpha = dsa_get_alpha_enable_gen6(dev, &state->alpha);
+ dsa->dw_ps_blend_alpha = (state->alpha.enabled) ?
+ GEN8_PS_BLEND_DW1_ALPHA_TEST_ENABLE : 0;
+
dsa->alpha_ref = float_to_ubyte(state->alpha.ref_value);
}
*
* "Logic Ops are only supported on *_UNORM surfaces (excluding _SRGB
* variants), otherwise Logic Ops must be DISABLED."
+ *
+ * According to the classic driver, this is lifted on Gen8+.
*/
- caps->can_logicop = (ch >= 0 && desc->channel[ch].normalized &&
- desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED &&
- desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB);
+ if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+ caps->can_logicop = true;
+ } else {
+ caps->can_logicop = (ch >= 0 && desc->channel[ch].normalized &&
+ desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED &&
+ desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB);
+ }
/* no blending for pure integer formats */
caps->can_blend = !util_format_is_pure_integer(format);