summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2012-05-22 16:04:33 +0100
committerJosé Fonseca <[email protected]>2012-05-22 19:23:49 +0100
commit7a75e7d6e85d27e102ff7e15583c33b1ce282fe4 (patch)
treea4343f2b8b3731addad28107502afed6cab0a1e2 /src/gallium/drivers
parente4fb332af1e62db930bc9a435cab3c0aa32cdea8 (diff)
llvmpipe: Fix alpha testing precision on rgba8 formats.
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 <[email protected]> Reviewed-by: Roland Scheidegger <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_alpha.c28
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_alpha.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c5
3 files changed, 34 insertions, 1 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
index 518969c3202..6e2d0376dcd 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
@@ -32,9 +32,12 @@
*/
#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");
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
index 06206a24d83..15f1284c5e1 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
@@ -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,
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 11a3871c408..0bdc17fb3e1 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -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);
}