• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2009 VMware, Inc.
4  * All Rights Reserved.
5  *
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:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
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.
25  *
26  **************************************************************************/
27 
28 
29 /**
30  * @file
31  * Blend LLVM IR generation -- AoS layout.
32  *
33  * AoS blending is in general much slower than SoA, but there are some cases
34  * where it might be faster. In particular, if a pixel is rendered only once
35  * then the overhead of tiling and untiling will dominate over the speedup that
36  * SoA gives. So we might want to detect such cases and fallback to AoS in the
37  * future, but for now this function is here for historical/benchmarking
38  * purposes.
39  *
40  * Run lp_blend_test after any change to this file.
41  *
42  * @author Jose Fonseca <jfonseca@vmware.com>
43  */
44 
45 
46 #include "pipe/p_state.h"
47 #include "util/u_debug.h"
48 #include "util/u_format.h"
49 
50 #include "gallivm/lp_bld_type.h"
51 #include "gallivm/lp_bld_const.h"
52 #include "gallivm/lp_bld_arit.h"
53 #include "gallivm/lp_bld_logic.h"
54 #include "gallivm/lp_bld_swizzle.h"
55 #include "gallivm/lp_bld_bitarit.h"
56 #include "gallivm/lp_bld_debug.h"
57 
58 #include "lp_bld_blend.h"
59 
60 
61 /**
62  * We may the same values several times, so we keep them here to avoid
63  * recomputing them. Also reusing the values allows us to do simplifications
64  * that LLVM optimization passes wouldn't normally be able to do.
65  */
66 struct lp_build_blend_aos_context
67 {
68    struct lp_build_context base;
69 
70    LLVMValueRef src;
71    LLVMValueRef dst;
72    LLVMValueRef const_;
73 
74    LLVMValueRef inv_src;
75    LLVMValueRef inv_dst;
76    LLVMValueRef inv_const;
77    LLVMValueRef saturate;
78 
79    LLVMValueRef rgb_src_factor;
80    LLVMValueRef alpha_src_factor;
81    LLVMValueRef rgb_dst_factor;
82    LLVMValueRef alpha_dst_factor;
83 };
84 
85 
86 static LLVMValueRef
lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context * bld,unsigned factor,boolean alpha)87 lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context *bld,
88                                  unsigned factor,
89                                  boolean alpha)
90 {
91    switch (factor) {
92    case PIPE_BLENDFACTOR_ZERO:
93       return bld->base.zero;
94    case PIPE_BLENDFACTOR_ONE:
95       return bld->base.one;
96    case PIPE_BLENDFACTOR_SRC_COLOR:
97    case PIPE_BLENDFACTOR_SRC_ALPHA:
98       return bld->src;
99    case PIPE_BLENDFACTOR_DST_COLOR:
100    case PIPE_BLENDFACTOR_DST_ALPHA:
101       return bld->dst;
102    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
103       if(alpha)
104          return bld->base.one;
105       else {
106          if(!bld->inv_dst)
107             bld->inv_dst = lp_build_comp(&bld->base, bld->dst);
108          if(!bld->saturate)
109             bld->saturate = lp_build_min(&bld->base, bld->src, bld->inv_dst);
110          return bld->saturate;
111       }
112    case PIPE_BLENDFACTOR_CONST_COLOR:
113    case PIPE_BLENDFACTOR_CONST_ALPHA:
114       return bld->const_;
115    case PIPE_BLENDFACTOR_SRC1_COLOR:
116    case PIPE_BLENDFACTOR_SRC1_ALPHA:
117       /* TODO */
118       assert(0);
119       return bld->base.zero;
120    case PIPE_BLENDFACTOR_INV_SRC_COLOR:
121    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
122       if(!bld->inv_src)
123          bld->inv_src = lp_build_comp(&bld->base, bld->src);
124       return bld->inv_src;
125    case PIPE_BLENDFACTOR_INV_DST_COLOR:
126    case PIPE_BLENDFACTOR_INV_DST_ALPHA:
127       if(!bld->inv_dst)
128          bld->inv_dst = lp_build_comp(&bld->base, bld->dst);
129       return bld->inv_dst;
130    case PIPE_BLENDFACTOR_INV_CONST_COLOR:
131    case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
132       if(!bld->inv_const)
133          bld->inv_const = lp_build_comp(&bld->base, bld->const_);
134       return bld->inv_const;
135    case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
136    case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
137       /* TODO */
138       assert(0);
139       return bld->base.zero;
140    default:
141       assert(0);
142       return bld->base.zero;
143    }
144 }
145 
146 
147 enum lp_build_blend_swizzle {
148    LP_BUILD_BLEND_SWIZZLE_RGBA = 0,
149    LP_BUILD_BLEND_SWIZZLE_AAAA = 1
150 };
151 
152 
153 /**
154  * How should we shuffle the base factor.
155  */
156 static enum lp_build_blend_swizzle
lp_build_blend_factor_swizzle(unsigned factor)157 lp_build_blend_factor_swizzle(unsigned factor)
158 {
159    switch (factor) {
160    case PIPE_BLENDFACTOR_ONE:
161    case PIPE_BLENDFACTOR_ZERO:
162    case PIPE_BLENDFACTOR_SRC_COLOR:
163    case PIPE_BLENDFACTOR_DST_COLOR:
164    case PIPE_BLENDFACTOR_CONST_COLOR:
165    case PIPE_BLENDFACTOR_SRC1_COLOR:
166    case PIPE_BLENDFACTOR_INV_SRC_COLOR:
167    case PIPE_BLENDFACTOR_INV_DST_COLOR:
168    case PIPE_BLENDFACTOR_INV_CONST_COLOR:
169    case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
170       return LP_BUILD_BLEND_SWIZZLE_RGBA;
171    case PIPE_BLENDFACTOR_SRC_ALPHA:
172    case PIPE_BLENDFACTOR_DST_ALPHA:
173    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
174    case PIPE_BLENDFACTOR_SRC1_ALPHA:
175    case PIPE_BLENDFACTOR_CONST_ALPHA:
176    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
177    case PIPE_BLENDFACTOR_INV_DST_ALPHA:
178    case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
179    case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
180       return LP_BUILD_BLEND_SWIZZLE_AAAA;
181    default:
182       assert(0);
183       return LP_BUILD_BLEND_SWIZZLE_RGBA;
184    }
185 }
186 
187 
188 static LLVMValueRef
lp_build_blend_swizzle(struct lp_build_blend_aos_context * bld,LLVMValueRef rgb,LLVMValueRef alpha,enum lp_build_blend_swizzle rgb_swizzle,unsigned alpha_swizzle)189 lp_build_blend_swizzle(struct lp_build_blend_aos_context *bld,
190                        LLVMValueRef rgb,
191                        LLVMValueRef alpha,
192                        enum lp_build_blend_swizzle rgb_swizzle,
193                        unsigned alpha_swizzle)
194 {
195    LLVMValueRef swizzled_rgb;
196 
197    switch (rgb_swizzle) {
198    case LP_BUILD_BLEND_SWIZZLE_RGBA:
199       swizzled_rgb = rgb;
200       break;
201    case LP_BUILD_BLEND_SWIZZLE_AAAA:
202       swizzled_rgb = lp_build_swizzle_scalar_aos(&bld->base, rgb, alpha_swizzle);
203       break;
204    default:
205       assert(0);
206       swizzled_rgb = bld->base.undef;
207    }
208 
209    if (rgb != alpha) {
210       swizzled_rgb = lp_build_select_aos(&bld->base, 1 << alpha_swizzle,
211                                          alpha, swizzled_rgb);
212    }
213 
214    return swizzled_rgb;
215 }
216 
217 
218 /**
219  * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml
220  */
221 static LLVMValueRef
lp_build_blend_factor(struct lp_build_blend_aos_context * bld,unsigned rgb_factor,unsigned alpha_factor,unsigned alpha_swizzle)222 lp_build_blend_factor(struct lp_build_blend_aos_context *bld,
223                       unsigned rgb_factor,
224                       unsigned alpha_factor,
225                       unsigned alpha_swizzle)
226 {
227    LLVMValueRef rgb_factor_, alpha_factor_;
228    enum lp_build_blend_swizzle rgb_swizzle;
229 
230    rgb_factor_ = lp_build_blend_factor_unswizzled(bld, rgb_factor, FALSE);
231 
232    if (alpha_swizzle != UTIL_FORMAT_SWIZZLE_NONE) {
233       rgb_swizzle   = lp_build_blend_factor_swizzle(rgb_factor);
234       alpha_factor_ = lp_build_blend_factor_unswizzled(bld, alpha_factor, TRUE);
235       return lp_build_blend_swizzle(bld, rgb_factor_, alpha_factor_, rgb_swizzle, alpha_swizzle);
236    } else {
237       return rgb_factor_;
238    }
239 }
240 
241 
242 /**
243  * Performs blending of src and dst pixels
244  *
245  * @param blend         the blend state of the shader variant
246  * @param cbuf_format   format of the colour buffer
247  * @param type          data type of the pixel vector
248  * @param rt            rt number
249  * @param src           blend src
250  * @param dst           blend dst
251  * @param mask          optional mask to apply to the blending result
252  * @param const_        const blend color
253  * @param swizzle       swizzle values for RGBA
254  *
255  * @return the result of blending src and dst
256  */
257 LLVMValueRef
lp_build_blend_aos(struct gallivm_state * gallivm,const struct pipe_blend_state * blend,const enum pipe_format * cbuf_format,struct lp_type type,unsigned rt,LLVMValueRef src,LLVMValueRef dst,LLVMValueRef mask,LLVMValueRef const_,const unsigned char swizzle[4])258 lp_build_blend_aos(struct gallivm_state *gallivm,
259                    const struct pipe_blend_state *blend,
260                    const enum pipe_format *cbuf_format,
261                    struct lp_type type,
262                    unsigned rt,
263                    LLVMValueRef src,
264                    LLVMValueRef dst,
265                    LLVMValueRef mask,
266                    LLVMValueRef const_,
267                    const unsigned char swizzle[4])
268 {
269    const struct pipe_rt_blend_state * state = &blend->rt[rt];
270    struct lp_build_blend_aos_context bld;
271    LLVMValueRef src_factor, dst_factor;
272    LLVMValueRef result;
273    unsigned alpha_swizzle = swizzle[3];
274    boolean fullcolormask;
275 
276    /* Setup build context */
277    memset(&bld, 0, sizeof bld);
278    lp_build_context_init(&bld.base, gallivm, type);
279    bld.src = src;
280    bld.dst = dst;
281    bld.const_ = const_;
282 
283    if (swizzle[3] > UTIL_FORMAT_SWIZZLE_W || swizzle[3] == swizzle[0])
284       alpha_swizzle = UTIL_FORMAT_SWIZZLE_NONE;
285 
286    if (!state->blend_enable) {
287       result = src;
288    } else {
289       boolean rgb_alpha_same = state->rgb_src_factor == state->rgb_dst_factor && state->alpha_src_factor == state->alpha_dst_factor;
290       assert(rgb_alpha_same || alpha_swizzle != UTIL_FORMAT_SWIZZLE_NONE);
291 
292       src_factor = lp_build_blend_factor(&bld, state->rgb_src_factor,
293                                          state->alpha_src_factor, alpha_swizzle);
294       dst_factor = lp_build_blend_factor(&bld, state->rgb_dst_factor,
295                                          state->alpha_dst_factor, alpha_swizzle);
296 
297       result = lp_build_blend(&bld.base,
298                               state->rgb_func,
299                               state->rgb_src_factor,
300                               state->rgb_dst_factor,
301                               src,
302                               dst,
303                               src_factor,
304                               dst_factor,
305                               rgb_alpha_same,
306                               false);
307 
308       if(state->rgb_func != state->alpha_func && alpha_swizzle != UTIL_FORMAT_SWIZZLE_NONE) {
309          LLVMValueRef alpha;
310 
311          alpha = lp_build_blend(&bld.base,
312                                 state->alpha_func,
313                                 state->alpha_src_factor,
314                                 state->alpha_dst_factor,
315                                 src,
316                                 dst,
317                                 src_factor,
318                                 dst_factor,
319                                 rgb_alpha_same,
320                                 false);
321 
322          result = lp_build_blend_swizzle(&bld,
323                                          result,
324                                          alpha,
325                                          LP_BUILD_BLEND_SWIZZLE_RGBA,
326                                          alpha_swizzle);
327       }
328    }
329 
330    /* Check if color mask is necessary */
331    fullcolormask = util_format_colormask_full(util_format_description(cbuf_format[rt]), state->colormask);
332 
333    if (!fullcolormask) {
334       LLVMValueRef color_mask;
335 
336       color_mask = lp_build_const_mask_aos_swizzled(gallivm, bld.base.type, state->colormask, swizzle);
337       lp_build_name(color_mask, "color_mask");
338 
339       /* Combine with input mask if necessary */
340       if (mask) {
341          mask = lp_build_and(&bld.base, color_mask, mask);
342       } else {
343          mask = color_mask;
344       }
345    }
346 
347    /* Apply mask, if one exists */
348    if (mask) {
349       result = lp_build_select(&bld.base, mask, result, dst);
350    }
351 
352    return result;
353 }
354