ilo: update ilo_blend_state and related functions for Gen8
authorChia-I Wu <olvaffe@gmail.com>
Sun, 25 Jan 2015 10:20:43 +0000 (18:20 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 11 Feb 2015 23:56:12 +0000 (07:56 +0800)
src/gallium/drivers/ilo/ilo_builder_3d_bottom.h
src/gallium/drivers/ilo/ilo_builder_decode.c
src/gallium/drivers/ilo/ilo_render_gen6.c
src/gallium/drivers/ilo/ilo_render_gen7.c
src/gallium/drivers/ilo/ilo_state.h
src/gallium/drivers/ilo/ilo_state_3d_bottom.c

index fd82d04..14360af 100644 (file)
@@ -706,6 +706,44 @@ gen8_3DSTATE_PS_EXTRA(struct ilo_builder *builder,
 }
 
 static inline void
+gen8_3DSTATE_PS_BLEND(struct ilo_builder *builder,
+                      const struct ilo_blend_state *blend,
+                      const struct ilo_fb_state *fb,
+                      const struct ilo_dsa_state *dsa)
+{
+   const uint8_t cmd_len = 2;
+   uint32_t dw1, *dw;
+
+   ILO_DEV_ASSERT(builder->dev, 8, 8);
+
+   dw1 = 0;
+   if (blend->alpha_to_coverage && fb->num_samples > 1)
+      dw1 |= GEN8_PS_BLEND_DW1_ALPHA_TO_COVERAGE;
+
+   if (fb->state.nr_cbufs && fb->state.cbufs[0]) {
+      const struct ilo_fb_blend_caps *caps = &fb->blend_caps[0];
+
+      dw1 |= GEN8_PS_BLEND_DW1_WRITABLE_RT;
+      if (caps->can_blend) {
+         if (caps->dst_alpha_forced_one)
+            dw1 |= blend->dw_ps_blend_dst_alpha_forced_one;
+         else
+            dw1 |= blend->dw_ps_blend;
+      }
+
+      if (caps->can_alpha_test)
+         dw1 |= dsa->dw_ps_blend_alpha;
+   } else {
+      dw1 |= dsa->dw_ps_blend_alpha;
+   }
+
+   ilo_builder_batch_pointer(builder, cmd_len, &dw);
+
+   dw[0] = GEN8_RENDER_CMD(3D, 3DSTATE_PS_BLEND) | (cmd_len - 2);
+   dw[1] = dw1;
+}
+
+static inline void
 gen6_3DSTATE_CONSTANT_PS(struct ilo_builder *builder,
                          const uint32_t *bufs, const int *sizes,
                          int num_bufs)
@@ -1517,7 +1555,7 @@ gen6_BLEND_STATE(struct ilo_builder *builder,
    assert(num_targets <= 8);
 
    if (!num_targets) {
-      if (!dsa->dw_alpha)
+      if (!dsa->dw_blend_alpha)
          return 0;
       /* to be able to reference alpha func */
       num_targets = 1;
@@ -1548,13 +1586,13 @@ gen6_BLEND_STATE(struct ilo_builder *builder,
             dw[1] |= blend->dw_logicop;
 
          if (caps->can_alpha_test)
-            dw[1] |= dsa->dw_alpha;
+            dw[1] |= dsa->dw_blend_alpha;
       } else {
          dw[1] |= GEN6_RT_DW1_WRITE_DISABLE_A |
                   GEN6_RT_DW1_WRITE_DISABLE_R |
                   GEN6_RT_DW1_WRITE_DISABLE_G |
                   GEN6_RT_DW1_WRITE_DISABLE_B |
-                  dsa->dw_alpha;
+                  dsa->dw_blend_alpha;
       }
 
       /*
@@ -1575,4 +1613,65 @@ gen6_BLEND_STATE(struct ilo_builder *builder,
    return state_offset;
 }
 
+static inline uint32_t
+gen8_BLEND_STATE(struct ilo_builder *builder,
+                 const struct ilo_blend_state *blend,
+                 const struct ilo_fb_state *fb,
+                 const struct ilo_dsa_state *dsa)
+{
+   const int state_align = 64;
+   int state_len;
+   uint32_t state_offset, *dw;
+   unsigned i;
+
+   ILO_DEV_ASSERT(builder->dev, 8, 8);
+
+   assert(fb->state.nr_cbufs <= 8);
+
+   /* may need to reference alpha func even when there is no color buffer */
+   if (!fb->state.nr_cbufs && !dsa->dw_blend_alpha)
+      return 0;
+
+   state_len = 1 + 2 * fb->state.nr_cbufs;
+
+   state_offset = ilo_builder_dynamic_pointer(builder,
+         ILO_BUILDER_ITEM_BLEND, state_align, state_len, &dw);
+
+   dw[0] = blend->dw_shared;
+   if (fb->num_samples > 1)
+      dw[0] |= blend->dw_alpha_mod;
+   if (!fb->state.nr_cbufs || fb->blend_caps[0].can_alpha_test)
+      dw[0] |= dsa->dw_blend_alpha;
+   dw++;
+
+   for (i = 0; i < fb->state.nr_cbufs; i++) {
+      const struct ilo_fb_blend_caps *caps = &fb->blend_caps[i];
+      const struct ilo_blend_cso *cso = &blend->cso[i];
+
+      dw[0] = cso->payload[0];
+      dw[1] = cso->payload[1];
+
+      if (fb->state.cbufs[i]) {
+         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;
+         }
+
+         if (caps->can_logicop)
+            dw[1] |= blend->dw_logicop;
+      } else {
+         dw[0] |= GEN8_RT_DW0_WRITE_DISABLE_A |
+                  GEN8_RT_DW0_WRITE_DISABLE_R |
+                  GEN8_RT_DW0_WRITE_DISABLE_G |
+                  GEN8_RT_DW0_WRITE_DISABLE_B;
+      }
+
+      dw += 2;
+   }
+
+   return state_offset;
+}
+
 #endif /* ILO_BUILDER_3D_BOTTOM_H */
index d645f38..f518b49 100644 (file)
@@ -371,6 +371,11 @@ writer_decode_blend(const struct ilo_builder *builder,
    unsigned offset = item->offset;
    unsigned i;
 
+   if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
+      writer_dw(builder, which, offset, 0, "BLEND\n");
+      offset += 4;
+   }
+
    for (i = 0; i < count; i++) {
       writer_dw(builder, which, offset, 0, "BLEND%d\n", i);
       writer_dw(builder, which, offset, 1, "BLEND%d\n", i);
index 3f0aa7c..5e8cb33 100644 (file)
@@ -702,7 +702,7 @@ gen6_draw_wm(struct ilo_render *r,
    if (DIRTY(FS) || DIRTY(BLEND) || DIRTY(DSA) ||
        DIRTY(RASTERIZER) || r->instruction_bo_changed) {
       const bool dual_blend = vec->blend->dual_blend;
-      const bool cc_may_kill = (vec->dsa->dw_alpha ||
+      const bool cc_may_kill = (vec->dsa->dw_blend_alpha ||
                                 vec->blend->alpha_to_coverage);
 
       if (ilo_dev_gen(r->dev) == ILO_GEN(6) && r->hw_ctx_changed)
index 5fe6995..1de6e2b 100644 (file)
@@ -516,7 +516,7 @@ gen7_draw_wm(struct ilo_render *r,
 {
    /* 3DSTATE_WM */
    if (DIRTY(FS) || DIRTY(BLEND) || DIRTY(DSA) || DIRTY(RASTERIZER)) {
-      const bool cc_may_kill = (vec->dsa->dw_alpha ||
+      const bool cc_may_kill = (vec->dsa->dw_blend_alpha ||
                                 vec->blend->alpha_to_coverage);
 
       gen7_3DSTATE_WM(r->builder, vec->fs, vec->rasterizer, cc_may_kill);
index e935e5d..737f50e 100644 (file)
@@ -250,7 +250,8 @@ struct ilo_dsa_state {
    /* DEPTH_STENCIL_STATE or Gen8+ 3DSTATE_WM_DEPTH_STENCIL */
    uint32_t payload[3];
 
-   uint32_t dw_alpha;
+   uint32_t dw_blend_alpha;
+   uint32_t dw_ps_blend_alpha;
    ubyte alpha_ref;
 };
 
@@ -271,6 +272,10 @@ struct ilo_blend_state {
    uint32_t dw_shared;
    uint32_t dw_alpha_mod;
    uint32_t dw_logicop;
+
+   /* a part of 3DSTATE_PS_BLEND */
+   uint32_t dw_ps_blend;
+   uint32_t dw_ps_blend_dst_alpha_forced_one;
 };
 
 struct ilo_sampler_cso {
index b309c94..5ad88de 100644 (file)
@@ -1529,6 +1529,49 @@ blend_get_rt_blend_enable_gen6(const struct ilo_dev_info *dev,
    return dw;
 }
 
+static uint32_t
+blend_get_rt_blend_enable_gen8(const struct ilo_dev_info *dev,
+                               const struct pipe_rt_blend_state *rt,
+                               bool dst_alpha_forced_one,
+                               bool *independent_alpha)
+{
+   int rgb_src, rgb_dst, a_src, a_dst;
+   uint32_t dw;
+
+   ILO_DEV_ASSERT(dev, 8, 8);
+
+   if (!rt->blend_enable) {
+      *independent_alpha = false;
+      return 0;
+   }
+
+   rgb_src = gen6_translate_pipe_blendfactor(rt->rgb_src_factor);
+   rgb_dst = gen6_translate_pipe_blendfactor(rt->rgb_dst_factor);
+   a_src = gen6_translate_pipe_blendfactor(rt->alpha_src_factor);
+   a_dst = gen6_translate_pipe_blendfactor(rt->alpha_dst_factor);
+
+   if (dst_alpha_forced_one) {
+      rgb_src = gen6_blend_factor_dst_alpha_forced_one(rgb_src);
+      rgb_dst = gen6_blend_factor_dst_alpha_forced_one(rgb_dst);
+      a_src = gen6_blend_factor_dst_alpha_forced_one(a_src);
+      a_dst = gen6_blend_factor_dst_alpha_forced_one(a_dst);
+   }
+
+   dw = GEN8_RT_DW0_BLEND_ENABLE |
+        rgb_src << 26 |
+        rgb_dst << 21 |
+        gen6_translate_pipe_blend(rt->rgb_func) << 18 |
+        a_src << 13 |
+        a_dst << 8 |
+        gen6_translate_pipe_blend(rt->alpha_func) << 5;
+
+   *independent_alpha = (rt->rgb_func != rt->alpha_func ||
+                         rgb_src != a_src ||
+                         rgb_dst != a_dst);
+
+   return dw;
+}
+
 static void
 blend_init_cso_gen6(const struct ilo_dev_info *dev,
                     const struct pipe_blend_state *state,
@@ -1573,6 +1616,49 @@ blend_init_cso_gen6(const struct ilo_dev_info *dev,
    }
 }
 
+static bool
+blend_init_cso_gen8(const struct ilo_dev_info *dev,
+                    const struct pipe_blend_state *state,
+                    struct ilo_blend_state *blend,
+                    unsigned index)
+{
+   const struct pipe_rt_blend_state *rt = &state->rt[index];
+   struct ilo_blend_cso *cso = &blend->cso[index];
+   bool independent_alpha = false;
+
+   ILO_DEV_ASSERT(dev, 8, 8);
+
+   cso->payload[0] = 0;
+   cso->payload[1] = GEN8_RT_DW1_COLORCLAMP_RTFORMAT |
+                     GEN8_RT_DW1_PRE_BLEND_CLAMP |
+                     GEN8_RT_DW1_POST_BLEND_CLAMP;
+
+   if (!(rt->colormask & PIPE_MASK_A))
+      cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_A;
+   if (!(rt->colormask & PIPE_MASK_R))
+      cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_R;
+   if (!(rt->colormask & PIPE_MASK_G))
+      cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_G;
+   if (!(rt->colormask & PIPE_MASK_B))
+      cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_B;
+
+   if (state->logicop_enable) {
+      cso->dw_blend = 0;
+      cso->dw_blend_dst_alpha_forced_one = 0;
+   } else {
+      bool tmp[2];
+
+      cso->dw_blend = blend_get_rt_blend_enable_gen8(dev, rt, false, &tmp[0]);
+      cso->dw_blend_dst_alpha_forced_one =
+         blend_get_rt_blend_enable_gen8(dev, rt, true, &tmp[1]);
+
+      if (tmp[0] || tmp[1])
+         independent_alpha = true;
+   }
+
+   return independent_alpha;
+}
+
 static uint32_t
 blend_get_logicop_enable_gen6(const struct ilo_dev_info *dev,
                               const struct pipe_blend_state *state)
@@ -1587,6 +1673,19 @@ blend_get_logicop_enable_gen6(const struct ilo_dev_info *dev,
 }
 
 static uint32_t
+blend_get_logicop_enable_gen8(const struct ilo_dev_info *dev,
+                              const struct pipe_blend_state *state)
+{
+   ILO_DEV_ASSERT(dev, 8, 8);
+
+   if (!state->logicop_enable)
+      return 0;
+
+   return GEN8_RT_DW1_LOGICOP_ENABLE |
+          gen6_translate_pipe_logicop(state->logicop_func) << 27;
+}
+
+static uint32_t
 blend_get_alpha_mod_gen6(const struct ilo_dev_info *dev,
                          const struct pipe_blend_state *state,
                          bool dual_blend)
@@ -1612,6 +1711,54 @@ blend_get_alpha_mod_gen6(const struct ilo_dev_info *dev,
    return dw;
 }
 
+static uint32_t
+blend_get_alpha_mod_gen8(const struct ilo_dev_info *dev,
+                         const struct pipe_blend_state *state,
+                         bool dual_blend)
+{
+   uint32_t dw = 0;
+
+   ILO_DEV_ASSERT(dev, 8, 8);
+
+   if (state->alpha_to_coverage) {
+      dw |= GEN8_BLEND_DW0_ALPHA_TO_COVERAGE |
+            GEN8_BLEND_DW0_ALPHA_TO_COVERAGE_DITHER;
+   }
+
+   if (state->alpha_to_one && !dual_blend)
+      dw |= GEN8_BLEND_DW0_ALPHA_TO_ONE;
+
+   return dw;
+}
+
+static uint32_t
+blend_get_ps_blend_gen8(const struct ilo_dev_info *dev, uint32_t rt_dw0)
+{
+   int rgb_src, rgb_dst, a_src, a_dst;
+   uint32_t dw;
+
+   ILO_DEV_ASSERT(dev, 8, 8);
+
+   if (!(rt_dw0 & GEN8_RT_DW0_BLEND_ENABLE))
+      return 0;
+
+   a_src = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_SRC_ALPHA_FACTOR);
+   a_dst = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_DST_ALPHA_FACTOR);
+   rgb_src = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_SRC_COLOR_FACTOR);
+   rgb_dst = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_DST_COLOR_FACTOR);
+
+   dw = GEN8_PS_BLEND_DW1_BLEND_ENABLE;
+   dw |= GEN_SHIFT32(a_src, GEN8_PS_BLEND_DW1_SRC_ALPHA_FACTOR);
+   dw |= GEN_SHIFT32(a_dst, GEN8_PS_BLEND_DW1_DST_ALPHA_FACTOR);
+   dw |= GEN_SHIFT32(rgb_src, GEN8_PS_BLEND_DW1_SRC_COLOR_FACTOR);
+   dw |= GEN_SHIFT32(rgb_dst, GEN8_PS_BLEND_DW1_DST_COLOR_FACTOR);
+
+   if (a_src != rgb_src || a_dst != rgb_dst)
+      dw |= GEN8_PS_BLEND_DW1_INDEPENDENT_ALPHA_ENABLE;
+
+   return dw;
+}
+
 void
 ilo_gpe_init_blend(const struct ilo_dev_info *dev,
                    const struct pipe_blend_state *state,
@@ -1619,25 +1766,57 @@ ilo_gpe_init_blend(const struct ilo_dev_info *dev,
 {
    unsigned i;
 
-   ILO_DEV_ASSERT(dev, 6, 7.5);
+   ILO_DEV_ASSERT(dev, 6, 8);
 
    blend->dual_blend = (util_blend_state_is_dual(state, 0) &&
                         state->rt[0].blend_enable &&
                         !state->logicop_enable);
    blend->alpha_to_coverage = state->alpha_to_coverage;
 
-   blend->dw_alpha_mod =
-      blend_get_alpha_mod_gen6(dev, state, blend->dual_blend);
-   blend->dw_logicop = blend_get_logicop_enable_gen6(dev, state);
-   blend->dw_shared = (state->dither) ? GEN6_RT_DW1_DITHER_ENABLE : 0;
-
-   blend_init_cso_gen6(dev, state, blend, 0);
-   if (state->independent_blend_enable) {
-      for (i = 1; i < Elements(blend->cso); i++)
-         blend_init_cso_gen6(dev, state, blend, i);
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      bool independent_alpha;
+
+      blend->dw_alpha_mod =
+         blend_get_alpha_mod_gen8(dev, state, blend->dual_blend);
+      blend->dw_logicop = blend_get_logicop_enable_gen8(dev, state);
+      blend->dw_shared = (state->dither) ? GEN8_BLEND_DW0_DITHER_ENABLE : 0;
+
+      independent_alpha = blend_init_cso_gen8(dev, state, blend, 0);
+      if (independent_alpha)
+         blend->dw_shared |= GEN8_BLEND_DW0_INDEPENDENT_ALPHA_ENABLE;
+
+      blend->dw_ps_blend = blend_get_ps_blend_gen8(dev,
+            blend->cso[0].dw_blend);
+      blend->dw_ps_blend_dst_alpha_forced_one = blend_get_ps_blend_gen8(dev,
+            blend->cso[0].dw_blend_dst_alpha_forced_one);
+
+      if (state->independent_blend_enable) {
+         for (i = 1; i < Elements(blend->cso); i++) {
+            independent_alpha = blend_init_cso_gen8(dev, state, blend, i);
+            if (independent_alpha)
+               blend->dw_shared |= GEN8_BLEND_DW0_INDEPENDENT_ALPHA_ENABLE;
+         }
+      } else {
+         for (i = 1; i < Elements(blend->cso); i++)
+            blend->cso[i] = blend->cso[0];
+      }
    } else {
-      for (i = 1; i < Elements(blend->cso); i++)
-         blend->cso[i] = blend->cso[0];
+      blend->dw_alpha_mod =
+         blend_get_alpha_mod_gen6(dev, state, blend->dual_blend);
+      blend->dw_logicop = blend_get_logicop_enable_gen6(dev, state);
+      blend->dw_shared = (state->dither) ? GEN6_RT_DW1_DITHER_ENABLE : 0;
+
+      blend->dw_ps_blend = 0;
+      blend->dw_ps_blend_dst_alpha_forced_one = 0;
+
+      blend_init_cso_gen6(dev, state, blend, 0);
+      if (state->independent_blend_enable) {
+         for (i = 1; i < Elements(blend->cso); i++)
+            blend_init_cso_gen6(dev, state, blend, i);
+      } else {
+         for (i = 1; i < Elements(blend->cso); i++)
+            blend->cso[i] = blend->cso[0];
+      }
    }
 }
 
@@ -1843,7 +2022,10 @@ ilo_gpe_init_dsa(const struct ilo_dev_info *dev,
                      state->stencil[1].valuemask << 8 |
                      state->stencil[1].writemask;
 
-   dsa->dw_alpha = dsa_get_alpha_enable_gen6(dev, &state->alpha);
+   dsa->dw_blend_alpha = dsa_get_alpha_enable_gen6(dev, &state->alpha);
+   dsa->dw_ps_blend_alpha = (state->alpha.enabled) ?
+      GEN8_PS_BLEND_DW1_ALPHA_TEST_ENABLE : 0;
+
    dsa->alpha_ref = float_to_ubyte(state->alpha.ref_value);
 }
 
@@ -1916,10 +2098,16 @@ fb_set_blend_caps(const struct ilo_dev_info *dev,
     *
     *     "Logic Ops are only supported on *_UNORM surfaces (excluding _SRGB
     *      variants), otherwise Logic Ops must be DISABLED."
+    *
+    * According to the classic driver, this is lifted on Gen8+.
     */
-   caps->can_logicop = (ch >= 0 && desc->channel[ch].normalized &&
-                        desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED &&
-                        desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB);
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      caps->can_logicop = true;
+   } else {
+      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);