Merge remote branch 'origin/master' into glsl2
[mesa.git] / src / gallium / auxiliary / draw / draw_llvm_sample.c
1 /**************************************************************************
2 *
3 * Copyright 2010 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 * Texture sampling code generation
30 * @author Jose Fonseca <jfonseca@vmware.com>
31 */
32
33 #include "pipe/p_defines.h"
34 #include "pipe/p_shader_tokens.h"
35 #include "gallivm/lp_bld_debug.h"
36 #include "gallivm/lp_bld_type.h"
37 #include "gallivm/lp_bld_sample.h"
38 #include "gallivm/lp_bld_tgsi.h"
39
40
41 #include "util/u_debug.h"
42 #include "util/u_memory.h"
43 #include "util/u_pointer.h"
44 #include "util/u_string.h"
45
46 #include "draw_llvm.h"
47
48
49 /**
50 * This provides the bridge between the sampler state store in
51 * lp_jit_context and lp_jit_texture and the sampler code
52 * generator. It provides the texture layout information required by
53 * the texture sampler code generator in terms of the state stored in
54 * lp_jit_context and lp_jit_texture in runtime.
55 */
56 struct draw_llvm_sampler_dynamic_state
57 {
58 struct lp_sampler_dynamic_state base;
59
60 const struct lp_sampler_static_state *static_state;
61
62 LLVMValueRef context_ptr;
63 };
64
65
66 /**
67 * This is the bridge between our sampler and the TGSI translator.
68 */
69 struct draw_llvm_sampler_soa
70 {
71 struct lp_build_sampler_soa base;
72
73 struct draw_llvm_sampler_dynamic_state dynamic_state;
74 };
75
76
77 /**
78 * Fetch the specified member of the lp_jit_texture structure.
79 * \param emit_load if TRUE, emit the LLVM load instruction to actually
80 * fetch the field's value. Otherwise, just emit the
81 * GEP code to address the field.
82 *
83 * @sa http://llvm.org/docs/GetElementPtr.html
84 */
85 static LLVMValueRef
86 draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
87 LLVMBuilderRef builder,
88 unsigned unit,
89 unsigned member_index,
90 const char *member_name,
91 boolean emit_load)
92 {
93 struct draw_llvm_sampler_dynamic_state *state =
94 (struct draw_llvm_sampler_dynamic_state *)base;
95 LLVMValueRef indices[4];
96 LLVMValueRef ptr;
97 LLVMValueRef res;
98
99 debug_assert(unit < PIPE_MAX_VERTEX_SAMPLERS);
100
101 /* context[0] */
102 indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
103 /* context[0].textures */
104 indices[1] = LLVMConstInt(LLVMInt32Type(), DRAW_JIT_CTX_TEXTURES, 0);
105 /* context[0].textures[unit] */
106 indices[2] = LLVMConstInt(LLVMInt32Type(), unit, 0);
107 /* context[0].textures[unit].member */
108 indices[3] = LLVMConstInt(LLVMInt32Type(), member_index, 0);
109
110 ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
111
112 if (emit_load)
113 res = LLVMBuildLoad(builder, ptr, "");
114 else
115 res = ptr;
116
117 lp_build_name(res, "context.texture%u.%s", unit, member_name);
118
119 return res;
120 }
121
122
123 /**
124 * Helper macro to instantiate the functions that generate the code to
125 * fetch the members of lp_jit_texture to fulfill the sampler code
126 * generator requests.
127 *
128 * This complexity is the price we have to pay to keep the texture
129 * sampler code generator a reusable module without dependencies to
130 * llvmpipe internals.
131 */
132 #define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \
133 static LLVMValueRef \
134 draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
135 LLVMBuilderRef builder, \
136 unsigned unit) \
137 { \
138 return draw_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \
139 }
140
141
142 DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE)
143 DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE)
144 DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE)
145 DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE)
146 DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE)
147 DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE)
148 DRAW_LLVM_TEXTURE_MEMBER(data_ptr, DRAW_JIT_TEXTURE_DATA, FALSE)
149
150
151 static void
152 draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
153 {
154 FREE(sampler);
155 }
156
157
158 /**
159 * Fetch filtered values from texture.
160 * The 'texel' parameter returns four vectors corresponding to R, G, B, A.
161 */
162 static void
163 draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
164 LLVMBuilderRef builder,
165 struct lp_type type,
166 unsigned unit,
167 unsigned num_coords,
168 const LLVMValueRef *coords,
169 const LLVMValueRef *ddx,
170 const LLVMValueRef *ddy,
171 LLVMValueRef lod_bias, /* optional */
172 LLVMValueRef explicit_lod, /* optional */
173 LLVMValueRef *texel)
174 {
175 struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
176
177 assert(unit < PIPE_MAX_VERTEX_SAMPLERS);
178
179 lp_build_sample_soa(builder,
180 &sampler->dynamic_state.static_state[unit],
181 &sampler->dynamic_state.base,
182 type,
183 unit,
184 num_coords, coords,
185 ddx, ddy,
186 lod_bias, explicit_lod,
187 texel);
188 }
189
190
191 struct lp_build_sampler_soa *
192 draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
193 LLVMValueRef context_ptr)
194 {
195 struct draw_llvm_sampler_soa *sampler;
196
197 sampler = CALLOC_STRUCT(draw_llvm_sampler_soa);
198 if(!sampler)
199 return NULL;
200
201 sampler->base.destroy = draw_llvm_sampler_soa_destroy;
202 sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel;
203 sampler->dynamic_state.base.width = draw_llvm_texture_width;
204 sampler->dynamic_state.base.height = draw_llvm_texture_height;
205 sampler->dynamic_state.base.depth = draw_llvm_texture_depth;
206 sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level;
207 sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride;
208 sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride;
209 sampler->dynamic_state.base.data_ptr = draw_llvm_texture_data_ptr;
210 sampler->dynamic_state.static_state = static_state;
211 sampler->dynamic_state.context_ptr = context_ptr;
212
213 return &sampler->base;
214 }
215