diff --git a/src/gallium/drivers/etnaviv/etnaviv_blend.c b/src/gallium/drivers/etnaviv/etnaviv_blend.c index 15fba559722..f61e2ccc444 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_blend.c +++ b/src/gallium/drivers/etnaviv/etnaviv_blend.c @@ -38,9 +38,8 @@ etna_blend_state_create(struct pipe_context *pctx, const struct pipe_blend_state *so) { struct etna_context *ctx = etna_context(pctx); - const struct pipe_rt_blend_state *rt0 = &so->rt[0]; struct etna_blend_state *co = CALLOC_STRUCT(etna_blend_state); - bool alpha_enable, logicop_enable; + bool logicop_enable; /* pipe_blend_func happens to match the hardware. */ STATIC_ASSERT(PIPE_BLEND_ADD == BLEND_EQ_ADD); @@ -57,41 +56,38 @@ etna_blend_state_create(struct pipe_context *pctx, logicop_enable = so->logicop_enable && VIV_FEATURE(ctx->screen, ETNA_FEATURE_LOGIC_OP); - /* Enable blending if - * - blend enabled in blend state - * - NOT source factor is ONE and destination factor ZERO and eq is ADD for - * both rgb and alpha (which mean that blending is effectively disabled) - */ - alpha_enable = rt0->blend_enable && - !(rt0->rgb_src_factor == PIPE_BLENDFACTOR_ONE && - rt0->rgb_dst_factor == PIPE_BLENDFACTOR_ZERO && - rt0->rgb_func == PIPE_BLEND_ADD && - rt0->alpha_src_factor == PIPE_BLENDFACTOR_ONE && - rt0->alpha_dst_factor == PIPE_BLENDFACTOR_ZERO && - rt0->alpha_func == PIPE_BLEND_ADD); + for (unsigned int i = 0; i < so->max_rt + 1; i++) { + const struct pipe_rt_blend_state *rt; - /* Enable separate alpha if - * - Blending enabled (see above) - * - NOT source/destination factor and eq is same for both rgb and alpha - * (which would effectively that mean alpha is not separate), and - */ - bool separate_alpha = alpha_enable && - !(rt0->rgb_src_factor == rt0->alpha_src_factor && - rt0->rgb_dst_factor == rt0->alpha_dst_factor && - rt0->rgb_func == rt0->alpha_func); + if (so->independent_blend_enable) + rt = &so->rt[i]; + else + rt = &so->rt[0]; - if (alpha_enable) { - co->rt[0].PE_ALPHA_CONFIG = - VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR | - COND(separate_alpha, VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA) | - VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR(translate_blend_factor(rt0->rgb_src_factor)) | - VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA(translate_blend_factor(rt0->alpha_src_factor)) | - VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR(translate_blend_factor(rt0->rgb_dst_factor)) | - VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA(translate_blend_factor(rt0->alpha_dst_factor)) | - VIVS_PE_ALPHA_CONFIG_EQ_COLOR(rt0->rgb_func) | - VIVS_PE_ALPHA_CONFIG_EQ_ALPHA(rt0->alpha_func); - } else { - co->rt[0].PE_ALPHA_CONFIG = 0; + /* Enable blending if + * - blend enabled in blend state + * - NOT source factor is ONE and destination factor ZERO and eq is ADD for + * both rgb and alpha (which mean that blending is effectively disabled) + */ + co->rt[i].alpha_enable = rt->blend_enable && + !(rt->rgb_src_factor == PIPE_BLENDFACTOR_ONE && + rt->rgb_dst_factor == PIPE_BLENDFACTOR_ZERO && + rt->rgb_func == PIPE_BLEND_ADD && + rt->alpha_src_factor == PIPE_BLENDFACTOR_ONE && + rt->alpha_dst_factor == PIPE_BLENDFACTOR_ZERO && + rt->alpha_func == PIPE_BLEND_ADD); + + /* Enable separate alpha if + * - Blending enabled (see above) + * - NOT source/destination factor and eq is same for both rgb and alpha + * (which would effectively that mean alpha is not separate), and + */ + co->rt[i].separate_alpha = co->rt[i].alpha_enable && + !(rt->rgb_src_factor == rt->alpha_src_factor && + rt->rgb_dst_factor == rt->alpha_dst_factor && + rt->rgb_func == rt->alpha_func); + + co->rt[i].fo_allowed = !co->rt[i].alpha_enable && !logicop_enable; } co->PE_LOGIC_OP = @@ -99,16 +95,13 @@ etna_blend_state_create(struct pipe_context *pctx, VIVS_PE_LOGIC_OP_DITHER_MODE(3) | /* TODO: related to dithering, sometimes 2 */ 0x000E4000 /* ??? */; - co->rt[0].fo_allowed = !alpha_enable && !logicop_enable; - - /* independent_blend_enable not needed: only one rt supported */ /* XXX alpha_to_coverage / alpha_to_one? */ /* Set dither registers based on dither status. These registers set the * dither pattern, * for now, set the same values as the blob. */ if (so->dither && - (!alpha_enable || + (!co->rt[0].alpha_enable || VIV_FEATURE(ctx->screen, ETNA_FEATURE_PE_DITHER_FIX))) { co->PE_DITHER[0] = 0x6e4ca280; co->PE_DITHER[1] = 0x5d7f91b3; @@ -126,33 +119,65 @@ etna_update_blend(struct etna_context *ctx) struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s; struct pipe_blend_state *pblend = ctx->blend; struct etna_blend_state *blend = etna_blend_state(pblend); - const struct pipe_rt_blend_state *rt0 = &pblend->rt[0]; - const struct util_format_description *desc; - uint32_t colormask; + unsigned current_rt = 0; - if (pfb->cbufs[0] && - translate_pe_format_rb_swap(pfb->cbufs[0]->format)) { - colormask = rt0->colormask & (PIPE_MASK_A | PIPE_MASK_G); - if (rt0->colormask & PIPE_MASK_R) - colormask |= PIPE_MASK_B; - if (rt0->colormask & PIPE_MASK_B) - colormask |= PIPE_MASK_R; - } else { - colormask = rt0->colormask; + for (unsigned i = 0; i < pfb->nr_cbufs; i++) { + if (!pfb->cbufs[i]) + continue; + + const struct pipe_rt_blend_state *rt; + uint32_t colormask; + + if (pblend->independent_blend_enable) + rt = &pblend->rt[i]; + else + rt = &pblend->rt[0]; + + if (translate_pe_format_rb_swap(pfb->cbufs[i]->format)) { + colormask = rt->colormask & (PIPE_MASK_A | PIPE_MASK_G); + if (rt->colormask & PIPE_MASK_R) + colormask |= PIPE_MASK_B; + if (rt->colormask & PIPE_MASK_B) + colormask |= PIPE_MASK_R; + } else { + colormask = rt->colormask; + } + + /* If the complete render target is written, set full_overwrite: + * - The color mask covers all channels of the render target + * - No blending or logicop is used + */ + const struct util_format_description *desc = util_format_description(pfb->cbufs[i]->format); + bool full_overwrite = (blend->rt[i].fo_allowed && + util_format_colormask_full(desc, colormask)); + + if (current_rt == 0) { + blend->rt[0].PE_COLOR_FORMAT = + VIVS_PE_COLOR_FORMAT_COMPONENTS(colormask) | + COND(full_overwrite, VIVS_PE_COLOR_FORMAT_OVERWRITE); + } else { + blend->rt[current_rt].PE_HALTI5_COLORMASK = + VIVS_PE_HALTI5_RT_COLORMASK_COMPONENTS(colormask) | + COND(full_overwrite, VIVS_PE_HALTI5_RT_COLORMASK_OVERWRITE); + } + + if (blend->rt[i].alpha_enable) { + blend->rt[current_rt].PE_ALPHA_CONFIG = + VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR | + COND(blend->rt[i].separate_alpha, VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA) | + VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR(translate_blend_factor(rt->rgb_src_factor)) | + VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA(translate_blend_factor(rt->alpha_src_factor)) | + VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR(translate_blend_factor(rt->rgb_dst_factor)) | + VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA(translate_blend_factor(rt->alpha_dst_factor)) | + VIVS_PE_ALPHA_CONFIG_EQ_COLOR(rt->rgb_func) | + VIVS_PE_ALPHA_CONFIG_EQ_ALPHA(rt->alpha_func); + } else { + blend->rt[current_rt].PE_ALPHA_CONFIG = 0; + } + + current_rt++; } - /* If the complete render target is written, set full_overwrite: - * - The color mask covers all channels of the render target - * - No blending or logicop is used - */ - if (pfb->cbufs[0]) - desc = util_format_description(pfb->cbufs[0]->format); - bool full_overwrite = !pfb->cbufs[0] || ((blend->rt[0].fo_allowed && - util_format_colormask_full(desc, colormask))); - blend->rt[0].PE_COLOR_FORMAT = - VIVS_PE_COLOR_FORMAT_COMPONENTS(colormask) | - COND(full_overwrite, VIVS_PE_COLOR_FORMAT_OVERWRITE); - return true; } diff --git a/src/gallium/drivers/etnaviv/etnaviv_blend.h b/src/gallium/drivers/etnaviv/etnaviv_blend.h index 09afc6e1e07..1b323789602 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_blend.h +++ b/src/gallium/drivers/etnaviv/etnaviv_blend.h @@ -35,6 +35,9 @@ struct etna_context; struct etna_rt_blend_state { uint32_t PE_ALPHA_CONFIG; uint32_t PE_COLOR_FORMAT; + uint32_t PE_HALTI5_COLORMASK; + bool alpha_enable : 1; + bool separate_alpha : 1; bool fo_allowed : 1; }; diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c index 33907112edb..fdc4867167f 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_emit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c @@ -151,6 +151,27 @@ emit_halti5_only_state(struct etna_context *ctx, int vs_output_count) /*01084*/ EMIT_STATE(PS_VARYING_NUM_COMPONENTS(1), ctx->shader_state.GL_VARYING_NUM_COMPONENTS[1]); /*03888*/ EMIT_STATE(GL_HALTI5_SH_SPECIALS, ctx->shader_state.GL_HALTI5_SH_SPECIALS); } + if (unlikely(dirty & (ETNA_DIRTY_BLEND))) { + for (int i = 1; i < ctx->framebuffer.num_rt; i++) { + const uint8_t rt = i - 1; + /*14920*/ EMIT_STATE(PE_HALTI5_RT_COLORMASK(rt), etna_blend_state(ctx->blend)->rt[i].PE_HALTI5_COLORMASK); + } + for (int i = 1; i < ctx->framebuffer.num_rt; i++) { + const uint8_t rt = i - 1; + /*14960*/ EMIT_STATE(PE_HALTI5_RT_ALPHA_CONFIG(rt), etna_blend_state(ctx->blend)->rt[i].PE_ALPHA_CONFIG); + } + } + if (unlikely(dirty & (ETNA_DIRTY_BLEND_COLOR))) { + for (int i = 1; i < ctx->framebuffer.num_rt; i++) { + const uint8_t rt = i - 1; + /*14980*/ EMIT_STATE(PE_HALTI5_RT_ALPHA_COLOR_EXT0(rt), ctx->blend_color.rt[i].PE_ALPHA_COLOR_EXT0); + } + for (int i = 1; i < ctx->framebuffer.num_rt; i++) { + const uint8_t rt = i - 1; + /*149A0*/ EMIT_STATE(PE_HALTI5_RT_ALPHA_COLOR_EXT1(rt), ctx->blend_color.rt[i].PE_ALPHA_COLOR_EXT1); + } + } + etna_coalesce_end(stream, &coalesce); }