From: Chia-I Wu Date: Sat, 4 Dec 2010 13:42:51 +0000 (+0800) Subject: st/vega: Fix pipe blend state for various blend modes. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=859106f196ade77f59f8787b071739901cd1a843;p=mesa.git st/vega: Fix pipe blend state for various blend modes. rgb_src_factor and rgb_dst_factor should be PIPE_BLENDFACTOR_ONE for VG_BLEND_SRC_IN and VG_BLEND_DST_IN respectively. VG_BLEND_SRC_OVER can be supported only when the fb has no alpha channel. VG_BLEND_DST_OVER and VG_BLEND_ADDITIVE have to be supported with a shader. Note that Porter-Duff blending rules assume premultiplied alpha. --- diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 3a332498b9a..7871c516c41 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -42,6 +42,7 @@ #include "util/u_sampler.h" #include "util/u_surface.h" #include "util/u_math.h" +#include "util/u_format.h" #include "cso_cache/cso_context.h" #include "tgsi/tgsi_ureg.h" @@ -1266,6 +1267,67 @@ static void update_clip_state(struct renderer *renderer, } } +static void renderer_validate_blend(struct renderer *renderer, + const struct vg_state *state, + enum pipe_format fb_format) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(blend)); + blend.rt[0].colormask = PIPE_MASK_RGBA; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + + /* TODO alpha masking happens after blending? */ + + switch (state->blend_mode) { + case VG_BLEND_SRC: + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + break; + case VG_BLEND_SRC_OVER: + if (!util_format_has_alpha(fb_format)) { + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend.rt[0].blend_enable = 1; + } + break; + case VG_BLEND_SRC_IN: + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].blend_enable = 1; + break; + case VG_BLEND_DST_IN: + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend.rt[0].blend_enable = 1; + break; + case VG_BLEND_DST_OVER: + case VG_BLEND_MULTIPLY: + case VG_BLEND_SCREEN: + case VG_BLEND_DARKEN: + case VG_BLEND_LIGHTEN: + case VG_BLEND_ADDITIVE: + /* need a shader */ + break; + default: + assert(!"not implemented blend mode"); + break; + } + + cso_set_blend(renderer->cso, &blend); +} + /** * Propogate OpenVG state changes to the renderer. Only framebuffer, blending * and scissoring states are relevant here. @@ -1280,66 +1342,6 @@ void renderer_validate(struct renderer *renderer, dirty |= renderer->dirty; renderer->dirty = 0; - if (dirty & BLEND_DIRTY) { - struct pipe_blend_state blend; - memset(&blend, 0, sizeof(blend)); - blend.rt[0].blend_enable = 1; - blend.rt[0].colormask = PIPE_MASK_RGBA; - - switch (state->blend_mode) { - case VG_BLEND_SRC: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].blend_enable = 0; - break; - case VG_BLEND_SRC_OVER: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; - break; - case VG_BLEND_DST_OVER: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; - break; - case VG_BLEND_SRC_IN: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - break; - case VG_BLEND_DST_IN: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - break; - case VG_BLEND_MULTIPLY: - case VG_BLEND_SCREEN: - case VG_BLEND_DARKEN: - case VG_BLEND_LIGHTEN: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].blend_enable = 0; - break; - case VG_BLEND_ADDITIVE: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; - break; - default: - assert(!"not implemented blend mode"); - } - cso_set_blend(renderer->cso, &blend); - } - if (dirty & FRAMEBUFFER_DIRTY) { struct pipe_framebuffer_state *fb = &renderer->g3d.fb; struct matrix *proj = &renderer->projection; @@ -1370,6 +1372,9 @@ void renderer_validate(struct renderer *renderer, update_clip_state(renderer, state); cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa); } + + if (dirty & BLEND_DIRTY) + renderer_validate_blend(renderer, state, stfb->strb->format); } /** diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index 92d3f5549e9..0ed721376cf 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -39,6 +39,7 @@ #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_format.h" #define MAX_CONSTANTS 28 @@ -133,10 +134,16 @@ static VGboolean blend_use_shader(struct vg_context *ctx) VGboolean advanced_blending; switch (ctx->state.vg.blend_mode) { + case VG_BLEND_SRC_OVER: + advanced_blending = + util_format_has_alpha(ctx->draw_buffer->strb->format); + break; + case VG_BLEND_DST_OVER: case VG_BLEND_MULTIPLY: case VG_BLEND_SCREEN: case VG_BLEND_DARKEN: case VG_BLEND_LIGHTEN: + case VG_BLEND_ADDITIVE: advanced_blending = VG_TRUE; break; default: diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index 5479edc8613..0844012cc3b 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -400,6 +400,10 @@ void vg_validate_state(struct vg_context *ctx) if (vg_context_update_depth_stencil_rb(ctx, stfb->width, stfb->height)) ctx->state.dirty |= DEPTH_STENCIL_DIRTY; + /* blend state depends on fb format */ + if (ctx->state.dirty & FRAMEBUFFER_DIRTY) + ctx->state.dirty |= BLEND_DIRTY; + renderer_validate(ctx->renderer, ctx->state.dirty, ctx->draw_buffer, &ctx->state.vg);