st/vega: Fix pipe blend state for various blend modes.
authorChia-I Wu <olv@lunarg.com>
Sat, 4 Dec 2010 13:42:51 +0000 (21:42 +0800)
committerChia-I Wu <olv@lunarg.com>
Sat, 4 Dec 2010 15:46:38 +0000 (23:46 +0800)
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
src/gallium/state_trackers/vega/shader.c
src/gallium/state_trackers/vega/vg_context.c

index 3a332498b9ab8a7847426472d49c2c4bc3c187eb..7871c516c41081e6fa2be40e384f64803f4d90fe 100644 (file)
@@ -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);
 }
 
 /**
index 92d3f5549e9fd6b224da92c2fc5d405b6b37a98e..0ed721376cfd5ed097cfd16d62a772a0f6b2dfd1 100644 (file)
@@ -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:
index 5479edc86136b5a00bde3865517968e58602c2f8..0844012cc3b45908722169b37809a5017ad88860 100644 (file)
@@ -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);