lp_bld_blend_aos.c revision 2529ed5616b1b152766a3355444260b88184cd6e
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 form. 32 * 33 * @author Jose Fonseca <jfonseca@vmware.com> 34 */ 35 36 37#include "pipe/p_state.h" 38 39#include "lp_bld_type.h" 40#include "lp_bld_const.h" 41#include "lp_bld_arit.h" 42#include "lp_bld_swizzle.h" 43#include "lp_bld_blend.h" 44 45 46/** 47 * We may the same values several times, so we keep them here to avoid 48 * recomputing them. Also reusing the values allows us to do simplifications 49 * that LLVM optimization passes wouldn't normally be able to do. 50 */ 51struct lp_build_blend_aos_context 52{ 53 struct lp_build_context base; 54 55 LLVMValueRef src; 56 LLVMValueRef dst; 57 LLVMValueRef const_; 58 59 LLVMValueRef inv_src; 60 LLVMValueRef inv_dst; 61 LLVMValueRef inv_const; 62 LLVMValueRef saturate; 63 64 LLVMValueRef rgb_src_factor; 65 LLVMValueRef alpha_src_factor; 66 LLVMValueRef rgb_dst_factor; 67 LLVMValueRef alpha_dst_factor; 68}; 69 70 71static LLVMValueRef 72lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context *bld, 73 unsigned factor, 74 boolean alpha) 75{ 76 switch (factor) { 77 case PIPE_BLENDFACTOR_ZERO: 78 return bld->base.zero; 79 case PIPE_BLENDFACTOR_ONE: 80 return bld->base.one; 81 case PIPE_BLENDFACTOR_SRC_COLOR: 82 case PIPE_BLENDFACTOR_SRC_ALPHA: 83 return bld->src; 84 case PIPE_BLENDFACTOR_DST_COLOR: 85 case PIPE_BLENDFACTOR_DST_ALPHA: 86 return bld->dst; 87 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 88 if(alpha) 89 return bld->base.one; 90 else { 91 if(!bld->inv_dst) 92 bld->inv_dst = lp_build_comp(&bld->base, bld->dst); 93 if(!bld->saturate) 94 bld->saturate = lp_build_min(&bld->base, bld->src, bld->inv_dst); 95 return bld->saturate; 96 } 97 case PIPE_BLENDFACTOR_CONST_COLOR: 98 case PIPE_BLENDFACTOR_CONST_ALPHA: 99 return bld->const_; 100 case PIPE_BLENDFACTOR_SRC1_COLOR: 101 case PIPE_BLENDFACTOR_SRC1_ALPHA: 102 /* TODO */ 103 assert(0); 104 return bld->base.zero; 105 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 106 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 107 if(!bld->inv_src) 108 bld->inv_src = lp_build_comp(&bld->base, bld->src); 109 return bld->inv_src; 110 case PIPE_BLENDFACTOR_INV_DST_COLOR: 111 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 112 if(!bld->inv_dst) 113 bld->inv_dst = lp_build_comp(&bld->base, bld->dst); 114 return bld->inv_dst; 115 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 116 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 117 if(!bld->inv_const) 118 bld->inv_const = lp_build_comp(&bld->base, bld->const_); 119 return bld->inv_const; 120 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 121 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 122 /* TODO */ 123 assert(0); 124 return bld->base.zero; 125 default: 126 assert(0); 127 return bld->base.zero; 128 } 129} 130 131 132enum lp_build_blend_swizzle { 133 LP_BUILD_BLEND_SWIZZLE_RGBA = 0, 134 LP_BUILD_BLEND_SWIZZLE_AAAA = 1, 135}; 136 137 138/** 139 * How should we shuffle the base factor. 140 */ 141static enum lp_build_blend_swizzle 142lp_build_blend_factor_swizzle(unsigned factor) 143{ 144 switch (factor) { 145 case PIPE_BLENDFACTOR_ONE: 146 case PIPE_BLENDFACTOR_ZERO: 147 case PIPE_BLENDFACTOR_SRC_COLOR: 148 case PIPE_BLENDFACTOR_DST_COLOR: 149 case PIPE_BLENDFACTOR_CONST_COLOR: 150 case PIPE_BLENDFACTOR_SRC1_COLOR: 151 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 152 case PIPE_BLENDFACTOR_INV_DST_COLOR: 153 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 154 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 155 return LP_BUILD_BLEND_SWIZZLE_RGBA; 156 case PIPE_BLENDFACTOR_SRC_ALPHA: 157 case PIPE_BLENDFACTOR_DST_ALPHA: 158 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 159 case PIPE_BLENDFACTOR_SRC1_ALPHA: 160 case PIPE_BLENDFACTOR_CONST_ALPHA: 161 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 162 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 163 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 164 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 165 return LP_BUILD_BLEND_SWIZZLE_AAAA; 166 default: 167 assert(0); 168 return LP_BUILD_BLEND_SWIZZLE_RGBA; 169 } 170} 171 172 173static LLVMValueRef 174lp_build_blend_swizzle(struct lp_build_blend_aos_context *bld, 175 LLVMValueRef rgb, 176 LLVMValueRef alpha, 177 enum lp_build_blend_swizzle rgb_swizzle, 178 unsigned alpha_swizzle) 179{ 180 if(rgb == alpha) { 181 if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_RGBA) 182 return rgb; 183 if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_AAAA) 184 return lp_build_broadcast_aos(&bld->base, rgb, alpha_swizzle); 185 } 186 else { 187 if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_RGBA) { 188 boolean cond[4] = {0, 0, 0, 0}; 189 cond[alpha_swizzle] = 1; 190 return lp_build_select_aos(&bld->base, alpha, rgb, cond); 191 } 192 if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_AAAA) { 193 unsigned char swizzle[4]; 194 swizzle[0] = alpha_swizzle; 195 swizzle[1] = alpha_swizzle; 196 swizzle[2] = alpha_swizzle; 197 swizzle[3] = alpha_swizzle; 198 swizzle[alpha_swizzle] += 4; 199 return lp_build_swizzle2_aos(&bld->base, rgb, alpha, swizzle); 200 } 201 } 202 assert(0); 203 return bld->base.undef; 204} 205 206 207/** 208 * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml 209 */ 210static LLVMValueRef 211lp_build_blend_factor(struct lp_build_blend_aos_context *bld, 212 LLVMValueRef factor1, 213 unsigned rgb_factor, 214 unsigned alpha_factor, 215 unsigned alpha_swizzle) 216{ 217 LLVMValueRef rgb_factor_; 218 LLVMValueRef alpha_factor_; 219 LLVMValueRef factor2; 220 enum lp_build_blend_swizzle rgb_swizzle; 221 222 rgb_factor_ = lp_build_blend_factor_unswizzled(bld, rgb_factor, FALSE); 223 alpha_factor_ = lp_build_blend_factor_unswizzled(bld, alpha_factor, TRUE); 224 225 rgb_swizzle = lp_build_blend_factor_swizzle(rgb_factor); 226 227 factor2 = lp_build_blend_swizzle(bld, rgb_factor_, alpha_factor_, rgb_swizzle, alpha_swizzle); 228 229 return lp_build_mul(&bld->base, factor1, factor2); 230} 231 232 233boolean 234lp_build_blend_func_commutative(unsigned func) 235{ 236 switch (func) { 237 case PIPE_BLEND_ADD: 238 case PIPE_BLEND_MIN: 239 case PIPE_BLEND_MAX: 240 return TRUE; 241 case PIPE_BLEND_SUBTRACT: 242 case PIPE_BLEND_REVERSE_SUBTRACT: 243 return FALSE; 244 default: 245 assert(0); 246 return TRUE; 247 } 248} 249 250 251boolean 252lp_build_blend_func_reverse(unsigned rgb_func, unsigned alpha_func) 253{ 254 if(rgb_func == alpha_func) 255 return FALSE; 256 if(rgb_func == PIPE_BLEND_SUBTRACT && alpha_func == PIPE_BLEND_REVERSE_SUBTRACT) 257 return TRUE; 258 if(rgb_func == PIPE_BLEND_REVERSE_SUBTRACT && alpha_func == PIPE_BLEND_SUBTRACT) 259 return TRUE; 260 return FALSE; 261} 262 263 264/** 265 * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml 266 */ 267LLVMValueRef 268lp_build_blend_func(struct lp_build_context *bld, 269 unsigned func, 270 LLVMValueRef term1, 271 LLVMValueRef term2) 272{ 273 switch (func) { 274 case PIPE_BLEND_ADD: 275 return lp_build_add(bld, term1, term2); 276 break; 277 case PIPE_BLEND_SUBTRACT: 278 return lp_build_sub(bld, term1, term2); 279 case PIPE_BLEND_REVERSE_SUBTRACT: 280 return lp_build_sub(bld, term2, term1); 281 case PIPE_BLEND_MIN: 282 return lp_build_min(bld, term1, term2); 283 case PIPE_BLEND_MAX: 284 return lp_build_max(bld, term1, term2); 285 default: 286 assert(0); 287 return bld->zero; 288 } 289} 290 291 292LLVMValueRef 293lp_build_blend_aos(LLVMBuilderRef builder, 294 const struct pipe_blend_state *blend, 295 union lp_type type, 296 LLVMValueRef src, 297 LLVMValueRef dst, 298 LLVMValueRef const_, 299 unsigned alpha_swizzle) 300{ 301 struct lp_build_blend_aos_context bld; 302 LLVMValueRef src_term; 303 LLVMValueRef dst_term; 304 305 /* It makes no sense to blend unless values are normalized */ 306 assert(type.norm); 307 308 /* Setup build context */ 309 memset(&bld, 0, sizeof bld); 310 lp_build_context_init(&bld.base, builder, type); 311 bld.src = src; 312 bld.dst = dst; 313 bld.const_ = const_; 314 315 /* TODO: There are still a few optimization opportunities here. For certain 316 * combinations it is possible to reorder the operations and therefore saving 317 * some instructions. */ 318 319 src_term = lp_build_blend_factor(&bld, src, blend->rgb_src_factor, blend->alpha_src_factor, alpha_swizzle); 320 dst_term = lp_build_blend_factor(&bld, dst, blend->rgb_dst_factor, blend->alpha_dst_factor, alpha_swizzle); 321 322#ifdef DEBUG 323 LLVMSetValueName(src_term, "src_term"); 324 LLVMSetValueName(dst_term, "dst_term"); 325#endif 326 327 if(blend->rgb_func == blend->alpha_func) { 328 return lp_build_blend_func(&bld.base, blend->rgb_func, src_term, dst_term); 329 } 330 else { 331 /* Seperate RGB / A functions */ 332 333 LLVMValueRef rgb; 334 LLVMValueRef alpha; 335 336 rgb = lp_build_blend_func(&bld.base, blend->rgb_func, src_term, dst_term); 337 alpha = lp_build_blend_func(&bld.base, blend->alpha_func, src_term, dst_term); 338 339 return lp_build_blend_swizzle(&bld, rgb, alpha, LP_BUILD_BLEND_SWIZZLE_RGBA, alpha_swizzle); 340 } 341} 342