1 /**************************************************************************
3 * Copyright 2012 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "pipe/p_state.h"
29 #include "util/u_debug.h"
31 #include "gallivm/lp_bld_type.h"
32 #include "gallivm/lp_bld_arit.h"
33 #include "gallivm/lp_bld_const.h"
34 #include "gallivm/lp_bld_logic.h"
35 #include "gallivm/lp_bld_swizzle.h"
36 #include "gallivm/lp_bld_flow.h"
37 #include "gallivm/lp_bld_debug.h"
39 #include "lp_bld_blend.h"
42 * Is (a OP b) == (b OP a)?
45 lp_build_blend_func_commutative(unsigned func
)
52 case PIPE_BLEND_SUBTRACT
:
53 case PIPE_BLEND_REVERSE_SUBTRACT
:
63 * Whether the blending functions are the reverse of each other.
66 lp_build_blend_func_reverse(unsigned rgb_func
, unsigned alpha_func
)
68 if(rgb_func
== alpha_func
)
70 if(rgb_func
== PIPE_BLEND_SUBTRACT
&& alpha_func
== PIPE_BLEND_REVERSE_SUBTRACT
)
72 if(rgb_func
== PIPE_BLEND_REVERSE_SUBTRACT
&& alpha_func
== PIPE_BLEND_SUBTRACT
)
79 * Whether the blending factors are complementary of each other.
82 lp_build_blend_factor_complementary(unsigned src_factor
, unsigned dst_factor
)
84 return dst_factor
== (src_factor
^ 0x10);
89 * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml
92 lp_build_blend_func(struct lp_build_context
*bld
,
99 return lp_build_add(bld
, term1
, term2
);
100 case PIPE_BLEND_SUBTRACT
:
101 return lp_build_sub(bld
, term1
, term2
);
102 case PIPE_BLEND_REVERSE_SUBTRACT
:
103 return lp_build_sub(bld
, term2
, term1
);
105 return lp_build_min(bld
, term1
, term2
);
107 return lp_build_max(bld
, term1
, term2
);
116 * Performs optimisations and blending independent of SoA/AoS
118 * @param func the blend function
119 * @param factor_src PIPE_BLENDFACTOR_xxx
120 * @param factor_dst PIPE_BLENDFACTOR_xxx
121 * @param src source rgba
122 * @param dst dest rgba
123 * @param src_factor src factor computed value
124 * @param dst_factor dst factor computed value
125 * @param not_alpha_dependent same factors accross all channels of src/dst
127 * not_alpha_dependent should be:
128 * SoA: always true as it is only one channel at a time
129 * AoS: rgb_src_factor == alpha_src_factor && rgb_dst_factor == alpha_dst_factor
131 * Note that pretty much every possible optimisation can only be done on non-unorm targets
132 * due to unorm values not going above 1.0 meaning factorisation can change results.
133 * e.g. (0.9 * 0.9) + (0.9 * 0.9) != 0.9 * (0.9 + 0.9) as result of + is always <= 1.
136 lp_build_blend(struct lp_build_context
*bld
,
142 LLVMValueRef src_factor
,
143 LLVMValueRef dst_factor
,
144 boolean not_alpha_dependent
,
145 boolean optimise_only
)
147 LLVMValueRef result
, src_term
, dst_term
;
149 /* If we are not alpha dependent we can mess with the src/dst factors */
150 if (not_alpha_dependent
) {
151 if (lp_build_blend_factor_complementary(factor_src
, factor_dst
)) {
152 if (func
== PIPE_BLEND_ADD
) {
153 if (factor_src
< factor_dst
) {
154 return lp_build_lerp(bld
, src_factor
, dst
, src
, 0);
156 return lp_build_lerp(bld
, dst_factor
, src
, dst
, 0);
158 } else if(bld
->type
.floating
&& func
== PIPE_BLEND_SUBTRACT
) {
159 result
= lp_build_add(bld
, src
, dst
);
161 if (factor_src
< factor_dst
) {
162 result
= lp_build_mul(bld
, result
, src_factor
);
163 return lp_build_sub(bld
, result
, dst
);
165 result
= lp_build_mul(bld
, result
, dst_factor
);
166 return lp_build_sub(bld
, src
, result
);
168 } else if(bld
->type
.floating
&& func
== PIPE_BLEND_REVERSE_SUBTRACT
) {
169 result
= lp_build_add(bld
, src
, dst
);
171 if (factor_src
< factor_dst
) {
172 result
= lp_build_mul(bld
, result
, src_factor
);
173 return lp_build_sub(bld
, dst
, result
);
175 result
= lp_build_mul(bld
, result
, dst_factor
);
176 return lp_build_sub(bld
, result
, src
);
181 if (bld
->type
.floating
&& factor_src
== factor_dst
) {
182 if (func
== PIPE_BLEND_ADD
||
183 func
== PIPE_BLEND_SUBTRACT
||
184 func
== PIPE_BLEND_REVERSE_SUBTRACT
) {
186 result
= lp_build_blend_func(bld
, func
, src
, dst
);
187 return lp_build_mul(bld
, result
, src_factor
);
195 src_term
= lp_build_mul(bld
, src
, src_factor
);
196 dst_term
= lp_build_mul(bld
, dst
, dst_factor
);
197 return lp_build_blend_func(bld
, func
, src_term
, dst_term
);
201 lp_build_alpha_to_coverage(struct gallivm_state
*gallivm
,
203 struct lp_build_mask_context
*mask
,
207 struct lp_build_context bld
;
209 LLVMValueRef alpha_ref_value
;
211 lp_build_context_init(&bld
, gallivm
, type
);
213 alpha_ref_value
= lp_build_const_vec(gallivm
, type
, 0.5);
215 test
= lp_build_cmp(&bld
, PIPE_FUNC_GREATER
, alpha
, alpha_ref_value
);
217 lp_build_name(test
, "alpha_to_coverage");
219 lp_build_mask_update(mask
, test
);
222 lp_build_mask_check(mask
);