ilo: derive fb blending caps at bind time
authorChia-I Wu <olvaffe@gmail.com>
Mon, 10 Nov 2014 05:44:45 +0000 (13:44 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Mon, 10 Nov 2014 07:46:31 +0000 (15:46 +0800)
Derive whether a RT supports blending, logicop, and the like when
set_framebuffer_state() is called.  This enables us to simplify
gen6_BLEND_STATE().

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
src/gallium/drivers/ilo/ilo_builder_3d_bottom.h
src/gallium/drivers/ilo/ilo_state.h
src/gallium/drivers/ilo/ilo_state_3d_bottom.c

index 456a494d12be7fcff8fd96055cf39d2e051cd64b..2397a2c7943abcc47efce6d95225144d29a0802d 100644 (file)
@@ -1224,71 +1224,35 @@ gen6_BLEND_STATE(struct ilo_builder *builder,
          ILO_BUILDER_ITEM_BLEND, state_align, state_len, &dw);
 
    for (i = 0; i < num_targets; i++) {
-      const unsigned idx = (blend->independent_blend_enable) ? i : 0;
-      const struct ilo_blend_cso *cso = &blend->cso[idx];
-      const int num_samples = fb->num_samples;
-      const struct util_format_description *format_desc =
-         (idx < fb->state.nr_cbufs && fb->state.cbufs[idx]) ?
-         util_format_description(fb->state.cbufs[idx]->format) : NULL;
-      bool rt_is_unorm, rt_is_pure_integer, rt_dst_alpha_forced_one;
-
-      rt_is_unorm = true;
-      rt_is_pure_integer = false;
-      rt_dst_alpha_forced_one = false;
-
-      if (format_desc) {
-         int ch;
-
-         switch (format_desc->format) {
-         case PIPE_FORMAT_B8G8R8X8_UNORM:
-            /* force alpha to one when the HW format has alpha */
-            assert(ilo_translate_render_format(builder->dev,
-                     PIPE_FORMAT_B8G8R8X8_UNORM) ==
-                  GEN6_FORMAT_B8G8R8A8_UNORM);
-            rt_dst_alpha_forced_one = true;
-            break;
-         default:
-            break;
-         }
+      const struct ilo_blend_cso *cso =
+         &blend->cso[(blend->independent_blend_enable) ? i : 0];
 
-         for (ch = 0; ch < 4; ch++) {
-            if (format_desc->channel[ch].type == UTIL_FORMAT_TYPE_VOID)
-               continue;
+      dw[0] = cso->payload[0];
+      dw[1] = cso->payload[1];
 
-            if (format_desc->channel[ch].pure_integer) {
-               rt_is_unorm = false;
-               rt_is_pure_integer = true;
-               break;
-            }
+      if (i < fb->state.nr_cbufs && fb->state.cbufs[i]) {
+         const struct ilo_fb_blend_caps *caps = &fb->blend_caps[i];
 
-            if (!format_desc->channel[ch].normalized ||
-                format_desc->channel[ch].type != UTIL_FORMAT_TYPE_UNSIGNED)
-               rt_is_unorm = false;
+         if (caps->can_blend) {
+            if (caps->dst_alpha_forced_one)
+               dw[0] |= cso->dw_blend_dst_alpha_forced_one;
+            else
+               dw[0] |= cso->dw_blend;
          }
-      }
 
-      dw[0] = cso->payload[0];
-      dw[1] = cso->payload[1];
-
-      if (!rt_is_pure_integer) {
-         if (rt_dst_alpha_forced_one)
-            dw[0] |= cso->dw_blend_dst_alpha_forced_one;
-         else
-            dw[0] |= cso->dw_blend;
+         if (caps->can_logicop)
+            dw[1] |= cso->dw_logicop;
+
+         if (caps->can_alpha_test)
+            dw[1] |= dsa->dw_alpha;
+      } else {
+         dw[1] |= GEN6_BLEND_DW1_WRITE_DISABLE_A |
+                  GEN6_BLEND_DW1_WRITE_DISABLE_R |
+                  GEN6_BLEND_DW1_WRITE_DISABLE_G |
+                  GEN6_BLEND_DW1_WRITE_DISABLE_B |
+                  dsa->dw_alpha;
       }
 
-      /*
-       * From the Sandy Bridge PRM, volume 2 part 1, page 365:
-       *
-       *     "Logic Ops are only supported on *_UNORM surfaces (excluding
-       *      _SRGB variants), otherwise Logic Ops must be DISABLED."
-       *
-       * Since logicop is ignored for non-UNORM color buffers, no special care
-       * is needed.
-       */
-      if (rt_is_unorm)
-         dw[1] |= cso->dw_logicop;
-
       /*
        * From the Sandy Bridge PRM, volume 2 part 1, page 356:
        *
@@ -1298,18 +1262,9 @@ gen6_BLEND_STATE(struct ilo_builder *builder,
        * There is no such limitation on GEN7, or for AlphaToOne.  But GL
        * requires that anyway.
        */
-      if (num_samples > 1)
+      if (fb->num_samples > 1)
          dw[1] |= cso->dw_alpha_mod;
 
-      /*
-       * From the Sandy Bridge PRM, volume 2 part 1, page 382:
-       *
-       *     "Alpha Test can only be enabled if Pixel Shader outputs a float
-       *      alpha value."
-       */
-      if (!rt_is_pure_integer)
-         dw[1] |= dsa->dw_alpha;
-
       dw += 2;
    }
 
index 6f544e1f7885dab3cda09aa65898786cdf8bd443..afe27847a9383a9f67e992d9eb8ddb93813238cc 100644 (file)
@@ -347,6 +347,13 @@ struct ilo_fb_state {
    struct ilo_view_surface null_rt;
    struct ilo_zs_surface null_zs;
 
+   struct ilo_fb_blend_caps {
+      bool can_logicop;
+      bool can_blend;
+      bool can_alpha_test;
+      bool dst_alpha_forced_one;
+   } blend_caps[PIPE_MAX_COLOR_BUFS];
+
    unsigned num_samples;
 };
 
index a390124c2e985318be40b7f95125d7c70022f13d..822f8a46f68db1622025a7636c550f327bd8c4fd 100644 (file)
@@ -1540,13 +1540,70 @@ ilo_gpe_set_scissor_null(const struct ilo_dev_info *dev,
    }
 }
 
+static void
+fb_set_blend_caps(const struct ilo_dev_info *dev,
+                  enum pipe_format format,
+                  struct ilo_fb_blend_caps *caps)
+{
+   const struct util_format_description *desc =
+      util_format_description(format);
+   const int ch = util_format_get_first_non_void_channel(format);
+
+   memset(caps, 0, sizeof(*caps));
+
+   if (format == PIPE_FORMAT_NONE || desc->is_mixed)
+      return;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 365:
+    *
+    *     "Logic Ops are only supported on *_UNORM surfaces (excluding _SRGB
+    *      variants), otherwise Logic Ops must be DISABLED."
+    */
+   caps->can_logicop = (ch >= 0 && desc->channel[ch].normalized &&
+                        desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED &&
+                        desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB);
+
+   /* no blending for pure integer formats */
+   caps->can_blend = !util_format_is_pure_integer(format);
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 382:
+    *
+    *     "Alpha Test can only be enabled if Pixel Shader outputs a float
+    *      alpha value."
+    */
+   caps->can_alpha_test = !util_format_is_pure_integer(format);
+
+   caps->dst_alpha_forced_one =
+      (ilo_translate_render_format(dev, format) !=
+       ilo_translate_color_format(dev, format));
+
+   /* sanity check */
+   if (caps->dst_alpha_forced_one) {
+      enum pipe_format render_format;
+
+      switch (format) {
+      case PIPE_FORMAT_B8G8R8X8_UNORM:
+         render_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+         break;
+      default:
+         render_format = PIPE_FORMAT_NONE;
+         break;
+      }
+
+      assert(ilo_translate_render_format(dev, format) ==
+             ilo_translate_color_format(dev, render_format));
+   }
+}
+
 void
 ilo_gpe_set_fb(const struct ilo_dev_info *dev,
                const struct pipe_framebuffer_state *state,
                struct ilo_fb_state *fb)
 {
-   const struct pipe_surface *first;
-   unsigned first_idx;
+   const struct pipe_surface *first_surf = NULL;
+   int i;
 
    ILO_DEV_ASSERT(dev, 6, 7.5);
 
@@ -1557,17 +1614,21 @@ ilo_gpe_set_fb(const struct ilo_dev_info *dev,
          (state->height) ? state->height : 1,
          1, 0, &fb->null_rt);
 
-   first = NULL;
-   for (first_idx = 0; first_idx < state->nr_cbufs; first_idx++) {
-      if (state->cbufs[first_idx]) {
-         first = state->cbufs[first_idx];
-         break;
+   for (i = 0; i < state->nr_cbufs; i++) {
+      if (state->cbufs[i]) {
+         fb_set_blend_caps(dev, state->cbufs[i]->format, &fb->blend_caps[i]);
+
+         if (!first_surf)
+            first_surf = state->cbufs[i];
+      } else {
+         fb_set_blend_caps(dev, PIPE_FORMAT_NONE, &fb->blend_caps[i]);
       }
    }
-   if (!first)
-      first = state->zsbuf;
 
-   fb->num_samples = (first) ? first->texture->nr_samples : 1;
+   if (!first_surf && state->zsbuf)
+      first_surf = state->zsbuf;
+
+   fb->num_samples = (first_surf) ? first_surf->texture->nr_samples : 1;
    if (!fb->num_samples)
       fb->num_samples = 1;