1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
4 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
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.
27 **************************************************************************/
30 * @author Jose Fonseca <jfonseca@vmware.com>
31 * @author Keith Whitwell <keith@tungstengraphics.com>
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"
41 #include "lp_bld_type.h"
42 #include "lp_bld_arit.h"
43 #include "lp_bld_logic.h"
44 #include "lp_bld_blend.h"
45 #include "lp_bld_debug.h"
49 blend_generate(struct llvmpipe_screen
*screen
,
50 struct lp_blend_state
*blend
)
53 struct lp_build_context bld
;
55 LLVMTypeRef int_vec_type
;
56 LLVMTypeRef arg_types
[4];
57 LLVMTypeRef func_type
;
58 LLVMValueRef mask_ptr
;
61 LLVMValueRef const_ptr
;
62 LLVMBasicBlockRef block
;
63 LLVMBuilderRef builder
;
72 type
.floating
= FALSE
;
78 vec_type
= lp_build_vec_type(type
);
79 int_vec_type
= lp_build_int_vec_type(type
);
81 arg_types
[0] = LLVMPointerType(int_vec_type
, 0); /* mask */
82 arg_types
[1] = LLVMPointerType(vec_type
, 0); /* src */
83 arg_types
[2] = LLVMPointerType(vec_type
, 0); /* con */
84 arg_types
[3] = LLVMPointerType(vec_type
, 0); /* dst */
85 func_type
= LLVMFunctionType(LLVMVoidType(), arg_types
, Elements(arg_types
), 0);
86 blend
->function
= LLVMAddFunction(screen
->module
, "blend", func_type
);
87 LLVMSetFunctionCallConv(blend
->function
, LLVMCCallConv
);
89 mask_ptr
= LLVMGetParam(blend
->function
, 0);
90 src_ptr
= LLVMGetParam(blend
->function
, 1);
91 const_ptr
= LLVMGetParam(blend
->function
, 2);
92 dst_ptr
= LLVMGetParam(blend
->function
, 3);
94 block
= LLVMAppendBasicBlock(blend
->function
, "entry");
95 builder
= LLVMCreateBuilder();
96 LLVMPositionBuilderAtEnd(builder
, block
);
98 lp_build_context_init(&bld
, builder
, type
);
100 mask
= LLVMBuildLoad(builder
, mask_ptr
, "mask");
102 for(i
= 0; i
< 4; ++i
) {
103 LLVMValueRef index
= LLVMConstInt(LLVMInt32Type(), i
, 0);
105 src
[i
] = LLVMBuildLoad(builder
, LLVMBuildGEP(builder
, src_ptr
, &index
, 1, ""), "");
106 con
[i
] = LLVMBuildLoad(builder
, LLVMBuildGEP(builder
, const_ptr
, &index
, 1, ""), "");
107 dst
[i
] = LLVMBuildLoad(builder
, LLVMBuildGEP(builder
, dst_ptr
, &index
, 1, ""), "");
109 lp_build_name(src
[i
], "src.%c", "rgba"[i
]);
110 lp_build_name(con
[i
], "con.%c", "rgba"[i
]);
111 lp_build_name(dst
[i
], "dst.%c", "rgba"[i
]);
114 lp_build_blend_soa(builder
, &blend
->base
, type
, src
, dst
, con
, res
);
116 for(i
= 0; i
< 4; ++i
) {
117 LLVMValueRef index
= LLVMConstInt(LLVMInt32Type(), i
, 0);
118 lp_build_name(res
[i
], "res.%c", "rgba"[i
]);
119 res
[i
] = lp_build_select(&bld
, mask
, res
[i
], dst
[i
]);
120 LLVMBuildStore(builder
, res
[i
], LLVMBuildGEP(builder
, dst_ptr
, &index
, 1, ""));
123 LLVMBuildRetVoid(builder
);;
125 LLVMDisposeBuilder(builder
);
130 llvmpipe_create_blend_state(struct pipe_context
*pipe
,
131 const struct pipe_blend_state
*base
)
133 struct llvmpipe_screen
*screen
= llvmpipe_screen(pipe
->screen
);
134 struct lp_blend_state
*blend
;
136 blend
= CALLOC_STRUCT(lp_blend_state
);
142 blend_generate(screen
, blend
);
144 LLVMRunFunctionPassManager(screen
->pass
, blend
->function
);
147 debug_printf("%s=%s %s=%s %s=%s %s=%s %s=%s %s=%s\n",
148 "rgb_func", debug_dump_blend_func (blend
->base
.rgb_func
, TRUE
),
149 "rgb_src_factor", debug_dump_blend_factor(blend
->base
.rgb_src_factor
, TRUE
),
150 "rgb_dst_factor", debug_dump_blend_factor(blend
->base
.rgb_dst_factor
, TRUE
),
151 "alpha_func", debug_dump_blend_func (blend
->base
.alpha_func
, TRUE
),
152 "alpha_src_factor", debug_dump_blend_factor(blend
->base
.alpha_src_factor
, TRUE
),
153 "alpha_dst_factor", debug_dump_blend_factor(blend
->base
.alpha_dst_factor
, TRUE
));
154 LLVMDumpValue(blend
->function
);
158 if(LLVMVerifyFunction(blend
->function
, LLVMPrintMessageAction
)) {
159 LLVMDumpValue(blend
->function
);
163 blend
->jit_function
= (lp_blend_func
)LLVMGetPointerToGlobal(screen
->engine
, blend
->function
);
166 lp_disassemble(blend
->jit_function
);
172 void llvmpipe_bind_blend_state( struct pipe_context
*pipe
,
175 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
177 llvmpipe
->blend
= (struct lp_blend_state
*)blend
;
179 llvmpipe
->dirty
|= LP_NEW_BLEND
;
182 void llvmpipe_delete_blend_state(struct pipe_context
*pipe
,
185 struct llvmpipe_screen
*screen
= llvmpipe_screen(pipe
->screen
);
186 struct lp_blend_state
*blend
= (struct lp_blend_state
*)_blend
;
188 if(blend
->function
) {
189 if(blend
->jit_function
)
190 LLVMFreeMachineCodeForFunction(screen
->engine
, blend
->function
);
191 LLVMDeleteFunction(blend
->function
);
198 void llvmpipe_set_blend_color( struct pipe_context
*pipe
,
199 const struct pipe_blend_color
*blend_color
)
201 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
204 for (i
= 0; i
< 4; ++i
)
205 for (j
= 0; j
< 16; ++j
)
206 llvmpipe
->blend_color
[i
][j
] = float_to_ubyte(blend_color
->color
[i
]);
208 llvmpipe
->dirty
|= LP_NEW_BLEND
;
212 /** XXX move someday? Or consolidate all these simple state setters
218 llvmpipe_create_depth_stencil_state(struct pipe_context
*pipe
,
219 const struct pipe_depth_stencil_alpha_state
*depth_stencil
)
221 return mem_dup(depth_stencil
, sizeof(*depth_stencil
));
225 llvmpipe_bind_depth_stencil_state(struct pipe_context
*pipe
,
228 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
230 llvmpipe
->depth_stencil
= (const struct pipe_depth_stencil_alpha_state
*)depth_stencil
;
232 llvmpipe
->dirty
|= LP_NEW_DEPTH_STENCIL_ALPHA
;
236 llvmpipe_delete_depth_stencil_state(struct pipe_context
*pipe
, void *depth
)