st/vega: Disable blending when the paint is opaque.
authorChia-I Wu <olv@lunarg.com>
Sun, 30 Jan 2011 14:54:40 +0000 (22:54 +0800)
committerChia-I Wu <olv@lunarg.com>
Sun, 30 Jan 2011 15:22:40 +0000 (23:22 +0800)
When the paint is opaque (currently, solid color with alpha 1.0f), no
blending is needed for VG_BLEND_SRC_OVER.  This eliminates the serious
performance hit introduced by 859106f196ade77f59f8787b071739901cd1a843
for a common scenario.

src/gallium/state_trackers/vega/api_paint.c
src/gallium/state_trackers/vega/api_params.c
src/gallium/state_trackers/vega/paint.c
src/gallium/state_trackers/vega/paint.h
src/gallium/state_trackers/vega/renderer.c
src/gallium/state_trackers/vega/shader.c
src/gallium/state_trackers/vega/vg_context.c
src/gallium/state_trackers/vega/vg_context.h

index 6a8ae9c96c82b8109e99d3b8156fe713e1ed0ba1..2610ebe0576ee2d763af3db22b6a4bd2ad7c359a 100644 (file)
@@ -72,6 +72,8 @@ void vegaSetPaint(VGPaint paint, VGbitfield paintModes)
    if (paintModes & VG_STROKE_PATH) {
       ctx->state.vg.stroke_paint = handle_to_paint(paint);
    }
+
+   ctx->state.dirty |= PAINT_DIRTY;
 }
 
 VGPaint vegaGetPaint(VGPaintMode paintMode)
@@ -98,6 +100,7 @@ VGPaint vegaGetPaint(VGPaintMode paintMode)
 void vegaSetColor(VGPaint paint, VGuint rgba)
 {
    struct vg_context *ctx = vg_current_context();
+   struct vg_paint *p;
 
    if (paint == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
@@ -109,7 +112,12 @@ void vegaSetColor(VGPaint paint, VGuint rgba)
       return;
    }
 
-   paint_set_colori(handle_to_paint(paint), rgba);
+   p = handle_to_paint(paint);
+   paint_set_colori(p, rgba);
+
+   if (ctx->state.vg.fill_paint == p ||
+       ctx->state.vg.stroke_paint == p)
+      ctx->state.dirty |= PAINT_DIRTY;
 }
 
 VGuint vegaGetColor(VGPaint paint)
index e5e55215b756b24e749c97ce8d3d6ffa8df74856..aa1e5dd280aabd7e0b4ff1fddc6e97d95e12dfaa 100644 (file)
@@ -1135,6 +1135,9 @@ void vegaSetParameterfv(VGHandle object,
       else {
          struct vg_paint *paint = handle_to_paint(object);
          paint_set_color(paint, values);
+         if (ctx->state.vg.fill_paint == paint ||
+             ctx->state.vg.stroke_paint == paint)
+            ctx->state.dirty |= PAINT_DIRTY;
       }
    }
       break;
@@ -1248,6 +1251,9 @@ void vegaSetParameteriv(VGHandle object,
       else {
          struct vg_paint *paint = handle_to_paint(object);
          paint_set_coloriv(paint, values);
+         if (ctx->state.vg.fill_paint == paint ||
+             ctx->state.vg.stroke_paint == paint)
+            ctx->state.dirty |= PAINT_DIRTY;
       }
    }
       break;
index 2db8cbcf7c89f01305e5527122cd3f89b8578cd1..6e5348a1ff21b60b0a49e7edbddd99ba9125c5f7 100644 (file)
@@ -748,3 +748,10 @@ void paint_fill_constant_buffer(struct vg_paint *paint,
       abort();
    }
 }
+
+VGboolean paint_is_opaque(struct vg_paint *paint)
+{
+   /* TODO add other paint types and make sure PAINT_DIRTY gets set */
+   return (paint->type == VG_PAINT_TYPE_COLOR &&
+           floatsEqual(paint->solid.color[3], 1.0f));
+}
index 3de3bbe12eda91fc9c00fd03df54ecdab09a5359..e5357763b8936199e9e6c71616c75ea5c6b30352 100644 (file)
@@ -118,5 +118,6 @@ void paint_fill_constant_buffer(struct vg_paint *paint,
                                 const struct matrix *mat,
                                 void *buffer);
 
+VGboolean paint_is_opaque(struct vg_paint *paint);
 
 #endif
index e42bad764922494d4478f617d2168ebc23e1b3fc..936bf2e4e03ff3582d3eb81356cbb69c18cb8f69 100644 (file)
@@ -28,6 +28,7 @@
 #include "renderer.h"
 
 #include "vg_context.h"
+#include "paint.h" /* for paint_is_opaque */
 
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
@@ -1289,7 +1290,11 @@ static void renderer_validate_blend(struct renderer *renderer,
       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
       break;
    case VG_BLEND_SRC_OVER:
-      if (!util_format_has_alpha(fb_format)) {
+      if (paint_is_opaque(state->fill_paint) &&
+          paint_is_opaque(state->stroke_paint)) {
+         /* no blending */
+      }
+      else 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;
index 2a6bae8a6305071579864645e398bf41a0640b8d..bee6d84001d03de92430f5f3f660eef06808fa88 100644 (file)
@@ -134,6 +134,8 @@ static VGboolean blend_use_shader(struct vg_context *ctx)
    switch (ctx->state.vg.blend_mode) {
    case VG_BLEND_SRC_OVER:
       advanced_blending =
+         (!paint_is_opaque(ctx->state.vg.fill_paint) ||
+          !paint_is_opaque(ctx->state.vg.stroke_paint)) &&
          util_format_has_alpha(ctx->draw_buffer->strb->format);
       break;
    case VG_BLEND_DST_OVER:
index cd251838e02a2be4d434e58874c265f3b151450b..83b42609e03432c8fc58e6435e9d7a02f0358ede 100644 (file)
@@ -408,8 +408,9 @@ 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)
+   /* blend state depends on fb format and paint color */
+   if ((ctx->state.dirty & FRAMEBUFFER_DIRTY) ||
+       (ctx->state.dirty & PAINT_DIRTY))
       ctx->state.dirty |= BLEND_DIRTY;
 
    renderer_validate(ctx->renderer, ctx->state.dirty,
index 45e5985c4bc69cd863f543dca1ba90d1789385e1..71491a5aa22e9f57d6cc507b73927338faf02394 100644 (file)
@@ -81,10 +81,12 @@ enum dirty_state {
    BLEND_DIRTY         = 1 << 0,
    FRAMEBUFFER_DIRTY   = 1 << 1,
    DEPTH_STENCIL_DIRTY = 1 << 2,
+   PAINT_DIRTY         = 1 << 3,
 
    ALL_DIRTY           = BLEND_DIRTY |
                          FRAMEBUFFER_DIRTY |
-                         DEPTH_STENCIL_DIRTY
+                         DEPTH_STENCIL_DIRTY |
+                         PAINT_DIRTY
 };
 
 struct vg_context