1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
32 * @author Jose Fonseca <jfonseca@vmware.com>
35 #include "pipe/p_defines.h"
36 #include "pipe/p_state.h"
37 #include "util/u_debug.h"
38 #include "util/u_memory.h"
39 #include "util/u_math.h"
40 #include "util/u_format.h"
41 #include "lp_bld_debug.h"
42 #include "lp_bld_type.h"
43 #include "lp_bld_const.h"
44 #include "lp_bld_arit.h"
45 #include "lp_bld_logic.h"
46 #include "lp_bld_swizzle.h"
47 #include "lp_bld_format.h"
48 #include "lp_bld_sample.h"
52 lp_sampler_static_state(struct lp_sampler_static_state
*state
,
53 const struct pipe_texture
*texture
,
54 const struct pipe_sampler_state
*sampler
)
56 memset(state
, 0, sizeof *state
);
64 state
->format
= texture
->format
;
65 state
->target
= texture
->target
;
66 state
->pot_width
= util_is_pot(texture
->width
[0]);
67 state
->pot_height
= util_is_pot(texture
->height
[0]);
68 state
->pot_depth
= util_is_pot(texture
->depth
[0]);
70 state
->wrap_s
= sampler
->wrap_s
;
71 state
->wrap_t
= sampler
->wrap_t
;
72 state
->wrap_r
= sampler
->wrap_r
;
73 state
->min_img_filter
= sampler
->min_img_filter
;
74 state
->min_mip_filter
= sampler
->min_mip_filter
;
75 state
->mag_img_filter
= sampler
->mag_img_filter
;
76 if(sampler
->compare_mode
) {
77 state
->compare_mode
= sampler
->compare_mode
;
78 state
->compare_func
= sampler
->compare_func
;
80 state
->normalized_coords
= sampler
->normalized_coords
;
81 state
->prefilter
= sampler
->prefilter
;
87 * Keep all information for sampling code generation in a single place.
89 struct lp_build_sample_context
91 LLVMBuilderRef builder
;
93 const struct lp_sampler_static_state
*static_state
;
95 struct lp_sampler_dynamic_state
*dynamic_state
;
97 const struct util_format_description
*format_desc
;
99 /** Incoming coordinates type and build context */
100 union lp_type coord_type
;
101 struct lp_build_context coord_bld
;
103 /** Integer coordinates */
104 union lp_type int_coord_type
;
105 struct lp_build_context int_coord_bld
;
107 /** Output texels type and build context */
108 union lp_type texel_type
;
109 struct lp_build_context texel_bld
;
114 lp_build_sample_texel(struct lp_build_sample_context
*bld
,
117 LLVMValueRef y_stride
,
118 LLVMValueRef data_ptr
,
121 struct lp_build_context
*int_coord_bld
= &bld
->int_coord_bld
;
122 LLVMValueRef x_stride
;
125 x_stride
= lp_build_const_scalar(bld
->int_coord_type
, bld
->format_desc
->block
.bits
/8);
127 if(bld
->format_desc
->colorspace
== UTIL_FORMAT_COLORSPACE_ZS
) {
128 LLVMValueRef x_lo
, x_hi
;
129 LLVMValueRef y_lo
, y_hi
;
130 LLVMValueRef x_stride_lo
, x_stride_hi
;
131 LLVMValueRef y_stride_lo
, y_stride_hi
;
132 LLVMValueRef x_offset_lo
, x_offset_hi
;
133 LLVMValueRef y_offset_lo
, y_offset_hi
;
134 LLVMValueRef offset_lo
, offset_hi
;
136 x_lo
= LLVMBuildAnd(bld
->builder
, x
, int_coord_bld
->one
, "");
137 y_lo
= LLVMBuildAnd(bld
->builder
, y
, int_coord_bld
->one
, "");
139 x_hi
= LLVMBuildLShr(bld
->builder
, x
, int_coord_bld
->one
, "");
140 y_hi
= LLVMBuildLShr(bld
->builder
, y
, int_coord_bld
->one
, "");
142 x_stride_lo
= x_stride
;
143 y_stride_lo
= lp_build_const_scalar(bld
->int_coord_type
, 2*bld
->format_desc
->block
.bits
/8);
145 x_stride_hi
= lp_build_const_scalar(bld
->int_coord_type
, 4*bld
->format_desc
->block
.bits
/8);
146 y_stride_hi
= LLVMBuildShl(bld
->builder
, y_stride
, int_coord_bld
->one
, "");
148 x_offset_lo
= lp_build_mul(int_coord_bld
, x_lo
, x_stride_lo
);
149 y_offset_lo
= lp_build_mul(int_coord_bld
, y_lo
, y_stride_lo
);
150 offset_lo
= lp_build_add(int_coord_bld
, x_offset_lo
, y_offset_lo
);
152 x_offset_hi
= lp_build_mul(int_coord_bld
, x_hi
, x_stride_hi
);
153 y_offset_hi
= lp_build_mul(int_coord_bld
, y_hi
, y_stride_hi
);
154 offset_hi
= lp_build_add(int_coord_bld
, x_offset_hi
, y_offset_hi
);
156 offset
= lp_build_add(int_coord_bld
, offset_hi
, offset_lo
);
159 LLVMValueRef x_offset
;
160 LLVMValueRef y_offset
;
162 x_offset
= lp_build_mul(int_coord_bld
, x
, x_stride
);
163 y_offset
= lp_build_mul(int_coord_bld
, y
, y_stride
);
165 offset
= lp_build_add(int_coord_bld
, x_offset
, y_offset
);
168 lp_build_load_rgba_soa(bld
->builder
,
178 lp_build_sample_wrap(struct lp_build_sample_context
*bld
,
184 struct lp_build_context
*int_coord_bld
= &bld
->int_coord_bld
;
185 LLVMValueRef length_minus_one
;
187 length_minus_one
= lp_build_sub(int_coord_bld
, length
, int_coord_bld
->one
);
190 case PIPE_TEX_WRAP_REPEAT
:
192 coord
= LLVMBuildAnd(bld
->builder
, coord
, length_minus_one
, "");
194 /* Signed remainder won't give the right results for negative
195 * dividends but unsigned remainder does.*/
196 coord
= LLVMBuildURem(bld
->builder
, coord
, length
, "");
199 case PIPE_TEX_WRAP_CLAMP
:
200 coord
= lp_build_max(int_coord_bld
, coord
, int_coord_bld
->zero
);
201 coord
= lp_build_min(int_coord_bld
, coord
, length_minus_one
);
204 case PIPE_TEX_WRAP_CLAMP_TO_EDGE
:
205 case PIPE_TEX_WRAP_CLAMP_TO_BORDER
:
206 case PIPE_TEX_WRAP_MIRROR_REPEAT
:
207 case PIPE_TEX_WRAP_MIRROR_CLAMP
:
208 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE
:
209 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER
:
220 lp_build_sample_2d_nearest_soa(struct lp_build_sample_context
*bld
,
226 LLVMValueRef data_ptr
,
232 x
= lp_build_ifloor(&bld
->coord_bld
, s
);
233 y
= lp_build_ifloor(&bld
->coord_bld
, t
);
235 x
= lp_build_sample_wrap(bld
, x
, width
, bld
->static_state
->pot_width
, bld
->static_state
->wrap_s
);
236 y
= lp_build_sample_wrap(bld
, y
, height
, bld
->static_state
->pot_height
, bld
->static_state
->wrap_t
);
238 lp_build_sample_texel(bld
, x
, y
, stride
, data_ptr
, texel
);
243 lp_build_sample_2d_linear_soa(struct lp_build_sample_context
*bld
,
249 LLVMValueRef data_ptr
,
253 LLVMValueRef s_ipart
;
254 LLVMValueRef t_ipart
;
255 LLVMValueRef s_fpart
;
256 LLVMValueRef t_fpart
;
259 LLVMValueRef neighbors
[2][2][4];
262 half
= lp_build_const_scalar(bld
->coord_type
, 0.5);
263 s
= lp_build_sub(&bld
->coord_bld
, s
, half
);
264 t
= lp_build_sub(&bld
->coord_bld
, t
, half
);
266 s_ipart
= lp_build_floor(&bld
->coord_bld
, s
);
267 t_ipart
= lp_build_floor(&bld
->coord_bld
, t
);
269 s_fpart
= lp_build_sub(&bld
->coord_bld
, s
, s_ipart
);
270 t_fpart
= lp_build_sub(&bld
->coord_bld
, t
, t_ipart
);
272 x0
= lp_build_int(&bld
->coord_bld
, s_ipart
);
273 y0
= lp_build_int(&bld
->coord_bld
, t_ipart
);
275 x0
= lp_build_sample_wrap(bld
, x0
, width
, bld
->static_state
->pot_width
, bld
->static_state
->wrap_s
);
276 y0
= lp_build_sample_wrap(bld
, y0
, height
, bld
->static_state
->pot_height
, bld
->static_state
->wrap_t
);
278 x1
= lp_build_add(&bld
->int_coord_bld
, x0
, bld
->int_coord_bld
.one
);
279 y1
= lp_build_add(&bld
->int_coord_bld
, y0
, bld
->int_coord_bld
.one
);
281 x1
= lp_build_sample_wrap(bld
, x1
, width
, bld
->static_state
->pot_width
, bld
->static_state
->wrap_s
);
282 y1
= lp_build_sample_wrap(bld
, y1
, height
, bld
->static_state
->pot_height
, bld
->static_state
->wrap_t
);
284 lp_build_sample_texel(bld
, x0
, y0
, stride
, data_ptr
, neighbors
[0][0]);
285 lp_build_sample_texel(bld
, x1
, y0
, stride
, data_ptr
, neighbors
[0][1]);
286 lp_build_sample_texel(bld
, x0
, y1
, stride
, data_ptr
, neighbors
[1][0]);
287 lp_build_sample_texel(bld
, x1
, y1
, stride
, data_ptr
, neighbors
[1][1]);
289 /* TODO: Don't interpolate missing channels */
290 for(chan
= 0; chan
< 4; ++chan
) {
291 texel
[chan
] = lp_build_lerp_2d(&bld
->texel_bld
,
293 neighbors
[0][0][chan
],
294 neighbors
[0][1][chan
],
295 neighbors
[1][0][chan
],
296 neighbors
[1][1][chan
]);
302 lp_build_sample_compare(struct lp_build_sample_context
*bld
,
306 struct lp_build_context
*texel_bld
= &bld
->texel_bld
;
310 if(!bld
->static_state
->compare_mode
)
313 /* TODO: Compare before swizzling, to avoid redundant computations */
315 for(chan
= 0; chan
< 4; ++chan
) {
317 cmp
= lp_build_cmp(texel_bld
, bld
->static_state
->compare_func
, p
, texel
[chan
]);
318 cmp
= lp_build_select(texel_bld
, cmp
, texel_bld
->one
, texel_bld
->zero
);
321 res
= lp_build_add(texel_bld
, res
, cmp
);
327 res
= lp_build_mul(texel_bld
, res
, lp_build_const_scalar(texel_bld
->type
, 0.25));
329 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
330 for(chan
= 0; chan
< 3; ++chan
)
332 texel
[3] = texel_bld
->one
;
337 lp_build_sample_soa(LLVMBuilderRef builder
,
338 const struct lp_sampler_static_state
*static_state
,
339 struct lp_sampler_dynamic_state
*dynamic_state
,
343 const LLVMValueRef
*coords
,
344 LLVMValueRef lodbias
,
347 struct lp_build_sample_context bld
;
351 LLVMValueRef data_ptr
;
356 /* Setup our build context */
357 memset(&bld
, 0, sizeof bld
);
358 bld
.builder
= builder
;
359 bld
.static_state
= static_state
;
360 bld
.dynamic_state
= dynamic_state
;
361 bld
.format_desc
= util_format_description(static_state
->format
);
362 bld
.coord_type
= type
;
363 bld
.int_coord_type
= lp_int_type(type
);
364 bld
.texel_type
= type
;
365 lp_build_context_init(&bld
.coord_bld
, builder
, bld
.coord_type
);
366 lp_build_context_init(&bld
.int_coord_bld
, builder
, bld
.int_coord_type
);
367 lp_build_context_init(&bld
.texel_bld
, builder
, bld
.texel_type
);
369 /* Get the dynamic state */
370 width
= dynamic_state
->width(dynamic_state
, builder
, unit
);
371 height
= dynamic_state
->height(dynamic_state
, builder
, unit
);
372 stride
= dynamic_state
->stride(dynamic_state
, builder
, unit
);
373 data_ptr
= dynamic_state
->data_ptr(dynamic_state
, builder
, unit
);
379 width
= lp_build_broadcast_scalar(&bld
.int_coord_bld
, width
);
380 height
= lp_build_broadcast_scalar(&bld
.int_coord_bld
, height
);
381 stride
= lp_build_broadcast_scalar(&bld
.int_coord_bld
, stride
);
383 if(static_state
->target
== PIPE_TEXTURE_1D
)
384 t
= bld
.coord_bld
.zero
;
386 if(static_state
->normalized_coords
) {
387 LLVMTypeRef coord_vec_type
= lp_build_vec_type(bld
.coord_type
);
388 LLVMValueRef fp_width
= LLVMBuildSIToFP(builder
, width
, coord_vec_type
, "");
389 LLVMValueRef fp_height
= LLVMBuildSIToFP(builder
, height
, coord_vec_type
, "");
390 s
= lp_build_mul(&bld
.coord_bld
, s
, fp_width
);
391 t
= lp_build_mul(&bld
.coord_bld
, t
, fp_height
);
394 switch (static_state
->min_img_filter
) {
395 case PIPE_TEX_FILTER_NEAREST
:
396 lp_build_sample_2d_nearest_soa(&bld
, s
, t
, width
, height
, stride
, data_ptr
, texel
);
398 case PIPE_TEX_FILTER_LINEAR
:
399 case PIPE_TEX_FILTER_ANISO
:
400 lp_build_sample_2d_linear_soa(&bld
, s
, t
, width
, height
, stride
, data_ptr
, texel
);
406 /* FIXME: respect static_state->min_mip_filter */;
407 /* FIXME: respect static_state->mag_img_filter */;
408 /* FIXME: respect static_state->prefilter */;
410 lp_build_sample_compare(&bld
, p
, texel
);