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