llvmpipe: Tiles in rgba8 format.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_state_blend.c
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
46 static void
47 blend_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
113 void *
114 llvmpipe_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
152 void 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
162 void 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
178 void 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
197 void *
198 llvmpipe_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
204 void
205 llvmpipe_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
215 void
216 llvmpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)
217 {
218 FREE( depth );
219 }