lp_bld_blend_soa.c revision 0f6c621aeeb171b5c30c2875b4cea383a19ac8b5
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 158/** 159 * Generate blend code in SOA mode. 160 * \param src src/fragment color 161 * \param dst dst/framebuffer color 162 * \param con constant blend color 163 * \param res the result/output 164 */ 165void 166lp_build_blend_soa(LLVMBuilderRef builder, 167 const struct pipe_blend_state *blend, 168 union lp_type type, 169 LLVMValueRef src[4], 170 LLVMValueRef dst[4], 171 LLVMValueRef con[4], 172 LLVMValueRef res[4]) 173{ 174 struct lp_build_blend_soa_context bld; 175 unsigned i, j, k; 176 177 /* Setup build context */ 178 memset(&bld, 0, sizeof bld); 179 lp_build_context_init(&bld.base, builder, type); 180 for (i = 0; i < 4; ++i) { 181 bld.src[i] = src[i]; 182 bld.dst[i] = dst[i]; 183 bld.con[i] = con[i]; 184 } 185 186 for (i = 0; i < 4; ++i) { 187 if (blend->colormask & (1 << i)) { 188 if (blend->logicop_enable) { 189 if(!type.floating) { 190 res[i] = lp_build_logicop(builder, blend->logicop_func, src[i], dst[i]); 191 } 192 else 193 res[i] = dst[i]; 194 } 195 else if (blend->blend_enable) { 196 unsigned src_factor = i < 3 ? blend->rgb_src_factor : blend->alpha_src_factor; 197 unsigned dst_factor = i < 3 ? blend->rgb_dst_factor : blend->alpha_dst_factor; 198 unsigned func = i < 3 ? blend->rgb_func : blend->alpha_func; 199 boolean func_commutative = lp_build_blend_func_commutative(func); 200 201 /* It makes no sense to blend unless values are normalized */ 202 assert(type.norm); 203 204 /* 205 * Compute src/dst factors. 206 */ 207 208 bld.factor[0][0][i] = src[i]; 209 bld.factor[0][1][i] = lp_build_blend_soa_factor(&bld, src_factor, i); 210 bld.factor[1][0][i] = dst[i]; 211 bld.factor[1][1][i] = lp_build_blend_soa_factor(&bld, dst_factor, i); 212 213 /* 214 * Compute src/dst terms 215 */ 216 217 for(k = 0; k < 2; ++k) { 218 /* See if this multiplication has been previously computed */ 219 for(j = 0; j < i; ++j) { 220 if((bld.factor[k][0][j] == bld.factor[k][0][i] && 221 bld.factor[k][1][j] == bld.factor[k][1][i]) || 222 (bld.factor[k][0][j] == bld.factor[k][1][i] && 223 bld.factor[k][1][j] == bld.factor[k][0][i])) 224 break; 225 } 226 227 if(j < i) 228 bld.term[k][i] = bld.term[k][j]; 229 else 230 bld.term[k][i] = lp_build_mul(&bld.base, bld.factor[k][0][i], bld.factor[k][1][i]); 231 } 232 233 /* 234 * Combine terms 235 */ 236 237 /* See if this function has been previously applied */ 238 for(j = 0; j < i; ++j) { 239 unsigned prev_func = j < 3 ? blend->rgb_func : blend->alpha_func; 240 unsigned func_reverse = lp_build_blend_func_reverse(func, prev_func); 241 242 if((!func_reverse && 243 bld.term[0][j] == bld.term[0][i] && 244 bld.term[1][j] == bld.term[1][i]) || 245 ((func_commutative || func_reverse) && 246 bld.term[0][j] == bld.term[1][i] && 247 bld.term[1][j] == bld.term[0][i])) 248 break; 249 } 250 251 if(j < i) 252 res[i] = res[j]; 253 else 254 res[i] = lp_build_blend_func(&bld.base, func, bld.term[0][i], bld.term[1][i]); 255 } 256 else { 257 res[i] = src[i]; 258 } 259 } 260 else { 261 res[i] = dst[i]; 262 } 263 } 264} 265