lp_bld_blend_soa.c revision 29d94a9cbb7858cc8b0cfb05c0bb66f56a6acfa5
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 -- SoA. 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_blend.h" 43 44 45/** 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. 49 */ 50struct lp_build_blend_soa_context 51{ 52 struct lp_build_context base; 53 54 LLVMValueRef src[4]; 55 LLVMValueRef dst[4]; 56 LLVMValueRef con[4]; 57 58 LLVMValueRef inv_src[4]; 59 LLVMValueRef inv_dst[4]; 60 LLVMValueRef inv_con[4]; 61 62 LLVMValueRef src_alpha_saturate; 63 64 /** 65 * We store all factors in a table in order to eliminate redundant 66 * multiplications later. 67 */ 68 LLVMValueRef factor[2][2][4]; 69 70 /** 71 * Table with all terms. 72 */ 73 LLVMValueRef term[2][4]; 74}; 75 76 77static LLVMValueRef 78lp_build_blend_soa_factor(struct lp_build_blend_soa_context *bld, 79 unsigned factor, unsigned i) 80{ 81 /* 82 * Compute src/first term RGB 83 */ 84 switch (factor) { 85 case PIPE_BLENDFACTOR_ONE: 86 return bld->base.one; 87 case PIPE_BLENDFACTOR_SRC_COLOR: 88 return bld->src[i]; 89 case PIPE_BLENDFACTOR_SRC_ALPHA: 90 return bld->src[3]; 91 case PIPE_BLENDFACTOR_DST_COLOR: 92 return bld->dst[i]; 93 case PIPE_BLENDFACTOR_DST_ALPHA: 94 return bld->dst[3]; 95 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 96 if(i == 3) 97 return bld->base.one; 98 else { 99 if(!bld->inv_dst[3]) 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; 104 } 105 case PIPE_BLENDFACTOR_CONST_COLOR: 106 return bld->con[i]; 107 case PIPE_BLENDFACTOR_CONST_ALPHA: 108 return bld->con[3]; 109 case PIPE_BLENDFACTOR_SRC1_COLOR: 110 /* TODO */ 111 assert(0); 112 return bld->base.zero; 113 case PIPE_BLENDFACTOR_SRC1_ALPHA: 114 /* TODO */ 115 assert(0); 116 return bld->base.zero; 117 case PIPE_BLENDFACTOR_ZERO: 118 return bld->base.zero; 119 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 120 if(!bld->inv_src[i]) 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: 124 if(!bld->inv_src[3]) 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: 128 if(!bld->inv_dst[i]) 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: 132 if(!bld->inv_dst[3]) 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: 136 if(!bld->inv_con[i]) 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: 140 if(!bld->inv_con[3]) 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: 144 /* TODO */ 145 assert(0); 146 return bld->base.zero; 147 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 148 /* TODO */ 149 assert(0); 150 return bld->base.zero; 151 default: 152 assert(0); 153 return bld->base.zero; 154 } 155} 156 157 158void 159lp_build_blend_soa(LLVMBuilderRef builder, 160 const struct pipe_blend_state *blend, 161 union lp_type type, 162 LLVMValueRef src[4], 163 LLVMValueRef dst[4], 164 LLVMValueRef con[4], 165 LLVMValueRef res[4]) 166{ 167 struct lp_build_blend_soa_context bld; 168 unsigned i, j, k; 169 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) { 174 bld.src[i] = src[i]; 175 bld.dst[i] = dst[i]; 176 bld.con[i] = con[i]; 177 } 178 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); 186 187 /* It makes no sense to blend unless values are normalized */ 188 assert(type.norm); 189 190 /* 191 * Compute src/dst factors. 192 */ 193 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); 198 199 /* 200 * Compute src/dst terms 201 */ 202 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])) 210 break; 211 } 212 213 if(j < i) 214 bld.term[k][i] = bld.term[k][j]; 215 else 216 bld.term[k][i] = lp_build_mul(&bld.base, bld.factor[k][0][i], bld.factor[k][1][i]); 217 } 218 219 /* 220 * Combine terms 221 */ 222 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); 227 228 if((!func_reverse && 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])) 234 break; 235 } 236 237 if(j < i) 238 res[i] = res[j]; 239 else 240 res[i] = lp_build_blend_func(&bld.base, func, bld.term[0][i], bld.term[1][i]); 241 } 242 else { 243 res[i] = src[i]; 244 } 245 } 246 else { 247 res[i] = dst[i]; 248 } 249 } 250} 251