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