lp_state_blend.c revision 2101c2941c1ff3ae7f3f587e6e9921ed336ce17c
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29/** 30 * @author Jose Fonseca <jfonseca@vmware.com> 31 * @author Keith Whitwell <keith@tungstengraphics.com> 32 */ 33 34#include "util/u_memory.h" 35#include "util/u_math.h" 36#include "util/u_debug_dump.h" 37#include "lp_screen.h" 38#include "lp_context.h" 39#include "lp_state.h" 40 41#include "lp_bld_type.h" 42#include "lp_bld_arit.h" 43#include "lp_bld_blend.h" 44 45 46static void 47blend_generate(struct llvmpipe_screen *screen, 48 struct lp_blend_state *blend) 49{ 50 union lp_type type; 51 LLVMTypeRef vec_type; 52 LLVMTypeRef args[4]; 53 LLVMValueRef src_ptr; 54 LLVMValueRef dst_ptr; 55 LLVMValueRef const_ptr; 56 LLVMValueRef res_ptr; 57 LLVMBasicBlockRef block; 58 LLVMBuilderRef builder; 59 LLVMValueRef src[4]; 60 LLVMValueRef dst[4]; 61 LLVMValueRef con[4]; 62 LLVMValueRef res[4]; 63 char src_name[5] = "src?"; 64 char dst_name[5] = "dst?"; 65 char con_name[5] = "con?"; 66 char res_name[5] = "res?"; 67 unsigned i; 68 69 type.value = 0; 70 type.floating = FALSE; 71 type.sign = FALSE; 72 type.norm = TRUE; 73 type.width = 8; 74 type.length = 16; 75 76 vec_type = lp_build_vec_type(type); 77 78 args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0); 79 blend->function = LLVMAddFunction(screen->module, "blend", LLVMFunctionType(LLVMVoidType(), args, 4, 0)); 80 LLVMSetFunctionCallConv(blend->function, LLVMCCallConv); 81 src_ptr = LLVMGetParam(blend->function, 0); 82 dst_ptr = LLVMGetParam(blend->function, 1); 83 const_ptr = LLVMGetParam(blend->function, 2); 84 res_ptr = LLVMGetParam(blend->function, 3); 85 86 block = LLVMAppendBasicBlock(blend->function, "entry"); 87 builder = LLVMCreateBuilder(); 88 LLVMPositionBuilderAtEnd(builder, block); 89 90 for(i = 0; i < 4; ++i) { 91 LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); 92 con_name[3] = dst_name[3] = src_name[3] = "rgba"[i]; 93 src[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, src_ptr, &index, 1, ""), src_name); 94 dst[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), dst_name); 95 con[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), con_name); 96 } 97 98 lp_build_blend_soa(builder, &blend->base, type, src, dst, con, res); 99 100 for(i = 0; i < 4; ++i) { 101 LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); 102 res_name[3] = "rgba"[i]; 103 LLVMSetValueName(res[i], res_name); 104 LLVMBuildStore(builder, res[i], LLVMBuildGEP(builder, res_ptr, &index, 1, "")); 105 } 106 107 LLVMBuildRetVoid(builder);; 108 109 LLVMDisposeBuilder(builder); 110} 111 112 113void * 114llvmpipe_create_blend_state(struct pipe_context *pipe, 115 const struct pipe_blend_state *base) 116{ 117 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 118 struct lp_blend_state *blend; 119 120 blend = CALLOC_STRUCT(lp_blend_state); 121 if(!blend) 122 return NULL; 123 124 blend->base = *base; 125 126 blend_generate(screen, blend); 127 128 LLVMRunFunctionPassManager(screen->pass, blend->function); 129 130#if 1 131 debug_printf("%s=%s %s=%s %s=%s %s=%s %s=%s %s=%s\n", 132 "rgb_func", debug_dump_blend_func (blend->base.rgb_func, TRUE), 133 "rgb_src_factor", debug_dump_blend_factor(blend->base.rgb_src_factor, TRUE), 134 "rgb_dst_factor", debug_dump_blend_factor(blend->base.rgb_dst_factor, TRUE), 135 "alpha_func", debug_dump_blend_func (blend->base.alpha_func, TRUE), 136 "alpha_src_factor", debug_dump_blend_factor(blend->base.alpha_src_factor, TRUE), 137 "alpha_dst_factor", debug_dump_blend_factor(blend->base.alpha_dst_factor, TRUE)); 138 LLVMDumpModule(screen->module); 139 debug_printf("\n"); 140#endif 141 142 if(LLVMVerifyFunction(blend->function, LLVMPrintMessageAction)) { 143 LLVMDumpModule(screen->module); 144 abort(); 145 } 146 147 blend->jit_function = (lp_blend_func)LLVMGetPointerToGlobal(screen->engine, blend->function); 148 149 return blend; 150} 151 152void llvmpipe_bind_blend_state( struct pipe_context *pipe, 153 void *blend ) 154{ 155 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 156 157 llvmpipe->blend = (struct lp_blend_state *)blend; 158 159 llvmpipe->dirty |= LP_NEW_BLEND; 160} 161 162void llvmpipe_delete_blend_state(struct pipe_context *pipe, 163 void *_blend) 164{ 165 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 166 struct lp_blend_state *blend = (struct lp_blend_state *)_blend; 167 168 if(blend->function) { 169 if(blend->jit_function) 170 LLVMFreeMachineCodeForFunction(screen->engine, blend->function); 171 LLVMDeleteFunction(blend->function); 172 } 173 174 FREE( blend ); 175} 176 177 178void llvmpipe_set_blend_color( struct pipe_context *pipe, 179 const struct pipe_blend_color *blend_color ) 180{ 181 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 182 unsigned i, j; 183 184 for (i = 0; i < 4; ++i) 185 for (j = 0; j < 16; ++j) 186 llvmpipe->blend_color[i][j] = float_to_ubyte(blend_color->color[i]); 187 188 llvmpipe->dirty |= LP_NEW_BLEND; 189} 190 191 192/** XXX move someday? Or consolidate all these simple state setters 193 * into one file. 194 */ 195 196 197void * 198llvmpipe_create_depth_stencil_state(struct pipe_context *pipe, 199 const struct pipe_depth_stencil_alpha_state *depth_stencil) 200{ 201 return mem_dup(depth_stencil, sizeof(*depth_stencil)); 202} 203 204void 205llvmpipe_bind_depth_stencil_state(struct pipe_context *pipe, 206 void *depth_stencil) 207{ 208 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 209 210 llvmpipe->depth_stencil = (const struct pipe_depth_stencil_alpha_state *)depth_stencil; 211 212 llvmpipe->dirty |= LP_NEW_DEPTH_STENCIL_ALPHA; 213} 214 215void 216llvmpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth) 217{ 218 FREE( depth ); 219} 220