swr: [rasterizer core] whitespace cleanup
[mesa.git] / src / gallium / drivers / swr / swr_tex_sample.cpp
1 /**************************************************************************
2 *
3 * Copyright 2009 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 * Largely a copy of llvmpipe's lp_tex_sample.c
30 */
31
32 /**
33 * Texture sampling code generation
34 *
35 * This file is nothing more than ugly glue between three largely independent
36 * entities:
37 * - TGSI -> LLVM translation (i.e., lp_build_tgsi_soa)
38 * - texture sampling code generation (i.e., lp_build_sample_soa)
39 * - SWR driver
40 *
41 * All interesting code is in the functions mentioned above. There is really
42 * nothing to see here.
43 *
44 * @author Jose Fonseca <jfonseca@vmware.com>
45 */
46
47 #include "state.h"
48 #include "JitManager.h"
49 #include "state_llvm.h"
50
51 #include "pipe/p_defines.h"
52 #include "pipe/p_shader_tokens.h"
53 #include "gallivm/lp_bld_debug.h"
54 #include "gallivm/lp_bld_const.h"
55 #include "gallivm/lp_bld_type.h"
56 #include "gallivm/lp_bld_sample.h"
57 #include "gallivm/lp_bld_tgsi.h"
58 #include "util/u_memory.h"
59
60 #include "swr_tex_sample.h"
61 #include "swr_context_llvm.h"
62
63
64 /**
65 * This provides the bridge between the sampler state store in
66 * lp_jit_context and lp_jit_texture and the sampler code
67 * generator. It provides the texture layout information required by
68 * the texture sampler code generator in terms of the state stored in
69 * lp_jit_context and lp_jit_texture in runtime.
70 */
71 struct swr_sampler_dynamic_state {
72 struct lp_sampler_dynamic_state base;
73
74 const struct swr_sampler_static_state *static_state;
75
76 unsigned shader_type;
77 };
78
79
80 /**
81 * This is the bridge between our sampler and the TGSI translator.
82 */
83 struct swr_sampler_soa {
84 struct lp_build_sampler_soa base;
85
86 struct swr_sampler_dynamic_state dynamic_state;
87 };
88
89
90 /**
91 * Fetch the specified member of the lp_jit_texture structure.
92 * \param emit_load if TRUE, emit the LLVM load instruction to actually
93 * fetch the field's value. Otherwise, just emit the
94 * GEP code to address the field.
95 *
96 * @sa http://llvm.org/docs/GetElementPtr.html
97 */
98 static LLVMValueRef
99 swr_texture_member(const struct lp_sampler_dynamic_state *base,
100 struct gallivm_state *gallivm,
101 LLVMValueRef context_ptr,
102 unsigned texture_unit,
103 unsigned member_index,
104 const char *member_name,
105 boolean emit_load)
106 {
107 LLVMBuilderRef builder = gallivm->builder;
108 LLVMValueRef indices[4];
109 LLVMValueRef ptr;
110 LLVMValueRef res;
111
112 assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
113
114 /* context[0] */
115 indices[0] = lp_build_const_int32(gallivm, 0);
116 /* context[0].textures */
117 auto dynamic = (const struct swr_sampler_dynamic_state *)base;
118 switch (dynamic->shader_type) {
119 case PIPE_SHADER_FRAGMENT:
120 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesFS);
121 break;
122 case PIPE_SHADER_VERTEX:
123 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesVS);
124 break;
125 default:
126 assert(0 && "unsupported shader type");
127 break;
128 }
129 /* context[0].textures[unit] */
130 indices[2] = lp_build_const_int32(gallivm, texture_unit);
131 /* context[0].textures[unit].member */
132 indices[3] = lp_build_const_int32(gallivm, member_index);
133
134 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
135
136 if (emit_load)
137 res = LLVMBuildLoad(builder, ptr, "");
138 else
139 res = ptr;
140
141 lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);
142
143 return res;
144 }
145
146
147 /**
148 * Helper macro to instantiate the functions that generate the code to
149 * fetch the members of lp_jit_texture to fulfill the sampler code
150 * generator requests.
151 *
152 * This complexity is the price we have to pay to keep the texture
153 * sampler code generator a reusable module without dependencies to
154 * swr internals.
155 */
156 #define SWR_TEXTURE_MEMBER(_name, _emit_load) \
157 static LLVMValueRef swr_texture_##_name( \
158 const struct lp_sampler_dynamic_state *base, \
159 struct gallivm_state *gallivm, \
160 LLVMValueRef context_ptr, \
161 unsigned texture_unit) \
162 { \
163 return swr_texture_member(base, \
164 gallivm, \
165 context_ptr, \
166 texture_unit, \
167 swr_jit_texture_##_name, \
168 #_name, \
169 _emit_load); \
170 }
171
172
173 SWR_TEXTURE_MEMBER(width, TRUE)
174 SWR_TEXTURE_MEMBER(height, TRUE)
175 SWR_TEXTURE_MEMBER(depth, TRUE)
176 SWR_TEXTURE_MEMBER(first_level, TRUE)
177 SWR_TEXTURE_MEMBER(last_level, TRUE)
178 SWR_TEXTURE_MEMBER(base_ptr, TRUE)
179 SWR_TEXTURE_MEMBER(row_stride, FALSE)
180 SWR_TEXTURE_MEMBER(img_stride, FALSE)
181 SWR_TEXTURE_MEMBER(mip_offsets, FALSE)
182
183
184 /**
185 * Fetch the specified member of the lp_jit_sampler structure.
186 * \param emit_load if TRUE, emit the LLVM load instruction to actually
187 * fetch the field's value. Otherwise, just emit the
188 * GEP code to address the field.
189 *
190 * @sa http://llvm.org/docs/GetElementPtr.html
191 */
192 static LLVMValueRef
193 swr_sampler_member(const struct lp_sampler_dynamic_state *base,
194 struct gallivm_state *gallivm,
195 LLVMValueRef context_ptr,
196 unsigned sampler_unit,
197 unsigned member_index,
198 const char *member_name,
199 boolean emit_load)
200 {
201 LLVMBuilderRef builder = gallivm->builder;
202 LLVMValueRef indices[4];
203 LLVMValueRef ptr;
204 LLVMValueRef res;
205
206 assert(sampler_unit < PIPE_MAX_SAMPLERS);
207
208 /* context[0] */
209 indices[0] = lp_build_const_int32(gallivm, 0);
210 /* context[0].samplers */
211 auto dynamic = (const struct swr_sampler_dynamic_state *)base;
212 switch (dynamic->shader_type) {
213 case PIPE_SHADER_FRAGMENT:
214 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersFS);
215 break;
216 case PIPE_SHADER_VERTEX:
217 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersVS);
218 break;
219 default:
220 assert(0 && "unsupported shader type");
221 break;
222 }
223 /* context[0].samplers[unit] */
224 indices[2] = lp_build_const_int32(gallivm, sampler_unit);
225 /* context[0].samplers[unit].member */
226 indices[3] = lp_build_const_int32(gallivm, member_index);
227
228 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
229
230 if (emit_load)
231 res = LLVMBuildLoad(builder, ptr, "");
232 else
233 res = ptr;
234
235 lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);
236
237 return res;
238 }
239
240
241 #define SWR_SAMPLER_MEMBER(_name, _emit_load) \
242 static LLVMValueRef swr_sampler_##_name( \
243 const struct lp_sampler_dynamic_state *base, \
244 struct gallivm_state *gallivm, \
245 LLVMValueRef context_ptr, \
246 unsigned sampler_unit) \
247 { \
248 return swr_sampler_member(base, \
249 gallivm, \
250 context_ptr, \
251 sampler_unit, \
252 swr_jit_sampler_##_name, \
253 #_name, \
254 _emit_load); \
255 }
256
257
258 SWR_SAMPLER_MEMBER(min_lod, TRUE)
259 SWR_SAMPLER_MEMBER(max_lod, TRUE)
260 SWR_SAMPLER_MEMBER(lod_bias, TRUE)
261 SWR_SAMPLER_MEMBER(border_color, FALSE)
262
263
264 static void
265 swr_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
266 {
267 FREE(sampler);
268 }
269
270
271 /**
272 * Fetch filtered values from texture.
273 * The 'texel' parameter returns four vectors corresponding to R, G, B, A.
274 */
275 static void
276 swr_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
277 struct gallivm_state *gallivm,
278 const struct lp_sampler_params *params)
279 {
280 struct swr_sampler_soa *sampler = (struct swr_sampler_soa *)base;
281 unsigned texture_index = params->texture_index;
282 unsigned sampler_index = params->sampler_index;
283
284 assert(sampler_index < PIPE_MAX_SAMPLERS);
285 assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
286
287 #if 0
288 lp_build_sample_nop(gallivm, params->type, params->coords, params->texel);
289 #else
290 lp_build_sample_soa(
291 &sampler->dynamic_state.static_state[texture_index].texture_state,
292 &sampler->dynamic_state.static_state[sampler_index].sampler_state,
293 &sampler->dynamic_state.base,
294 gallivm,
295 params);
296 #endif
297 }
298
299 /**
300 * Fetch the texture size.
301 */
302 static void
303 swr_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
304 struct gallivm_state *gallivm,
305 const struct lp_sampler_size_query_params *params)
306 {
307 struct swr_sampler_soa *sampler = (struct swr_sampler_soa *)base;
308
309 assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
310
311 lp_build_size_query_soa(
312 gallivm,
313 &sampler->dynamic_state.static_state[params->texture_unit].texture_state,
314 &sampler->dynamic_state.base,
315 params);
316 }
317
318
319 struct lp_build_sampler_soa *
320 swr_sampler_soa_create(const struct swr_sampler_static_state *static_state,
321 unsigned shader_type)
322 {
323 struct swr_sampler_soa *sampler;
324
325 sampler = CALLOC_STRUCT(swr_sampler_soa);
326 if (!sampler)
327 return NULL;
328
329 sampler->base.destroy = swr_sampler_soa_destroy;
330 sampler->base.emit_tex_sample = swr_sampler_soa_emit_fetch_texel;
331 sampler->base.emit_size_query = swr_sampler_soa_emit_size_query;
332 sampler->dynamic_state.base.width = swr_texture_width;
333 sampler->dynamic_state.base.height = swr_texture_height;
334 sampler->dynamic_state.base.depth = swr_texture_depth;
335 sampler->dynamic_state.base.first_level = swr_texture_first_level;
336 sampler->dynamic_state.base.last_level = swr_texture_last_level;
337 sampler->dynamic_state.base.base_ptr = swr_texture_base_ptr;
338 sampler->dynamic_state.base.row_stride = swr_texture_row_stride;
339 sampler->dynamic_state.base.img_stride = swr_texture_img_stride;
340 sampler->dynamic_state.base.mip_offsets = swr_texture_mip_offsets;
341 sampler->dynamic_state.base.min_lod = swr_sampler_min_lod;
342 sampler->dynamic_state.base.max_lod = swr_sampler_max_lod;
343 sampler->dynamic_state.base.lod_bias = swr_sampler_lod_bias;
344 sampler->dynamic_state.base.border_color = swr_sampler_border_color;
345
346 sampler->dynamic_state.static_state = static_state;
347
348 sampler->dynamic_state.shader_type = shader_type;
349
350 return &sampler->base;
351 }