llvmpipe: Implement alpha_to_coverage for non-MSAA framebuffers.
authorSi Chen <sichen@vmware.com>
Wed, 18 Dec 2013 10:17:55 +0000 (02:17 -0800)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 7 Jan 2014 16:04:42 +0000 (16:04 +0000)
Implement Alpha to Coverage by discarding a fragment alpha component is
less than 0.5.  This is a joint work of Jose and Si.

Reviewed-by: José Fonseca <jfonseca@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/drivers/llvmpipe/lp_bld_blend.c
src/gallium/drivers/llvmpipe/lp_bld_blend.h
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 1dab28cedfbbc87f18ecb1834c4abcebef3b596f..1de43f77ee031b858a940a21c2af22d7932d6ae9 100644 (file)
 
 #include "gallivm/lp_bld_type.h"
 #include "gallivm/lp_bld_arit.h"
+#include "gallivm/lp_bld_const.h"
+#include "gallivm/lp_bld_logic.h"
+#include "gallivm/lp_bld_swizzle.h"
+#include "gallivm/lp_bld_flow.h"
+#include "gallivm/lp_bld_debug.h"
 
 #include "lp_bld_blend.h"
 
@@ -191,3 +196,28 @@ lp_build_blend(struct lp_build_context *bld,
    dst_term = lp_build_mul(bld, dst, dst_factor);
    return lp_build_blend_func(bld, func, src_term, dst_term);
 }
+
+void
+lp_build_alpha_to_coverage(struct gallivm_state *gallivm,
+                           struct lp_type type,
+                           struct lp_build_mask_context *mask,
+                           LLVMValueRef alpha,
+                           boolean do_branch)
+{
+   struct lp_build_context bld;
+   LLVMValueRef test;
+   LLVMValueRef alpha_ref_value;
+
+   lp_build_context_init(&bld, gallivm, type);
+
+   alpha_ref_value = lp_build_const_vec(gallivm, type, 0.5);
+
+   test = lp_build_cmp(&bld, PIPE_FUNC_GREATER, alpha, alpha_ref_value);
+
+   lp_build_name(test, "alpha_to_coverage");
+
+   lp_build_mask_update(mask, test);
+
+   if (do_branch)
+      lp_build_mask_check(mask);
+}
index 249a3454159f7b0649d423f2d0a51774bdb2e701..adfab85dc097491e636635b3c8eab99c233a6765 100644 (file)
@@ -38,6 +38,7 @@
 struct pipe_blend_state;
 struct lp_type;
 struct lp_build_context;
+struct lp_build_mask_context;
 
 
 LLVMValueRef
@@ -99,5 +100,11 @@ lp_build_blend_func_reverse(unsigned rgb_func,
 boolean
 lp_build_blend_func_commutative(unsigned func);
 
+void
+lp_build_alpha_to_coverage(struct gallivm_state *gallivm,
+                           struct lp_type type,
+                           struct lp_build_mask_context *mask,
+                           LLVMValueRef alpha,
+                           boolean do_branch);
 
 #endif /* !LP_BLD_BLEND_H */
index 2118c1ab4899db654565f494cd980cfb037237f4..eedafa368384bf2081a6abba8eda39a4435bde4d 100644 (file)
@@ -296,7 +296,9 @@ generate_fs_loop(struct gallivm_state *gallivm,
       assert(zs_format_desc);
 
       if (!shader->info.base.writes_z) {
-         if (key->alpha.enabled || shader->info.base.uses_kill) {
+         if (key->alpha.enabled ||
+             key->blend.alpha_to_coverage ||
+             shader->info.base.uses_kill) {
             /* With alpha test and kill, can do the depth test early
              * and hopefully eliminate some quads.  But need to do a
              * special deferred depth write once the final mask value
@@ -438,6 +440,21 @@ generate_fs_loop(struct gallivm_state *gallivm,
       }
    }
 
+   /* Emulate Alpha to Coverage with Alpha test */
+   if (key->blend.alpha_to_coverage) {
+      int color0 = find_output_by_semantic(&shader->info.base,
+                                           TGSI_SEMANTIC_COLOR,
+                                           0);
+
+      if (color0 != -1 && outputs[color0][3]) {
+         LLVMValueRef alpha = LLVMBuildLoad(builder, outputs[color0][3], "alpha");
+
+         lp_build_alpha_to_coverage(gallivm, type,
+                                    &mask, alpha,
+                                    (depth_mode & LATE_DEPTH_TEST) != 0);
+      }
+   }
+
    /* Late Z test */
    if (depth_mode & LATE_DEPTH_TEST) {
       int pos0 = find_output_by_semantic(&shader->info.base,
@@ -2426,6 +2443,9 @@ dump_fs_variant_key(const struct lp_fragment_shader_variant_key *key)
       debug_printf("blend.alpha_dst_factor = %s\n", util_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE));
    }
    debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask);
+   if (key->blend.alpha_to_coverage) {
+      debug_printf("blend.alpha_to_coverage is enabled\n");
+   }
    for (i = 0; i < key->nr_samplers; ++i) {
       const struct lp_static_sampler_state *sampler = &key->state[i].sampler_state;
       debug_printf("sampler[%u] = \n", i);
@@ -2521,6 +2541,7 @@ generate_variant(struct llvmpipe_context *lp,
          fullcolormask &&
          !key->stencil[0].enabled &&
          !key->alpha.enabled &&
+         !key->blend.alpha_to_coverage &&
          !key->depth.enabled &&
          !shader->info.base.uses_kill
       ? TRUE : FALSE;