lp_bld_blend_soa.c revision e7fc21434d2c5a9177a427950be5029ff4db43ee
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][8]; 69 70 /** 71 * Table with all terms. 72 */ 73 LLVMValueRef term[8]; 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; 169 170 if(!blend->blend_enable) { 171 for (i = 0; i < 4; ++i) 172 res[i] = src[i]; 173 return; 174 } 175 176 /* It makes no sense to blend unless values are normalized */ 177 assert(type.norm); 178 179 /* Setup build context */ 180 memset(&bld, 0, sizeof bld); 181 lp_build_context_init(&bld.base, builder, type); 182 for (i = 0; i < 4; ++i) { 183 bld.src[i] = src[i]; 184 bld.dst[i] = dst[i]; 185 bld.con[i] = con[i]; 186 } 187 188 /* 189 * Compute src/dst factors. 190 */ 191 for (i = 0; i < 4; ++i) { 192 unsigned src_factor = i < 3 ? blend->rgb_src_factor : blend->alpha_src_factor; 193 unsigned dst_factor = i < 3 ? blend->rgb_dst_factor : blend->alpha_dst_factor; 194 bld.factor[0][0 + i] = src[i]; 195 bld.factor[1][0 + i] = lp_build_blend_soa_factor(&bld, src_factor, i); 196 bld.factor[0][4 + i] = dst[i]; 197 bld.factor[1][4 + i] = lp_build_blend_soa_factor(&bld, dst_factor, i); 198 } 199 200 /* 201 * Compute src/dst terms 202 */ 203 for (i = 0; i < 8; ++i) { 204 205 /* See if this multiplication has been previously computed */ 206 for(j = 0; j < i; ++j) { 207 if((bld.factor[0][j] == bld.factor[0][i] && 208 bld.factor[1][j] == bld.factor[1][i]) || 209 (bld.factor[0][j] == bld.factor[1][i] && 210 bld.factor[1][j] == bld.factor[0][i])) 211 break; 212 } 213 214 if(j < i) 215 bld.term[i] = bld.term[j]; 216 else 217 bld.term[i] = lp_build_mul(&bld.base, bld.factor[0][i], bld.factor[1][i]); 218 } 219 220 /* 221 * Combine terms 222 */ 223 for (i = 0; i < 4; ++i) { 224 unsigned func = i < 3 ? blend->rgb_func : blend->alpha_func; 225 boolean func_commutative = lp_build_blend_func_commutative(func); 226 227 /* See if this function has been previously applied */ 228 for(j = 0; j < i; ++j) { 229 unsigned prev_func = j < 3 ? blend->rgb_func : blend->alpha_func; 230 unsigned func_reverse = lp_build_blend_func_reverse(func, prev_func); 231 232 if((!func_reverse && 233 bld.factor[0 + j] == bld.factor[0 + i] && 234 bld.factor[4 + j] == bld.factor[4 + i]) || 235 ((func_commutative || func_reverse) && 236 bld.factor[0 + j] == bld.factor[4 + i] && 237 bld.factor[4 + j] == bld.factor[0 + i])) 238 break; 239 } 240 241 if(j < i) 242 res[i] = res[j]; 243 else 244 res[i] = lp_build_blend_func(&bld.base, func, bld.term[i + 0], bld.term[i + 4]); 245 } 246} 247