llvmpipe: Fix alpha testing precision on rgba8 formats.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 22 May 2012 15:04:33 +0000 (16:04 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 22 May 2012 18:23:49 +0000 (19:23 +0100)
This is a long standing problem, that recently surfaced with the change
to enable perspective correct color interpolation.

A fix for all possible formats is left to the future.

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/drivers/llvmpipe/lp_bld_alpha.c
src/gallium/drivers/llvmpipe/lp_bld_alpha.h
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 518969c3202bb8d23b08085a2fec5beff3f8976f..6e2d0376dcded7c676c7a8c133e188b64f09c309 100644 (file)
  */
 
 #include "pipe/p_state.h"
+#include "util/u_format.h"
 
 #include "gallivm/lp_bld_type.h"
 #include "gallivm/lp_bld_const.h"
+#include "gallivm/lp_bld_arit.h"
+#include "gallivm/lp_bld_conv.h"
 #include "gallivm/lp_bld_logic.h"
 #include "gallivm/lp_bld_flow.h"
 #include "gallivm/lp_bld_debug.h"
@@ -46,6 +49,7 @@ void
 lp_build_alpha_test(struct gallivm_state *gallivm,
                     unsigned func,
                     struct lp_type type,
+                    const struct util_format_description *cbuf_format_desc,
                     struct lp_build_mask_context *mask,
                     LLVMValueRef alpha,
                     LLVMValueRef ref,
@@ -56,6 +60,30 @@ lp_build_alpha_test(struct gallivm_state *gallivm,
 
    lp_build_context_init(&bld, gallivm, type);
 
+   /*
+    * Alpha testing needs to be done in the color buffer precision.
+    *
+    * TODO: Ideally, instead of duplicating the color conversion code, we would do
+    * alpha testing after converting the output colors, but that's not very
+    * convenient, because it needs to be done before depth testing.  Hopefully
+    * LLVM will detect and remove the duplicate expression.
+    *
+    * FIXME: This should be generalized to formats other than rgba8 variants.
+    */
+   if (type.floating &&
+       util_format_is_rgba8_variant(cbuf_format_desc)) {
+      const unsigned dst_width = 8;
+
+      alpha = lp_build_clamp(&bld, alpha, bld.zero, bld.one);
+      ref   = lp_build_clamp(&bld, ref,   bld.zero, bld.one);
+
+      alpha = lp_build_clamped_float_to_unsigned_norm(gallivm, type, dst_width, alpha);
+      ref   = lp_build_clamped_float_to_unsigned_norm(gallivm, type, dst_width, ref);
+
+      type.floating = 0;
+      lp_build_context_init(&bld, gallivm, type);
+   }
+
    test = lp_build_cmp(&bld, func, alpha, ref);
 
    lp_build_name(test, "alpha_mask");
index 06206a24d835d5a934965fd259f8f863c5f7bfee..15f1284c5e1f5937f59b9a2e95935ca3048d406e 100644 (file)
@@ -39,6 +39,7 @@
 #include "gallivm/lp_bld.h"
 
 struct pipe_alpha_state;
+struct util_format_description;
 struct gallivm_state;
 struct lp_type;
 struct lp_build_mask_context;
@@ -48,6 +49,7 @@ void
 lp_build_alpha_test(struct gallivm_state *gallivm,
                     unsigned func,
                     struct lp_type type,
+                    const struct util_format_description *cbuf_format_desc,
                     struct lp_build_mask_context *mask,
                     LLVMValueRef alpha,
                     LLVMValueRef ref,
index 11a3871c40817c20f65a809054bedee511fa4a4c..0bdc17fb3e1017631f97f1e99071a85cb75fd049 100644 (file)
@@ -345,13 +345,16 @@ generate_fs(struct gallivm_state *gallivm,
                                            0);
 
       if (color0 != -1 && outputs[color0][3]) {
+         const struct util_format_description *cbuf_format_desc;
          LLVMValueRef alpha = LLVMBuildLoad(builder, outputs[color0][3], "alpha");
          LLVMValueRef alpha_ref_value;
 
          alpha_ref_value = lp_jit_context_alpha_ref_value(gallivm, context_ptr);
          alpha_ref_value = lp_build_broadcast(gallivm, vec_type, alpha_ref_value);
 
-         lp_build_alpha_test(gallivm, key->alpha.func, type,
+         cbuf_format_desc = util_format_description(key->cbuf_format[0]);
+
+         lp_build_alpha_test(gallivm, key->alpha.func, type, cbuf_format_desc,
                              &mask, alpha, alpha_ref_value,
                              (depth_mode & LATE_DEPTH_TEST) != 0);
       }