Mesa (master): st/vega: Fix pipe blend state for various blend modes.

Chia-I Wu olv at kemper.freedesktop.org
Sat Dec 4 15:47:20 UTC 2010


Module: Mesa
Branch: master
Commit: 859106f196ade77f59f8787b071739901cd1a843
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=859106f196ade77f59f8787b071739901cd1a843

Author: Chia-I Wu <olv at lunarg.com>
Date:   Sat Dec  4 21:42:51 2010 +0800

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.

---

 src/gallium/state_trackers/vega/renderer.c   |  125 +++++++++++++------------
 src/gallium/state_trackers/vega/shader.c     |    7 ++
 src/gallium/state_trackers/vega/vg_context.c |    4 +
 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 3a33249..7871c51 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 92d3f55..0ed7213 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 5479edc..0844012 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);
 




More information about the mesa-commit mailing list