1 /**************************************************************************
3 * Copyright 2009 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 **************************************************************************/
31 * Blend LLVM IR generation -- SoA.
33 * @author Jose Fonseca <jfonseca@vmware.com>
37 #include "pipe/p_state.h"
39 #include "lp_bld_type.h"
40 #include "lp_bld_const.h"
41 #include "lp_bld_arit.h"
42 #include "lp_bld_blend.h"
46 * We may the same values several times, so we keep them here to avoid
47 * recomputing them. Also reusing the values allows us to do simplifications
48 * that LLVM optimization passes wouldn't normally be able to do.
50 struct lp_build_blend_soa_context
52 struct lp_build_context base
;
58 LLVMValueRef inv_src
[4];
59 LLVMValueRef inv_dst
[4];
60 LLVMValueRef inv_con
[4];
62 LLVMValueRef src_alpha_saturate
;
65 * We store all factors in a table in order to eliminate redundant
66 * multiplications later.
68 LLVMValueRef factor
[2][2][4];
71 * Table with all terms.
73 LLVMValueRef term
[2][4];
78 lp_build_blend_soa_factor(struct lp_build_blend_soa_context
*bld
,
79 unsigned factor
, unsigned i
)
82 * Compute src/first term RGB
85 case PIPE_BLENDFACTOR_ONE
:
87 case PIPE_BLENDFACTOR_SRC_COLOR
:
89 case PIPE_BLENDFACTOR_SRC_ALPHA
:
91 case PIPE_BLENDFACTOR_DST_COLOR
:
93 case PIPE_BLENDFACTOR_DST_ALPHA
:
95 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
100 bld
->inv_dst
[3] = lp_build_comp(&bld
->base
, bld
->dst
[3]);
101 if(!bld
->src_alpha_saturate
)
102 bld
->src_alpha_saturate
= lp_build_min(&bld
->base
, bld
->src
[3], bld
->inv_dst
[3]);
103 return bld
->src_alpha_saturate
;
105 case PIPE_BLENDFACTOR_CONST_COLOR
:
107 case PIPE_BLENDFACTOR_CONST_ALPHA
:
109 case PIPE_BLENDFACTOR_SRC1_COLOR
:
112 return bld
->base
.zero
;
113 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
116 return bld
->base
.zero
;
117 case PIPE_BLENDFACTOR_ZERO
:
118 return bld
->base
.zero
;
119 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
121 bld
->inv_src
[i
] = lp_build_comp(&bld
->base
, bld
->src
[i
]);
122 return bld
->inv_src
[i
];
123 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
125 bld
->inv_src
[3] = lp_build_comp(&bld
->base
, bld
->src
[3]);
126 return bld
->inv_src
[3];
127 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
129 bld
->inv_dst
[i
] = lp_build_comp(&bld
->base
, bld
->dst
[i
]);
130 return bld
->inv_dst
[i
];
131 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
133 bld
->inv_dst
[3] = lp_build_comp(&bld
->base
, bld
->dst
[3]);
134 return bld
->inv_dst
[3];
135 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
137 bld
->inv_con
[i
] = lp_build_comp(&bld
->base
, bld
->con
[i
]);
138 return bld
->inv_con
[i
];
139 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
141 bld
->inv_con
[3] = lp_build_comp(&bld
->base
, bld
->con
[3]);
142 return bld
->inv_con
[3];
143 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
146 return bld
->base
.zero
;
147 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
150 return bld
->base
.zero
;
153 return bld
->base
.zero
;
159 lp_build_blend_soa(LLVMBuilderRef builder
,
160 const struct pipe_blend_state
*blend
,
167 struct lp_build_blend_soa_context bld
;
170 /* Setup build context */
171 memset(&bld
, 0, sizeof bld
);
172 lp_build_context_init(&bld
.base
, builder
, type
);
173 for (i
= 0; i
< 4; ++i
) {
179 for (i
= 0; i
< 4; ++i
) {
180 if (blend
->colormask
& (1 << i
)) {
181 if (blend
->blend_enable
) {
182 unsigned src_factor
= i
< 3 ? blend
->rgb_src_factor
: blend
->alpha_src_factor
;
183 unsigned dst_factor
= i
< 3 ? blend
->rgb_dst_factor
: blend
->alpha_dst_factor
;
184 unsigned func
= i
< 3 ? blend
->rgb_func
: blend
->alpha_func
;
185 boolean func_commutative
= lp_build_blend_func_commutative(func
);
187 /* It makes no sense to blend unless values are normalized */
191 * Compute src/dst factors.
194 bld
.factor
[0][0][i
] = src
[i
];
195 bld
.factor
[0][1][i
] = lp_build_blend_soa_factor(&bld
, src_factor
, i
);
196 bld
.factor
[1][0][i
] = dst
[i
];
197 bld
.factor
[1][1][i
] = lp_build_blend_soa_factor(&bld
, dst_factor
, i
);
200 * Compute src/dst terms
203 for(k
= 0; k
< 2; ++k
) {
204 /* See if this multiplication has been previously computed */
205 for(j
= 0; j
< i
; ++j
) {
206 if((bld
.factor
[k
][0][j
] == bld
.factor
[k
][0][i
] &&
207 bld
.factor
[k
][1][j
] == bld
.factor
[k
][1][i
]) ||
208 (bld
.factor
[k
][0][j
] == bld
.factor
[k
][1][i
] &&
209 bld
.factor
[k
][1][j
] == bld
.factor
[k
][0][i
]))
214 bld
.term
[k
][i
] = bld
.term
[k
][j
];
216 bld
.term
[k
][i
] = lp_build_mul(&bld
.base
, bld
.factor
[k
][0][i
], bld
.factor
[k
][1][i
]);
223 /* See if this function has been previously applied */
224 for(j
= 0; j
< i
; ++j
) {
225 unsigned prev_func
= j
< 3 ? blend
->rgb_func
: blend
->alpha_func
;
226 unsigned func_reverse
= lp_build_blend_func_reverse(func
, prev_func
);
229 bld
.term
[0][j
] == bld
.term
[0][i
] &&
230 bld
.term
[1][j
] == bld
.term
[1][i
]) ||
231 ((func_commutative
|| func_reverse
) &&
232 bld
.term
[0][j
] == bld
.term
[1][i
] &&
233 bld
.term
[1][j
] == bld
.term
[0][i
]))
240 res
[i
] = lp_build_blend_func(&bld
.base
, func
, bld
.term
[0][i
], bld
.term
[1][i
]);