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"
34 #include "lp_bld_blend.h"
37 * Is (a OP b) == (b OP a)?
40 lp_build_blend_func_commutative(unsigned func
)
47 case PIPE_BLEND_SUBTRACT
:
48 case PIPE_BLEND_REVERSE_SUBTRACT
:
58 * Whether the blending functions are the reverse of each other.
61 lp_build_blend_func_reverse(unsigned rgb_func
, unsigned alpha_func
)
63 if(rgb_func
== alpha_func
)
65 if(rgb_func
== PIPE_BLEND_SUBTRACT
&& alpha_func
== PIPE_BLEND_REVERSE_SUBTRACT
)
67 if(rgb_func
== PIPE_BLEND_REVERSE_SUBTRACT
&& alpha_func
== PIPE_BLEND_SUBTRACT
)
74 * Whether the blending factors are complementary of each other.
77 lp_build_blend_factor_complementary(unsigned src_factor
, unsigned dst_factor
)
79 return dst_factor
== (src_factor
^ 0x10);
84 * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml
87 lp_build_blend_func(struct lp_build_context
*bld
,
94 return lp_build_add(bld
, term1
, term2
);
95 case PIPE_BLEND_SUBTRACT
:
96 return lp_build_sub(bld
, term1
, term2
);
97 case PIPE_BLEND_REVERSE_SUBTRACT
:
98 return lp_build_sub(bld
, term2
, term1
);
100 return lp_build_min(bld
, term1
, term2
);
102 return lp_build_max(bld
, term1
, term2
);
111 * Performs optimisations and blending independent of SoA/AoS
113 * @param func the blend function
114 * @param factor_src PIPE_BLENDFACTOR_xxx
115 * @param factor_dst PIPE_BLENDFACTOR_xxx
116 * @param src source rgba
117 * @param dst dest rgba
118 * @param src_factor src factor computed value
119 * @param dst_factor dst factor computed value
120 * @param not_alpha_dependent same factors accross all channels of src/dst
122 * not_alpha_dependent should be:
123 * SoA: always true as it is only one channel at a time
124 * AoS: rgb_src_factor == alpha_src_factor && rgb_dst_factor == alpha_dst_factor
126 * Note that pretty much every possible optimisation can only be done on non-unorm targets
127 * due to unorm values not going above 1.0 meaning factorisation can change results.
128 * e.g. (0.9 * 0.9) + (0.9 * 0.9) != 0.9 * (0.9 + 0.9) as result of + is always <= 1.
131 lp_build_blend(struct lp_build_context
*bld
,
137 LLVMValueRef src_factor
,
138 LLVMValueRef dst_factor
,
139 boolean not_alpha_dependent
,
140 boolean optimise_only
)
142 LLVMValueRef result
, src_term
, dst_term
;
144 /* If we are not alpha dependent we can mess with the src/dst factors */
145 if (not_alpha_dependent
) {
146 if (lp_build_blend_factor_complementary(factor_src
, factor_dst
)) {
147 if (func
== PIPE_BLEND_ADD
) {
148 if (factor_src
< factor_dst
) {
149 return lp_build_lerp(bld
, src_factor
, dst
, src
);
151 return lp_build_lerp(bld
, dst_factor
, src
, dst
);
153 } else if(bld
->type
.floating
&& func
== PIPE_BLEND_SUBTRACT
) {
154 result
= lp_build_add(bld
, src
, dst
);
156 if (factor_src
< factor_dst
) {
157 result
= lp_build_mul(bld
, result
, src_factor
);
158 return lp_build_sub(bld
, result
, dst
);
160 result
= lp_build_mul(bld
, result
, dst_factor
);
161 return lp_build_sub(bld
, src
, result
);
163 } else if(bld
->type
.floating
&& func
== PIPE_BLEND_REVERSE_SUBTRACT
) {
164 result
= lp_build_add(bld
, src
, dst
);
166 if (factor_src
< factor_dst
) {
167 result
= lp_build_mul(bld
, result
, src_factor
);
168 return lp_build_sub(bld
, dst
, result
);
170 result
= lp_build_mul(bld
, result
, dst_factor
);
171 return lp_build_sub(bld
, result
, src
);
176 if (bld
->type
.floating
&& factor_src
== factor_dst
) {
177 if (func
== PIPE_BLEND_ADD
||
178 func
== PIPE_BLEND_SUBTRACT
||
179 func
== PIPE_BLEND_REVERSE_SUBTRACT
) {
181 result
= lp_build_blend_func(bld
, func
, src
, dst
);
182 return lp_build_mul(bld
, result
, src_factor
);
190 src_term
= lp_build_mul(bld
, src
, src_factor
);
191 dst_term
= lp_build_mul(bld
, dst
, dst_factor
);
192 return lp_build_blend_func(bld
, func
, src_term
, dst_term
);