summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Scheidegger <sroland@vmware.com>2013-03-01 02:25:13 +0100
committerRoland Scheidegger <sroland@vmware.com>2013-03-02 02:54:30 +0100
commitb3b3b389fa7756869e7a8bc2755bce081c94945f (patch)
tree127e2e87e309c97dd503c55d2c94bf818cf55ec1
parenta99eb5c83fd64d64fee2b6d7f2bb3fea3264ce47 (diff)
gallivm: add support for texel offsets for ordinary texturing.
This was previously only handled for texelFetch (much easier). Depending on the wrap mode this works slightly differently (for somewhat efficient implementation), hence have to do that separately in all roughly 137 places - it is easy if we use fixed point coords for wrapping, however some wrapping modes are near impossible with fixed point (the repeat stuff) hence we have to normalize the offsets if we can't do the wrapping in unnormalized space (which is a division which is slow but should still be much better than the alternative, which would be integer modulo for wrapping which is just unusable). This should still give accurate results in all cases that really matter, though it might be not quite conformant behavior for some apis (but we have much worse problems there anyway even without using offsets). (Untested, no piglit test.) Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c130
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_aos.h1
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c132
3 files changed, 210 insertions, 53 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
index bddff2c4a13..16d57189ed4 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
@@ -64,9 +64,11 @@
64 * for scaled integer texcoords. 64 * for scaled integer texcoords.
65 * \param block_length is the length of the pixel block along the 65 * \param block_length is the length of the pixel block along the
66 * coordinate axis 66 * coordinate axis
67 * \param coord the incoming texcoord (s,t,r or q) scaled to the texture size 67 * \param coord the incoming texcoord (s,t or r) scaled to the texture size
68 * \param coord_f the incoming texcoord (s,t or r) as float vec
68 * \param length the texture size along one dimension 69 * \param length the texture size along one dimension
69 * \param stride pixel stride along the coordinate axis (in bytes) 70 * \param stride pixel stride along the coordinate axis (in bytes)
71 * \param offset the texel offset along the coord axis
70 * \param is_pot if TRUE, length is a power of two 72 * \param is_pot if TRUE, length is a power of two
71 * \param wrap_mode one of PIPE_TEX_WRAP_x 73 * \param wrap_mode one of PIPE_TEX_WRAP_x
72 * \param out_offset byte offset for the wrapped coordinate 74 * \param out_offset byte offset for the wrapped coordinate
@@ -79,6 +81,7 @@ lp_build_sample_wrap_nearest_int(struct lp_build_sample_context *bld,
79 LLVMValueRef coord_f, 81 LLVMValueRef coord_f,
80 LLVMValueRef length, 82 LLVMValueRef length,
81 LLVMValueRef stride, 83 LLVMValueRef stride,
84 LLVMValueRef offset,
82 boolean is_pot, 85 boolean is_pot,
83 unsigned wrap_mode, 86 unsigned wrap_mode,
84 LLVMValueRef *out_offset, 87 LLVMValueRef *out_offset,
@@ -97,6 +100,11 @@ lp_build_sample_wrap_nearest_int(struct lp_build_sample_context *bld,
97 else { 100 else {
98 struct lp_build_context *coord_bld = &bld->coord_bld; 101 struct lp_build_context *coord_bld = &bld->coord_bld;
99 LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length); 102 LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length);
103 if (offset) {
104 offset = lp_build_int_to_float(coord_bld, offset);
105 offset = lp_build_div(coord_bld, offset, length_f);
106 coord_f = lp_build_add(coord_bld, coord_f, offset);
107 }
100 coord = lp_build_fract_safe(coord_bld, coord_f); 108 coord = lp_build_fract_safe(coord_bld, coord_f);
101 coord = lp_build_mul(coord_bld, coord, length_f); 109 coord = lp_build_mul(coord_bld, coord, length_f);
102 coord = lp_build_itrunc(coord_bld, coord); 110 coord = lp_build_itrunc(coord_bld, coord);
@@ -126,8 +134,9 @@ lp_build_sample_wrap_nearest_int(struct lp_build_sample_context *bld,
126/** 134/**
127 * Build LLVM code for texture coord wrapping, for nearest filtering, 135 * Build LLVM code for texture coord wrapping, for nearest filtering,
128 * for float texcoords. 136 * for float texcoords.
129 * \param coord the incoming texcoord (s,t,r or q) 137 * \param coord the incoming texcoord (s,t or r)
130 * \param length the texture size along one dimension 138 * \param length the texture size along one dimension
139 * \param offset the texel offset along the coord axis
131 * \param is_pot if TRUE, length is a power of two 140 * \param is_pot if TRUE, length is a power of two
132 * \param wrap_mode one of PIPE_TEX_WRAP_x 141 * \param wrap_mode one of PIPE_TEX_WRAP_x
133 * \param icoord the texcoord after wrapping, as int 142 * \param icoord the texcoord after wrapping, as int
@@ -136,6 +145,7 @@ static void
136lp_build_sample_wrap_nearest_float(struct lp_build_sample_context *bld, 145lp_build_sample_wrap_nearest_float(struct lp_build_sample_context *bld,
137 LLVMValueRef coord, 146 LLVMValueRef coord,
138 LLVMValueRef length, 147 LLVMValueRef length,
148 LLVMValueRef offset,
139 boolean is_pot, 149 boolean is_pot,
140 unsigned wrap_mode, 150 unsigned wrap_mode,
141 LLVMValueRef *icoord) 151 LLVMValueRef *icoord)
@@ -145,6 +155,12 @@ lp_build_sample_wrap_nearest_float(struct lp_build_sample_context *bld,
145 155
146 switch(wrap_mode) { 156 switch(wrap_mode) {
147 case PIPE_TEX_WRAP_REPEAT: 157 case PIPE_TEX_WRAP_REPEAT:
158 if (offset) {
159 /* this is definitely not ideal for POT case */
160 offset = lp_build_int_to_float(coord_bld, offset);
161 offset = lp_build_div(coord_bld, offset, length);
162 coord = lp_build_add(coord_bld, coord, offset);
163 }
148 /* take fraction, unnormalize */ 164 /* take fraction, unnormalize */
149 coord = lp_build_fract_safe(coord_bld, coord); 165 coord = lp_build_fract_safe(coord_bld, coord);
150 coord = lp_build_mul(coord_bld, coord, length); 166 coord = lp_build_mul(coord_bld, coord, length);
@@ -156,6 +172,10 @@ lp_build_sample_wrap_nearest_float(struct lp_build_sample_context *bld,
156 /* scale coord to length */ 172 /* scale coord to length */
157 coord = lp_build_mul(coord_bld, coord, length); 173 coord = lp_build_mul(coord_bld, coord, length);
158 } 174 }
175 if (offset) {
176 offset = lp_build_int_to_float(coord_bld, offset);
177 coord = lp_build_add(coord_bld, coord, offset);
178 }
159 coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, 179 coord = lp_build_clamp(coord_bld, coord, coord_bld->zero,
160 length_minus_one); 180 length_minus_one);
161 *icoord = lp_build_itrunc(coord_bld, coord); 181 *icoord = lp_build_itrunc(coord_bld, coord);
@@ -178,9 +198,11 @@ lp_build_sample_wrap_nearest_float(struct lp_build_sample_context *bld,
178 * for scaled integer texcoords. 198 * for scaled integer texcoords.
179 * \param block_length is the length of the pixel block along the 199 * \param block_length is the length of the pixel block along the
180 * coordinate axis 200 * coordinate axis
181 * \param coord0 the incoming texcoord (s,t,r or q) scaled to the texture size 201 * \param coord0 the incoming texcoord (s,t or r) scaled to the texture size
202 * \param coord_f the incoming texcoord (s,t or r) as float vec
182 * \param length the texture size along one dimension 203 * \param length the texture size along one dimension
183 * \param stride pixel stride along the coordinate axis (in bytes) 204 * \param stride pixel stride along the coordinate axis (in bytes)
205 * \param offset the texel offset along the coord axis
184 * \param is_pot if TRUE, length is a power of two 206 * \param is_pot if TRUE, length is a power of two
185 * \param wrap_mode one of PIPE_TEX_WRAP_x 207 * \param wrap_mode one of PIPE_TEX_WRAP_x
186 * \param offset0 resulting relative offset for coord0 208 * \param offset0 resulting relative offset for coord0
@@ -196,6 +218,7 @@ lp_build_sample_wrap_linear_int(struct lp_build_sample_context *bld,
196 LLVMValueRef coord_f, 218 LLVMValueRef coord_f,
197 LLVMValueRef length, 219 LLVMValueRef length,
198 LLVMValueRef stride, 220 LLVMValueRef stride,
221 LLVMValueRef offset,
199 boolean is_pot, 222 boolean is_pot,
200 unsigned wrap_mode, 223 unsigned wrap_mode,
201 LLVMValueRef *offset0, 224 LLVMValueRef *offset0,
@@ -230,6 +253,11 @@ lp_build_sample_wrap_linear_int(struct lp_build_sample_context *bld,
230 LLVMValueRef mask; 253 LLVMValueRef mask;
231 LLVMValueRef weight; 254 LLVMValueRef weight;
232 LLVMValueRef length_f = lp_build_int_to_float(&bld->coord_bld, length); 255 LLVMValueRef length_f = lp_build_int_to_float(&bld->coord_bld, length);
256 if (offset) {
257 offset = lp_build_int_to_float(&bld->coord_bld, offset);
258 offset = lp_build_div(&bld->coord_bld, offset, length_f);
259 coord_f = lp_build_add(&bld->coord_bld, coord_f, offset);
260 }
233 lp_build_coord_repeat_npot_linear(bld, coord_f, 261 lp_build_coord_repeat_npot_linear(bld, coord_f,
234 length, length_f, 262 length, length_f,
235 &coord0, &weight); 263 &coord0, &weight);
@@ -282,6 +310,11 @@ lp_build_sample_wrap_linear_int(struct lp_build_sample_context *bld,
282 else { 310 else {
283 LLVMValueRef weight; 311 LLVMValueRef weight;
284 LLVMValueRef length_f = lp_build_int_to_float(&bld->coord_bld, length); 312 LLVMValueRef length_f = lp_build_int_to_float(&bld->coord_bld, length);
313 if (offset) {
314 offset = lp_build_int_to_float(&bld->coord_bld, offset);
315 offset = lp_build_div(&bld->coord_bld, offset, length_f);
316 coord_f = lp_build_add(&bld->coord_bld, coord_f, offset);
317 }
285 lp_build_coord_repeat_npot_linear(bld, coord_f, 318 lp_build_coord_repeat_npot_linear(bld, coord_f,
286 length, length_f, 319 length, length_f,
287 &coord0, &weight); 320 &coord0, &weight);
@@ -340,8 +373,9 @@ lp_build_sample_wrap_linear_int(struct lp_build_sample_context *bld,
340 * for float texcoords. 373 * for float texcoords.
341 * \param block_length is the length of the pixel block along the 374 * \param block_length is the length of the pixel block along the
342 * coordinate axis 375 * coordinate axis
343 * \param coord the incoming texcoord (s,t,r or q) 376 * \param coord the incoming texcoord (s,t or r)
344 * \param length the texture size along one dimension 377 * \param length the texture size along one dimension
378 * \param offset the texel offset along the coord axis
345 * \param is_pot if TRUE, length is a power of two 379 * \param is_pot if TRUE, length is a power of two
346 * \param wrap_mode one of PIPE_TEX_WRAP_x 380 * \param wrap_mode one of PIPE_TEX_WRAP_x
347 * \param coord0 the first texcoord after wrapping, as int 381 * \param coord0 the first texcoord after wrapping, as int
@@ -354,6 +388,7 @@ lp_build_sample_wrap_linear_float(struct lp_build_sample_context *bld,
354 unsigned block_length, 388 unsigned block_length,
355 LLVMValueRef coord, 389 LLVMValueRef coord,
356 LLVMValueRef length, 390 LLVMValueRef length,
391 LLVMValueRef offset,
357 boolean is_pot, 392 boolean is_pot,
358 unsigned wrap_mode, 393 unsigned wrap_mode,
359 LLVMValueRef *coord0, 394 LLVMValueRef *coord0,
@@ -372,6 +407,10 @@ lp_build_sample_wrap_linear_float(struct lp_build_sample_context *bld,
372 if (is_pot) { 407 if (is_pot) {
373 /* mul by size and subtract 0.5 */ 408 /* mul by size and subtract 0.5 */
374 coord = lp_build_mul(coord_bld, coord, length); 409 coord = lp_build_mul(coord_bld, coord, length);
410 if (offset) {
411 offset = lp_build_int_to_float(coord_bld, offset);
412 coord = lp_build_add(coord_bld, coord, offset);
413 }
375 if (!force_nearest) 414 if (!force_nearest)
376 coord = lp_build_sub(coord_bld, coord, half); 415 coord = lp_build_sub(coord_bld, coord, half);
377 *coord1 = lp_build_add(coord_bld, coord, coord_bld->one); 416 *coord1 = lp_build_add(coord_bld, coord, coord_bld->one);
@@ -385,6 +424,11 @@ lp_build_sample_wrap_linear_float(struct lp_build_sample_context *bld,
385 } 424 }
386 else { 425 else {
387 LLVMValueRef mask; 426 LLVMValueRef mask;
427 if (offset) {
428 offset = lp_build_int_to_float(coord_bld, offset);
429 offset = lp_build_div(coord_bld, offset, length);
430 coord = lp_build_add(coord_bld, coord, offset);
431 }
388 /* wrap with normalized floats is just fract */ 432 /* wrap with normalized floats is just fract */
389 coord = lp_build_fract(coord_bld, coord); 433 coord = lp_build_fract(coord_bld, coord);
390 /* unnormalize */ 434 /* unnormalize */
@@ -411,6 +455,10 @@ lp_build_sample_wrap_linear_float(struct lp_build_sample_context *bld,
411 /* mul by tex size */ 455 /* mul by tex size */
412 coord = lp_build_mul(coord_bld, coord, length); 456 coord = lp_build_mul(coord_bld, coord, length);
413 } 457 }
458 if (offset) {
459 offset = lp_build_int_to_float(coord_bld, offset);
460 coord = lp_build_add(coord_bld, coord, offset);
461 }
414 /* subtract 0.5 */ 462 /* subtract 0.5 */
415 if (!force_nearest) { 463 if (!force_nearest) {
416 coord = lp_build_sub(coord_bld, coord, half); 464 coord = lp_build_sub(coord_bld, coord, half);
@@ -520,6 +568,7 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
520 LLVMValueRef s, 568 LLVMValueRef s,
521 LLVMValueRef t, 569 LLVMValueRef t,
522 LLVMValueRef r, 570 LLVMValueRef r,
571 const LLVMValueRef *offsets,
523 LLVMValueRef *colors_lo, 572 LLVMValueRef *colors_lo,
524 LLVMValueRef *colors_hi) 573 LLVMValueRef *colors_hi)
525{ 574{
@@ -584,6 +633,17 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
584 if (dims >= 3) 633 if (dims >= 3)
585 r_ipart = LLVMBuildAShr(builder, r, i32_c8, ""); 634 r_ipart = LLVMBuildAShr(builder, r, i32_c8, "");
586 635
636 /* add texel offsets */
637 if (offsets[0]) {
638 s_ipart = lp_build_add(&i32, s_ipart, offsets[0]);
639 if (dims >= 2) {
640 t_ipart = lp_build_add(&i32, t_ipart, offsets[1]);
641 if (dims >= 3) {
642 r_ipart = lp_build_add(&i32, r_ipart, offsets[2]);
643 }
644 }
645 }
646
587 /* get pixel, row, image strides */ 647 /* get pixel, row, image strides */
588 x_stride = lp_build_const_vec(bld->gallivm, 648 x_stride = lp_build_const_vec(bld->gallivm,
589 bld->int_coord_bld.type, 649 bld->int_coord_bld.type,
@@ -593,7 +653,7 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
593 lp_build_sample_wrap_nearest_int(bld, 653 lp_build_sample_wrap_nearest_int(bld,
594 bld->format_desc->block.width, 654 bld->format_desc->block.width,
595 s_ipart, s_float, 655 s_ipart, s_float,
596 width_vec, x_stride, 656 width_vec, x_stride, offsets[0],
597 bld->static_texture_state->pot_width, 657 bld->static_texture_state->pot_width,
598 bld->static_sampler_state->wrap_s, 658 bld->static_sampler_state->wrap_s,
599 &x_offset, &x_subcoord); 659 &x_offset, &x_subcoord);
@@ -603,7 +663,7 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
603 lp_build_sample_wrap_nearest_int(bld, 663 lp_build_sample_wrap_nearest_int(bld,
604 bld->format_desc->block.height, 664 bld->format_desc->block.height,
605 t_ipart, t_float, 665 t_ipart, t_float,
606 height_vec, row_stride_vec, 666 height_vec, row_stride_vec, offsets[1],
607 bld->static_texture_state->pot_height, 667 bld->static_texture_state->pot_height,
608 bld->static_sampler_state->wrap_t, 668 bld->static_sampler_state->wrap_t,
609 &y_offset, &y_subcoord); 669 &y_offset, &y_subcoord);
@@ -613,7 +673,7 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
613 lp_build_sample_wrap_nearest_int(bld, 673 lp_build_sample_wrap_nearest_int(bld,
614 1, /* block length (depth) */ 674 1, /* block length (depth) */
615 r_ipart, r_float, 675 r_ipart, r_float,
616 depth_vec, img_stride_vec, 676 depth_vec, img_stride_vec, offsets[2],
617 bld->static_texture_state->pot_depth, 677 bld->static_texture_state->pot_depth,
618 bld->static_sampler_state->wrap_r, 678 bld->static_sampler_state->wrap_r,
619 &z_offset, &z_subcoord); 679 &z_offset, &z_subcoord);
@@ -655,6 +715,7 @@ lp_build_sample_image_nearest_afloat(struct lp_build_sample_context *bld,
655 LLVMValueRef s, 715 LLVMValueRef s,
656 LLVMValueRef t, 716 LLVMValueRef t,
657 LLVMValueRef r, 717 LLVMValueRef r,
718 const LLVMValueRef *offsets,
658 LLVMValueRef *colors_lo, 719 LLVMValueRef *colors_lo,
659 LLVMValueRef *colors_hi) 720 LLVMValueRef *colors_hi)
660 { 721 {
@@ -677,21 +738,21 @@ lp_build_sample_image_nearest_afloat(struct lp_build_sample_context *bld,
677 738
678 /* Do texcoord wrapping */ 739 /* Do texcoord wrapping */
679 lp_build_sample_wrap_nearest_float(bld, 740 lp_build_sample_wrap_nearest_float(bld,
680 s, width_vec, 741 s, width_vec, offsets[0],
681 bld->static_texture_state->pot_width, 742 bld->static_texture_state->pot_width,
682 bld->static_sampler_state->wrap_s, 743 bld->static_sampler_state->wrap_s,
683 &x_icoord); 744 &x_icoord);
684 745
685 if (dims >= 2) { 746 if (dims >= 2) {
686 lp_build_sample_wrap_nearest_float(bld, 747 lp_build_sample_wrap_nearest_float(bld,
687 t, height_vec, 748 t, height_vec, offsets[1],
688 bld->static_texture_state->pot_height, 749 bld->static_texture_state->pot_height,
689 bld->static_sampler_state->wrap_t, 750 bld->static_sampler_state->wrap_t,
690 &y_icoord); 751 &y_icoord);
691 752
692 if (dims >= 3) { 753 if (dims >= 3) {
693 lp_build_sample_wrap_nearest_float(bld, 754 lp_build_sample_wrap_nearest_float(bld,
694 r, depth_vec, 755 r, depth_vec, offsets[2],
695 bld->static_texture_state->pot_depth, 756 bld->static_texture_state->pot_depth,
696 bld->static_sampler_state->wrap_r, 757 bld->static_sampler_state->wrap_r,
697 &z_icoord); 758 &z_icoord);
@@ -982,6 +1043,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
982 LLVMValueRef s, 1043 LLVMValueRef s,
983 LLVMValueRef t, 1044 LLVMValueRef t,
984 LLVMValueRef r, 1045 LLVMValueRef r,
1046 const LLVMValueRef *offsets,
985 LLVMValueRef *colors_lo, 1047 LLVMValueRef *colors_lo,
986 LLVMValueRef *colors_hi) 1048 LLVMValueRef *colors_hi)
987{ 1049{
@@ -1063,6 +1125,17 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
1063 if (dims >= 3) 1125 if (dims >= 3)
1064 r_ipart = LLVMBuildAShr(builder, r, i32_c8, ""); 1126 r_ipart = LLVMBuildAShr(builder, r, i32_c8, "");
1065 1127
1128 /* add texel offsets */
1129 if (offsets[0]) {
1130 s_ipart = lp_build_add(&i32, s_ipart, offsets[0]);
1131 if (dims >= 2) {
1132 t_ipart = lp_build_add(&i32, t_ipart, offsets[1]);
1133 if (dims >= 3) {
1134 r_ipart = lp_build_add(&i32, r_ipart, offsets[2]);
1135 }
1136 }
1137 }
1138
1066 /* compute fractional part (AND with 0xff) */ 1139 /* compute fractional part (AND with 0xff) */
1067 i32_c255 = lp_build_const_int_vec(bld->gallivm, i32.type, 255); 1140 i32_c255 = lp_build_const_int_vec(bld->gallivm, i32.type, 255);
1068 s_fpart = LLVMBuildAnd(builder, s, i32_c255, ""); 1141 s_fpart = LLVMBuildAnd(builder, s, i32_c255, "");
@@ -1081,7 +1154,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
1081 lp_build_sample_wrap_linear_int(bld, 1154 lp_build_sample_wrap_linear_int(bld,
1082 bld->format_desc->block.width, 1155 bld->format_desc->block.width,
1083 s_ipart, &s_fpart, s_float, 1156 s_ipart, &s_fpart, s_float,
1084 width_vec, x_stride, 1157 width_vec, x_stride, offsets[0],
1085 bld->static_texture_state->pot_width, 1158 bld->static_texture_state->pot_width,
1086 bld->static_sampler_state->wrap_s, 1159 bld->static_sampler_state->wrap_s,
1087 &x_offset0, &x_offset1, 1160 &x_offset0, &x_offset1,
@@ -1113,7 +1186,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
1113 lp_build_sample_wrap_linear_int(bld, 1186 lp_build_sample_wrap_linear_int(bld,
1114 bld->format_desc->block.height, 1187 bld->format_desc->block.height,
1115 t_ipart, &t_fpart, t_float, 1188 t_ipart, &t_fpart, t_float,
1116 height_vec, y_stride, 1189 height_vec, y_stride, offsets[1],
1117 bld->static_texture_state->pot_height, 1190 bld->static_texture_state->pot_height,
1118 bld->static_sampler_state->wrap_t, 1191 bld->static_sampler_state->wrap_t,
1119 &y_offset0, &y_offset1, 1192 &y_offset0, &y_offset1,
@@ -1133,7 +1206,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
1133 lp_build_sample_wrap_linear_int(bld, 1206 lp_build_sample_wrap_linear_int(bld,
1134 bld->format_desc->block.height, 1207 bld->format_desc->block.height,
1135 r_ipart, &r_fpart, r_float, 1208 r_ipart, &r_fpart, r_float,
1136 depth_vec, z_stride, 1209 depth_vec, z_stride, offsets[2],
1137 bld->static_texture_state->pot_depth, 1210 bld->static_texture_state->pot_depth,
1138 bld->static_sampler_state->wrap_r, 1211 bld->static_sampler_state->wrap_r,
1139 &z_offset0, &z_offset1, 1212 &z_offset0, &z_offset1,
@@ -1171,6 +1244,7 @@ lp_build_sample_image_linear_afloat(struct lp_build_sample_context *bld,
1171 LLVMValueRef s, 1244 LLVMValueRef s,
1172 LLVMValueRef t, 1245 LLVMValueRef t,
1173 LLVMValueRef r, 1246 LLVMValueRef r,
1247 const LLVMValueRef *offsets,
1174 LLVMValueRef *colors_lo, 1248 LLVMValueRef *colors_lo,
1175 LLVMValueRef *colors_hi) 1249 LLVMValueRef *colors_hi)
1176{ 1250{
@@ -1204,7 +1278,7 @@ lp_build_sample_image_linear_afloat(struct lp_build_sample_context *bld,
1204 /* do texcoord wrapping and compute texel offsets */ 1278 /* do texcoord wrapping and compute texel offsets */
1205 lp_build_sample_wrap_linear_float(bld, 1279 lp_build_sample_wrap_linear_float(bld,
1206 bld->format_desc->block.width, 1280 bld->format_desc->block.width,
1207 s, width_vec, 1281 s, width_vec, offsets[0],
1208 bld->static_texture_state->pot_width, 1282 bld->static_texture_state->pot_width,
1209 bld->static_sampler_state->wrap_s, 1283 bld->static_sampler_state->wrap_s,
1210 &x_icoord0, &x_icoord1, 1284 &x_icoord0, &x_icoord1,
@@ -1214,7 +1288,7 @@ lp_build_sample_image_linear_afloat(struct lp_build_sample_context *bld,
1214 if (dims >= 2) { 1288 if (dims >= 2) {
1215 lp_build_sample_wrap_linear_float(bld, 1289 lp_build_sample_wrap_linear_float(bld,
1216 bld->format_desc->block.height, 1290 bld->format_desc->block.height,
1217 t, height_vec, 1291 t, height_vec, offsets[1],
1218 bld->static_texture_state->pot_height, 1292 bld->static_texture_state->pot_height,
1219 bld->static_sampler_state->wrap_t, 1293 bld->static_sampler_state->wrap_t,
1220 &y_icoord0, &y_icoord1, 1294 &y_icoord0, &y_icoord1,
@@ -1224,7 +1298,7 @@ lp_build_sample_image_linear_afloat(struct lp_build_sample_context *bld,
1224 if (dims >= 3) { 1298 if (dims >= 3) {
1225 lp_build_sample_wrap_linear_float(bld, 1299 lp_build_sample_wrap_linear_float(bld,
1226 bld->format_desc->block.height, 1300 bld->format_desc->block.height,
1227 r, depth_vec, 1301 r, depth_vec, offsets[2],
1228 bld->static_texture_state->pot_depth, 1302 bld->static_texture_state->pot_depth,
1229 bld->static_sampler_state->wrap_r, 1303 bld->static_sampler_state->wrap_r,
1230 &z_icoord0, &z_icoord1, 1304 &z_icoord0, &z_icoord1,
@@ -1339,6 +1413,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
1339 LLVMValueRef s, 1413 LLVMValueRef s,
1340 LLVMValueRef t, 1414 LLVMValueRef t,
1341 LLVMValueRef r, 1415 LLVMValueRef r,
1416 const LLVMValueRef *offsets,
1342 LLVMValueRef ilevel0, 1417 LLVMValueRef ilevel0,
1343 LLVMValueRef ilevel1, 1418 LLVMValueRef ilevel1,
1344 LLVMValueRef lod_fpart, 1419 LLVMValueRef lod_fpart,
@@ -1377,7 +1452,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
1377 lp_build_sample_image_nearest_afloat(bld, 1452 lp_build_sample_image_nearest_afloat(bld,
1378 size0, 1453 size0,
1379 row_stride0_vec, img_stride0_vec, 1454 row_stride0_vec, img_stride0_vec,
1380 data_ptr0, mipoff0, s, t, r, 1455 data_ptr0, mipoff0, s, t, r, offsets,
1381 &colors0_lo, &colors0_hi); 1456 &colors0_lo, &colors0_hi);
1382 } 1457 }
1383 else { 1458 else {
@@ -1385,7 +1460,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
1385 lp_build_sample_image_linear_afloat(bld, 1460 lp_build_sample_image_linear_afloat(bld,
1386 size0, 1461 size0,
1387 row_stride0_vec, img_stride0_vec, 1462 row_stride0_vec, img_stride0_vec,
1388 data_ptr0, mipoff0, s, t, r, 1463 data_ptr0, mipoff0, s, t, r, offsets,
1389 &colors0_lo, &colors0_hi); 1464 &colors0_lo, &colors0_hi);
1390 } 1465 }
1391 } 1466 }
@@ -1394,7 +1469,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
1394 lp_build_sample_image_nearest(bld, 1469 lp_build_sample_image_nearest(bld,
1395 size0, 1470 size0,
1396 row_stride0_vec, img_stride0_vec, 1471 row_stride0_vec, img_stride0_vec,
1397 data_ptr0, mipoff0, s, t, r, 1472 data_ptr0, mipoff0, s, t, r, offsets,
1398 &colors0_lo, &colors0_hi); 1473 &colors0_lo, &colors0_hi);
1399 } 1474 }
1400 else { 1475 else {
@@ -1402,7 +1477,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
1402 lp_build_sample_image_linear(bld, 1477 lp_build_sample_image_linear(bld,
1403 size0, 1478 size0,
1404 row_stride0_vec, img_stride0_vec, 1479 row_stride0_vec, img_stride0_vec,
1405 data_ptr0, mipoff0, s, t, r, 1480 data_ptr0, mipoff0, s, t, r, offsets,
1406 &colors0_lo, &colors0_hi); 1481 &colors0_lo, &colors0_hi);
1407 } 1482 }
1408 } 1483 }
@@ -1472,14 +1547,14 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
1472 lp_build_sample_image_nearest_afloat(bld, 1547 lp_build_sample_image_nearest_afloat(bld,
1473 size1, 1548 size1,
1474 row_stride1_vec, img_stride1_vec, 1549 row_stride1_vec, img_stride1_vec,
1475 data_ptr1, mipoff1, s, t, r, 1550 data_ptr1, mipoff1, s, t, r, offsets,
1476 &colors1_lo, &colors1_hi); 1551 &colors1_lo, &colors1_hi);
1477 } 1552 }
1478 else { 1553 else {
1479 lp_build_sample_image_linear_afloat(bld, 1554 lp_build_sample_image_linear_afloat(bld,
1480 size1, 1555 size1,
1481 row_stride1_vec, img_stride1_vec, 1556 row_stride1_vec, img_stride1_vec,
1482 data_ptr1, mipoff1, s, t, r, 1557 data_ptr1, mipoff1, s, t, r, offsets,
1483 &colors1_lo, &colors1_hi); 1558 &colors1_lo, &colors1_hi);
1484 } 1559 }
1485 } 1560 }
@@ -1488,14 +1563,14 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
1488 lp_build_sample_image_nearest(bld, 1563 lp_build_sample_image_nearest(bld,
1489 size1, 1564 size1,
1490 row_stride1_vec, img_stride1_vec, 1565 row_stride1_vec, img_stride1_vec,
1491 data_ptr1, mipoff1, s, t, r, 1566 data_ptr1, mipoff1, s, t, r, offsets,
1492 &colors1_lo, &colors1_hi); 1567 &colors1_lo, &colors1_hi);
1493 } 1568 }
1494 else { 1569 else {
1495 lp_build_sample_image_linear(bld, 1570 lp_build_sample_image_linear(bld,
1496 size1, 1571 size1,
1497 row_stride1_vec, img_stride1_vec, 1572 row_stride1_vec, img_stride1_vec,
1498 data_ptr1, mipoff1, s, t, r, 1573 data_ptr1, mipoff1, s, t, r, offsets,
1499 &colors1_lo, &colors1_hi); 1574 &colors1_lo, &colors1_hi);
1500 } 1575 }
1501 } 1576 }
@@ -1574,6 +1649,7 @@ lp_build_sample_aos(struct lp_build_sample_context *bld,
1574 LLVMValueRef s, 1649 LLVMValueRef s,
1575 LLVMValueRef t, 1650 LLVMValueRef t,
1576 LLVMValueRef r, 1651 LLVMValueRef r,
1652 const LLVMValueRef *offsets,
1577 LLVMValueRef lod_ipart, 1653 LLVMValueRef lod_ipart,
1578 LLVMValueRef lod_fpart, 1654 LLVMValueRef lod_fpart,
1579 LLVMValueRef ilevel0, 1655 LLVMValueRef ilevel0,
@@ -1612,7 +1688,7 @@ lp_build_sample_aos(struct lp_build_sample_context *bld,
1612 /* no need to distinguish between minification and magnification */ 1688 /* no need to distinguish between minification and magnification */
1613 lp_build_sample_mipmap(bld, 1689 lp_build_sample_mipmap(bld,
1614 min_filter, mip_filter, 1690 min_filter, mip_filter,
1615 s, t, r, 1691 s, t, r, offsets,
1616 ilevel0, ilevel1, lod_fpart, 1692 ilevel0, ilevel1, lod_fpart,
1617 packed_lo, packed_hi); 1693 packed_lo, packed_hi);
1618 } 1694 }
@@ -1645,7 +1721,7 @@ lp_build_sample_aos(struct lp_build_sample_context *bld,
1645 /* Use the minification filter */ 1721 /* Use the minification filter */
1646 lp_build_sample_mipmap(bld, 1722 lp_build_sample_mipmap(bld,
1647 min_filter, mip_filter, 1723 min_filter, mip_filter,
1648 s, t, r, 1724 s, t, r, offsets,
1649 ilevel0, ilevel1, lod_fpart, 1725 ilevel0, ilevel1, lod_fpart,
1650 packed_lo, packed_hi); 1726 packed_lo, packed_hi);
1651 } 1727 }
@@ -1654,7 +1730,7 @@ lp_build_sample_aos(struct lp_build_sample_context *bld,
1654 /* Use the magnification filter */ 1730 /* Use the magnification filter */
1655 lp_build_sample_mipmap(bld, 1731 lp_build_sample_mipmap(bld,
1656 mag_filter, PIPE_TEX_MIPFILTER_NONE, 1732 mag_filter, PIPE_TEX_MIPFILTER_NONE,
1657 s, t, r, 1733 s, t, r, offsets,
1658 ilevel0, NULL, NULL, 1734 ilevel0, NULL, NULL,
1659 packed_lo, packed_hi); 1735 packed_lo, packed_hi);
1660 } 1736 }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.h b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.h
index 6590e8ce090..6fce9712a48 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.h
@@ -46,6 +46,7 @@ lp_build_sample_aos(struct lp_build_sample_context *bld,
46 LLVMValueRef s, 46 LLVMValueRef s,
47 LLVMValueRef t, 47 LLVMValueRef t,
48 LLVMValueRef r, 48 LLVMValueRef r,
49 const LLVMValueRef *offsets,
49 LLVMValueRef lod_ipart, 50 LLVMValueRef lod_ipart,
50 LLVMValueRef lod_fpart, 51 LLVMValueRef lod_fpart,
51 LLVMValueRef ilevel0, 52 LLVMValueRef ilevel0,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 50ccd2a1741..8aa41662d67 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -277,6 +277,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
277 LLVMValueRef coord, 277 LLVMValueRef coord,
278 LLVMValueRef length, 278 LLVMValueRef length,
279 LLVMValueRef length_f, 279 LLVMValueRef length_f,
280 LLVMValueRef offset,
280 boolean is_pot, 281 boolean is_pot,
281 unsigned wrap_mode, 282 unsigned wrap_mode,
282 LLVMValueRef *x0_out, 283 LLVMValueRef *x0_out,
@@ -296,6 +297,10 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
296 /* mul by size and subtract 0.5 */ 297 /* mul by size and subtract 0.5 */
297 coord = lp_build_mul(coord_bld, coord, length_f); 298 coord = lp_build_mul(coord_bld, coord, length_f);
298 coord = lp_build_sub(coord_bld, coord, half); 299 coord = lp_build_sub(coord_bld, coord, half);
300 if (offset) {
301 offset = lp_build_int_to_float(coord_bld, offset);
302 coord = lp_build_add(coord_bld, coord, offset);
303 }
299 /* convert to int, compute lerp weight */ 304 /* convert to int, compute lerp weight */
300 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 305 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
301 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 306 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
@@ -305,6 +310,11 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
305 } 310 }
306 else { 311 else {
307 LLVMValueRef mask; 312 LLVMValueRef mask;
313 if (offset) {
314 offset = lp_build_int_to_float(coord_bld, offset);
315 offset = lp_build_div(coord_bld, offset, length_f);
316 coord = lp_build_add(coord_bld, coord, offset);
317 }
308 lp_build_coord_repeat_npot_linear(bld, coord, 318 lp_build_coord_repeat_npot_linear(bld, coord,
309 length, length_f, 319 length, length_f,
310 &coord0, &weight); 320 &coord0, &weight);
@@ -321,6 +331,10 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
321 /* scale coord to length */ 331 /* scale coord to length */
322 coord = lp_build_mul(coord_bld, coord, length_f); 332 coord = lp_build_mul(coord_bld, coord, length_f);
323 } 333 }
334 if (offset) {
335 offset = lp_build_int_to_float(coord_bld, offset);
336 coord = lp_build_add(coord_bld, coord, offset);
337 }
324 338
325 /* clamp to [0, length] */ 339 /* clamp to [0, length] */
326 coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, length_f); 340 coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, length_f);
@@ -341,6 +355,11 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
341 /* mul by tex size */ 355 /* mul by tex size */
342 coord = lp_build_mul(coord_bld, coord, length_f); 356 coord = lp_build_mul(coord_bld, coord, length_f);
343 } 357 }
358 if (offset) {
359 offset = lp_build_int_to_float(coord_bld, offset);
360 coord = lp_build_add(coord_bld, coord, offset);
361 }
362
344 /* clamp to length max */ 363 /* clamp to length max */
345 coord = lp_build_min(coord_bld, coord, length_f); 364 coord = lp_build_min(coord_bld, coord, length_f);
346 /* subtract 0.5 */ 365 /* subtract 0.5 */
@@ -360,6 +379,10 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
360 /* scale coord to length */ 379 /* scale coord to length */
361 coord = lp_build_mul(coord_bld, coord, length_f); 380 coord = lp_build_mul(coord_bld, coord, length_f);
362 } 381 }
382 if (offset) {
383 offset = lp_build_int_to_float(coord_bld, offset);
384 coord = lp_build_add(coord_bld, coord, offset);
385 }
363 /* was: clamp to [-0.5, length + 0.5], then sub 0.5 */ 386 /* was: clamp to [-0.5, length + 0.5], then sub 0.5 */
364 /* can skip clamp (though might not work for very large coord values */ 387 /* can skip clamp (though might not work for very large coord values */
365 coord = lp_build_sub(coord_bld, coord, half); 388 coord = lp_build_sub(coord_bld, coord, half);
@@ -375,6 +398,10 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
375 /* scale coord to length */ 398 /* scale coord to length */
376 coord = lp_build_mul(coord_bld, coord, length_f); 399 coord = lp_build_mul(coord_bld, coord, length_f);
377 coord = lp_build_sub(coord_bld, coord, half); 400 coord = lp_build_sub(coord_bld, coord, half);
401 if (offset) {
402 offset = lp_build_int_to_float(coord_bld, offset);
403 coord = lp_build_add(coord_bld, coord, offset);
404 }
378 405
379 /* convert to int, compute lerp weight */ 406 /* convert to int, compute lerp weight */
380 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 407 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
@@ -387,12 +414,15 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
387 break; 414 break;
388 415
389 case PIPE_TEX_WRAP_MIRROR_CLAMP: 416 case PIPE_TEX_WRAP_MIRROR_CLAMP:
390 coord = lp_build_abs(coord_bld, coord);
391
392 if (bld->static_sampler_state->normalized_coords) { 417 if (bld->static_sampler_state->normalized_coords) {
393 /* scale coord to length */ 418 /* scale coord to length */
394 coord = lp_build_mul(coord_bld, coord, length_f); 419 coord = lp_build_mul(coord_bld, coord, length_f);
395 } 420 }
421 if (offset) {
422 offset = lp_build_int_to_float(coord_bld, offset);
423 coord = lp_build_add(coord_bld, coord, offset);
424 }
425 coord = lp_build_abs(coord_bld, coord);
396 426
397 /* clamp to [0, length] */ 427 /* clamp to [0, length] */
398 coord = lp_build_min(coord_bld, coord, length_f); 428 coord = lp_build_min(coord_bld, coord, length_f);
@@ -409,12 +439,16 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
409 LLVMValueRef min, max; 439 LLVMValueRef min, max;
410 struct lp_build_context abs_coord_bld = bld->coord_bld; 440 struct lp_build_context abs_coord_bld = bld->coord_bld;
411 abs_coord_bld.type.sign = FALSE; 441 abs_coord_bld.type.sign = FALSE;
412 coord = lp_build_abs(coord_bld, coord);
413 442
414 if (bld->static_sampler_state->normalized_coords) { 443 if (bld->static_sampler_state->normalized_coords) {
415 /* scale coord to length */ 444 /* scale coord to length */
416 coord = lp_build_mul(coord_bld, coord, length_f); 445 coord = lp_build_mul(coord_bld, coord, length_f);
417 } 446 }
447 if (offset) {
448 offset = lp_build_int_to_float(coord_bld, offset);
449 coord = lp_build_add(coord_bld, coord, offset);
450 }
451 coord = lp_build_abs(coord_bld, coord);
418 452
419 /* clamp to [0.5, length - 0.5] */ 453 /* clamp to [0.5, length - 0.5] */
420 min = half; 454 min = half;
@@ -431,12 +465,15 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
431 465
432 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 466 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
433 { 467 {
434 coord = lp_build_abs(coord_bld, coord);
435
436 if (bld->static_sampler_state->normalized_coords) { 468 if (bld->static_sampler_state->normalized_coords) {
437 /* scale coord to length */ 469 /* scale coord to length */
438 coord = lp_build_mul(coord_bld, coord, length_f); 470 coord = lp_build_mul(coord_bld, coord, length_f);
439 } 471 }
472 if (offset) {
473 offset = lp_build_int_to_float(coord_bld, offset);
474 coord = lp_build_add(coord_bld, coord, offset);
475 }
476 coord = lp_build_abs(coord_bld, coord);
440 477
441 /* was: clamp to [-0.5, length + 0.5] then sub 0.5 */ 478 /* was: clamp to [-0.5, length + 0.5] then sub 0.5 */
442 /* skip clamp - always positive, and other side 479 /* skip clamp - always positive, and other side
@@ -466,6 +503,8 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
466 * Build LLVM code for texture wrap mode for nearest filtering. 503 * Build LLVM code for texture wrap mode for nearest filtering.
467 * \param coord the incoming texcoord (nominally in [0,1]) 504 * \param coord the incoming texcoord (nominally in [0,1])
468 * \param length the texture size along one dimension, as int vector 505 * \param length the texture size along one dimension, as int vector
506 * \param length_f the texture size along one dimension, as float vector
507 * \param offset texel offset along one dimension (as int vector)
469 * \param is_pot if TRUE, length is a power of two 508 * \param is_pot if TRUE, length is a power of two
470 * \param wrap_mode one of PIPE_TEX_WRAP_x 509 * \param wrap_mode one of PIPE_TEX_WRAP_x
471 */ 510 */
@@ -474,6 +513,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
474 LLVMValueRef coord, 513 LLVMValueRef coord,
475 LLVMValueRef length, 514 LLVMValueRef length,
476 LLVMValueRef length_f, 515 LLVMValueRef length_f,
516 LLVMValueRef offset,
477 boolean is_pot, 517 boolean is_pot,
478 unsigned wrap_mode) 518 unsigned wrap_mode)
479{ 519{
@@ -488,9 +528,17 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
488 if (is_pot) { 528 if (is_pot) {
489 coord = lp_build_mul(coord_bld, coord, length_f); 529 coord = lp_build_mul(coord_bld, coord, length_f);
490 icoord = lp_build_ifloor(coord_bld, coord); 530 icoord = lp_build_ifloor(coord_bld, coord);
531 if (offset) {
532 icoord = lp_build_add(int_coord_bld, icoord, offset);
533 }
491 icoord = LLVMBuildAnd(builder, icoord, length_minus_one, ""); 534 icoord = LLVMBuildAnd(builder, icoord, length_minus_one, "");
492 } 535 }
493 else { 536 else {
537 if (offset) {
538 offset = lp_build_int_to_float(coord_bld, offset);
539 offset = lp_build_div(coord_bld, offset, length_f);
540 coord = lp_build_add(coord_bld, coord, offset);
541 }
494 /* take fraction, unnormalize */ 542 /* take fraction, unnormalize */
495 coord = lp_build_fract_safe(coord_bld, coord); 543 coord = lp_build_fract_safe(coord_bld, coord);
496 coord = lp_build_mul(coord_bld, coord, length_f); 544 coord = lp_build_mul(coord_bld, coord, length_f);
@@ -508,6 +556,9 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
508 /* floor */ 556 /* floor */
509 /* use itrunc instead since we clamp to 0 anyway */ 557 /* use itrunc instead since we clamp to 0 anyway */
510 icoord = lp_build_itrunc(coord_bld, coord); 558 icoord = lp_build_itrunc(coord_bld, coord);
559 if (offset) {
560 icoord = lp_build_add(int_coord_bld, icoord, offset);
561 }
511 562
512 /* clamp to [0, length - 1]. */ 563 /* clamp to [0, length - 1]. */
513 icoord = lp_build_clamp(int_coord_bld, icoord, int_coord_bld->zero, 564 icoord = lp_build_clamp(int_coord_bld, icoord, int_coord_bld->zero,
@@ -521,9 +572,17 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
521 } 572 }
522 /* no clamp necessary, border masking will handle this */ 573 /* no clamp necessary, border masking will handle this */
523 icoord = lp_build_ifloor(coord_bld, coord); 574 icoord = lp_build_ifloor(coord_bld, coord);
575 if (offset) {
576 icoord = lp_build_add(int_coord_bld, icoord, offset);
577 }
524 break; 578 break;
525 579
526 case PIPE_TEX_WRAP_MIRROR_REPEAT: 580 case PIPE_TEX_WRAP_MIRROR_REPEAT:
581 if (offset) {
582 offset = lp_build_int_to_float(coord_bld, offset);
583 offset = lp_build_div(coord_bld, offset, length_f);
584 coord = lp_build_add(coord_bld, coord, offset);
585 }
527 /* compute mirror function */ 586 /* compute mirror function */
528 coord = lp_build_coord_mirror(bld, coord); 587 coord = lp_build_coord_mirror(bld, coord);
529 588
@@ -540,12 +599,15 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
540 599
541 case PIPE_TEX_WRAP_MIRROR_CLAMP: 600 case PIPE_TEX_WRAP_MIRROR_CLAMP:
542 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 601 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
543 coord = lp_build_abs(coord_bld, coord);
544
545 if (bld->static_sampler_state->normalized_coords) { 602 if (bld->static_sampler_state->normalized_coords) {
546 /* scale coord to length */ 603 /* scale coord to length */
547 coord = lp_build_mul(coord_bld, coord, length_f); 604 coord = lp_build_mul(coord_bld, coord, length_f);
548 } 605 }
606 if (offset) {
607 offset = lp_build_int_to_float(coord_bld, offset);
608 coord = lp_build_add(coord_bld, coord, offset);
609 }
610 coord = lp_build_abs(coord_bld, coord);
549 611
550 /* itrunc == ifloor here */ 612 /* itrunc == ifloor here */
551 icoord = lp_build_itrunc(coord_bld, coord); 613 icoord = lp_build_itrunc(coord_bld, coord);
@@ -555,12 +617,15 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
555 break; 617 break;
556 618
557 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 619 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
558 coord = lp_build_abs(coord_bld, coord);
559
560 if (bld->static_sampler_state->normalized_coords) { 620 if (bld->static_sampler_state->normalized_coords) {
561 /* scale coord to length */ 621 /* scale coord to length */
562 coord = lp_build_mul(coord_bld, coord, length_f); 622 coord = lp_build_mul(coord_bld, coord, length_f);
563 } 623 }
624 if (offset) {
625 offset = lp_build_int_to_float(coord_bld, offset);
626 coord = lp_build_add(coord_bld, coord, offset);
627 }
628 coord = lp_build_abs(coord_bld, coord);
564 629
565 /* itrunc == ifloor here */ 630 /* itrunc == ifloor here */
566 icoord = lp_build_itrunc(coord_bld, coord); 631 icoord = lp_build_itrunc(coord_bld, coord);
@@ -590,6 +655,7 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
590 LLVMValueRef s, 655 LLVMValueRef s,
591 LLVMValueRef t, 656 LLVMValueRef t,
592 LLVMValueRef r, 657 LLVMValueRef r,
658 const LLVMValueRef *offsets,
593 LLVMValueRef colors_out[4]) 659 LLVMValueRef colors_out[4])
594{ 660{
595 const unsigned dims = bld->dims; 661 const unsigned dims = bld->dims;
@@ -619,19 +685,19 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
619 /* 685 /*
620 * Compute integer texcoords. 686 * Compute integer texcoords.
621 */ 687 */
622 x = lp_build_sample_wrap_nearest(bld, s, width_vec, flt_width_vec, 688 x = lp_build_sample_wrap_nearest(bld, s, width_vec, flt_width_vec, offsets[0],
623 bld->static_texture_state->pot_width, 689 bld->static_texture_state->pot_width,
624 bld->static_sampler_state->wrap_s); 690 bld->static_sampler_state->wrap_s);
625 lp_build_name(x, "tex.x.wrapped"); 691 lp_build_name(x, "tex.x.wrapped");
626 692
627 if (dims >= 2) { 693 if (dims >= 2) {
628 y = lp_build_sample_wrap_nearest(bld, t, height_vec, flt_height_vec, 694 y = lp_build_sample_wrap_nearest(bld, t, height_vec, flt_height_vec, offsets[1],
629 bld->static_texture_state->pot_height, 695 bld->static_texture_state->pot_height,
630 bld->static_sampler_state->wrap_t); 696 bld->static_sampler_state->wrap_t);
631 lp_build_name(y, "tex.y.wrapped"); 697 lp_build_name(y, "tex.y.wrapped");
632 698
633 if (dims == 3) { 699 if (dims == 3) {
634 z = lp_build_sample_wrap_nearest(bld, r, depth_vec, flt_depth_vec, 700 z = lp_build_sample_wrap_nearest(bld, r, depth_vec, flt_depth_vec, offsets[2],
635 bld->static_texture_state->pot_depth, 701 bld->static_texture_state->pot_depth,
636 bld->static_sampler_state->wrap_r); 702 bld->static_sampler_state->wrap_r);
637 lp_build_name(z, "tex.z.wrapped"); 703 lp_build_name(z, "tex.z.wrapped");
@@ -670,6 +736,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
670 LLVMValueRef s, 736 LLVMValueRef s,
671 LLVMValueRef t, 737 LLVMValueRef t,
672 LLVMValueRef r, 738 LLVMValueRef r,
739 const LLVMValueRef *offsets,
673 LLVMValueRef colors_out[4]) 740 LLVMValueRef colors_out[4])
674{ 741{
675 const unsigned dims = bld->dims; 742 const unsigned dims = bld->dims;
@@ -702,7 +769,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
702 /* 769 /*
703 * Compute integer texcoords. 770 * Compute integer texcoords.
704 */ 771 */
705 lp_build_sample_wrap_linear(bld, s, width_vec, flt_width_vec, 772 lp_build_sample_wrap_linear(bld, s, width_vec, flt_width_vec, offsets[0],
706 bld->static_texture_state->pot_width, 773 bld->static_texture_state->pot_width,
707 bld->static_sampler_state->wrap_s, 774 bld->static_sampler_state->wrap_s,
708 &x0, &x1, &s_fpart); 775 &x0, &x1, &s_fpart);
@@ -710,7 +777,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
710 lp_build_name(x1, "tex.x1.wrapped"); 777 lp_build_name(x1, "tex.x1.wrapped");
711 778
712 if (dims >= 2) { 779 if (dims >= 2) {
713 lp_build_sample_wrap_linear(bld, t, height_vec, flt_height_vec, 780 lp_build_sample_wrap_linear(bld, t, height_vec, flt_height_vec, offsets[1],
714 bld->static_texture_state->pot_height, 781 bld->static_texture_state->pot_height,
715 bld->static_sampler_state->wrap_t, 782 bld->static_sampler_state->wrap_t,
716 &y0, &y1, &t_fpart); 783 &y0, &y1, &t_fpart);
@@ -718,7 +785,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
718 lp_build_name(y1, "tex.y1.wrapped"); 785 lp_build_name(y1, "tex.y1.wrapped");
719 786
720 if (dims == 3) { 787 if (dims == 3) {
721 lp_build_sample_wrap_linear(bld, r, depth_vec, flt_depth_vec, 788 lp_build_sample_wrap_linear(bld, r, depth_vec, flt_depth_vec, offsets[2],
722 bld->static_texture_state->pot_depth, 789 bld->static_texture_state->pot_depth,
723 bld->static_sampler_state->wrap_r, 790 bld->static_sampler_state->wrap_r,
724 &z0, &z1, &r_fpart); 791 &z0, &z1, &r_fpart);
@@ -851,6 +918,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
851 LLVMValueRef s, 918 LLVMValueRef s,
852 LLVMValueRef t, 919 LLVMValueRef t,
853 LLVMValueRef r, 920 LLVMValueRef r,
921 const LLVMValueRef *offsets,
854 LLVMValueRef ilevel0, 922 LLVMValueRef ilevel0,
855 LLVMValueRef ilevel1, 923 LLVMValueRef ilevel1,
856 LLVMValueRef lod_fpart, 924 LLVMValueRef lod_fpart,
@@ -886,7 +954,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
886 lp_build_sample_image_nearest(bld, sampler_unit, 954 lp_build_sample_image_nearest(bld, sampler_unit,
887 size0, 955 size0,
888 row_stride0_vec, img_stride0_vec, 956 row_stride0_vec, img_stride0_vec,
889 data_ptr0, mipoff0, s, t, r, 957 data_ptr0, mipoff0, s, t, r, offsets,
890 colors0); 958 colors0);
891 } 959 }
892 else { 960 else {
@@ -894,7 +962,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
894 lp_build_sample_image_linear(bld, sampler_unit, 962 lp_build_sample_image_linear(bld, sampler_unit,
895 size0, 963 size0,
896 row_stride0_vec, img_stride0_vec, 964 row_stride0_vec, img_stride0_vec,
897 data_ptr0, mipoff0, s, t, r, 965 data_ptr0, mipoff0, s, t, r, offsets,
898 colors0); 966 colors0);
899 } 967 }
900 968
@@ -950,14 +1018,14 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
950 lp_build_sample_image_nearest(bld, sampler_unit, 1018 lp_build_sample_image_nearest(bld, sampler_unit,
951 size1, 1019 size1,
952 row_stride1_vec, img_stride1_vec, 1020 row_stride1_vec, img_stride1_vec,
953 data_ptr1, mipoff1, s, t, r, 1021 data_ptr1, mipoff1, s, t, r, offsets,
954 colors1); 1022 colors1);
955 } 1023 }
956 else { 1024 else {
957 lp_build_sample_image_linear(bld, sampler_unit, 1025 lp_build_sample_image_linear(bld, sampler_unit,
958 size1, 1026 size1,
959 row_stride1_vec, img_stride1_vec, 1027 row_stride1_vec, img_stride1_vec,
960 data_ptr1, mipoff1, s, t, r, 1028 data_ptr1, mipoff1, s, t, r, offsets,
961 colors1); 1029 colors1);
962 } 1030 }
963 1031
@@ -1120,6 +1188,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
1120 LLVMValueRef s, 1188 LLVMValueRef s,
1121 LLVMValueRef t, 1189 LLVMValueRef t,
1122 LLVMValueRef r, 1190 LLVMValueRef r,
1191 const LLVMValueRef *offsets,
1123 LLVMValueRef lod_ipart, 1192 LLVMValueRef lod_ipart,
1124 LLVMValueRef lod_fpart, 1193 LLVMValueRef lod_fpart,
1125 LLVMValueRef ilevel0, 1194 LLVMValueRef ilevel0,
@@ -1147,7 +1216,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
1147 /* no need to distinguish between minification and magnification */ 1216 /* no need to distinguish between minification and magnification */
1148 lp_build_sample_mipmap(bld, sampler_unit, 1217 lp_build_sample_mipmap(bld, sampler_unit,
1149 min_filter, mip_filter, 1218 min_filter, mip_filter,
1150 s, t, r, 1219 s, t, r, offsets,
1151 ilevel0, ilevel1, lod_fpart, 1220 ilevel0, ilevel1, lod_fpart,
1152 texels); 1221 texels);
1153 } 1222 }
@@ -1180,7 +1249,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
1180 /* Use the minification filter */ 1249 /* Use the minification filter */
1181 lp_build_sample_mipmap(bld, sampler_unit, 1250 lp_build_sample_mipmap(bld, sampler_unit,
1182 min_filter, mip_filter, 1251 min_filter, mip_filter,
1183 s, t, r, 1252 s, t, r, offsets,
1184 ilevel0, ilevel1, lod_fpart, 1253 ilevel0, ilevel1, lod_fpart,
1185 texels); 1254 texels);
1186 } 1255 }
@@ -1189,7 +1258,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
1189 /* Use the magnification filter */ 1258 /* Use the magnification filter */
1190 lp_build_sample_mipmap(bld, sampler_unit, 1259 lp_build_sample_mipmap(bld, sampler_unit,
1191 mag_filter, PIPE_TEX_MIPFILTER_NONE, 1260 mag_filter, PIPE_TEX_MIPFILTER_NONE,
1192 s, t, r, 1261 s, t, r, offsets,
1193 ilevel0, NULL, NULL, 1262 ilevel0, NULL, NULL,
1194 texels); 1263 texels);
1195 } 1264 }
@@ -1605,7 +1674,7 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
1605 if (use_aos) { 1674 if (use_aos) {
1606 /* do sampling/filtering with fixed pt arithmetic */ 1675 /* do sampling/filtering with fixed pt arithmetic */
1607 lp_build_sample_aos(&bld, sampler_index, 1676 lp_build_sample_aos(&bld, sampler_index,
1608 s, t, r, 1677 s, t, r, offsets,
1609 lod_ipart, lod_fpart, 1678 lod_ipart, lod_fpart,
1610 ilevel0, ilevel1, 1679 ilevel0, ilevel1,
1611 texel_out); 1680 texel_out);
@@ -1613,7 +1682,7 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
1613 1682
1614 else { 1683 else {
1615 lp_build_sample_general(&bld, sampler_index, 1684 lp_build_sample_general(&bld, sampler_index,
1616 s, t, r, 1685 s, t, r, offsets,
1617 lod_ipart, lod_fpart, 1686 lod_ipart, lod_fpart,
1618 ilevel0, ilevel1, 1687 ilevel0, ilevel1,
1619 texel_out); 1688 texel_out);
@@ -1681,10 +1750,21 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
1681 LLVMValueRef lod_iparts, lod_fparts = NULL; 1750 LLVMValueRef lod_iparts, lod_fparts = NULL;
1682 LLVMValueRef ilevel0s, ilevel1s = NULL; 1751 LLVMValueRef ilevel0s, ilevel1s = NULL;
1683 LLVMValueRef indexi = lp_build_const_int32(gallivm, i); 1752 LLVMValueRef indexi = lp_build_const_int32(gallivm, i);
1753 LLVMValueRef offsets4[4] = { NULL };
1684 1754
1685 s4 = lp_build_extract_range(gallivm, s, 4*i, 4); 1755 s4 = lp_build_extract_range(gallivm, s, 4*i, 4);
1686 t4 = lp_build_extract_range(gallivm, t, 4*i, 4); 1756 t4 = lp_build_extract_range(gallivm, t, 4*i, 4);
1687 r4 = lp_build_extract_range(gallivm, r, 4*i, 4); 1757 r4 = lp_build_extract_range(gallivm, r, 4*i, 4);
1758
1759 if (offsets[0]) {
1760 offsets4[0] = lp_build_extract_range(gallivm, offsets[0], 4*i, 4);
1761 if (dims > 1) {
1762 offsets4[1] = lp_build_extract_range(gallivm, offsets[1], 4*i, 4);
1763 if (dims > 2) {
1764 offsets4[2] = lp_build_extract_range(gallivm, offsets[2], 4*i, 4);
1765 }
1766 }
1767 }
1688 lod_iparts = LLVMBuildExtractElement(builder, lod_ipart, indexi, ""); 1768 lod_iparts = LLVMBuildExtractElement(builder, lod_ipart, indexi, "");
1689 ilevel0s = LLVMBuildExtractElement(builder, ilevel0, indexi, ""); 1769 ilevel0s = LLVMBuildExtractElement(builder, ilevel0, indexi, "");
1690 if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { 1770 if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
@@ -1695,7 +1775,7 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
1695 if (use_aos) { 1775 if (use_aos) {
1696 /* do sampling/filtering with fixed pt arithmetic */ 1776 /* do sampling/filtering with fixed pt arithmetic */
1697 lp_build_sample_aos(&bld4, sampler_index, 1777 lp_build_sample_aos(&bld4, sampler_index,
1698 s4, t4, r4, 1778 s4, t4, r4, offsets4,
1699 lod_iparts, lod_fparts, 1779 lod_iparts, lod_fparts,
1700 ilevel0s, ilevel1s, 1780 ilevel0s, ilevel1s,
1701 texelout4); 1781 texelout4);
@@ -1703,7 +1783,7 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
1703 1783
1704 else { 1784 else {
1705 lp_build_sample_general(&bld4, sampler_index, 1785 lp_build_sample_general(&bld4, sampler_index,
1706 s4, t4, r4, 1786 s4, t4, r4, offsets4,
1707 lod_iparts, lod_fparts, 1787 lod_iparts, lod_fparts,
1708 ilevel0s, ilevel1s, 1788 ilevel0s, ilevel1s,
1709 texelout4); 1789 texelout4);