[Mesa-dev] [PATCH] llvmpipe: Fix alpha testing precision on rgba8 formats.

Brian Paul brianp at vmware.com
Tue May 22 08:44:31 PDT 2012


On 05/22/2012 09:07 AM, jfonseca at vmware.com wrote:
> From: José Fonseca<jfonseca at vmware.com>
>
> 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.
> ---
>   src/gallium/drivers/llvmpipe/lp_bld_alpha.c |   31 +++++++++++++++++++++++++++
>   src/gallium/drivers/llvmpipe/lp_bld_alpha.h |    2 ++
>   src/gallium/drivers/llvmpipe/lp_state_fs.c  |    5 ++++-
>   3 files changed, 37 insertions(+), 1 deletion(-)
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
> index 518969c..bf4e8c4 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,33 @@ 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.
> +    * It is, however, difficult to come up with a truly generic rule that would
> +    * work for an arbitrary format.  For example, how many bits should we use
> +    * when doing alpha testing for B5G5R5X1_UNORM?
 > +    */

The GL spec addresses this in section 2.14.9 on page 71 of the 2.1 spec:

"""
For an RGBA color, each color component (which lies in [0, 1]) is 
converted (by rounding to nearest) to a fixed-point value with m bits.
[...]
m must be at least as large as the number of bits in the corresponding
component of the framebuffer. m must be at least 2 for A if the 
framebuffer does not contain an A component, or if there is only 1 bit 
of A in the framebuffer.
"""


> +   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 06206a2..15f1284 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 11a3871..0bdc17f 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);
>         }

Reviewed-by: Brian Paul <brianp at vmware.com>


More information about the mesa-dev mailing list