summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/vega
diff options
context:
space:
mode:
authorChia-I Wu <olv@lunarg.com>2010-12-04 21:42:51 +0800
committerChia-I Wu <olv@lunarg.com>2010-12-04 23:46:38 +0800
commit859106f196ade77f59f8787b071739901cd1a843 (patch)
tree632ca04f16bcf6ad64614b3cf86b278181591099 /src/gallium/state_trackers/vega
parent0ee73edeccd21034e03e9e43dd0d09fa6fbf7842 (diff)
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.
Diffstat (limited to 'src/gallium/state_trackers/vega')
-rw-r--r--src/gallium/state_trackers/vega/renderer.c125
-rw-r--r--src/gallium/state_trackers/vega/shader.c7
-rw-r--r--src/gallium/state_trackers/vega/vg_context.c4
3 files changed, 76 insertions, 60 deletions
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c
index 3a332498b9..7871c516c4 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 92d3f5549e..0ed721376c 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 5479edc861..0844012cc3 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);