Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[mesa.git] / src / gallium / drivers / llvmpipe / lp_tex_sample.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 * Copyright 2008 VMware, Inc. All rights reserved.
6 *
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:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
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.
26 *
27 **************************************************************************/
28
29 /**
30 * Texture sampling
31 *
32 * Authors:
33 * Brian Paul
34 */
35
36 #include "lp_context.h"
37 #include "lp_quad.h"
38 #include "lp_surface.h"
39 #include "lp_texture.h"
40 #include "lp_tex_sample.h"
41 #include "lp_tex_cache.h"
42 #include "pipe/p_context.h"
43 #include "pipe/p_defines.h"
44 #include "pipe/p_shader_tokens.h"
45 #include "util/u_math.h"
46 #include "util/u_memory.h"
47
48
49
50 /*
51 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
52 * see 1-pixel bands of improperly weighted linear-filtered textures.
53 * The tests/texwrap.c demo is a good test.
54 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
55 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
56 */
57 #define FRAC(f) ((f) - util_ifloor(f))
58
59
60 /**
61 * Linear interpolation macro
62 */
63 static INLINE float
64 lerp(float a, float v0, float v1)
65 {
66 return v0 + a * (v1 - v0);
67 }
68
69
70 /**
71 * Do 2D/biliner interpolation of float values.
72 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
73 * a and b are the horizontal and vertical interpolants.
74 * It's important that this function is inlined when compiled with
75 * optimization! If we find that's not true on some systems, convert
76 * to a macro.
77 */
78 static INLINE float
79 lerp_2d(float a, float b,
80 float v00, float v10, float v01, float v11)
81 {
82 const float temp0 = lerp(a, v00, v10);
83 const float temp1 = lerp(a, v01, v11);
84 return lerp(b, temp0, temp1);
85 }
86
87
88 /**
89 * As above, but 3D interpolation of 8 values.
90 */
91 static INLINE float
92 lerp_3d(float a, float b, float c,
93 float v000, float v100, float v010, float v110,
94 float v001, float v101, float v011, float v111)
95 {
96 const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
97 const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
98 return lerp(c, temp0, temp1);
99 }
100
101
102
103 /**
104 * If A is a signed integer, A % B doesn't give the right value for A < 0
105 * (in terms of texture repeat). Just casting to unsigned fixes that.
106 */
107 #define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
108
109
110 /**
111 * Apply texture coord wrapping mode and return integer texture indexes
112 * for a vector of four texcoords (S or T or P).
113 * \param wrapMode PIPE_TEX_WRAP_x
114 * \param s the incoming texcoords
115 * \param size the texture image size
116 * \param icoord returns the integer texcoords
117 * \return integer texture index
118 */
119 static INLINE void
120 nearest_texcoord_4(unsigned wrapMode, const float s[4], unsigned size,
121 int icoord[4])
122 {
123 uint ch;
124 switch (wrapMode) {
125 case PIPE_TEX_WRAP_REPEAT:
126 /* s limited to [0,1) */
127 /* i limited to [0,size-1] */
128 for (ch = 0; ch < 4; ch++) {
129 int i = util_ifloor(s[ch] * size);
130 icoord[ch] = REMAINDER(i, size);
131 }
132 return;
133 case PIPE_TEX_WRAP_CLAMP:
134 /* s limited to [0,1] */
135 /* i limited to [0,size-1] */
136 for (ch = 0; ch < 4; ch++) {
137 if (s[ch] <= 0.0F)
138 icoord[ch] = 0;
139 else if (s[ch] >= 1.0F)
140 icoord[ch] = size - 1;
141 else
142 icoord[ch] = util_ifloor(s[ch] * size);
143 }
144 return;
145 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
146 {
147 /* s limited to [min,max] */
148 /* i limited to [0, size-1] */
149 const float min = 1.0F / (2.0F * size);
150 const float max = 1.0F - min;
151 for (ch = 0; ch < 4; ch++) {
152 if (s[ch] < min)
153 icoord[ch] = 0;
154 else if (s[ch] > max)
155 icoord[ch] = size - 1;
156 else
157 icoord[ch] = util_ifloor(s[ch] * size);
158 }
159 }
160 return;
161 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
162 {
163 /* s limited to [min,max] */
164 /* i limited to [-1, size] */
165 const float min = -1.0F / (2.0F * size);
166 const float max = 1.0F - min;
167 for (ch = 0; ch < 4; ch++) {
168 if (s[ch] <= min)
169 icoord[ch] = -1;
170 else if (s[ch] >= max)
171 icoord[ch] = size;
172 else
173 icoord[ch] = util_ifloor(s[ch] * size);
174 }
175 }
176 return;
177 case PIPE_TEX_WRAP_MIRROR_REPEAT:
178 {
179 const float min = 1.0F / (2.0F * size);
180 const float max = 1.0F - min;
181 for (ch = 0; ch < 4; ch++) {
182 const int flr = util_ifloor(s[ch]);
183 float u;
184 if (flr & 1)
185 u = 1.0F - (s[ch] - (float) flr);
186 else
187 u = s[ch] - (float) flr;
188 if (u < min)
189 icoord[ch] = 0;
190 else if (u > max)
191 icoord[ch] = size - 1;
192 else
193 icoord[ch] = util_ifloor(u * size);
194 }
195 }
196 return;
197 case PIPE_TEX_WRAP_MIRROR_CLAMP:
198 for (ch = 0; ch < 4; ch++) {
199 /* s limited to [0,1] */
200 /* i limited to [0,size-1] */
201 const float u = fabsf(s[ch]);
202 if (u <= 0.0F)
203 icoord[ch] = 0;
204 else if (u >= 1.0F)
205 icoord[ch] = size - 1;
206 else
207 icoord[ch] = util_ifloor(u * size);
208 }
209 return;
210 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
211 {
212 /* s limited to [min,max] */
213 /* i limited to [0, size-1] */
214 const float min = 1.0F / (2.0F * size);
215 const float max = 1.0F - min;
216 for (ch = 0; ch < 4; ch++) {
217 const float u = fabsf(s[ch]);
218 if (u < min)
219 icoord[ch] = 0;
220 else if (u > max)
221 icoord[ch] = size - 1;
222 else
223 icoord[ch] = util_ifloor(u * size);
224 }
225 }
226 return;
227 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
228 {
229 /* s limited to [min,max] */
230 /* i limited to [0, size-1] */
231 const float min = -1.0F / (2.0F * size);
232 const float max = 1.0F - min;
233 for (ch = 0; ch < 4; ch++) {
234 const float u = fabsf(s[ch]);
235 if (u < min)
236 icoord[ch] = -1;
237 else if (u > max)
238 icoord[ch] = size;
239 else
240 icoord[ch] = util_ifloor(u * size);
241 }
242 }
243 return;
244 default:
245 assert(0);
246 }
247 }
248
249
250 /**
251 * Used to compute texel locations for linear sampling for four texcoords.
252 * \param wrapMode PIPE_TEX_WRAP_x
253 * \param s the texcoords
254 * \param size the texture image size
255 * \param icoord0 returns first texture indexes
256 * \param icoord1 returns second texture indexes (usually icoord0 + 1)
257 * \param w returns blend factor/weight between texture indexes
258 * \param icoord returns the computed integer texture coords
259 */
260 static INLINE void
261 linear_texcoord_4(unsigned wrapMode, const float s[4], unsigned size,
262 int icoord0[4], int icoord1[4], float w[4])
263 {
264 uint ch;
265
266 switch (wrapMode) {
267 case PIPE_TEX_WRAP_REPEAT:
268 for (ch = 0; ch < 4; ch++) {
269 float u = s[ch] * size - 0.5F;
270 icoord0[ch] = REMAINDER(util_ifloor(u), size);
271 icoord1[ch] = REMAINDER(icoord0[ch] + 1, size);
272 w[ch] = FRAC(u);
273 }
274 break;;
275 case PIPE_TEX_WRAP_CLAMP:
276 for (ch = 0; ch < 4; ch++) {
277 float u = CLAMP(s[ch], 0.0F, 1.0F);
278 u = u * size - 0.5f;
279 icoord0[ch] = util_ifloor(u);
280 icoord1[ch] = icoord0[ch] + 1;
281 w[ch] = FRAC(u);
282 }
283 break;;
284 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
285 for (ch = 0; ch < 4; ch++) {
286 float u = CLAMP(s[ch], 0.0F, 1.0F);
287 u = u * size - 0.5f;
288 icoord0[ch] = util_ifloor(u);
289 icoord1[ch] = icoord0[ch] + 1;
290 if (icoord0[ch] < 0)
291 icoord0[ch] = 0;
292 if (icoord1[ch] >= (int) size)
293 icoord1[ch] = size - 1;
294 w[ch] = FRAC(u);
295 }
296 break;;
297 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
298 {
299 const float min = -1.0F / (2.0F * size);
300 const float max = 1.0F - min;
301 for (ch = 0; ch < 4; ch++) {
302 float u = CLAMP(s[ch], min, max);
303 u = u * size - 0.5f;
304 icoord0[ch] = util_ifloor(u);
305 icoord1[ch] = icoord0[ch] + 1;
306 w[ch] = FRAC(u);
307 }
308 }
309 break;;
310 case PIPE_TEX_WRAP_MIRROR_REPEAT:
311 for (ch = 0; ch < 4; ch++) {
312 const int flr = util_ifloor(s[ch]);
313 float u;
314 if (flr & 1)
315 u = 1.0F - (s[ch] - (float) flr);
316 else
317 u = s[ch] - (float) flr;
318 u = u * size - 0.5F;
319 icoord0[ch] = util_ifloor(u);
320 icoord1[ch] = icoord0[ch] + 1;
321 if (icoord0[ch] < 0)
322 icoord0[ch] = 0;
323 if (icoord1[ch] >= (int) size)
324 icoord1[ch] = size - 1;
325 w[ch] = FRAC(u);
326 }
327 break;;
328 case PIPE_TEX_WRAP_MIRROR_CLAMP:
329 for (ch = 0; ch < 4; ch++) {
330 float u = fabsf(s[ch]);
331 if (u >= 1.0F)
332 u = (float) size;
333 else
334 u *= size;
335 u -= 0.5F;
336 icoord0[ch] = util_ifloor(u);
337 icoord1[ch] = icoord0[ch] + 1;
338 w[ch] = FRAC(u);
339 }
340 break;;
341 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
342 for (ch = 0; ch < 4; ch++) {
343 float u = fabsf(s[ch]);
344 if (u >= 1.0F)
345 u = (float) size;
346 else
347 u *= size;
348 u -= 0.5F;
349 icoord0[ch] = util_ifloor(u);
350 icoord1[ch] = icoord0[ch] + 1;
351 if (icoord0[ch] < 0)
352 icoord0[ch] = 0;
353 if (icoord1[ch] >= (int) size)
354 icoord1[ch] = size - 1;
355 w[ch] = FRAC(u);
356 }
357 break;;
358 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
359 {
360 const float min = -1.0F / (2.0F * size);
361 const float max = 1.0F - min;
362 for (ch = 0; ch < 4; ch++) {
363 float u = fabsf(s[ch]);
364 if (u <= min)
365 u = min * size;
366 else if (u >= max)
367 u = max * size;
368 else
369 u *= size;
370 u -= 0.5F;
371 icoord0[ch] = util_ifloor(u);
372 icoord1[ch] = icoord0[ch] + 1;
373 w[ch] = FRAC(u);
374 }
375 }
376 break;;
377 default:
378 assert(0);
379 }
380 }
381
382
383 /**
384 * For RECT textures / unnormalized texcoords
385 * Only a subset of wrap modes supported.
386 */
387 static INLINE void
388 nearest_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size,
389 int icoord[4])
390 {
391 uint ch;
392 switch (wrapMode) {
393 case PIPE_TEX_WRAP_CLAMP:
394 for (ch = 0; ch < 4; ch++) {
395 int i = util_ifloor(s[ch]);
396 icoord[ch]= CLAMP(i, 0, (int) size-1);
397 }
398 return;
399 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
400 /* fall-through */
401 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
402 for (ch = 0; ch < 4; ch++) {
403 icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) );
404 }
405 return;
406 default:
407 assert(0);
408 }
409 }
410
411
412 /**
413 * For RECT textures / unnormalized texcoords.
414 * Only a subset of wrap modes supported.
415 */
416 static INLINE void
417 linear_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size,
418 int icoord0[4], int icoord1[4], float w[4])
419 {
420 uint ch;
421 switch (wrapMode) {
422 case PIPE_TEX_WRAP_CLAMP:
423 for (ch = 0; ch < 4; ch++) {
424 /* Not exactly what the spec says, but it matches NVIDIA output */
425 float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f);
426 icoord0[ch] = util_ifloor(u);
427 icoord1[ch] = icoord0[ch] + 1;
428 w[ch] = FRAC(u);
429 }
430 return;
431 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
432 /* fall-through */
433 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
434 for (ch = 0; ch < 4; ch++) {
435 float u = CLAMP(s[ch], 0.5F, (float) size - 0.5F);
436 u -= 0.5F;
437 icoord0[ch] = util_ifloor(u);
438 icoord1[ch] = icoord0[ch] + 1;
439 if (icoord1[ch] > (int) size - 1)
440 icoord1[ch] = size - 1;
441 w[ch] = FRAC(u);
442 }
443 break;
444 default:
445 assert(0);
446 }
447 }
448
449
450 static unsigned
451 choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)
452 {
453 /*
454 major axis
455 direction target sc tc ma
456 ---------- ------------------------------- --- --- ---
457 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
458 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
459 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
460 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
461 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
462 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
463 */
464 const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
465 unsigned face;
466 float sc, tc, ma;
467
468 if (arx > ary && arx > arz) {
469 if (rx >= 0.0F) {
470 face = PIPE_TEX_FACE_POS_X;
471 sc = -rz;
472 tc = -ry;
473 ma = arx;
474 }
475 else {
476 face = PIPE_TEX_FACE_NEG_X;
477 sc = rz;
478 tc = -ry;
479 ma = arx;
480 }
481 }
482 else if (ary > arx && ary > arz) {
483 if (ry >= 0.0F) {
484 face = PIPE_TEX_FACE_POS_Y;
485 sc = rx;
486 tc = rz;
487 ma = ary;
488 }
489 else {
490 face = PIPE_TEX_FACE_NEG_Y;
491 sc = rx;
492 tc = -rz;
493 ma = ary;
494 }
495 }
496 else {
497 if (rz > 0.0F) {
498 face = PIPE_TEX_FACE_POS_Z;
499 sc = rx;
500 tc = -ry;
501 ma = arz;
502 }
503 else {
504 face = PIPE_TEX_FACE_NEG_Z;
505 sc = -rx;
506 tc = -ry;
507 ma = arz;
508 }
509 }
510
511 *newS = ( sc / ma + 1.0F ) * 0.5F;
512 *newT = ( tc / ma + 1.0F ) * 0.5F;
513
514 return face;
515 }
516
517
518 /**
519 * Examine the quad's texture coordinates to compute the partial
520 * derivatives w.r.t X and Y, then compute lambda (level of detail).
521 *
522 * This is only done for fragment shaders, not vertex shaders.
523 */
524 static float
525 compute_lambda(struct tgsi_sampler *tgsi_sampler,
526 const float s[QUAD_SIZE],
527 const float t[QUAD_SIZE],
528 const float p[QUAD_SIZE],
529 float lodbias)
530 {
531 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
532 const struct pipe_texture *texture = samp->texture;
533 const struct pipe_sampler_state *sampler = samp->sampler;
534 float rho, lambda;
535
536 if (samp->processor == TGSI_PROCESSOR_VERTEX)
537 return lodbias;
538
539 assert(sampler->normalized_coords);
540
541 assert(s);
542 {
543 float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
544 float dsdy = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT];
545 dsdx = fabsf(dsdx);
546 dsdy = fabsf(dsdy);
547 rho = MAX2(dsdx, dsdy) * texture->width[0];
548 }
549 if (t) {
550 float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT];
551 float dtdy = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT];
552 float max;
553 dtdx = fabsf(dtdx);
554 dtdy = fabsf(dtdy);
555 max = MAX2(dtdx, dtdy) * texture->height[0];
556 rho = MAX2(rho, max);
557 }
558 if (p) {
559 float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT];
560 float dpdy = p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT];
561 float max;
562 dpdx = fabsf(dpdx);
563 dpdy = fabsf(dpdy);
564 max = MAX2(dpdx, dpdy) * texture->depth[0];
565 rho = MAX2(rho, max);
566 }
567
568 lambda = util_fast_log2(rho);
569 lambda += lodbias + sampler->lod_bias;
570 lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod);
571
572 return lambda;
573 }
574
575
576 /**
577 * Do several things here:
578 * 1. Compute lambda from the texcoords, if needed
579 * 2. Determine if we're minifying or magnifying
580 * 3. If minifying, choose mipmap levels
581 * 4. Return image filter to use within mipmap images
582 * \param level0 Returns first mipmap level to sample from
583 * \param level1 Returns second mipmap level to sample from
584 * \param levelBlend Returns blend factor between levels, in [0,1]
585 * \param imgFilter Returns either the min or mag filter, depending on lambda
586 */
587 static void
588 choose_mipmap_levels(struct tgsi_sampler *tgsi_sampler,
589 const float s[QUAD_SIZE],
590 const float t[QUAD_SIZE],
591 const float p[QUAD_SIZE],
592 float lodbias,
593 unsigned *level0, unsigned *level1, float *levelBlend,
594 unsigned *imgFilter)
595 {
596 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
597 const struct pipe_texture *texture = samp->texture;
598 const struct pipe_sampler_state *sampler = samp->sampler;
599
600 if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
601 /* no mipmap selection needed */
602 *level0 = *level1 = CLAMP((int) sampler->min_lod,
603 0, (int) texture->last_level);
604
605 if (sampler->min_img_filter != sampler->mag_img_filter) {
606 /* non-mipmapped texture, but still need to determine if doing
607 * minification or magnification.
608 */
609 float lambda = compute_lambda(tgsi_sampler, s, t, p, lodbias);
610 if (lambda <= 0.0) {
611 *imgFilter = sampler->mag_img_filter;
612 }
613 else {
614 *imgFilter = sampler->min_img_filter;
615 }
616 }
617 else {
618 *imgFilter = sampler->mag_img_filter;
619 }
620 }
621 else {
622 float lambda = compute_lambda(tgsi_sampler, s, t, p, lodbias);
623
624 if (lambda <= 0.0) { /* XXX threshold depends on the filter */
625 /* magnifying */
626 *imgFilter = sampler->mag_img_filter;
627 *level0 = *level1 = 0;
628 }
629 else {
630 /* minifying */
631 *imgFilter = sampler->min_img_filter;
632
633 /* choose mipmap level(s) and compute the blend factor between them */
634 if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
635 /* Nearest mipmap level */
636 const int lvl = (int) (lambda + 0.5);
637 *level0 =
638 *level1 = CLAMP(lvl, 0, (int) texture->last_level);
639 }
640 else {
641 /* Linear interpolation between mipmap levels */
642 const int lvl = (int) lambda;
643 *level0 = CLAMP(lvl, 0, (int) texture->last_level);
644 *level1 = CLAMP(lvl + 1, 0, (int) texture->last_level);
645 *levelBlend = FRAC(lambda); /* blending weight between levels */
646 }
647 }
648 }
649 }
650
651
652 /**
653 * Get a texel from a texture, using the texture tile cache.
654 *
655 * \param face the cube face in 0..5
656 * \param level the mipmap level
657 * \param x the x coord of texel within 2D image
658 * \param y the y coord of texel within 2D image
659 * \param z which slice of a 3D texture
660 * \param rgba the quad to put the texel/color into
661 * \param j which element of the rgba quad to write to
662 *
663 * XXX maybe move this into lp_tile_cache.c and merge with the
664 * lp_get_cached_tile_tex() function. Also, get 4 texels instead of 1...
665 */
666 static void
667 get_texel_quad_2d(const struct tgsi_sampler *tgsi_sampler,
668 unsigned face, unsigned level, int x, int y,
669 const uint8_t *out[4])
670 {
671 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
672
673 const struct llvmpipe_cached_tex_tile *tile
674 = lp_get_cached_tex_tile(samp->cache,
675 tex_tile_address(x, y, 0, face, level));
676
677 y %= TEX_TILE_SIZE;
678 x %= TEX_TILE_SIZE;
679
680 out[0] = &tile->color[y ][x ][0];
681 out[1] = &tile->color[y ][x+1][0];
682 out[2] = &tile->color[y+1][x ][0];
683 out[3] = &tile->color[y+1][x+1][0];
684 }
685
686 static INLINE const uint8_t *
687 get_texel_2d_ptr(const struct tgsi_sampler *tgsi_sampler,
688 unsigned face, unsigned level, int x, int y)
689 {
690 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
691
692 const struct llvmpipe_cached_tex_tile *tile
693 = lp_get_cached_tex_tile(samp->cache,
694 tex_tile_address(x, y, 0, face, level));
695
696 y %= TEX_TILE_SIZE;
697 x %= TEX_TILE_SIZE;
698
699 return &tile->color[y][x][0];
700 }
701
702
703 static void
704 get_texel_quad_2d_mt(const struct tgsi_sampler *tgsi_sampler,
705 unsigned face, unsigned level,
706 int x0, int y0,
707 int x1, int y1,
708 const uint8_t *out[4])
709 {
710 unsigned i;
711
712 for (i = 0; i < 4; i++) {
713 unsigned tx = (i & 1) ? x1 : x0;
714 unsigned ty = (i >> 1) ? y1 : y0;
715
716 out[i] = get_texel_2d_ptr( tgsi_sampler, face, level, tx, ty );
717 }
718 }
719
720 static void
721 get_texel(const struct tgsi_sampler *tgsi_sampler,
722 unsigned face, unsigned level, int x, int y, int z,
723 float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
724 {
725 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
726 const struct pipe_texture *texture = samp->texture;
727 const struct pipe_sampler_state *sampler = samp->sampler;
728
729 if (x < 0 || x >= (int) texture->width[level] ||
730 y < 0 || y >= (int) texture->height[level] ||
731 z < 0 || z >= (int) texture->depth[level]) {
732 rgba[0][j] = sampler->border_color[0];
733 rgba[1][j] = sampler->border_color[1];
734 rgba[2][j] = sampler->border_color[2];
735 rgba[3][j] = sampler->border_color[3];
736 }
737 else {
738 const unsigned tx = x % TEX_TILE_SIZE;
739 const unsigned ty = y % TEX_TILE_SIZE;
740 const struct llvmpipe_cached_tex_tile *tile;
741
742 tile = lp_get_cached_tex_tile(samp->cache,
743 tex_tile_address(x, y, z, face, level));
744
745 rgba[0][j] = ubyte_to_float(tile->color[ty][tx][0]);
746 rgba[1][j] = ubyte_to_float(tile->color[ty][tx][1]);
747 rgba[2][j] = ubyte_to_float(tile->color[ty][tx][2]);
748 rgba[3][j] = ubyte_to_float(tile->color[ty][tx][3]);
749 if (0)
750 {
751 debug_printf("Get texel %f %f %f %f from %s\n",
752 rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j],
753 pf_name(texture->format));
754 }
755 }
756 }
757
758
759 /**
760 * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
761 * When we sampled the depth texture, the depth value was put into all
762 * RGBA channels. We look at the red channel here.
763 * \param rgba quad of (depth) texel values
764 * \param p texture 'P' components for four pixels in quad
765 * \param j which pixel in the quad to test [0..3]
766 */
767 static INLINE void
768 shadow_compare(const struct pipe_sampler_state *sampler,
769 float rgba[NUM_CHANNELS][QUAD_SIZE],
770 const float p[QUAD_SIZE],
771 uint j)
772 {
773 int k;
774 switch (sampler->compare_func) {
775 case PIPE_FUNC_LESS:
776 k = p[j] < rgba[0][j];
777 break;
778 case PIPE_FUNC_LEQUAL:
779 k = p[j] <= rgba[0][j];
780 break;
781 case PIPE_FUNC_GREATER:
782 k = p[j] > rgba[0][j];
783 break;
784 case PIPE_FUNC_GEQUAL:
785 k = p[j] >= rgba[0][j];
786 break;
787 case PIPE_FUNC_EQUAL:
788 k = p[j] == rgba[0][j];
789 break;
790 case PIPE_FUNC_NOTEQUAL:
791 k = p[j] != rgba[0][j];
792 break;
793 case PIPE_FUNC_ALWAYS:
794 k = 1;
795 break;
796 case PIPE_FUNC_NEVER:
797 k = 0;
798 break;
799 default:
800 k = 0;
801 assert(0);
802 break;
803 }
804
805 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
806 rgba[0][j] = rgba[1][j] = rgba[2][j] = (float) k;
807 rgba[3][j] = 1.0F;
808 }
809
810
811 /**
812 * As above, but do four z/texture comparisons.
813 */
814 static INLINE void
815 shadow_compare4(const struct pipe_sampler_state *sampler,
816 float rgba[NUM_CHANNELS][QUAD_SIZE],
817 const float p[QUAD_SIZE])
818 {
819 int j, k0, k1, k2, k3;
820 float val;
821
822 /* compare four texcoords vs. four texture samples */
823 switch (sampler->compare_func) {
824 case PIPE_FUNC_LESS:
825 k0 = p[0] < rgba[0][0];
826 k1 = p[1] < rgba[0][1];
827 k2 = p[2] < rgba[0][2];
828 k3 = p[3] < rgba[0][3];
829 break;
830 case PIPE_FUNC_LEQUAL:
831 k0 = p[0] <= rgba[0][0];
832 k1 = p[1] <= rgba[0][1];
833 k2 = p[2] <= rgba[0][2];
834 k3 = p[3] <= rgba[0][3];
835 break;
836 case PIPE_FUNC_GREATER:
837 k0 = p[0] > rgba[0][0];
838 k1 = p[1] > rgba[0][1];
839 k2 = p[2] > rgba[0][2];
840 k3 = p[3] > rgba[0][3];
841 break;
842 case PIPE_FUNC_GEQUAL:
843 k0 = p[0] >= rgba[0][0];
844 k1 = p[1] >= rgba[0][1];
845 k2 = p[2] >= rgba[0][2];
846 k3 = p[3] >= rgba[0][3];
847 break;
848 case PIPE_FUNC_EQUAL:
849 k0 = p[0] == rgba[0][0];
850 k1 = p[1] == rgba[0][1];
851 k2 = p[2] == rgba[0][2];
852 k3 = p[3] == rgba[0][3];
853 break;
854 case PIPE_FUNC_NOTEQUAL:
855 k0 = p[0] != rgba[0][0];
856 k1 = p[1] != rgba[0][1];
857 k2 = p[2] != rgba[0][2];
858 k3 = p[3] != rgba[0][3];
859 break;
860 case PIPE_FUNC_ALWAYS:
861 k0 = k1 = k2 = k3 = 1;
862 break;
863 case PIPE_FUNC_NEVER:
864 k0 = k1 = k2 = k3 = 0;
865 break;
866 default:
867 k0 = k1 = k2 = k3 = 0;
868 assert(0);
869 break;
870 }
871
872 /* convert four pass/fail values to an intensity in [0,1] */
873 val = 0.25F * (k0 + k1 + k2 + k3);
874
875 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
876 for (j = 0; j < 4; j++) {
877 rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
878 rgba[3][j] = 1.0F;
879 }
880 }
881
882
883
884 static void
885 lp_get_samples_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler,
886 const float s[QUAD_SIZE],
887 const float t[QUAD_SIZE],
888 const float p[QUAD_SIZE],
889 float lodbias,
890 float rgba[NUM_CHANNELS][QUAD_SIZE])
891 {
892 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
893 unsigned j;
894 unsigned level = samp->level;
895 unsigned xpot = 1 << (samp->xpot - level);
896 unsigned ypot = 1 << (samp->ypot - level);
897 unsigned xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */
898 unsigned ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */
899
900 for (j = 0; j < QUAD_SIZE; j++) {
901 int c;
902
903 float u = s[j] * xpot - 0.5F;
904 float v = t[j] * ypot - 0.5F;
905
906 int uflr = util_ifloor(u);
907 int vflr = util_ifloor(v);
908
909 float xw = u - (float)uflr;
910 float yw = v - (float)vflr;
911
912 int x0 = uflr & (xpot - 1);
913 int y0 = vflr & (ypot - 1);
914
915 const uint8_t *tx[4];
916
917
918 /* Can we fetch all four at once:
919 */
920 if (x0 < xmax && y0 < ymax)
921 {
922 get_texel_quad_2d(tgsi_sampler, 0, level, x0, y0, tx);
923 }
924 else
925 {
926 unsigned x1 = (x0 + 1) & (xpot - 1);
927 unsigned y1 = (y0 + 1) & (ypot - 1);
928 get_texel_quad_2d_mt(tgsi_sampler, 0, level,
929 x0, y0, x1, y1, tx);
930 }
931
932
933 /* interpolate R, G, B, A */
934 for (c = 0; c < 4; c++) {
935 rgba[c][j] = lerp_2d(xw, yw,
936 ubyte_to_float(tx[0][c]), ubyte_to_float(tx[1][c]),
937 ubyte_to_float(tx[2][c]), ubyte_to_float(tx[3][c]));
938 }
939 }
940 }
941
942
943 static void
944 lp_get_samples_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler,
945 const float s[QUAD_SIZE],
946 const float t[QUAD_SIZE],
947 const float p[QUAD_SIZE],
948 float lodbias,
949 float rgba[NUM_CHANNELS][QUAD_SIZE])
950 {
951 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
952 unsigned j;
953 unsigned level = samp->level;
954 unsigned xpot = 1 << (samp->xpot - level);
955 unsigned ypot = 1 << (samp->ypot - level);
956
957 for (j = 0; j < QUAD_SIZE; j++) {
958 int c;
959
960 float u = s[j] * xpot;
961 float v = t[j] * ypot;
962
963 int uflr = util_ifloor(u);
964 int vflr = util_ifloor(v);
965
966 int x0 = uflr & (xpot - 1);
967 int y0 = vflr & (ypot - 1);
968
969 const uint8_t *out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0);
970
971 for (c = 0; c < 4; c++) {
972 rgba[c][j] = ubyte_to_float(out[c]);
973 }
974 }
975 }
976
977
978 static void
979 lp_get_samples_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler,
980 const float s[QUAD_SIZE],
981 const float t[QUAD_SIZE],
982 const float p[QUAD_SIZE],
983 float lodbias,
984 float rgba[NUM_CHANNELS][QUAD_SIZE])
985 {
986 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
987 unsigned j;
988 unsigned level = samp->level;
989 unsigned xpot = 1 << (samp->xpot - level);
990 unsigned ypot = 1 << (samp->ypot - level);
991
992 for (j = 0; j < QUAD_SIZE; j++) {
993 int c;
994
995 float u = s[j] * xpot;
996 float v = t[j] * ypot;
997
998 int x0, y0;
999 const uint8_t *out;
1000
1001 x0 = util_ifloor(u);
1002 if (x0 < 0)
1003 x0 = 0;
1004 else if (x0 > xpot - 1)
1005 x0 = xpot - 1;
1006
1007 y0 = util_ifloor(v);
1008 if (y0 < 0)
1009 y0 = 0;
1010 else if (y0 > ypot - 1)
1011 y0 = ypot - 1;
1012
1013 out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0);
1014
1015 for (c = 0; c < 4; c++) {
1016 rgba[c][j] = ubyte_to_float(out[c]);
1017 }
1018 }
1019 }
1020
1021
1022 static void
1023 lp_get_samples_2d_linear_mip_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler,
1024 const float s[QUAD_SIZE],
1025 const float t[QUAD_SIZE],
1026 const float p[QUAD_SIZE],
1027 float lodbias,
1028 float rgba[NUM_CHANNELS][QUAD_SIZE])
1029 {
1030 struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
1031 const struct pipe_texture *texture = samp->texture;
1032 int level0;
1033 float lambda;
1034
1035 lambda = compute_lambda(tgsi_sampler, s, t, p, lodbias);
1036 level0 = (int)lambda;
1037
1038 if (lambda < 0.0) {
1039 samp->level = 0;
1040 lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
1041 s, t, p, 0, rgba );
1042 }
1043 else if (level0 >= texture->last_level) {
1044 samp->level = texture->last_level;
1045 lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
1046 s, t, p, 0, rgba );
1047 }
1048 else {
1049 float levelBlend = lambda - level0;
1050 float rgba0[4][4];
1051 float rgba1[4][4];
1052 int c,j;
1053
1054 samp->level = level0;
1055 lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
1056 s, t, p, 0, rgba0 );
1057
1058 samp->level = level0+1;
1059 lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
1060 s, t, p, 0, rgba1 );
1061
1062 for (j = 0; j < QUAD_SIZE; j++) {
1063 for (c = 0; c < 4; c++) {
1064 rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
1065 }
1066 }
1067 }
1068 }
1069
1070 /**
1071 * Common code for sampling 1D/2D/cube textures.
1072 * Could probably extend for 3D...
1073 */
1074 static void
1075 lp_get_samples_2d_common(struct tgsi_sampler *tgsi_sampler,
1076 const float s[QUAD_SIZE],
1077 const float t[QUAD_SIZE],
1078 const float p[QUAD_SIZE],
1079 float lodbias,
1080 float rgba[NUM_CHANNELS][QUAD_SIZE],
1081 const unsigned faces[4])
1082 {
1083 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
1084 const struct pipe_texture *texture = samp->texture;
1085 const struct pipe_sampler_state *sampler = samp->sampler;
1086 unsigned level0, level1, j, imgFilter;
1087 int width, height;
1088 float levelBlend;
1089
1090 choose_mipmap_levels(tgsi_sampler, s, t, p,
1091 lodbias,
1092 &level0, &level1, &levelBlend, &imgFilter);
1093
1094 assert(sampler->normalized_coords);
1095
1096 width = texture->width[level0];
1097 height = texture->height[level0];
1098
1099 assert(width > 0);
1100
1101 switch (imgFilter) {
1102 case PIPE_TEX_FILTER_NEAREST:
1103 {
1104 int x[4], y[4];
1105 nearest_texcoord_4(sampler->wrap_s, s, width, x);
1106 nearest_texcoord_4(sampler->wrap_t, t, height, y);
1107
1108 for (j = 0; j < QUAD_SIZE; j++) {
1109 get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j);
1110 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
1111 shadow_compare(sampler, rgba, p, j);
1112 }
1113
1114 if (level0 != level1) {
1115 /* get texels from second mipmap level and blend */
1116 float rgba2[4][4];
1117 unsigned c;
1118 x[j] /= 2;
1119 y[j] /= 2;
1120 get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0,
1121 rgba2, j);
1122 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
1123 shadow_compare(sampler, rgba2, p, j);
1124 }
1125
1126 for (c = 0; c < NUM_CHANNELS; c++) {
1127 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
1128 }
1129 }
1130 }
1131 }
1132 break;
1133 case PIPE_TEX_FILTER_LINEAR:
1134 case PIPE_TEX_FILTER_ANISO:
1135 {
1136 int x0[4], y0[4], x1[4], y1[4];
1137 float xw[4], yw[4]; /* weights */
1138
1139 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
1140 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);
1141
1142 for (j = 0; j < QUAD_SIZE; j++) {
1143 float tx[4][4]; /* texels */
1144 int c;
1145 get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0);
1146 get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1);
1147 get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2);
1148 get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3);
1149 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
1150 shadow_compare4(sampler, tx, p);
1151 }
1152
1153 /* interpolate R, G, B, A */
1154 for (c = 0; c < 4; c++) {
1155 rgba[c][j] = lerp_2d(xw[j], yw[j],
1156 tx[c][0], tx[c][1],
1157 tx[c][2], tx[c][3]);
1158 }
1159
1160 if (level0 != level1) {
1161 /* get texels from second mipmap level and blend */
1162 float rgba2[4][4];
1163
1164 /* XXX: This is incorrect -- will often end up with (x0
1165 * == x1 && y0 == y1), meaning that we fetch the same
1166 * texel four times and linearly interpolate between
1167 * identical values. The correct approach would be to
1168 * call linear_texcoord again for the second level.
1169 */
1170 x0[j] /= 2;
1171 y0[j] /= 2;
1172 x1[j] /= 2;
1173 y1[j] /= 2;
1174 get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0);
1175 get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1);
1176 get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2);
1177 get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3);
1178 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
1179 shadow_compare4(sampler, tx, p);
1180 }
1181
1182 /* interpolate R, G, B, A */
1183 for (c = 0; c < 4; c++) {
1184 rgba2[c][j] = lerp_2d(xw[j], yw[j],
1185 tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
1186 }
1187
1188 for (c = 0; c < NUM_CHANNELS; c++) {
1189 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
1190 }
1191 }
1192 }
1193 }
1194 break;
1195 default:
1196 assert(0);
1197 }
1198 }
1199
1200
1201 static INLINE void
1202 lp_get_samples_1d(struct tgsi_sampler *sampler,
1203 const float s[QUAD_SIZE],
1204 const float t[QUAD_SIZE],
1205 const float p[QUAD_SIZE],
1206 float lodbias,
1207 float rgba[NUM_CHANNELS][QUAD_SIZE])
1208 {
1209 static const unsigned faces[4] = {0, 0, 0, 0};
1210 static const float tzero[4] = {0, 0, 0, 0};
1211 lp_get_samples_2d_common(sampler, s, tzero, NULL,
1212 lodbias, rgba, faces);
1213 }
1214
1215
1216 static INLINE void
1217 lp_get_samples_2d(struct tgsi_sampler *sampler,
1218 const float s[QUAD_SIZE],
1219 const float t[QUAD_SIZE],
1220 const float p[QUAD_SIZE],
1221 float lodbias,
1222 float rgba[NUM_CHANNELS][QUAD_SIZE])
1223 {
1224 static const unsigned faces[4] = {0, 0, 0, 0};
1225 lp_get_samples_2d_common(sampler, s, t, p,
1226 lodbias, rgba, faces);
1227 }
1228
1229
1230 static INLINE void
1231 lp_get_samples_3d(struct tgsi_sampler *tgsi_sampler,
1232 const float s[QUAD_SIZE],
1233 const float t[QUAD_SIZE],
1234 const float p[QUAD_SIZE],
1235 float lodbias,
1236 float rgba[NUM_CHANNELS][QUAD_SIZE])
1237 {
1238 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
1239 const struct pipe_texture *texture = samp->texture;
1240 const struct pipe_sampler_state *sampler = samp->sampler;
1241 /* get/map pipe_surfaces corresponding to 3D tex slices */
1242 unsigned level0, level1, j, imgFilter;
1243 int width, height, depth;
1244 float levelBlend;
1245 const uint face = 0;
1246
1247 choose_mipmap_levels(tgsi_sampler, s, t, p,
1248 lodbias,
1249 &level0, &level1, &levelBlend, &imgFilter);
1250
1251 assert(sampler->normalized_coords);
1252
1253 width = texture->width[level0];
1254 height = texture->height[level0];
1255 depth = texture->depth[level0];
1256
1257 assert(width > 0);
1258 assert(height > 0);
1259 assert(depth > 0);
1260
1261 switch (imgFilter) {
1262 case PIPE_TEX_FILTER_NEAREST:
1263 {
1264 int x[4], y[4], z[4];
1265 nearest_texcoord_4(sampler->wrap_s, s, width, x);
1266 nearest_texcoord_4(sampler->wrap_t, t, height, y);
1267 nearest_texcoord_4(sampler->wrap_r, p, depth, z);
1268 for (j = 0; j < QUAD_SIZE; j++) {
1269 get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j);
1270 if (level0 != level1) {
1271 /* get texels from second mipmap level and blend */
1272 float rgba2[4][4];
1273 unsigned c;
1274 x[j] /= 2;
1275 y[j] /= 2;
1276 z[j] /= 2;
1277 get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j);
1278 for (c = 0; c < NUM_CHANNELS; c++) {
1279 rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]);
1280 }
1281 }
1282 }
1283 }
1284 break;
1285 case PIPE_TEX_FILTER_LINEAR:
1286 case PIPE_TEX_FILTER_ANISO:
1287 {
1288 int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4];
1289 float xw[4], yw[4], zw[4]; /* interpolation weights */
1290 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
1291 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);
1292 linear_texcoord_4(sampler->wrap_r, p, depth, z0, z1, zw);
1293
1294 for (j = 0; j < QUAD_SIZE; j++) {
1295 int c;
1296 float tx0[4][4], tx1[4][4];
1297 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0);
1298 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1);
1299 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2);
1300 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3);
1301 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0);
1302 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1);
1303 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2);
1304 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3);
1305
1306 /* interpolate R, G, B, A */
1307 for (c = 0; c < 4; c++) {
1308 rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j],
1309 tx0[c][0], tx0[c][1],
1310 tx0[c][2], tx0[c][3],
1311 tx1[c][0], tx1[c][1],
1312 tx1[c][2], tx1[c][3]);
1313 }
1314
1315 if (level0 != level1) {
1316 /* get texels from second mipmap level and blend */
1317 float rgba2[4][4];
1318 x0[j] /= 2;
1319 y0[j] /= 2;
1320 z0[j] /= 2;
1321 x1[j] /= 2;
1322 y1[j] /= 2;
1323 z1[j] /= 2;
1324 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0);
1325 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1);
1326 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2);
1327 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3);
1328 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0);
1329 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1);
1330 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2);
1331 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3);
1332
1333 /* interpolate R, G, B, A */
1334 for (c = 0; c < 4; c++) {
1335 rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j],
1336 tx0[c][0], tx0[c][1],
1337 tx0[c][2], tx0[c][3],
1338 tx1[c][0], tx1[c][1],
1339 tx1[c][2], tx1[c][3]);
1340 }
1341
1342 /* blend mipmap levels */
1343 for (c = 0; c < NUM_CHANNELS; c++) {
1344 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
1345 }
1346 }
1347 }
1348 }
1349 break;
1350 default:
1351 assert(0);
1352 }
1353 }
1354
1355
1356 static void
1357 lp_get_samples_cube(struct tgsi_sampler *sampler,
1358 const float s[QUAD_SIZE],
1359 const float t[QUAD_SIZE],
1360 const float p[QUAD_SIZE],
1361 float lodbias,
1362 float rgba[NUM_CHANNELS][QUAD_SIZE])
1363 {
1364 unsigned faces[QUAD_SIZE], j;
1365 float ssss[4], tttt[4];
1366 for (j = 0; j < QUAD_SIZE; j++) {
1367 faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j);
1368 }
1369 lp_get_samples_2d_common(sampler, ssss, tttt, NULL,
1370 lodbias, rgba, faces);
1371 }
1372
1373
1374 static void
1375 lp_get_samples_rect(struct tgsi_sampler *tgsi_sampler,
1376 const float s[QUAD_SIZE],
1377 const float t[QUAD_SIZE],
1378 const float p[QUAD_SIZE],
1379 float lodbias,
1380 float rgba[NUM_CHANNELS][QUAD_SIZE])
1381 {
1382 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
1383 const struct pipe_texture *texture = samp->texture;
1384 const struct pipe_sampler_state *sampler = samp->sampler;
1385 const uint face = 0;
1386 unsigned level0, level1, j, imgFilter;
1387 int width, height;
1388 float levelBlend;
1389
1390 choose_mipmap_levels(tgsi_sampler, s, t, p,
1391 lodbias,
1392 &level0, &level1, &levelBlend, &imgFilter);
1393
1394 /* texture RECTS cannot be mipmapped */
1395 assert(level0 == level1);
1396
1397 width = texture->width[level0];
1398 height = texture->height[level0];
1399
1400 assert(width > 0);
1401
1402 switch (imgFilter) {
1403 case PIPE_TEX_FILTER_NEAREST:
1404 {
1405 int x[4], y[4];
1406 nearest_texcoord_unnorm_4(sampler->wrap_s, s, width, x);
1407 nearest_texcoord_unnorm_4(sampler->wrap_t, t, height, y);
1408 for (j = 0; j < QUAD_SIZE; j++) {
1409 get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j);
1410 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
1411 shadow_compare(sampler, rgba, p, j);
1412 }
1413 }
1414 }
1415 break;
1416 case PIPE_TEX_FILTER_LINEAR:
1417 case PIPE_TEX_FILTER_ANISO:
1418 {
1419 int x0[4], y0[4], x1[4], y1[4];
1420 float xw[4], yw[4]; /* weights */
1421 linear_texcoord_unnorm_4(sampler->wrap_s, s, width, x0, x1, xw);
1422 linear_texcoord_unnorm_4(sampler->wrap_t, t, height, y0, y1, yw);
1423 for (j = 0; j < QUAD_SIZE; j++) {
1424 float tx[4][4]; /* texels */
1425 int c;
1426 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], 0, tx, 0);
1427 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], 0, tx, 1);
1428 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2);
1429 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3);
1430 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
1431 shadow_compare4(sampler, tx, p);
1432 }
1433 for (c = 0; c < 4; c++) {
1434 rgba[c][j] = lerp_2d(xw[j], yw[j],
1435 tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
1436 }
1437 }
1438 }
1439 break;
1440 default:
1441 assert(0);
1442 }
1443 }
1444
1445
1446 /**
1447 * Error condition handler
1448 */
1449 static INLINE void
1450 lp_get_samples_null(struct tgsi_sampler *tgsi_sampler,
1451 const float s[QUAD_SIZE],
1452 const float t[QUAD_SIZE],
1453 const float p[QUAD_SIZE],
1454 float lodbias,
1455 float rgba[NUM_CHANNELS][QUAD_SIZE])
1456 {
1457 int i,j;
1458
1459 for (i = 0; i < 4; i++)
1460 for (j = 0; j < 4; j++)
1461 rgba[i][j] = 1.0;
1462 }
1463
1464 /**
1465 * Called via tgsi_sampler::get_samples() when using a sampler for the
1466 * first time. Determine the actual sampler function, link it in and
1467 * call it.
1468 */
1469 void
1470 lp_get_samples(struct tgsi_sampler *tgsi_sampler,
1471 const float s[QUAD_SIZE],
1472 const float t[QUAD_SIZE],
1473 const float p[QUAD_SIZE],
1474 float lodbias,
1475 float rgba[NUM_CHANNELS][QUAD_SIZE])
1476 {
1477 struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
1478 const struct pipe_texture *texture = samp->texture;
1479 const struct pipe_sampler_state *sampler = samp->sampler;
1480
1481 /* Default to the 'undefined' case:
1482 */
1483 tgsi_sampler->get_samples = lp_get_samples_null;
1484
1485 if (!texture) {
1486 assert(0); /* is this legal?? */
1487 goto out;
1488 }
1489
1490 if (!sampler->normalized_coords) {
1491 assert (texture->target == PIPE_TEXTURE_2D);
1492 tgsi_sampler->get_samples = lp_get_samples_rect;
1493 goto out;
1494 }
1495
1496 switch (texture->target) {
1497 case PIPE_TEXTURE_1D:
1498 tgsi_sampler->get_samples = lp_get_samples_1d;
1499 break;
1500 case PIPE_TEXTURE_2D:
1501 tgsi_sampler->get_samples = lp_get_samples_2d;
1502 break;
1503 case PIPE_TEXTURE_3D:
1504 tgsi_sampler->get_samples = lp_get_samples_3d;
1505 break;
1506 case PIPE_TEXTURE_CUBE:
1507 tgsi_sampler->get_samples = lp_get_samples_cube;
1508 break;
1509 default:
1510 assert(0);
1511 break;
1512 }
1513
1514 /* Do this elsewhere:
1515 */
1516 samp->xpot = util_unsigned_logbase2( samp->texture->width[0] );
1517 samp->ypot = util_unsigned_logbase2( samp->texture->height[0] );
1518
1519 /* Try to hook in a faster sampler. Ultimately we'll have to
1520 * code-generate these. Luckily most of this looks like it is
1521 * orthogonal state within the sampler.
1522 */
1523 if (texture->target == PIPE_TEXTURE_2D &&
1524 sampler->min_img_filter == sampler->mag_img_filter &&
1525 sampler->wrap_s == sampler->wrap_t &&
1526 sampler->compare_mode == FALSE &&
1527 sampler->normalized_coords)
1528 {
1529 if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
1530 samp->level = CLAMP((int) sampler->min_lod,
1531 0, (int) texture->last_level);
1532
1533 if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT) {
1534 switch (sampler->min_img_filter) {
1535 case PIPE_TEX_FILTER_NEAREST:
1536 tgsi_sampler->get_samples = lp_get_samples_2d_nearest_repeat_POT;
1537 break;
1538 case PIPE_TEX_FILTER_LINEAR:
1539 tgsi_sampler->get_samples = lp_get_samples_2d_linear_repeat_POT;
1540 break;
1541 default:
1542 break;
1543 }
1544 }
1545 else if (sampler->wrap_s == PIPE_TEX_WRAP_CLAMP) {
1546 switch (sampler->min_img_filter) {
1547 case PIPE_TEX_FILTER_NEAREST:
1548 tgsi_sampler->get_samples = lp_get_samples_2d_nearest_clamp_POT;
1549 break;
1550 default:
1551 break;
1552 }
1553 }
1554 }
1555 else if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
1556 if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT) {
1557 switch (sampler->min_img_filter) {
1558 case PIPE_TEX_FILTER_LINEAR:
1559 tgsi_sampler->get_samples = lp_get_samples_2d_linear_mip_linear_repeat_POT;
1560 break;
1561 default:
1562 break;
1563 }
1564 }
1565 }
1566 }
1567 else if (0) {
1568 _debug_printf("target %d/%d min_mip %d/%d min_img %d/%d wrap %d/%d compare %d/%d norm %d/%d\n",
1569 texture->target, PIPE_TEXTURE_2D,
1570 sampler->min_mip_filter, PIPE_TEX_MIPFILTER_NONE,
1571 sampler->min_img_filter, sampler->mag_img_filter,
1572 sampler->wrap_s, sampler->wrap_t,
1573 sampler->compare_mode, FALSE,
1574 sampler->normalized_coords, TRUE);
1575 }
1576
1577 out:
1578 tgsi_sampler->get_samples( tgsi_sampler, s, t, p, lodbias, rgba );
1579 }
1580