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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user