[Mesa-dev] [PATCH 4/4] svga: adjust blending terms according to pipe_surface::alpha_one

Brian Paul brianp at vmware.com
Fri Jun 24 02:07:54 UTC 2016


This is needed when we're using an RGBA surface but it should act as if
it were RGB (A=1).
---
 src/gallium/drivers/svga/svga_context.h    |  3 +-
 src/gallium/drivers/svga/svga_pipe_blend.c | 90 ++++++++++++++++++++++--------
 src/gallium/drivers/svga/svga_state_rss.c  |  9 ++-
 3 files changed, 76 insertions(+), 26 deletions(-)

diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index 391a93a..1a80db9 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -116,7 +116,7 @@ struct svga_blend_state {
       uint8_t blendeq_alpha;
    } rt[PIPE_MAX_COLOR_BUFS];
 
-   SVGA3dBlendStateId id;  /**< vgpu10 */
+   SVGA3dBlendStateId id[2];  /**< vgpu10 */
 };
 
 struct svga_depth_stencil_state {
@@ -634,6 +634,7 @@ void svga_init_stream_output_functions( struct svga_context *svga );
 enum pipe_error
 svga_bind_blend_state_object(struct svga_context *svga,
                              struct svga_blend_state *bs,
+                             boolean have_dst_alpha,
                              const float blend_factor[4],
                              unsigned sample_mask);
 
diff --git a/src/gallium/drivers/svga/svga_pipe_blend.c b/src/gallium/drivers/svga/svga_pipe_blend.c
index e10bc56..bae2d8a 100644
--- a/src/gallium/drivers/svga/svga_pipe_blend.c
+++ b/src/gallium/drivers/svga/svga_pipe_blend.c
@@ -89,13 +89,53 @@ svga_translate_blend_func(unsigned mode)
 
 
 /**
+ * If the destination color buffer does not have an alpha channel, reading
+ * from it should return 1.0.  But if the user requested an RGB surface and
+ * we actually allocated an RGBA surface, there actually is an alpha channel.
+ * But we have to act as if the alpha channel wasn't there.  This function
+ * adjusts the blending mode to use 0 or 1 instead of DESTALPHA or
+ * INVDESTALPHA.
+ */
+static unsigned
+adjust_color(unsigned mode, boolean have_dst_alpha)
+{
+   if (!have_dst_alpha) {
+      if (mode == SVGA3D_BLENDOP_DESTALPHA)
+         return SVGA3D_BLENDOP_ONE;
+      if (mode == SVGA3D_BLENDOP_INVDESTALPHA)
+         return SVGA3D_BLENDOP_ZERO;
+   }
+   return mode;
+}
+
+
+/**
+ * As above, but for the blend equation's alpha terms.
+ */
+static unsigned
+adjust_alpha(unsigned mode, boolean have_dst_alpha)
+{
+   if (!have_dst_alpha) {
+      if (mode == SVGA3D_BLENDOP_DESTALPHA ||
+          mode == SVGA3D_BLENDOP_DESTCOLOR)
+         return SVGA3D_BLENDOP_ONE;
+      if (mode == SVGA3D_BLENDOP_INVDESTALPHA ||
+          mode == SVGA3D_BLENDOP_INVDESTCOLOR)
+         return SVGA3D_BLENDOP_ZERO;
+   }
+   return mode;
+}
+
+
+/**
  * Define a vgpu10 blend state object for the given svga blend state using
  * the given ID number.
  */
 static enum pipe_error
 define_blend_state_object(struct svga_context *svga,
                           struct svga_blend_state *bs,
-                          unsigned id)
+                          unsigned id,
+                          boolean have_dst_alpha)
 {
    SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
    int i;
@@ -104,11 +144,13 @@ define_blend_state_object(struct svga_context *svga,
 
    for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) {
       perRT[i].blendEnable = bs->rt[i].blend_enable;
-      perRT[i].srcBlend = bs->rt[i].srcblend;
-      perRT[i].destBlend = bs->rt[i].dstblend;
+      perRT[i].srcBlend = adjust_color(bs->rt[i].srcblend, have_dst_alpha);
+      perRT[i].destBlend = adjust_color(bs->rt[i].dstblend, have_dst_alpha);
       perRT[i].blendOp = bs->rt[i].blendeq;
-      perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha;
-      perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;
+      perRT[i].srcBlendAlpha =
+         adjust_alpha(bs->rt[i].srcblend_alpha, have_dst_alpha);
+      perRT[i].destBlendAlpha =
+         adjust_alpha(bs->rt[i].dstblend_alpha, have_dst_alpha);
       perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;
       perRT[i].renderTargetWriteMask = bs->rt[i].writemask;
       perRT[i].logicOpEnable = 0;
@@ -131,6 +173,7 @@ define_blend_state_object(struct svga_context *svga,
 enum pipe_error
 svga_bind_blend_state_object(struct svga_context *svga,
                              struct svga_blend_state *bs,
+                             boolean have_dst_alpha,
                              const float blend_factor[4],
                              unsigned sample_mask)
 {
@@ -139,15 +182,15 @@ svga_bind_blend_state_object(struct svga_context *svga,
 
    assert(svga_have_vgpu10(svga));
 
-   if (bs->id != SVGA3D_INVALID_ID) {
-      obj_id = bs->id;
+   if (bs->id[have_dst_alpha] != SVGA3D_INVALID_ID) {
+      obj_id = bs->id[have_dst_alpha];
    }
    else {
       /* create blend state object */
       obj_id = util_bitmask_add(svga->blend_object_id_bm);
-      bs->id = obj_id;
+      bs->id[have_dst_alpha] = obj_id;
 
-      ret = define_blend_state_object(svga, bs, obj_id);
+      ret = define_blend_state_object(svga, bs, obj_id, have_dst_alpha);
       if (ret != PIPE_OK) {
          util_bitmask_clear(svga->blend_object_id_bm, obj_id);
          return ret;
@@ -356,7 +399,7 @@ svga_create_blend_state(struct pipe_context *pipe,
    blend->alpha_to_coverage = templ->alpha_to_coverage;
 
    /* blend state objects will be created on demand */
-   blend->id = SVGA3D_INVALID_ID;
+   blend->id[0] = blend->id[1] = SVGA3D_INVALID_ID;
 
    svga->hud.num_blend_objects++;
 
@@ -378,22 +421,25 @@ static void svga_delete_blend_state(struct pipe_context *pipe,
 {
    struct svga_context *svga = svga_context(pipe);
    struct svga_blend_state *bs = (struct svga_blend_state *) blend;
+   int i;
 
-   if (bs->id != SVGA3D_INVALID_ID) {
-      enum pipe_error ret;
+   for (i = 0; i < 2; i++) {
+      if (bs->id[i] != SVGA3D_INVALID_ID) {
+         enum pipe_error ret;
 
-      ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
-      if (ret != PIPE_OK) {
-         svga_context_flush(svga, NULL);
-         ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
-         assert(ret == PIPE_OK);
-      }
+         ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id[i]);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id[i]);
+            assert(ret == PIPE_OK);
+         }
 
-      if (bs->id == svga->state.hw_draw.blend_id)
-         svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
+         if (bs->id[i] == svga->state.hw_draw.blend_id)
+            svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
 
-      util_bitmask_clear(svga->blend_object_id_bm, bs->id);
-      bs->id = SVGA3D_INVALID_ID;
+         util_bitmask_clear(svga->blend_object_id_bm, bs->id[i]);
+         bs->id[i] = SVGA3D_INVALID_ID;
+      }
    }
 
    FREE(blend);
diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c
index 1540899..335b82b 100644
--- a/src/gallium/drivers/svga/svga_state_rss.c
+++ b/src/gallium/drivers/svga/svga_state_rss.c
@@ -346,6 +346,9 @@ emit_rss_vgpu10(struct svga_context *svga, unsigned dirty)
    if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR | SVGA_NEW_FRAME_BUFFER)) {
       struct svga_blend_state *curr;
       float blend_factor[4];
+      boolean have_dst_alpha =
+         svga->curr.framebuffer.cbufs[0] != NULL &&
+         !svga->curr.framebuffer.cbufs[0]->alpha_one;
 
       if (svga_has_any_integer_cbufs(svga)) {
          /* Blending is not supported in integer-valued render targets. */
@@ -374,19 +377,19 @@ emit_rss_vgpu10(struct svga_context *svga, unsigned dirty)
       }
 
       /* Set/bind the blend state object */
-      if (svga->state.hw_draw.blend_id != curr->id ||
+      if (svga->state.hw_draw.blend_id != curr->id[have_dst_alpha] ||
           svga->state.hw_draw.blend_factor[0] != blend_factor[0] ||
           svga->state.hw_draw.blend_factor[1] != blend_factor[1] ||
           svga->state.hw_draw.blend_factor[2] != blend_factor[2] ||
           svga->state.hw_draw.blend_factor[3] != blend_factor[3] ||
           svga->state.hw_draw.blend_sample_mask != svga->curr.sample_mask) {
-         ret = svga_bind_blend_state_object(svga, curr,
+         ret = svga_bind_blend_state_object(svga, curr, have_dst_alpha,
                                             blend_factor,
                                             svga->curr.sample_mask);
          if (ret != PIPE_OK)
             return ret;
 
-         svga->state.hw_draw.blend_id = curr->id;
+         svga->state.hw_draw.blend_id = curr->id[have_dst_alpha];
          svga->state.hw_draw.blend_factor[0] = blend_factor[0];
          svga->state.hw_draw.blend_factor[1] = blend_factor[1];
          svga->state.hw_draw.blend_factor[2] = blend_factor[2];
-- 
1.9.1



More information about the mesa-dev mailing list