softpipe/draw/tgsi: simplify driver/tgsi sampler interface
[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-2010 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 "pipe/p_context.h"
38 #include "pipe/p_defines.h"
39 #include "pipe/p_shader_tokens.h"
40 #include "util/u_math.h"
41 #include "util/u_format.h"
42 #include "util/u_memory.h"
43 #include "sp_quad.h" /* only for #define QUAD_* tokens */
44 #include "sp_tex_sample.h"
45 #include "sp_tex_tile_cache.h"
46
47
48 /** Set to one to help debug texture sampling */
49 #define DEBUG_TEX 0
50
51
52 /*
53 * Return fractional part of 'f'. Used for computing interpolation weights.
54 * Need to be careful with negative values.
55 * Note, if this function isn't perfect you'll sometimes see 1-pixel bands
56 * of improperly weighted linear-filtered textures.
57 * The tests/texwrap.c demo is a good test.
58 */
59 static INLINE float
60 frac(float f)
61 {
62 return f - floorf(f);
63 }
64
65
66
67 /**
68 * Linear interpolation macro
69 */
70 static INLINE float
71 lerp(float a, float v0, float v1)
72 {
73 return v0 + a * (v1 - v0);
74 }
75
76
77 /**
78 * Do 2D/bilinear interpolation of float values.
79 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
80 * a and b are the horizontal and vertical interpolants.
81 * It's important that this function is inlined when compiled with
82 * optimization! If we find that's not true on some systems, convert
83 * to a macro.
84 */
85 static INLINE float
86 lerp_2d(float a, float b,
87 float v00, float v10, float v01, float v11)
88 {
89 const float temp0 = lerp(a, v00, v10);
90 const float temp1 = lerp(a, v01, v11);
91 return lerp(b, temp0, temp1);
92 }
93
94
95 /**
96 * As above, but 3D interpolation of 8 values.
97 */
98 static INLINE float
99 lerp_3d(float a, float b, float c,
100 float v000, float v100, float v010, float v110,
101 float v001, float v101, float v011, float v111)
102 {
103 const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
104 const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
105 return lerp(c, temp0, temp1);
106 }
107
108
109
110 /**
111 * Compute coord % size for repeat wrap modes.
112 * Note that if coord is negative, coord % size doesn't give the right
113 * value. To avoid that problem we add a large multiple of the size
114 * (rather than using a conditional).
115 */
116 static INLINE int
117 repeat(int coord, unsigned size)
118 {
119 return (coord + size * 1024) % size;
120 }
121
122
123 /**
124 * Apply texture coord wrapping mode and return integer texture indexes
125 * for a vector of four texcoords (S or T or P).
126 * \param wrapMode PIPE_TEX_WRAP_x
127 * \param s the incoming texcoords
128 * \param size the texture image size
129 * \param icoord returns the integer texcoords
130 */
131 static void
132 wrap_nearest_repeat(float s, unsigned size, int *icoord)
133 {
134 /* s limited to [0,1) */
135 /* i limited to [0,size-1] */
136 int i = util_ifloor(s * size);
137 *icoord = repeat(i, size);
138 }
139
140
141 static void
142 wrap_nearest_clamp(float s, unsigned size, int *icoord)
143 {
144 /* s limited to [0,1] */
145 /* i limited to [0,size-1] */
146 if (s <= 0.0F)
147 *icoord = 0;
148 else if (s >= 1.0F)
149 *icoord = size - 1;
150 else
151 *icoord = util_ifloor(s * size);
152 }
153
154
155 static void
156 wrap_nearest_clamp_to_edge(float s, unsigned size, int *icoord)
157 {
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 if (s < min)
163 *icoord = 0;
164 else if (s > max)
165 *icoord = size - 1;
166 else
167 *icoord = util_ifloor(s * size);
168 }
169
170
171 static void
172 wrap_nearest_clamp_to_border(float s, unsigned size, int *icoord)
173 {
174 /* s limited to [min,max] */
175 /* i limited to [-1, size] */
176 const float min = -1.0F / (2.0F * size);
177 const float max = 1.0F - min;
178 if (s <= min)
179 *icoord = -1;
180 else if (s >= max)
181 *icoord = size;
182 else
183 *icoord = util_ifloor(s * size);
184 }
185
186
187 static void
188 wrap_nearest_mirror_repeat(float s, unsigned size, int *icoord)
189 {
190 const float min = 1.0F / (2.0F * size);
191 const float max = 1.0F - min;
192 const int flr = util_ifloor(s);
193 float u = frac(s);
194 if (flr & 1)
195 u = 1.0F - u;
196 if (u < min)
197 *icoord = 0;
198 else if (u > max)
199 *icoord = size - 1;
200 else
201 *icoord = util_ifloor(u * size);
202 }
203
204
205 static void
206 wrap_nearest_mirror_clamp(float s, unsigned size, int *icoord)
207 {
208 /* s limited to [0,1] */
209 /* i limited to [0,size-1] */
210 const float u = fabsf(s);
211 if (u <= 0.0F)
212 *icoord = 0;
213 else if (u >= 1.0F)
214 *icoord = size - 1;
215 else
216 *icoord = util_ifloor(u * size);
217 }
218
219
220 static void
221 wrap_nearest_mirror_clamp_to_edge(float s, unsigned size, int *icoord)
222 {
223 /* s limited to [min,max] */
224 /* i limited to [0, size-1] */
225 const float min = 1.0F / (2.0F * size);
226 const float max = 1.0F - min;
227 const float u = fabsf(s);
228 if (u < min)
229 *icoord = 0;
230 else if (u > max)
231 *icoord = size - 1;
232 else
233 *icoord = util_ifloor(u * size);
234 }
235
236
237 static void
238 wrap_nearest_mirror_clamp_to_border(float s, unsigned size, int *icoord)
239 {
240 /* s limited to [min,max] */
241 /* i limited to [0, size-1] */
242 const float min = -1.0F / (2.0F * size);
243 const float max = 1.0F - min;
244 const float u = fabsf(s);
245 if (u < min)
246 *icoord = -1;
247 else if (u > max)
248 *icoord = size;
249 else
250 *icoord = util_ifloor(u * size);
251 }
252
253
254 /**
255 * Used to compute texel locations for linear sampling
256 * \param wrapMode PIPE_TEX_WRAP_x
257 * \param s the texcoord
258 * \param size the texture image size
259 * \param icoord0 returns first texture index
260 * \param icoord1 returns second texture index (usually icoord0 + 1)
261 * \param w returns blend factor/weight between texture indices
262 * \param icoord returns the computed integer texture coord
263 */
264 static void
265 wrap_linear_repeat(float s, unsigned size,
266 int *icoord0, int *icoord1, float *w)
267 {
268 float u = s * size - 0.5F;
269 *icoord0 = repeat(util_ifloor(u), size);
270 *icoord1 = repeat(*icoord0 + 1, size);
271 *w = frac(u);
272 }
273
274
275 static void
276 wrap_linear_clamp(float s, unsigned size,
277 int *icoord0, int *icoord1, float *w)
278 {
279 float u = CLAMP(s, 0.0F, 1.0F);
280 u = u * size - 0.5f;
281 *icoord0 = util_ifloor(u);
282 *icoord1 = *icoord0 + 1;
283 *w = frac(u);
284 }
285
286
287 static void
288 wrap_linear_clamp_to_edge(float s, unsigned size,
289 int *icoord0, int *icoord1, float *w)
290 {
291 float u = CLAMP(s, 0.0F, 1.0F);
292 u = u * size - 0.5f;
293 *icoord0 = util_ifloor(u);
294 *icoord1 = *icoord0 + 1;
295 if (*icoord0 < 0)
296 *icoord0 = 0;
297 if (*icoord1 >= (int) size)
298 *icoord1 = size - 1;
299 *w = frac(u);
300 }
301
302
303 static void
304 wrap_linear_clamp_to_border(float s, unsigned size,
305 int *icoord0, int *icoord1, float *w)
306 {
307 const float min = -1.0F / (2.0F * size);
308 const float max = 1.0F - min;
309 float u = CLAMP(s, min, max);
310 u = u * size - 0.5f;
311 *icoord0 = util_ifloor(u);
312 *icoord1 = *icoord0 + 1;
313 *w = frac(u);
314 }
315
316
317 static void
318 wrap_linear_mirror_repeat(float s, unsigned size,
319 int *icoord0, int *icoord1, float *w)
320 {
321 const int flr = util_ifloor(s);
322 float u = frac(s);
323 if (flr & 1)
324 u = 1.0F - u;
325 u = u * size - 0.5F;
326 *icoord0 = util_ifloor(u);
327 *icoord1 = *icoord0 + 1;
328 if (*icoord0 < 0)
329 *icoord0 = 0;
330 if (*icoord1 >= (int) size)
331 *icoord1 = size - 1;
332 *w = frac(u);
333 }
334
335
336 static void
337 wrap_linear_mirror_clamp(float s, unsigned size,
338 int *icoord0, int *icoord1, float *w)
339 {
340 float u = fabsf(s);
341 if (u >= 1.0F)
342 u = (float) size;
343 else
344 u *= size;
345 u -= 0.5F;
346 *icoord0 = util_ifloor(u);
347 *icoord1 = *icoord0 + 1;
348 *w = frac(u);
349 }
350
351
352 static void
353 wrap_linear_mirror_clamp_to_edge(float s, unsigned size,
354 int *icoord0, int *icoord1, float *w)
355 {
356 float u = fabsf(s);
357 if (u >= 1.0F)
358 u = (float) size;
359 else
360 u *= size;
361 u -= 0.5F;
362 *icoord0 = util_ifloor(u);
363 *icoord1 = *icoord0 + 1;
364 if (*icoord0 < 0)
365 *icoord0 = 0;
366 if (*icoord1 >= (int) size)
367 *icoord1 = size - 1;
368 *w = frac(u);
369 }
370
371
372 static void
373 wrap_linear_mirror_clamp_to_border(float s, unsigned size,
374 int *icoord0, int *icoord1, float *w)
375 {
376 const float min = -1.0F / (2.0F * size);
377 const float max = 1.0F - min;
378 float u = fabsf(s);
379 if (u <= min)
380 u = min * size;
381 else if (u >= max)
382 u = max * size;
383 else
384 u *= size;
385 u -= 0.5F;
386 *icoord0 = util_ifloor(u);
387 *icoord1 = *icoord0 + 1;
388 *w = frac(u);
389 }
390
391
392 /**
393 * PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords.
394 */
395 static void
396 wrap_nearest_unorm_clamp(float s, unsigned size, int *icoord)
397 {
398 int i = util_ifloor(s);
399 *icoord = CLAMP(i, 0, (int) size-1);
400 }
401
402
403 /**
404 * PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords.
405 */
406 static void
407 wrap_nearest_unorm_clamp_to_border(float s, unsigned size, int *icoord)
408 {
409 *icoord = util_ifloor( CLAMP(s, -0.5F, (float) size + 0.5F) );
410 }
411
412
413 /**
414 * PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords.
415 */
416 static void
417 wrap_nearest_unorm_clamp_to_edge(float s, unsigned size, int *icoord)
418 {
419 *icoord = util_ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) );
420 }
421
422
423 /**
424 * PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords.
425 */
426 static void
427 wrap_linear_unorm_clamp(float s, unsigned size,
428 int *icoord0, int *icoord1, float *w)
429 {
430 /* Not exactly what the spec says, but it matches NVIDIA output */
431 float u = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f);
432 *icoord0 = util_ifloor(u);
433 *icoord1 = *icoord0 + 1;
434 *w = frac(u);
435 }
436
437
438 /**
439 * PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords.
440 */
441 static void
442 wrap_linear_unorm_clamp_to_border(float s, unsigned size,
443 int *icoord0, int *icoord1, float *w)
444 {
445 float u = CLAMP(s, -0.5F, (float) size + 0.5F);
446 u -= 0.5F;
447 *icoord0 = util_ifloor(u);
448 *icoord1 = *icoord0 + 1;
449 if (*icoord1 > (int) size - 1)
450 *icoord1 = size - 1;
451 *w = frac(u);
452 }
453
454
455 /**
456 * PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords.
457 */
458 static void
459 wrap_linear_unorm_clamp_to_edge(float s, unsigned size,
460 int *icoord0, int *icoord1, float *w)
461 {
462 float u = CLAMP(s, +0.5F, (float) size - 0.5F);
463 u -= 0.5F;
464 *icoord0 = util_ifloor(u);
465 *icoord1 = *icoord0 + 1;
466 if (*icoord1 > (int) size - 1)
467 *icoord1 = size - 1;
468 *w = frac(u);
469 }
470
471
472 /**
473 * Do coordinate to array index conversion. For array textures.
474 */
475 static INLINE void
476 wrap_array_layer(float coord, unsigned size, int *layer)
477 {
478 int c = util_ifloor(coord + 0.5F);
479 *layer = CLAMP(c, 0, size - 1);
480 }
481
482
483 /**
484 * Examine the quad's texture coordinates to compute the partial
485 * derivatives w.r.t X and Y, then compute lambda (level of detail).
486 */
487 static float
488 compute_lambda_1d(const struct sp_sampler_variant *samp,
489 const float s[TGSI_QUAD_SIZE],
490 const float t[TGSI_QUAD_SIZE],
491 const float p[TGSI_QUAD_SIZE])
492 {
493 const struct pipe_resource *texture = samp->view->texture;
494 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
495 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
496 float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, samp->view->u.tex.first_level);
497
498 return util_fast_log2(rho);
499 }
500
501
502 static float
503 compute_lambda_2d(const struct sp_sampler_variant *samp,
504 const float s[TGSI_QUAD_SIZE],
505 const float t[TGSI_QUAD_SIZE],
506 const float p[TGSI_QUAD_SIZE])
507 {
508 const struct pipe_resource *texture = samp->view->texture;
509 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
510 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
511 float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
512 float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]);
513 float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, samp->view->u.tex.first_level);
514 float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, samp->view->u.tex.first_level);
515 float rho = MAX2(maxx, maxy);
516
517 return util_fast_log2(rho);
518 }
519
520
521 static float
522 compute_lambda_3d(const struct sp_sampler_variant *samp,
523 const float s[TGSI_QUAD_SIZE],
524 const float t[TGSI_QUAD_SIZE],
525 const float p[TGSI_QUAD_SIZE])
526 {
527 const struct pipe_resource *texture = samp->view->texture;
528 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
529 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
530 float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
531 float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]);
532 float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
533 float dpdy = fabsf(p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]);
534 float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, samp->view->u.tex.first_level);
535 float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, samp->view->u.tex.first_level);
536 float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, samp->view->u.tex.first_level);
537 float rho;
538
539 rho = MAX2(maxx, maxy);
540 rho = MAX2(rho, maxz);
541
542 return util_fast_log2(rho);
543 }
544
545
546 /**
547 * Compute lambda for a vertex texture sampler.
548 * Since there aren't derivatives to use, just return 0.
549 */
550 static float
551 compute_lambda_vert(const struct sp_sampler_variant *samp,
552 const float s[TGSI_QUAD_SIZE],
553 const float t[TGSI_QUAD_SIZE],
554 const float p[TGSI_QUAD_SIZE])
555 {
556 return 0.0f;
557 }
558
559
560
561 /**
562 * Get a texel from a texture, using the texture tile cache.
563 *
564 * \param addr the template tex address containing cube, z, face info.
565 * \param x the x coord of texel within 2D image
566 * \param y the y coord of texel within 2D image
567 * \param rgba the quad to put the texel/color into
568 *
569 * XXX maybe move this into sp_tex_tile_cache.c and merge with the
570 * sp_get_cached_tile_tex() function.
571 */
572
573
574
575
576 static INLINE const float *
577 get_texel_2d_no_border(const struct sp_sampler_variant *samp,
578 union tex_tile_address addr, int x, int y)
579 {
580 const struct softpipe_tex_cached_tile *tile;
581
582 addr.bits.x = x / TILE_SIZE;
583 addr.bits.y = y / TILE_SIZE;
584 y %= TILE_SIZE;
585 x %= TILE_SIZE;
586
587 tile = sp_get_cached_tile_tex(samp->cache, addr);
588
589 return &tile->data.color[y][x][0];
590 }
591
592
593 static INLINE const float *
594 get_texel_2d(const struct sp_sampler_variant *samp,
595 union tex_tile_address addr, int x, int y)
596 {
597 const struct pipe_resource *texture = samp->view->texture;
598 unsigned level = addr.bits.level;
599
600 if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
601 y < 0 || y >= (int) u_minify(texture->height0, level)) {
602 return samp->sampler->border_color.f;
603 }
604 else {
605 return get_texel_2d_no_border( samp, addr, x, y );
606 }
607 }
608
609 /*
610 * seamless cubemap neighbour array.
611 * this array is used to find the adjacent face in each of 4 directions,
612 * left, right, up, down. (or -x, +x, -y, +y).
613 */
614 static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
615 /* pos X first then neg X is Z different, Y the same */
616 /* PIPE_TEX_FACE_POS_X,*/
617 { PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
618 PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
619 /* PIPE_TEX_FACE_NEG_X */
620 { PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
621 PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
622
623 /* pos Y first then neg Y is X different, X the same */
624 /* PIPE_TEX_FACE_POS_Y */
625 { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
626 PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
627
628 /* PIPE_TEX_FACE_NEG_Y */
629 { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
630 PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
631
632 /* pos Z first then neg Y is X different, X the same */
633 /* PIPE_TEX_FACE_POS_Z */
634 { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
635 PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
636
637 /* PIPE_TEX_FACE_NEG_Z */
638 { PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
639 PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y }
640 };
641
642 static INLINE unsigned
643 get_next_face(unsigned face, int x, int y)
644 {
645 int idx = 0;
646
647 if (x == 0 && y == 0)
648 return face;
649 if (x == -1)
650 idx = 0;
651 else if (x == 1)
652 idx = 1;
653 else if (y == -1)
654 idx = 2;
655 else if (y == 1)
656 idx = 3;
657
658 return face_array[face][idx];
659 }
660
661 static INLINE const float *
662 get_texel_cube_seamless(const struct sp_sampler_variant *samp,
663 union tex_tile_address addr, int x, int y,
664 float *corner)
665 {
666 const struct pipe_resource *texture = samp->view->texture;
667 unsigned level = addr.bits.level;
668 unsigned face = addr.bits.face;
669 int new_x, new_y;
670 int max_x, max_y;
671 int c;
672
673 max_x = (int) u_minify(texture->width0, level);
674 max_y = (int) u_minify(texture->height0, level);
675 new_x = x;
676 new_y = y;
677
678 /* the corner case */
679 if ((x < 0 || x >= max_x) &&
680 (y < 0 || y >= max_y)) {
681 const float *c1, *c2, *c3;
682 int fx = x < 0 ? 0 : max_x - 1;
683 int fy = y < 0 ? 0 : max_y - 1;
684 c1 = get_texel_2d_no_border( samp, addr, fx, fy);
685 addr.bits.face = get_next_face(face, (x < 0) ? -1 : 1, 0);
686 c2 = get_texel_2d_no_border( samp, addr, (x < 0) ? max_x - 1 : 0, fy);
687 addr.bits.face = get_next_face(face, 0, (y < 0) ? -1 : 1);
688 c3 = get_texel_2d_no_border( samp, addr, fx, (y < 0) ? max_y - 1 : 0);
689 for (c = 0; c < TGSI_QUAD_SIZE; c++)
690 corner[c] = CLAMP((c1[c] + c2[c] + c3[c]), 0.0F, 1.0F) / 3;
691
692 return corner;
693 }
694 /* change the face */
695 if (x < 0) {
696 new_x = max_x - 1;
697 face = get_next_face(face, -1, 0);
698 } else if (x >= max_x) {
699 new_x = 0;
700 face = get_next_face(face, 1, 0);
701 } else if (y < 0) {
702 new_y = max_y - 1;
703 face = get_next_face(face, 0, -1);
704 } else if (y >= max_y) {
705 new_y = 0;
706 face = get_next_face(face, 0, 1);
707 }
708
709 addr.bits.face = face;
710 return get_texel_2d_no_border( samp, addr, new_x, new_y );
711 }
712
713 /* Gather a quad of adjacent texels within a tile:
714 */
715 static INLINE void
716 get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_variant *samp,
717 union tex_tile_address addr,
718 unsigned x, unsigned y,
719 const float *out[4])
720 {
721 const struct softpipe_tex_cached_tile *tile;
722
723 addr.bits.x = x / TILE_SIZE;
724 addr.bits.y = y / TILE_SIZE;
725 y %= TILE_SIZE;
726 x %= TILE_SIZE;
727
728 tile = sp_get_cached_tile_tex(samp->cache, addr);
729
730 out[0] = &tile->data.color[y ][x ][0];
731 out[1] = &tile->data.color[y ][x+1][0];
732 out[2] = &tile->data.color[y+1][x ][0];
733 out[3] = &tile->data.color[y+1][x+1][0];
734 }
735
736
737 /* Gather a quad of potentially non-adjacent texels:
738 */
739 static INLINE void
740 get_texel_quad_2d_no_border(const struct sp_sampler_variant *samp,
741 union tex_tile_address addr,
742 int x0, int y0,
743 int x1, int y1,
744 const float *out[4])
745 {
746 out[0] = get_texel_2d_no_border( samp, addr, x0, y0 );
747 out[1] = get_texel_2d_no_border( samp, addr, x1, y0 );
748 out[2] = get_texel_2d_no_border( samp, addr, x0, y1 );
749 out[3] = get_texel_2d_no_border( samp, addr, x1, y1 );
750 }
751
752 /* Can involve a lot of unnecessary checks for border color:
753 */
754 static INLINE void
755 get_texel_quad_2d(const struct sp_sampler_variant *samp,
756 union tex_tile_address addr,
757 int x0, int y0,
758 int x1, int y1,
759 const float *out[4])
760 {
761 out[0] = get_texel_2d( samp, addr, x0, y0 );
762 out[1] = get_texel_2d( samp, addr, x1, y0 );
763 out[3] = get_texel_2d( samp, addr, x1, y1 );
764 out[2] = get_texel_2d( samp, addr, x0, y1 );
765 }
766
767
768
769 /* 3d variants:
770 */
771 static INLINE const float *
772 get_texel_3d_no_border(const struct sp_sampler_variant *samp,
773 union tex_tile_address addr, int x, int y, int z)
774 {
775 const struct softpipe_tex_cached_tile *tile;
776
777 addr.bits.x = x / TILE_SIZE;
778 addr.bits.y = y / TILE_SIZE;
779 addr.bits.z = z;
780 y %= TILE_SIZE;
781 x %= TILE_SIZE;
782
783 tile = sp_get_cached_tile_tex(samp->cache, addr);
784
785 return &tile->data.color[y][x][0];
786 }
787
788
789 static INLINE const float *
790 get_texel_3d(const struct sp_sampler_variant *samp,
791 union tex_tile_address addr, int x, int y, int z)
792 {
793 const struct pipe_resource *texture = samp->view->texture;
794 unsigned level = addr.bits.level;
795
796 if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
797 y < 0 || y >= (int) u_minify(texture->height0, level) ||
798 z < 0 || z >= (int) u_minify(texture->depth0, level)) {
799 return samp->sampler->border_color.f;
800 }
801 else {
802 return get_texel_3d_no_border( samp, addr, x, y, z );
803 }
804 }
805
806
807 /* Get texel pointer for 1D array texture */
808 static INLINE const float *
809 get_texel_1d_array(const struct sp_sampler_variant *samp,
810 union tex_tile_address addr, int x, int y)
811 {
812 const struct pipe_resource *texture = samp->view->texture;
813 unsigned level = addr.bits.level;
814
815 if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
816 return samp->sampler->border_color.f;
817 }
818 else {
819 return get_texel_2d_no_border(samp, addr, x, y);
820 }
821 }
822
823
824 /* Get texel pointer for 2D array texture */
825 static INLINE const float *
826 get_texel_2d_array(const struct sp_sampler_variant *samp,
827 union tex_tile_address addr, int x, int y, int layer)
828 {
829 const struct pipe_resource *texture = samp->view->texture;
830 unsigned level = addr.bits.level;
831
832 assert(layer < (int) texture->array_size);
833 assert(layer >= 0);
834
835 if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
836 y < 0 || y >= (int) u_minify(texture->height0, level)) {
837 return samp->sampler->border_color.f;
838 }
839 else {
840 return get_texel_3d_no_border(samp, addr, x, y, layer);
841 }
842 }
843
844
845 /* Get texel pointer for cube array texture */
846 static INLINE const float *
847 get_texel_cube_array(const struct sp_sampler_variant *samp,
848 union tex_tile_address addr, int x, int y, int layer)
849 {
850 const struct pipe_resource *texture = samp->view->texture;
851 unsigned level = addr.bits.level;
852
853 assert(layer < (int) texture->array_size);
854 assert(layer >= 0);
855
856 if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
857 y < 0 || y >= (int) u_minify(texture->height0, level)) {
858 return samp->sampler->border_color.f;
859 }
860 else {
861 return get_texel_3d_no_border(samp, addr, x, y, layer);
862 }
863 }
864 /**
865 * Given the logbase2 of a mipmap's base level size and a mipmap level,
866 * return the size (in texels) of that mipmap level.
867 * For example, if level[0].width = 256 then base_pot will be 8.
868 * If level = 2, then we'll return 64 (the width at level=2).
869 * Return 1 if level > base_pot.
870 */
871 static INLINE unsigned
872 pot_level_size(unsigned base_pot, unsigned level)
873 {
874 return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
875 }
876
877
878 static void
879 print_sample(const char *function, const float *rgba)
880 {
881 debug_printf("%s %g %g %g %g\n",
882 function,
883 rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]);
884 }
885
886
887 static void
888 print_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
889 {
890 debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
891 function,
892 rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
893 rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
894 rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
895 rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
896 }
897
898 /* Some image-filter fastpaths:
899 */
900 static INLINE void
901 img_filter_2d_linear_repeat_POT(struct sp_sampler_variant *samp,
902 float s,
903 float t,
904 float p,
905 unsigned level,
906 unsigned face_id,
907 float *rgba)
908 {
909 unsigned xpot = pot_level_size(samp->xpot, level);
910 unsigned ypot = pot_level_size(samp->ypot, level);
911 unsigned xmax = (xpot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, xpot) - 1; */
912 unsigned ymax = (ypot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, ypot) - 1; */
913 union tex_tile_address addr;
914 int c;
915
916 float u = s * xpot - 0.5F;
917 float v = t * ypot - 0.5F;
918
919 int uflr = util_ifloor(u);
920 int vflr = util_ifloor(v);
921
922 float xw = u - (float)uflr;
923 float yw = v - (float)vflr;
924
925 int x0 = uflr & (xpot - 1);
926 int y0 = vflr & (ypot - 1);
927
928 const float *tx[4];
929
930 addr.value = 0;
931 addr.bits.level = level;
932
933 /* Can we fetch all four at once:
934 */
935 if (x0 < xmax && y0 < ymax) {
936 get_texel_quad_2d_no_border_single_tile(samp, addr, x0, y0, tx);
937 }
938 else {
939 unsigned x1 = (x0 + 1) & (xpot - 1);
940 unsigned y1 = (y0 + 1) & (ypot - 1);
941 get_texel_quad_2d_no_border(samp, addr, x0, y0, x1, y1, tx);
942 }
943
944 /* interpolate R, G, B, A */
945 for (c = 0; c < TGSI_QUAD_SIZE; c++) {
946 rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
947 tx[0][c], tx[1][c],
948 tx[2][c], tx[3][c]);
949 }
950
951 if (DEBUG_TEX) {
952 print_sample(__FUNCTION__, rgba);
953 }
954 }
955
956
957 static INLINE void
958 img_filter_2d_nearest_repeat_POT(struct sp_sampler_variant *samp,
959 float s,
960 float t,
961 float p,
962 unsigned level,
963 unsigned face_id,
964 float rgba[TGSI_QUAD_SIZE])
965 {
966 unsigned xpot = pot_level_size(samp->xpot, level);
967 unsigned ypot = pot_level_size(samp->ypot, level);
968 const float *out;
969 union tex_tile_address addr;
970 int c;
971
972 float u = s * xpot;
973 float v = t * ypot;
974
975 int uflr = util_ifloor(u);
976 int vflr = util_ifloor(v);
977
978 int x0 = uflr & (xpot - 1);
979 int y0 = vflr & (ypot - 1);
980
981 addr.value = 0;
982 addr.bits.level = level;
983
984 out = get_texel_2d_no_border(samp, addr, x0, y0);
985 for (c = 0; c < TGSI_QUAD_SIZE; c++)
986 rgba[TGSI_NUM_CHANNELS*c] = out[c];
987
988 if (DEBUG_TEX) {
989 print_sample(__FUNCTION__, rgba);
990 }
991 }
992
993
994 static INLINE void
995 img_filter_2d_nearest_clamp_POT(struct sp_sampler_variant *samp,
996 float s,
997 float t,
998 float p,
999 unsigned level,
1000 unsigned face_id,
1001 float rgba[TGSI_QUAD_SIZE])
1002 {
1003 unsigned xpot = pot_level_size(samp->xpot, level);
1004 unsigned ypot = pot_level_size(samp->ypot, level);
1005 union tex_tile_address addr;
1006 int c;
1007
1008 float u = s * xpot;
1009 float v = t * ypot;
1010
1011 int x0, y0;
1012 const float *out;
1013
1014 addr.value = 0;
1015 addr.bits.level = level;
1016
1017 x0 = util_ifloor(u);
1018 if (x0 < 0)
1019 x0 = 0;
1020 else if (x0 > xpot - 1)
1021 x0 = xpot - 1;
1022
1023 y0 = util_ifloor(v);
1024 if (y0 < 0)
1025 y0 = 0;
1026 else if (y0 > ypot - 1)
1027 y0 = ypot - 1;
1028
1029 out = get_texel_2d_no_border(samp, addr, x0, y0);
1030 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1031 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1032
1033 if (DEBUG_TEX) {
1034 print_sample(__FUNCTION__, rgba);
1035 }
1036 }
1037
1038
1039 static void
1040 img_filter_1d_nearest(struct sp_sampler_variant *samp,
1041 float s,
1042 float t,
1043 float p,
1044 unsigned level,
1045 unsigned face_id,
1046 float rgba[TGSI_QUAD_SIZE])
1047 {
1048 const struct pipe_resource *texture = samp->view->texture;
1049 int width;
1050 int x;
1051 union tex_tile_address addr;
1052 const float *out;
1053 int c;
1054
1055 width = u_minify(texture->width0, level);
1056
1057 assert(width > 0);
1058
1059 addr.value = 0;
1060 addr.bits.level = level;
1061
1062 samp->nearest_texcoord_s(s, width, &x);
1063
1064 out = get_texel_2d(samp, addr, x, 0);
1065 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1066 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1067
1068 if (DEBUG_TEX) {
1069 print_sample(__FUNCTION__, rgba);
1070 }
1071 }
1072
1073
1074 static void
1075 img_filter_1d_array_nearest(struct sp_sampler_variant *samp,
1076 float s,
1077 float t,
1078 float p,
1079 unsigned level,
1080 unsigned face_id,
1081 float *rgba)
1082 {
1083 const struct pipe_resource *texture = samp->view->texture;
1084 int width;
1085 int x, layer;
1086 union tex_tile_address addr;
1087 const float *out;
1088 int c;
1089
1090 width = u_minify(texture->width0, level);
1091
1092 assert(width > 0);
1093
1094 addr.value = 0;
1095 addr.bits.level = level;
1096
1097 samp->nearest_texcoord_s(s, width, &x);
1098 wrap_array_layer(t, texture->array_size, &layer);
1099
1100 out = get_texel_1d_array(samp, addr, x, layer);
1101 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1102 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1103
1104 if (DEBUG_TEX) {
1105 print_sample(__FUNCTION__, rgba);
1106 }
1107 }
1108
1109
1110 static void
1111 img_filter_2d_nearest(struct sp_sampler_variant *samp,
1112 float s,
1113 float t,
1114 float p,
1115 unsigned level,
1116 unsigned face_id,
1117 float *rgba)
1118 {
1119 const struct pipe_resource *texture = samp->view->texture;
1120 int width, height;
1121 int x, y;
1122 union tex_tile_address addr;
1123 const float *out;
1124 int c;
1125
1126 width = u_minify(texture->width0, level);
1127 height = u_minify(texture->height0, level);
1128
1129 assert(width > 0);
1130 assert(height > 0);
1131
1132 addr.value = 0;
1133 addr.bits.level = level;
1134
1135 samp->nearest_texcoord_s(s, width, &x);
1136 samp->nearest_texcoord_t(t, height, &y);
1137
1138 out = get_texel_2d(samp, addr, x, y);
1139 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1140 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1141
1142 if (DEBUG_TEX) {
1143 print_sample(__FUNCTION__, rgba);
1144 }
1145 }
1146
1147
1148 static void
1149 img_filter_2d_array_nearest(struct sp_sampler_variant *samp,
1150 float s,
1151 float t,
1152 float p,
1153 unsigned level,
1154 unsigned face_id,
1155 float *rgba)
1156 {
1157 const struct pipe_resource *texture = samp->view->texture;
1158 int width, height;
1159 int x, y, layer;
1160 union tex_tile_address addr;
1161 const float *out;
1162 int c;
1163
1164 width = u_minify(texture->width0, level);
1165 height = u_minify(texture->height0, level);
1166
1167 assert(width > 0);
1168 assert(height > 0);
1169
1170 addr.value = 0;
1171 addr.bits.level = level;
1172
1173 samp->nearest_texcoord_s(s, width, &x);
1174 samp->nearest_texcoord_t(t, height, &y);
1175 wrap_array_layer(p, texture->array_size, &layer);
1176
1177 out = get_texel_2d_array(samp, addr, x, y, layer);
1178 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1179 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1180
1181 if (DEBUG_TEX) {
1182 print_sample(__FUNCTION__, rgba);
1183 }
1184 }
1185
1186
1187 static INLINE union tex_tile_address
1188 face(union tex_tile_address addr, unsigned face )
1189 {
1190 addr.bits.face = face;
1191 return addr;
1192 }
1193
1194
1195 static void
1196 img_filter_cube_nearest(struct sp_sampler_variant *samp,
1197 float s,
1198 float t,
1199 float p,
1200 unsigned level,
1201 unsigned face_id,
1202 float *rgba)
1203 {
1204 const struct pipe_resource *texture = samp->view->texture;
1205 int width, height;
1206 int x, y;
1207 union tex_tile_address addr;
1208 const float *out;
1209 int c;
1210
1211 width = u_minify(texture->width0, level);
1212 height = u_minify(texture->height0, level);
1213
1214 assert(width > 0);
1215 assert(height > 0);
1216
1217 addr.value = 0;
1218 addr.bits.level = level;
1219
1220 /*
1221 * If NEAREST filtering is done within a miplevel, always apply wrap
1222 * mode CLAMP_TO_EDGE.
1223 */
1224 if (samp->sampler->seamless_cube_map) {
1225 wrap_nearest_clamp_to_edge(s, width, &x);
1226 wrap_nearest_clamp_to_edge(t, height, &y);
1227 } else {
1228 samp->nearest_texcoord_s(s, width, &x);
1229 samp->nearest_texcoord_t(t, height, &y);
1230 }
1231
1232 out = get_texel_2d(samp, face(addr, face_id), x, y);
1233 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1234 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1235
1236 if (DEBUG_TEX) {
1237 print_sample(__FUNCTION__, rgba);
1238 }
1239 }
1240
1241 static void
1242 img_filter_cube_array_nearest(struct sp_sampler_variant *samp,
1243 float s,
1244 float t,
1245 float p,
1246 unsigned level,
1247 unsigned face_id,
1248 float *rgba)
1249 {
1250 const struct pipe_resource *texture = samp->view->texture;
1251 int width, height;
1252 int x, y, layer;
1253 union tex_tile_address addr;
1254 const float *out;
1255 int c;
1256
1257 width = u_minify(texture->width0, level);
1258 height = u_minify(texture->height0, level);
1259
1260 assert(width > 0);
1261 assert(height > 0);
1262
1263 addr.value = 0;
1264 addr.bits.level = level;
1265
1266 samp->nearest_texcoord_s(s, width, &x);
1267 samp->nearest_texcoord_t(t, height, &y);
1268 wrap_array_layer(p, texture->array_size, &layer);
1269
1270 out = get_texel_cube_array(samp, addr, x, y, layer * 6 + face_id);
1271 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1272 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1273
1274 if (DEBUG_TEX) {
1275 print_sample(__FUNCTION__, rgba);
1276 }
1277 }
1278
1279 static void
1280 img_filter_3d_nearest(struct sp_sampler_variant *samp,
1281 float s,
1282 float t,
1283 float p,
1284 unsigned level,
1285 unsigned face_id,
1286 float *rgba)
1287 {
1288 const struct pipe_resource *texture = samp->view->texture;
1289 int width, height, depth;
1290 int x, y, z;
1291 union tex_tile_address addr;
1292 const float *out;
1293 int c;
1294
1295 width = u_minify(texture->width0, level);
1296 height = u_minify(texture->height0, level);
1297 depth = u_minify(texture->depth0, level);
1298
1299 assert(width > 0);
1300 assert(height > 0);
1301 assert(depth > 0);
1302
1303 samp->nearest_texcoord_s(s, width, &x);
1304 samp->nearest_texcoord_t(t, height, &y);
1305 samp->nearest_texcoord_p(p, depth, &z);
1306
1307 addr.value = 0;
1308 addr.bits.level = level;
1309
1310 out = get_texel_3d(samp, addr, x, y, z);
1311 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1312 rgba[TGSI_NUM_CHANNELS*c] = out[c];
1313 }
1314
1315
1316 static void
1317 img_filter_1d_linear(struct sp_sampler_variant *samp,
1318 float s,
1319 float t,
1320 float p,
1321 unsigned level,
1322 unsigned face_id,
1323 float *rgba)
1324 {
1325 const struct pipe_resource *texture = samp->view->texture;
1326 int width;
1327 int x0, x1;
1328 float xw; /* weights */
1329 union tex_tile_address addr;
1330 const float *tx0, *tx1;
1331 int c;
1332
1333 width = u_minify(texture->width0, level);
1334
1335 assert(width > 0);
1336
1337 addr.value = 0;
1338 addr.bits.level = level;
1339
1340 samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1341
1342 tx0 = get_texel_2d(samp, addr, x0, 0);
1343 tx1 = get_texel_2d(samp, addr, x1, 0);
1344
1345 /* interpolate R, G, B, A */
1346 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1347 rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
1348 }
1349
1350
1351 static void
1352 img_filter_1d_array_linear(struct sp_sampler_variant *samp,
1353 float s,
1354 float t,
1355 float p,
1356 unsigned level,
1357 unsigned face_id,
1358 float *rgba)
1359 {
1360 const struct pipe_resource *texture = samp->view->texture;
1361 int width;
1362 int x0, x1, layer;
1363 float xw; /* weights */
1364 union tex_tile_address addr;
1365 const float *tx0, *tx1;
1366 int c;
1367
1368 width = u_minify(texture->width0, level);
1369
1370 assert(width > 0);
1371
1372 addr.value = 0;
1373 addr.bits.level = level;
1374
1375 samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1376 wrap_array_layer(t, texture->array_size, &layer);
1377
1378 tx0 = get_texel_1d_array(samp, addr, x0, layer);
1379 tx1 = get_texel_1d_array(samp, addr, x1, layer);
1380
1381 /* interpolate R, G, B, A */
1382 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1383 rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
1384 }
1385
1386
1387 static void
1388 img_filter_2d_linear(struct sp_sampler_variant *samp,
1389 float s,
1390 float t,
1391 float p,
1392 unsigned level,
1393 unsigned face_id,
1394 float *rgba)
1395 {
1396 const struct pipe_resource *texture = samp->view->texture;
1397 int width, height;
1398 int x0, y0, x1, y1;
1399 float xw, yw; /* weights */
1400 union tex_tile_address addr;
1401 const float *tx0, *tx1, *tx2, *tx3;
1402 int c;
1403
1404 width = u_minify(texture->width0, level);
1405 height = u_minify(texture->height0, level);
1406
1407 assert(width > 0);
1408 assert(height > 0);
1409
1410 addr.value = 0;
1411 addr.bits.level = level;
1412
1413 samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1414 samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1415
1416 tx0 = get_texel_2d(samp, addr, x0, y0);
1417 tx1 = get_texel_2d(samp, addr, x1, y0);
1418 tx2 = get_texel_2d(samp, addr, x0, y1);
1419 tx3 = get_texel_2d(samp, addr, x1, y1);
1420
1421 /* interpolate R, G, B, A */
1422 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1423 rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1424 tx0[c], tx1[c],
1425 tx2[c], tx3[c]);
1426 }
1427
1428
1429 static void
1430 img_filter_2d_array_linear(struct sp_sampler_variant *samp,
1431 float s,
1432 float t,
1433 float p,
1434 unsigned level,
1435 unsigned face_id,
1436 float *rgba)
1437 {
1438 const struct pipe_resource *texture = samp->view->texture;
1439 int width, height;
1440 int x0, y0, x1, y1, layer;
1441 float xw, yw; /* weights */
1442 union tex_tile_address addr;
1443 const float *tx0, *tx1, *tx2, *tx3;
1444 int c;
1445
1446 width = u_minify(texture->width0, level);
1447 height = u_minify(texture->height0, level);
1448
1449 assert(width > 0);
1450 assert(height > 0);
1451
1452 addr.value = 0;
1453 addr.bits.level = level;
1454
1455 samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1456 samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1457 wrap_array_layer(p, texture->array_size, &layer);
1458
1459 tx0 = get_texel_2d_array(samp, addr, x0, y0, layer);
1460 tx1 = get_texel_2d_array(samp, addr, x1, y0, layer);
1461 tx2 = get_texel_2d_array(samp, addr, x0, y1, layer);
1462 tx3 = get_texel_2d_array(samp, addr, x1, y1, layer);
1463
1464 /* interpolate R, G, B, A */
1465 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1466 rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1467 tx0[c], tx1[c],
1468 tx2[c], tx3[c]);
1469 }
1470
1471
1472 static void
1473 img_filter_cube_linear(struct sp_sampler_variant *samp,
1474 float s,
1475 float t,
1476 float p,
1477 unsigned level,
1478 unsigned face_id,
1479 float *rgba)
1480 {
1481 const struct pipe_resource *texture = samp->view->texture;
1482 int width, height;
1483 int x0, y0, x1, y1;
1484 float xw, yw; /* weights */
1485 union tex_tile_address addr, addrj;
1486 const float *tx0, *tx1, *tx2, *tx3;
1487 float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE], corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
1488 int c;
1489
1490 width = u_minify(texture->width0, level);
1491 height = u_minify(texture->height0, level);
1492
1493 assert(width > 0);
1494 assert(height > 0);
1495
1496 addr.value = 0;
1497 addr.bits.level = level;
1498
1499 /*
1500 * For seamless if LINEAR filtering is done within a miplevel,
1501 * always apply wrap mode CLAMP_TO_BORDER.
1502 */
1503 if (samp->sampler->seamless_cube_map) {
1504 wrap_linear_clamp_to_border(s, width, &x0, &x1, &xw);
1505 wrap_linear_clamp_to_border(t, height, &y0, &y1, &yw);
1506 } else {
1507 samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1508 samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1509 }
1510
1511 addrj = face(addr, face_id);
1512
1513 if (samp->sampler->seamless_cube_map) {
1514 tx0 = get_texel_cube_seamless(samp, addrj, x0, y0, corner0);
1515 tx1 = get_texel_cube_seamless(samp, addrj, x1, y0, corner1);
1516 tx2 = get_texel_cube_seamless(samp, addrj, x0, y1, corner2);
1517 tx3 = get_texel_cube_seamless(samp, addrj, x1, y1, corner3);
1518 } else {
1519 tx0 = get_texel_2d(samp, addrj, x0, y0);
1520 tx1 = get_texel_2d(samp, addrj, x1, y0);
1521 tx2 = get_texel_2d(samp, addrj, x0, y1);
1522 tx3 = get_texel_2d(samp, addrj, x1, y1);
1523 }
1524 /* interpolate R, G, B, A */
1525 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1526 rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1527 tx0[c], tx1[c],
1528 tx2[c], tx3[c]);
1529 }
1530
1531
1532 static void
1533 img_filter_cube_array_linear(struct sp_sampler_variant *samp,
1534 float s,
1535 float t,
1536 float p,
1537 unsigned level,
1538 unsigned face_id,
1539 float *rgba)
1540 {
1541 const struct pipe_resource *texture = samp->view->texture;
1542 int width, height;
1543 int x0, y0, x1, y1, layer;
1544 float xw, yw; /* weights */
1545 union tex_tile_address addr;
1546 const float *tx0, *tx1, *tx2, *tx3;
1547 int c;
1548
1549 width = u_minify(texture->width0, level);
1550 height = u_minify(texture->height0, level);
1551
1552 assert(width > 0);
1553 assert(height > 0);
1554
1555 addr.value = 0;
1556 addr.bits.level = level;
1557
1558 samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1559 samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1560 wrap_array_layer(p, texture->array_size, &layer);
1561
1562 tx0 = get_texel_cube_array(samp, addr, x0, y0, layer * 6 + face_id);
1563 tx1 = get_texel_cube_array(samp, addr, x1, y0, layer * 6 + face_id);
1564 tx2 = get_texel_cube_array(samp, addr, x0, y1, layer * 6 + face_id);
1565 tx3 = get_texel_cube_array(samp, addr, x1, y1, layer * 6 + face_id);
1566
1567 /* interpolate R, G, B, A */
1568 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1569 rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1570 tx0[c], tx1[c],
1571 tx2[c], tx3[c]);
1572 }
1573
1574 static void
1575 img_filter_3d_linear(struct sp_sampler_variant *samp,
1576 float s,
1577 float t,
1578 float p,
1579 unsigned level,
1580 unsigned face_id,
1581 float *rgba)
1582 {
1583 const struct pipe_resource *texture = samp->view->texture;
1584 int width, height, depth;
1585 int x0, x1, y0, y1, z0, z1;
1586 float xw, yw, zw; /* interpolation weights */
1587 union tex_tile_address addr;
1588 const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13;
1589 int c;
1590
1591 width = u_minify(texture->width0, level);
1592 height = u_minify(texture->height0, level);
1593 depth = u_minify(texture->depth0, level);
1594
1595 addr.value = 0;
1596 addr.bits.level = level;
1597
1598 assert(width > 0);
1599 assert(height > 0);
1600 assert(depth > 0);
1601
1602 samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1603 samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1604 samp->linear_texcoord_p(p, depth, &z0, &z1, &zw);
1605
1606
1607 tx00 = get_texel_3d(samp, addr, x0, y0, z0);
1608 tx01 = get_texel_3d(samp, addr, x1, y0, z0);
1609 tx02 = get_texel_3d(samp, addr, x0, y1, z0);
1610 tx03 = get_texel_3d(samp, addr, x1, y1, z0);
1611
1612 tx10 = get_texel_3d(samp, addr, x0, y0, z1);
1613 tx11 = get_texel_3d(samp, addr, x1, y0, z1);
1614 tx12 = get_texel_3d(samp, addr, x0, y1, z1);
1615 tx13 = get_texel_3d(samp, addr, x1, y1, z1);
1616
1617 /* interpolate R, G, B, A */
1618 for (c = 0; c < TGSI_QUAD_SIZE; c++)
1619 rgba[TGSI_NUM_CHANNELS*c] = lerp_3d(xw, yw, zw,
1620 tx00[c], tx01[c],
1621 tx02[c], tx03[c],
1622 tx10[c], tx11[c],
1623 tx12[c], tx13[c]);
1624 }
1625
1626
1627 /* Calculate level of detail for every fragment,
1628 * with lambda already computed.
1629 * Note that lambda has already been biased by global LOD bias.
1630 * \param biased_lambda per-quad lambda.
1631 * \param lod_in per-fragment lod_bias or explicit_lod.
1632 * \param lod returns the per-fragment lod.
1633 */
1634 static INLINE void
1635 compute_lod(const struct pipe_sampler_state *sampler,
1636 enum tgsi_sampler_control control,
1637 const float biased_lambda,
1638 const float lod_in[TGSI_QUAD_SIZE],
1639 float lod[TGSI_QUAD_SIZE])
1640 {
1641 float min_lod = sampler->min_lod;
1642 float max_lod = sampler->max_lod;
1643 uint i;
1644
1645 switch (control) {
1646 case tgsi_sampler_lod_none:
1647 case tgsi_sampler_lod_zero:
1648 lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
1649 break;
1650 case tgsi_sampler_lod_bias:
1651 for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1652 lod[i] = biased_lambda + lod_in[i];
1653 lod[i] = CLAMP(lod[i], min_lod, max_lod);
1654 }
1655 break;
1656 case tgsi_sampler_lod_explicit:
1657 for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1658 lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
1659 }
1660 break;
1661 default:
1662 assert(0);
1663 lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
1664 }
1665 }
1666
1667
1668 /* Calculate level of detail for every fragment.
1669 * \param lod_in per-fragment lod_bias or explicit_lod.
1670 * \param lod results per-fragment lod.
1671 */
1672 static INLINE void
1673 compute_lambda_lod(struct sp_sampler_variant *samp,
1674 const float s[TGSI_QUAD_SIZE],
1675 const float t[TGSI_QUAD_SIZE],
1676 const float p[TGSI_QUAD_SIZE],
1677 const float lod_in[TGSI_QUAD_SIZE],
1678 enum tgsi_sampler_control control,
1679 float lod[TGSI_QUAD_SIZE])
1680 {
1681 const struct pipe_sampler_state *sampler = samp->sampler;
1682 float lod_bias = sampler->lod_bias;
1683 float min_lod = sampler->min_lod;
1684 float max_lod = sampler->max_lod;
1685 float lambda;
1686 uint i;
1687
1688 switch (control) {
1689 case tgsi_sampler_lod_none:
1690 lambda = samp->compute_lambda(samp, s, t, p) + lod_bias;
1691 lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lambda, min_lod, max_lod);
1692 break;
1693 case tgsi_sampler_lod_bias:
1694 lambda = samp->compute_lambda(samp, s, t, p) + lod_bias;
1695 for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1696 lod[i] = lambda + lod_in[i];
1697 lod[i] = CLAMP(lod[i], min_lod, max_lod);
1698 }
1699 break;
1700 case tgsi_sampler_lod_explicit:
1701 for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1702 lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
1703 }
1704 break;
1705 case tgsi_sampler_lod_zero:
1706 /* this is all static state in the sampler really need clamp here? */
1707 lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lod_bias, min_lod, max_lod);
1708 break;
1709 default:
1710 assert(0);
1711 lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
1712 }
1713 }
1714
1715
1716 static void
1717 mip_filter_linear(struct sp_sampler_variant *samp,
1718 const float s[TGSI_QUAD_SIZE],
1719 const float t[TGSI_QUAD_SIZE],
1720 const float p[TGSI_QUAD_SIZE],
1721 const float c0[TGSI_QUAD_SIZE],
1722 const float lod_in[TGSI_QUAD_SIZE],
1723 enum tgsi_sampler_control control,
1724 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1725 {
1726 const struct pipe_resource *texture = samp->view->texture;
1727 int j;
1728 float lod[TGSI_QUAD_SIZE];
1729
1730 compute_lambda_lod(samp, s, t, p, lod_in, control, lod);
1731
1732 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
1733 int level0 = samp->view->u.tex.first_level + (int)lod[j];
1734
1735 if (lod[j] < 0.0)
1736 samp->mag_img_filter(samp, s[j], t[j], p[j], samp->view->u.tex.first_level,
1737 samp->faces[j], &rgba[0][j]);
1738
1739 else if (level0 >= texture->last_level)
1740 samp->min_img_filter(samp, s[j], t[j], p[j], texture->last_level,
1741 samp->faces[j], &rgba[0][j]);
1742
1743 else {
1744 float levelBlend = frac(lod[j]);
1745 float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
1746 int c;
1747
1748 samp->min_img_filter(samp, s[j], t[j], p[j], level0,
1749 samp->faces[j], &rgbax[0][0]);
1750 samp->min_img_filter(samp, s[j], t[j], p[j], level0+1,
1751 samp->faces[j], &rgbax[0][1]);
1752
1753 for (c = 0; c < 4; c++) {
1754 rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
1755 }
1756 }
1757 }
1758
1759 if (DEBUG_TEX) {
1760 print_sample_4(__FUNCTION__, rgba);
1761 }
1762 }
1763
1764
1765 /**
1766 * Compute nearest mipmap level from texcoords.
1767 * Then sample the texture level for four elements of a quad.
1768 * \param c0 the LOD bias factors, or absolute LODs (depending on control)
1769 */
1770 static void
1771 mip_filter_nearest(struct sp_sampler_variant *samp,
1772 const float s[TGSI_QUAD_SIZE],
1773 const float t[TGSI_QUAD_SIZE],
1774 const float p[TGSI_QUAD_SIZE],
1775 const float c0[TGSI_QUAD_SIZE],
1776 const float lod_in[TGSI_QUAD_SIZE],
1777 enum tgsi_sampler_control control,
1778 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1779 {
1780 const struct pipe_resource *texture = samp->view->texture;
1781 float lod[TGSI_QUAD_SIZE];
1782 int j;
1783
1784 compute_lambda_lod(samp, s, t, p, lod_in, control, lod);
1785
1786 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
1787 if (lod[j] < 0.0)
1788 samp->mag_img_filter(samp, s[j], t[j], p[j], samp->view->u.tex.first_level,
1789 samp->faces[j], &rgba[0][j]);
1790 else {
1791 float level = samp->view->u.tex.first_level + (int)(lod[j] + 0.5F) ;
1792 level = MIN2(level, (int)texture->last_level);
1793 samp->min_img_filter(samp, s[j], t[j], p[j], level, samp->faces[j],
1794 &rgba[0][j]);
1795 }
1796 }
1797
1798 if (DEBUG_TEX) {
1799 print_sample_4(__FUNCTION__, rgba);
1800 }
1801 }
1802
1803
1804 static void
1805 mip_filter_none(struct sp_sampler_variant *samp,
1806 const float s[TGSI_QUAD_SIZE],
1807 const float t[TGSI_QUAD_SIZE],
1808 const float p[TGSI_QUAD_SIZE],
1809 const float c0[TGSI_QUAD_SIZE],
1810 const float lod_in[TGSI_QUAD_SIZE],
1811 enum tgsi_sampler_control control,
1812 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1813 {
1814 float lod[TGSI_QUAD_SIZE];
1815 int j;
1816
1817 compute_lambda_lod(samp, s, t, p, lod_in, control, lod);
1818
1819 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
1820 if (lod[j] < 0.0) {
1821 samp->mag_img_filter(samp, s[j], t[j], p[j], samp->view->u.tex.first_level,
1822 samp->faces[j], &rgba[0][j]);
1823 }
1824 else {
1825 samp->min_img_filter(samp, s[j], t[j], p[j], samp->view->u.tex.first_level,
1826 samp->faces[j], &rgba[0][j]);
1827 }
1828 }
1829 }
1830
1831
1832 static void
1833 mip_filter_none_no_filter_select(struct sp_sampler_variant *samp,
1834 const float s[TGSI_QUAD_SIZE],
1835 const float t[TGSI_QUAD_SIZE],
1836 const float p[TGSI_QUAD_SIZE],
1837 const float c0[TGSI_QUAD_SIZE],
1838 const float lod_in[TGSI_QUAD_SIZE],
1839 enum tgsi_sampler_control control,
1840 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1841 {
1842 int j;
1843
1844 for (j = 0; j < TGSI_QUAD_SIZE; j++)
1845 samp->mag_img_filter(samp, s[j], t[j], p[j], samp->view->u.tex.first_level,
1846 samp->faces[j], &rgba[0][j]);
1847 }
1848
1849
1850 /* For anisotropic filtering */
1851 #define WEIGHT_LUT_SIZE 1024
1852
1853 static float *weightLut = NULL;
1854
1855 /**
1856 * Creates the look-up table used to speed-up EWA sampling
1857 */
1858 static void
1859 create_filter_table(void)
1860 {
1861 unsigned i;
1862 if (!weightLut) {
1863 weightLut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float));
1864
1865 for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
1866 float alpha = 2;
1867 float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1);
1868 float weight = (float) exp(-alpha * r2);
1869 weightLut[i] = weight;
1870 }
1871 }
1872 }
1873
1874
1875 /**
1876 * Elliptical weighted average (EWA) filter for producing high quality
1877 * anisotropic filtered results.
1878 * Based on the Higher Quality Elliptical Weighted Average Filter
1879 * published by Paul S. Heckbert in his Master's Thesis
1880 * "Fundamentals of Texture Mapping and Image Warping" (1989)
1881 */
1882 static void
1883 img_filter_2d_ewa(struct sp_sampler_variant *samp,
1884 const float s[TGSI_QUAD_SIZE],
1885 const float t[TGSI_QUAD_SIZE],
1886 const float p[TGSI_QUAD_SIZE],
1887 unsigned level,
1888 const float dudx, const float dvdx,
1889 const float dudy, const float dvdy,
1890 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1891 {
1892 const struct pipe_resource *texture = samp->view->texture;
1893
1894 // ??? Won't the image filters blow up if level is negative?
1895 unsigned level0 = level > 0 ? level : 0;
1896 float scaling = 1.0 / (1 << level0);
1897 int width = u_minify(texture->width0, level0);
1898 int height = u_minify(texture->height0, level0);
1899
1900 float ux = dudx * scaling;
1901 float vx = dvdx * scaling;
1902 float uy = dudy * scaling;
1903 float vy = dvdy * scaling;
1904
1905 /* compute ellipse coefficients to bound the region:
1906 * A*x*x + B*x*y + C*y*y = F.
1907 */
1908 float A = vx*vx+vy*vy+1;
1909 float B = -2*(ux*vx+uy*vy);
1910 float C = ux*ux+uy*uy+1;
1911 float F = A*C-B*B/4.0;
1912
1913 /* check if it is an ellipse */
1914 /* ASSERT(F > 0.0); */
1915
1916 /* Compute the ellipse's (u,v) bounding box in texture space */
1917 float d = -B*B+4.0*C*A;
1918 float box_u = 2.0 / d * sqrt(d*C*F); /* box_u -> half of bbox with */
1919 float box_v = 2.0 / d * sqrt(A*d*F); /* box_v -> half of bbox height */
1920
1921 float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
1922 float s_buffer[TGSI_QUAD_SIZE];
1923 float t_buffer[TGSI_QUAD_SIZE];
1924 float weight_buffer[TGSI_QUAD_SIZE];
1925 unsigned buffer_next;
1926 int j;
1927 float den; /* = 0.0F; */
1928 float ddq;
1929 float U; /* = u0 - tex_u; */
1930 int v;
1931
1932 /* Scale ellipse formula to directly index the Filter Lookup Table.
1933 * i.e. scale so that F = WEIGHT_LUT_SIZE-1
1934 */
1935 double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
1936 A *= formScale;
1937 B *= formScale;
1938 C *= formScale;
1939 /* F *= formScale; */ /* no need to scale F as we don't use it below here */
1940
1941 /* For each quad, the du and dx values are the same and so the ellipse is
1942 * also the same. Note that texel/image access can only be performed using
1943 * a quad, i.e. it is not possible to get the pixel value for a single
1944 * tex coord. In order to have a better performance, the access is buffered
1945 * using the s_buffer/t_buffer and weight_buffer. Only when the buffer is
1946 * full, then the pixel values are read from the image.
1947 */
1948 ddq = 2 * A;
1949
1950 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
1951 /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
1952 * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
1953 * value, q, is less than F, we're inside the ellipse
1954 */
1955 float tex_u = -0.5F + s[j] * texture->width0 * scaling;
1956 float tex_v = -0.5F + t[j] * texture->height0 * scaling;
1957
1958 int u0 = (int) floorf(tex_u - box_u);
1959 int u1 = (int) ceilf(tex_u + box_u);
1960 int v0 = (int) floorf(tex_v - box_v);
1961 int v1 = (int) ceilf(tex_v + box_v);
1962
1963 float num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
1964 buffer_next = 0;
1965 den = 0;
1966 U = u0 - tex_u;
1967 for (v = v0; v <= v1; ++v) {
1968 float V = v - tex_v;
1969 float dq = A * (2 * U + 1) + B * V;
1970 float q = (C * V + B * U) * V + A * U * U;
1971
1972 int u;
1973 for (u = u0; u <= u1; ++u) {
1974 /* Note that the ellipse has been pre-scaled so F =
1975 * WEIGHT_LUT_SIZE - 1
1976 */
1977 if (q < WEIGHT_LUT_SIZE) {
1978 /* as a LUT is used, q must never be negative;
1979 * should not happen, though
1980 */
1981 const int qClamped = q >= 0.0F ? q : 0;
1982 float weight = weightLut[qClamped];
1983
1984 weight_buffer[buffer_next] = weight;
1985 s_buffer[buffer_next] = u / ((float) width);
1986 t_buffer[buffer_next] = v / ((float) height);
1987
1988 buffer_next++;
1989 if (buffer_next == TGSI_QUAD_SIZE) {
1990 /* 4 texel coords are in the buffer -> read it now */
1991 unsigned jj;
1992 /* it is assumed that samp->min_img_filter is set to
1993 * img_filter_2d_nearest or one of the
1994 * accelerated img_filter_2d_nearest_XXX functions.
1995 */
1996 for (jj = 0; jj < buffer_next; jj++) {
1997 samp->min_img_filter(samp, s_buffer[jj], t_buffer[jj], p[jj],
1998 level, samp->faces[j], &rgba_temp[0][jj]);
1999 num[0] += weight_buffer[jj] * rgba_temp[0][jj];
2000 num[1] += weight_buffer[jj] * rgba_temp[1][jj];
2001 num[2] += weight_buffer[jj] * rgba_temp[2][jj];
2002 num[3] += weight_buffer[jj] * rgba_temp[3][jj];
2003 }
2004
2005 buffer_next = 0;
2006 }
2007
2008 den += weight;
2009 }
2010 q += dq;
2011 dq += ddq;
2012 }
2013 }
2014
2015 /* if the tex coord buffer contains unread values, we will read
2016 * them now.
2017 */
2018 if (buffer_next > 0) {
2019 unsigned jj;
2020 /* it is assumed that samp->min_img_filter is set to
2021 * img_filter_2d_nearest or one of the
2022 * accelerated img_filter_2d_nearest_XXX functions.
2023 */
2024 for (jj = 0; jj < buffer_next; jj++) {
2025 samp->min_img_filter(samp, s_buffer[jj], t_buffer[jj], p[jj], level,
2026 samp->faces[j], &rgba_temp[0][jj]);
2027 num[0] += weight_buffer[jj] * rgba_temp[0][jj];
2028 num[1] += weight_buffer[jj] * rgba_temp[1][jj];
2029 num[2] += weight_buffer[jj] * rgba_temp[2][jj];
2030 num[3] += weight_buffer[jj] * rgba_temp[3][jj];
2031 }
2032 }
2033
2034 if (den <= 0.0F) {
2035 /* Reaching this place would mean that no pixels intersected
2036 * the ellipse. This should never happen because the filter
2037 * we use always intersects at least one pixel.
2038 */
2039
2040 /*rgba[0]=0;
2041 rgba[1]=0;
2042 rgba[2]=0;
2043 rgba[3]=0;*/
2044 /* not enough pixels in resampling, resort to direct interpolation */
2045 samp->min_img_filter(samp, s[j], t[j], p[j], level, samp->faces[j],
2046 &rgba_temp[0][j]);
2047 den = 1;
2048 num[0] = rgba_temp[0][j];
2049 num[1] = rgba_temp[1][j];
2050 num[2] = rgba_temp[2][j];
2051 num[3] = rgba_temp[3][j];
2052 }
2053
2054 rgba[0][j] = num[0] / den;
2055 rgba[1][j] = num[1] / den;
2056 rgba[2][j] = num[2] / den;
2057 rgba[3][j] = num[3] / den;
2058 }
2059 }
2060
2061
2062 /**
2063 * Sample 2D texture using an anisotropic filter.
2064 */
2065 static void
2066 mip_filter_linear_aniso(struct sp_sampler_variant *samp,
2067 const float s[TGSI_QUAD_SIZE],
2068 const float t[TGSI_QUAD_SIZE],
2069 const float p[TGSI_QUAD_SIZE],
2070 const float c0[TGSI_QUAD_SIZE],
2071 const float lod_in[TGSI_QUAD_SIZE],
2072 enum tgsi_sampler_control control,
2073 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2074 {
2075 const struct pipe_resource *texture = samp->view->texture;
2076 int level0;
2077 float lambda;
2078 float lod[TGSI_QUAD_SIZE];
2079
2080 float s_to_u = u_minify(texture->width0, samp->view->u.tex.first_level);
2081 float t_to_v = u_minify(texture->height0, samp->view->u.tex.first_level);
2082 float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
2083 float dudy = (s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
2084 float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
2085 float dvdy = (t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
2086
2087 if (control == tgsi_sampler_lod_bias ||
2088 control == tgsi_sampler_lod_none) {
2089 /* note: instead of working with Px and Py, we will use the
2090 * squared length instead, to avoid sqrt.
2091 */
2092 float Px2 = dudx * dudx + dvdx * dvdx;
2093 float Py2 = dudy * dudy + dvdy * dvdy;
2094
2095 float Pmax2;
2096 float Pmin2;
2097 float e;
2098 const float maxEccentricity = samp->sampler->max_anisotropy * samp->sampler->max_anisotropy;
2099
2100 if (Px2 < Py2) {
2101 Pmax2 = Py2;
2102 Pmin2 = Px2;
2103 }
2104 else {
2105 Pmax2 = Px2;
2106 Pmin2 = Py2;
2107 }
2108
2109 /* if the eccentricity of the ellipse is too big, scale up the shorter
2110 * of the two vectors to limit the maximum amount of work per pixel
2111 */
2112 e = Pmax2 / Pmin2;
2113 if (e > maxEccentricity) {
2114 /* float s=e / maxEccentricity;
2115 minor[0] *= s;
2116 minor[1] *= s;
2117 Pmin2 *= s; */
2118 Pmin2 = Pmax2 / maxEccentricity;
2119 }
2120
2121 /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
2122 * this since 0.5*log(x) = log(sqrt(x))
2123 */
2124 lambda = 0.5F * util_fast_log2(Pmin2) + samp->sampler->lod_bias;
2125 compute_lod(samp->sampler, control, lambda, lod_in, lod);
2126 }
2127 else {
2128 assert(control == tgsi_sampler_lod_explicit ||
2129 control == tgsi_sampler_lod_zero);
2130 compute_lod(samp->sampler, control, samp->sampler->lod_bias, lod_in, lod);
2131 }
2132
2133 /* XXX: Take into account all lod values.
2134 */
2135 lambda = lod[0];
2136 level0 = samp->view->u.tex.first_level + (int)lambda;
2137
2138 /* If the ellipse covers the whole image, we can
2139 * simply return the average of the whole image.
2140 */
2141 if (level0 >= (int) texture->last_level) {
2142 int j;
2143 for (j = 0; j < TGSI_QUAD_SIZE; j++)
2144 samp->min_img_filter(samp, s[j], t[j], p[j], texture->last_level,
2145 samp->faces[j], &rgba[0][j]);
2146 }
2147 else {
2148 /* don't bother interpolating between multiple LODs; it doesn't
2149 * seem to be worth the extra running time.
2150 */
2151 img_filter_2d_ewa(samp, s, t, p, level0,
2152 dudx, dvdx, dudy, dvdy, rgba);
2153 }
2154
2155 if (DEBUG_TEX) {
2156 print_sample_4(__FUNCTION__, rgba);
2157 }
2158 }
2159
2160
2161 /**
2162 * Specialized version of mip_filter_linear with hard-wired calls to
2163 * 2d lambda calculation and 2d_linear_repeat_POT img filters.
2164 */
2165 static void
2166 mip_filter_linear_2d_linear_repeat_POT(
2167 struct sp_sampler_variant *samp,
2168 const float s[TGSI_QUAD_SIZE],
2169 const float t[TGSI_QUAD_SIZE],
2170 const float p[TGSI_QUAD_SIZE],
2171 const float c0[TGSI_QUAD_SIZE],
2172 const float lod_in[TGSI_QUAD_SIZE],
2173 enum tgsi_sampler_control control,
2174 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2175 {
2176 const struct pipe_resource *texture = samp->view->texture;
2177 int j;
2178 float lod[TGSI_QUAD_SIZE];
2179
2180 compute_lambda_lod(samp, s, t, p, lod_in, control, lod);
2181
2182 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2183 int level0 = samp->view->u.tex.first_level + (int)lod[j];
2184
2185 /* Catches both negative and large values of level0:
2186 */
2187 if ((unsigned)level0 >= texture->last_level) {
2188 if (level0 < 0)
2189 img_filter_2d_linear_repeat_POT(samp, s[j], t[j], p[j],
2190 samp->view->u.tex.first_level,
2191 samp->faces[j], &rgba[0][j]);
2192 else
2193 img_filter_2d_linear_repeat_POT(samp, s[j], t[j], p[j],
2194 samp->view->texture->last_level,
2195 samp->faces[j], &rgba[0][j]);
2196
2197 }
2198 else {
2199 float levelBlend = frac(lod[j]);
2200 float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2201 int c;
2202
2203 img_filter_2d_linear_repeat_POT(samp, s[j], t[j], p[j], level0,
2204 samp->faces[j], &rgbax[0][0]);
2205 img_filter_2d_linear_repeat_POT(samp, s[j], t[j], p[j], level0+1,
2206 samp->faces[j], &rgbax[0][1]);
2207
2208 for (c = 0; c < TGSI_NUM_CHANNELS; c++)
2209 rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
2210 }
2211 }
2212
2213 if (DEBUG_TEX) {
2214 print_sample_4(__FUNCTION__, rgba);
2215 }
2216 }
2217
2218
2219 /**
2220 * Do shadow/depth comparisons.
2221 */
2222 static void
2223 sample_compare(struct sp_sampler_variant *samp,
2224 const float s[TGSI_QUAD_SIZE],
2225 const float t[TGSI_QUAD_SIZE],
2226 const float p[TGSI_QUAD_SIZE],
2227 const float c0[TGSI_QUAD_SIZE],
2228 const float c1[TGSI_QUAD_SIZE],
2229 enum tgsi_sampler_control control,
2230 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2231 {
2232 const struct pipe_sampler_state *sampler = samp->sampler;
2233 int j, k0, k1, k2, k3;
2234 float val;
2235 float pc0, pc1, pc2, pc3;
2236
2237 samp->mip_filter(samp, s, t, p, c0, c1, control, rgba);
2238
2239 /**
2240 * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
2241 * for 2D Array texture we need to use the 'c0' (aka Q).
2242 * When we sampled the depth texture, the depth value was put into all
2243 * RGBA channels. We look at the red channel here.
2244 */
2245
2246 if (samp->view->texture->target == PIPE_TEXTURE_2D_ARRAY ||
2247 samp->view->texture->target == PIPE_TEXTURE_CUBE) {
2248 pc0 = CLAMP(c0[0], 0.0F, 1.0F);
2249 pc1 = CLAMP(c0[1], 0.0F, 1.0F);
2250 pc2 = CLAMP(c0[2], 0.0F, 1.0F);
2251 pc3 = CLAMP(c0[3], 0.0F, 1.0F);
2252 } else if (samp->view->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
2253 pc0 = CLAMP(c1[0], 0.0F, 1.0F);
2254 pc1 = CLAMP(c1[1], 0.0F, 1.0F);
2255 pc2 = CLAMP(c1[2], 0.0F, 1.0F);
2256 pc3 = CLAMP(c1[3], 0.0F, 1.0F);
2257 } else {
2258 pc0 = CLAMP(p[0], 0.0F, 1.0F);
2259 pc1 = CLAMP(p[1], 0.0F, 1.0F);
2260 pc2 = CLAMP(p[2], 0.0F, 1.0F);
2261 pc3 = CLAMP(p[3], 0.0F, 1.0F);
2262 }
2263 /* compare four texcoords vs. four texture samples */
2264 switch (sampler->compare_func) {
2265 case PIPE_FUNC_LESS:
2266 k0 = pc0 < rgba[0][0];
2267 k1 = pc1 < rgba[0][1];
2268 k2 = pc2 < rgba[0][2];
2269 k3 = pc3 < rgba[0][3];
2270 break;
2271 case PIPE_FUNC_LEQUAL:
2272 k0 = pc0 <= rgba[0][0];
2273 k1 = pc1 <= rgba[0][1];
2274 k2 = pc2 <= rgba[0][2];
2275 k3 = pc3 <= rgba[0][3];
2276 break;
2277 case PIPE_FUNC_GREATER:
2278 k0 = pc0 > rgba[0][0];
2279 k1 = pc1 > rgba[0][1];
2280 k2 = pc2 > rgba[0][2];
2281 k3 = pc3 > rgba[0][3];
2282 break;
2283 case PIPE_FUNC_GEQUAL:
2284 k0 = pc0 >= rgba[0][0];
2285 k1 = pc1 >= rgba[0][1];
2286 k2 = pc2 >= rgba[0][2];
2287 k3 = pc3 >= rgba[0][3];
2288 break;
2289 case PIPE_FUNC_EQUAL:
2290 k0 = pc0 == rgba[0][0];
2291 k1 = pc1 == rgba[0][1];
2292 k2 = pc2 == rgba[0][2];
2293 k3 = pc3 == rgba[0][3];
2294 break;
2295 case PIPE_FUNC_NOTEQUAL:
2296 k0 = pc0 != rgba[0][0];
2297 k1 = pc1 != rgba[0][1];
2298 k2 = pc2 != rgba[0][2];
2299 k3 = pc3 != rgba[0][3];
2300 break;
2301 case PIPE_FUNC_ALWAYS:
2302 k0 = k1 = k2 = k3 = 1;
2303 break;
2304 case PIPE_FUNC_NEVER:
2305 k0 = k1 = k2 = k3 = 0;
2306 break;
2307 default:
2308 k0 = k1 = k2 = k3 = 0;
2309 assert(0);
2310 break;
2311 }
2312
2313 if (sampler->mag_img_filter == PIPE_TEX_FILTER_LINEAR) {
2314 /* convert four pass/fail values to an intensity in [0,1] */
2315 val = 0.25F * (k0 + k1 + k2 + k3);
2316
2317 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
2318 for (j = 0; j < 4; j++) {
2319 rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
2320 rgba[3][j] = 1.0F;
2321 }
2322 } else {
2323 for (j = 0; j < 4; j++) {
2324 rgba[0][j] = k0;
2325 rgba[1][j] = k1;
2326 rgba[2][j] = k2;
2327 rgba[3][j] = 1.0F;
2328 }
2329 }
2330 }
2331
2332
2333 /**
2334 * Use 3D texcoords to choose a cube face, then sample the 2D cube faces.
2335 * Put face info into the sampler faces[] array.
2336 */
2337 static void
2338 sample_cube(struct sp_sampler_variant *samp,
2339 const float s[TGSI_QUAD_SIZE],
2340 const float t[TGSI_QUAD_SIZE],
2341 const float p[TGSI_QUAD_SIZE],
2342 const float c0[TGSI_QUAD_SIZE],
2343 const float c1[TGSI_QUAD_SIZE],
2344 enum tgsi_sampler_control control,
2345 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2346 {
2347 unsigned j;
2348 float ssss[4], tttt[4];
2349
2350 /* Not actually used, but the intermediate steps that do the
2351 * dereferencing don't know it.
2352 */
2353 static float pppp[4] = { 0, 0, 0, 0 };
2354
2355 pppp[0] = c0[0];
2356 pppp[1] = c0[1];
2357 pppp[2] = c0[2];
2358 pppp[3] = c0[3];
2359 /*
2360 major axis
2361 direction target sc tc ma
2362 ---------- ------------------------------- --- --- ---
2363 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2364 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2365 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2366 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2367 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2368 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2369 */
2370
2371 /* Choose the cube face and compute new s/t coords for the 2D face.
2372 *
2373 * Use the same cube face for all four pixels in the quad.
2374 *
2375 * This isn't ideal, but if we want to use a different cube face
2376 * per pixel in the quad, we'd have to also compute the per-face
2377 * LOD here too. That's because the four post-face-selection
2378 * texcoords are no longer related to each other (they're
2379 * per-face!) so we can't use subtraction to compute the partial
2380 * deriviates to compute the LOD. Doing so (near cube edges
2381 * anyway) gives us pretty much random values.
2382 */
2383 {
2384 /* use the average of the four pixel's texcoords to choose the face */
2385 const float rx = 0.25F * (s[0] + s[1] + s[2] + s[3]);
2386 const float ry = 0.25F * (t[0] + t[1] + t[2] + t[3]);
2387 const float rz = 0.25F * (p[0] + p[1] + p[2] + p[3]);
2388 const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
2389
2390 if (arx >= ary && arx >= arz) {
2391 float sign = (rx >= 0.0F) ? 1.0F : -1.0F;
2392 uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X;
2393 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2394 const float ima = -0.5F / fabsf(s[j]);
2395 ssss[j] = sign * p[j] * ima + 0.5F;
2396 tttt[j] = t[j] * ima + 0.5F;
2397 samp->faces[j] = face;
2398 }
2399 }
2400 else if (ary >= arx && ary >= arz) {
2401 float sign = (ry >= 0.0F) ? 1.0F : -1.0F;
2402 uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y;
2403 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2404 const float ima = -0.5F / fabsf(t[j]);
2405 ssss[j] = -s[j] * ima + 0.5F;
2406 tttt[j] = sign * -p[j] * ima + 0.5F;
2407 samp->faces[j] = face;
2408 }
2409 }
2410 else {
2411 float sign = (rz >= 0.0F) ? 1.0F : -1.0F;
2412 uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z;
2413 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2414 const float ima = -0.5F / fabsf(p[j]);
2415 ssss[j] = sign * -s[j] * ima + 0.5F;
2416 tttt[j] = t[j] * ima + 0.5F;
2417 samp->faces[j] = face;
2418 }
2419 }
2420 }
2421
2422 /* In our little pipeline, the compare stage is next. If compare
2423 * is not active, this will point somewhere deeper into the
2424 * pipeline, eg. to mip_filter or even img_filter.
2425 */
2426 samp->compare(samp, ssss, tttt, pppp, c0, c1, control, rgba);
2427 }
2428
2429
2430 static void
2431 do_swizzling(const struct sp_sampler_variant *samp,
2432 float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
2433 float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2434 {
2435 int j;
2436 const unsigned swizzle_r = samp->key.bits.swizzle_r;
2437 const unsigned swizzle_g = samp->key.bits.swizzle_g;
2438 const unsigned swizzle_b = samp->key.bits.swizzle_b;
2439 const unsigned swizzle_a = samp->key.bits.swizzle_a;
2440
2441 switch (swizzle_r) {
2442 case PIPE_SWIZZLE_ZERO:
2443 for (j = 0; j < 4; j++)
2444 out[0][j] = 0.0f;
2445 break;
2446 case PIPE_SWIZZLE_ONE:
2447 for (j = 0; j < 4; j++)
2448 out[0][j] = 1.0f;
2449 break;
2450 default:
2451 assert(swizzle_r < 4);
2452 for (j = 0; j < 4; j++)
2453 out[0][j] = in[swizzle_r][j];
2454 }
2455
2456 switch (swizzle_g) {
2457 case PIPE_SWIZZLE_ZERO:
2458 for (j = 0; j < 4; j++)
2459 out[1][j] = 0.0f;
2460 break;
2461 case PIPE_SWIZZLE_ONE:
2462 for (j = 0; j < 4; j++)
2463 out[1][j] = 1.0f;
2464 break;
2465 default:
2466 assert(swizzle_g < 4);
2467 for (j = 0; j < 4; j++)
2468 out[1][j] = in[swizzle_g][j];
2469 }
2470
2471 switch (swizzle_b) {
2472 case PIPE_SWIZZLE_ZERO:
2473 for (j = 0; j < 4; j++)
2474 out[2][j] = 0.0f;
2475 break;
2476 case PIPE_SWIZZLE_ONE:
2477 for (j = 0; j < 4; j++)
2478 out[2][j] = 1.0f;
2479 break;
2480 default:
2481 assert(swizzle_b < 4);
2482 for (j = 0; j < 4; j++)
2483 out[2][j] = in[swizzle_b][j];
2484 }
2485
2486 switch (swizzle_a) {
2487 case PIPE_SWIZZLE_ZERO:
2488 for (j = 0; j < 4; j++)
2489 out[3][j] = 0.0f;
2490 break;
2491 case PIPE_SWIZZLE_ONE:
2492 for (j = 0; j < 4; j++)
2493 out[3][j] = 1.0f;
2494 break;
2495 default:
2496 assert(swizzle_a < 4);
2497 for (j = 0; j < 4; j++)
2498 out[3][j] = in[swizzle_a][j];
2499 }
2500 }
2501
2502
2503 static void
2504 sample_swizzle(struct sp_sampler_variant *samp,
2505 const float s[TGSI_QUAD_SIZE],
2506 const float t[TGSI_QUAD_SIZE],
2507 const float p[TGSI_QUAD_SIZE],
2508 const float c0[TGSI_QUAD_SIZE],
2509 const float c1[TGSI_QUAD_SIZE],
2510 enum tgsi_sampler_control control,
2511 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2512 {
2513 float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2514
2515 samp->sample_target(samp, s, t, p, c0, c1, control, rgba_temp);
2516
2517 do_swizzling(samp, rgba_temp, rgba);
2518 }
2519
2520
2521 static wrap_nearest_func
2522 get_nearest_unorm_wrap(unsigned mode)
2523 {
2524 switch (mode) {
2525 case PIPE_TEX_WRAP_CLAMP:
2526 return wrap_nearest_unorm_clamp;
2527 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2528 return wrap_nearest_unorm_clamp_to_edge;
2529 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2530 return wrap_nearest_unorm_clamp_to_border;
2531 default:
2532 assert(0);
2533 return wrap_nearest_unorm_clamp;
2534 }
2535 }
2536
2537
2538 static wrap_nearest_func
2539 get_nearest_wrap(unsigned mode)
2540 {
2541 switch (mode) {
2542 case PIPE_TEX_WRAP_REPEAT:
2543 return wrap_nearest_repeat;
2544 case PIPE_TEX_WRAP_CLAMP:
2545 return wrap_nearest_clamp;
2546 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2547 return wrap_nearest_clamp_to_edge;
2548 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2549 return wrap_nearest_clamp_to_border;
2550 case PIPE_TEX_WRAP_MIRROR_REPEAT:
2551 return wrap_nearest_mirror_repeat;
2552 case PIPE_TEX_WRAP_MIRROR_CLAMP:
2553 return wrap_nearest_mirror_clamp;
2554 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
2555 return wrap_nearest_mirror_clamp_to_edge;
2556 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
2557 return wrap_nearest_mirror_clamp_to_border;
2558 default:
2559 assert(0);
2560 return wrap_nearest_repeat;
2561 }
2562 }
2563
2564
2565 static wrap_linear_func
2566 get_linear_unorm_wrap(unsigned mode)
2567 {
2568 switch (mode) {
2569 case PIPE_TEX_WRAP_CLAMP:
2570 return wrap_linear_unorm_clamp;
2571 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2572 return wrap_linear_unorm_clamp_to_edge;
2573 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2574 return wrap_linear_unorm_clamp_to_border;
2575 default:
2576 assert(0);
2577 return wrap_linear_unorm_clamp;
2578 }
2579 }
2580
2581
2582 static wrap_linear_func
2583 get_linear_wrap(unsigned mode)
2584 {
2585 switch (mode) {
2586 case PIPE_TEX_WRAP_REPEAT:
2587 return wrap_linear_repeat;
2588 case PIPE_TEX_WRAP_CLAMP:
2589 return wrap_linear_clamp;
2590 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2591 return wrap_linear_clamp_to_edge;
2592 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2593 return wrap_linear_clamp_to_border;
2594 case PIPE_TEX_WRAP_MIRROR_REPEAT:
2595 return wrap_linear_mirror_repeat;
2596 case PIPE_TEX_WRAP_MIRROR_CLAMP:
2597 return wrap_linear_mirror_clamp;
2598 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
2599 return wrap_linear_mirror_clamp_to_edge;
2600 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
2601 return wrap_linear_mirror_clamp_to_border;
2602 default:
2603 assert(0);
2604 return wrap_linear_repeat;
2605 }
2606 }
2607
2608
2609 /**
2610 * Is swizzling needed for the given state key?
2611 */
2612 static INLINE bool
2613 any_swizzle(union sp_sampler_key key)
2614 {
2615 return (key.bits.swizzle_r != PIPE_SWIZZLE_RED ||
2616 key.bits.swizzle_g != PIPE_SWIZZLE_GREEN ||
2617 key.bits.swizzle_b != PIPE_SWIZZLE_BLUE ||
2618 key.bits.swizzle_a != PIPE_SWIZZLE_ALPHA);
2619 }
2620
2621
2622 static compute_lambda_func
2623 get_lambda_func(const union sp_sampler_key key)
2624 {
2625 if (key.bits.processor == TGSI_PROCESSOR_VERTEX)
2626 return compute_lambda_vert;
2627
2628 switch (key.bits.target) {
2629 case PIPE_BUFFER:
2630 case PIPE_TEXTURE_1D:
2631 case PIPE_TEXTURE_1D_ARRAY:
2632 return compute_lambda_1d;
2633 case PIPE_TEXTURE_2D:
2634 case PIPE_TEXTURE_2D_ARRAY:
2635 case PIPE_TEXTURE_RECT:
2636 case PIPE_TEXTURE_CUBE:
2637 case PIPE_TEXTURE_CUBE_ARRAY:
2638 return compute_lambda_2d;
2639 case PIPE_TEXTURE_3D:
2640 return compute_lambda_3d;
2641 default:
2642 assert(0);
2643 return compute_lambda_1d;
2644 }
2645 }
2646
2647
2648 static img_filter_func
2649 get_img_filter(const union sp_sampler_key key,
2650 unsigned filter,
2651 const struct pipe_sampler_state *sampler)
2652 {
2653 switch (key.bits.target) {
2654 case PIPE_BUFFER:
2655 case PIPE_TEXTURE_1D:
2656 if (filter == PIPE_TEX_FILTER_NEAREST)
2657 return img_filter_1d_nearest;
2658 else
2659 return img_filter_1d_linear;
2660 break;
2661 case PIPE_TEXTURE_1D_ARRAY:
2662 if (filter == PIPE_TEX_FILTER_NEAREST)
2663 return img_filter_1d_array_nearest;
2664 else
2665 return img_filter_1d_array_linear;
2666 break;
2667 case PIPE_TEXTURE_2D:
2668 case PIPE_TEXTURE_RECT:
2669 /* Try for fast path:
2670 */
2671 if (key.bits.is_pot &&
2672 sampler->wrap_s == sampler->wrap_t &&
2673 sampler->normalized_coords)
2674 {
2675 switch (sampler->wrap_s) {
2676 case PIPE_TEX_WRAP_REPEAT:
2677 switch (filter) {
2678 case PIPE_TEX_FILTER_NEAREST:
2679 return img_filter_2d_nearest_repeat_POT;
2680 case PIPE_TEX_FILTER_LINEAR:
2681 return img_filter_2d_linear_repeat_POT;
2682 default:
2683 break;
2684 }
2685 break;
2686 case PIPE_TEX_WRAP_CLAMP:
2687 switch (filter) {
2688 case PIPE_TEX_FILTER_NEAREST:
2689 return img_filter_2d_nearest_clamp_POT;
2690 default:
2691 break;
2692 }
2693 }
2694 }
2695 /* Otherwise use default versions:
2696 */
2697 if (filter == PIPE_TEX_FILTER_NEAREST)
2698 return img_filter_2d_nearest;
2699 else
2700 return img_filter_2d_linear;
2701 break;
2702 case PIPE_TEXTURE_2D_ARRAY:
2703 if (filter == PIPE_TEX_FILTER_NEAREST)
2704 return img_filter_2d_array_nearest;
2705 else
2706 return img_filter_2d_array_linear;
2707 break;
2708 case PIPE_TEXTURE_CUBE:
2709 if (filter == PIPE_TEX_FILTER_NEAREST)
2710 return img_filter_cube_nearest;
2711 else
2712 return img_filter_cube_linear;
2713 break;
2714 case PIPE_TEXTURE_CUBE_ARRAY:
2715 if (filter == PIPE_TEX_FILTER_NEAREST)
2716 return img_filter_cube_array_nearest;
2717 else
2718 return img_filter_cube_array_linear;
2719 break;
2720 case PIPE_TEXTURE_3D:
2721 if (filter == PIPE_TEX_FILTER_NEAREST)
2722 return img_filter_3d_nearest;
2723 else
2724 return img_filter_3d_linear;
2725 break;
2726 default:
2727 assert(0);
2728 return img_filter_1d_nearest;
2729 }
2730 }
2731
2732
2733 /**
2734 * Bind the given texture object and texture cache to the sampler variant.
2735 */
2736 void
2737 sp_sampler_variant_bind_view( struct sp_sampler_variant *samp,
2738 struct softpipe_tex_tile_cache *tex_cache,
2739 const struct pipe_sampler_view *view )
2740 {
2741 const struct pipe_resource *texture = view->texture;
2742
2743 samp->view = view;
2744 samp->cache = tex_cache;
2745 samp->xpot = util_logbase2( texture->width0 );
2746 samp->ypot = util_logbase2( texture->height0 );
2747 }
2748
2749
2750 void
2751 sp_sampler_variant_destroy( struct sp_sampler_variant *samp )
2752 {
2753 FREE(samp);
2754 }
2755
2756
2757 static void
2758 sample_get_dims(struct sp_sampler_variant *samp, int level,
2759 int dims[4])
2760 {
2761 const struct pipe_sampler_view *view = samp->view;
2762 const struct pipe_resource *texture = view->texture;
2763
2764 /* undefined according to EXT_gpu_program */
2765 level += view->u.tex.first_level;
2766 if (level > view->u.tex.last_level)
2767 return;
2768
2769 dims[0] = u_minify(texture->width0, level);
2770
2771 switch(texture->target) {
2772 case PIPE_TEXTURE_1D_ARRAY:
2773 dims[1] = texture->array_size;
2774 /* fallthrough */
2775 case PIPE_TEXTURE_1D:
2776 return;
2777 case PIPE_TEXTURE_2D_ARRAY:
2778 dims[2] = texture->array_size;
2779 /* fallthrough */
2780 case PIPE_TEXTURE_2D:
2781 case PIPE_TEXTURE_CUBE:
2782 case PIPE_TEXTURE_RECT:
2783 dims[1] = u_minify(texture->height0, level);
2784 return;
2785 case PIPE_TEXTURE_3D:
2786 dims[1] = u_minify(texture->height0, level);
2787 dims[2] = u_minify(texture->depth0, level);
2788 return;
2789 case PIPE_TEXTURE_CUBE_ARRAY:
2790 dims[1] = u_minify(texture->height0, level);
2791 dims[2] = texture->array_size / 6;
2792 break;
2793 case PIPE_BUFFER:
2794 dims[0] /= util_format_get_blocksize(view->format);
2795 return;
2796 default:
2797 assert(!"unexpected texture target in sample_get_dims()");
2798 return;
2799 }
2800 }
2801
2802 /**
2803 * This function is only used for getting unfiltered texels via the
2804 * TXF opcode. The GL spec says that out-of-bounds texel fetches
2805 * produce undefined results. Instead of crashing, lets just clamp
2806 * coords to the texture image size.
2807 */
2808 static void
2809 sample_get_texels(struct sp_sampler_variant *samp,
2810 const int v_i[TGSI_QUAD_SIZE],
2811 const int v_j[TGSI_QUAD_SIZE],
2812 const int v_k[TGSI_QUAD_SIZE],
2813 const int lod[TGSI_QUAD_SIZE],
2814 const int8_t offset[3],
2815 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2816 {
2817 union tex_tile_address addr;
2818 const struct pipe_resource *texture = samp->view->texture;
2819 int j, c;
2820 const float *tx;
2821 const bool need_swizzle = any_swizzle(samp->key);
2822 int width, height, depth, layers;
2823
2824 addr.value = 0;
2825 /* TODO write a better test for LOD */
2826 addr.bits.level = lod[0];
2827
2828 width = u_minify(texture->width0, addr.bits.level);
2829 height = u_minify(texture->height0, addr.bits.level);
2830 depth = u_minify(texture->depth0, addr.bits.level);
2831 layers = texture->array_size;
2832
2833 switch(texture->target) {
2834 case PIPE_BUFFER:
2835 case PIPE_TEXTURE_1D:
2836 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2837 int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2838 tx = get_texel_2d(samp, addr, x, 0);
2839 for (c = 0; c < 4; c++) {
2840 rgba[c][j] = tx[c];
2841 }
2842 }
2843 break;
2844 case PIPE_TEXTURE_1D_ARRAY:
2845 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2846 int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2847 int y = CLAMP(v_j[j], 0, layers - 1);
2848 tx = get_texel_1d_array(samp, addr, x, y);
2849 for (c = 0; c < 4; c++) {
2850 rgba[c][j] = tx[c];
2851 }
2852 }
2853 break;
2854 case PIPE_TEXTURE_2D:
2855 case PIPE_TEXTURE_RECT:
2856 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2857 int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2858 int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
2859 tx = get_texel_2d(samp, addr, x, y);
2860 for (c = 0; c < 4; c++) {
2861 rgba[c][j] = tx[c];
2862 }
2863 }
2864 break;
2865 case PIPE_TEXTURE_2D_ARRAY:
2866 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2867 int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2868 int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
2869 int layer = CLAMP(v_k[j], 0, layers - 1);
2870 tx = get_texel_2d_array(samp, addr, x, y, layer);
2871 for (c = 0; c < 4; c++) {
2872 rgba[c][j] = tx[c];
2873 }
2874 }
2875 break;
2876 case PIPE_TEXTURE_3D:
2877 for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2878 int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2879 int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
2880 int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
2881
2882 tx = get_texel_3d(samp, addr, x, y, z);
2883 for (c = 0; c < 4; c++) {
2884 rgba[c][j] = tx[c];
2885 }
2886 }
2887 break;
2888 case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */
2889 default:
2890 assert(!"Unknown or CUBE texture type in TXF processing\n");
2891 break;
2892 }
2893
2894 if (need_swizzle) {
2895 float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2896 memcpy(rgba_temp, rgba, sizeof(rgba_temp));
2897 do_swizzling(samp, rgba_temp, rgba);
2898 }
2899 }
2900
2901
2902 /**
2903 * Create a sampler variant for a given set of non-orthogonal state.
2904 */
2905 struct sp_sampler_variant *
2906 sp_create_sampler_variant( const struct pipe_sampler_state *sampler,
2907 const union sp_sampler_key key )
2908 {
2909 struct sp_sampler_variant *samp = CALLOC_STRUCT(sp_sampler_variant);
2910 if (!samp)
2911 return NULL;
2912
2913 samp->sampler = sampler;
2914 samp->key = key;
2915
2916 /* Note that (for instance) linear_texcoord_s and
2917 * nearest_texcoord_s may be active at the same time, if the
2918 * sampler min_img_filter differs from its mag_img_filter.
2919 */
2920 if (sampler->normalized_coords) {
2921 samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
2922 samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
2923 samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
2924
2925 samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
2926 samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
2927 samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
2928 }
2929 else {
2930 samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
2931 samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
2932 samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
2933
2934 samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
2935 samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
2936 samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
2937 }
2938
2939 samp->compute_lambda = get_lambda_func( key );
2940
2941 samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler);
2942 samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler);
2943
2944 switch (sampler->min_mip_filter) {
2945 case PIPE_TEX_MIPFILTER_NONE:
2946 if (sampler->min_img_filter == sampler->mag_img_filter)
2947 samp->mip_filter = mip_filter_none_no_filter_select;
2948 else
2949 samp->mip_filter = mip_filter_none;
2950 break;
2951
2952 case PIPE_TEX_MIPFILTER_NEAREST:
2953 samp->mip_filter = mip_filter_nearest;
2954 break;
2955
2956 case PIPE_TEX_MIPFILTER_LINEAR:
2957 if (key.bits.is_pot &&
2958 key.bits.target == PIPE_TEXTURE_2D &&
2959 sampler->min_img_filter == sampler->mag_img_filter &&
2960 sampler->normalized_coords &&
2961 sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
2962 sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
2963 sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR) {
2964 samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT;
2965 }
2966 else {
2967 samp->mip_filter = mip_filter_linear;
2968 }
2969
2970 /* Anisotropic filtering extension. */
2971 if (sampler->max_anisotropy > 1) {
2972 samp->mip_filter = mip_filter_linear_aniso;
2973
2974 /* Override min_img_filter:
2975 * min_img_filter needs to be set to NEAREST since we need to access
2976 * each texture pixel as it is and weight it later; using linear
2977 * filters will have incorrect results.
2978 * By setting the filter to NEAREST here, we can avoid calling the
2979 * generic img_filter_2d_nearest in the anisotropic filter function,
2980 * making it possible to use one of the accelerated implementations
2981 */
2982 samp->min_img_filter = get_img_filter(key, PIPE_TEX_FILTER_NEAREST, sampler);
2983
2984 /* on first access create the lookup table containing the filter weights. */
2985 if (!weightLut) {
2986 create_filter_table();
2987 }
2988 }
2989
2990 break;
2991 }
2992
2993 if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE) {
2994 samp->compare = sample_compare;
2995 }
2996 else {
2997 /* Skip compare operation by promoting the mip_filter function
2998 * pointer:
2999 */
3000 samp->compare = samp->mip_filter;
3001 }
3002
3003 if (key.bits.target == PIPE_TEXTURE_CUBE || key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) {
3004 samp->sample_target = sample_cube;
3005 }
3006 else {
3007 samp->faces[0] = 0;
3008 samp->faces[1] = 0;
3009 samp->faces[2] = 0;
3010 samp->faces[3] = 0;
3011
3012 /* Skip cube face determination by promoting the compare
3013 * function pointer:
3014 */
3015 samp->sample_target = samp->compare;
3016 }
3017
3018 if (any_swizzle(key)) {
3019 samp->get_samples = sample_swizzle;
3020 }
3021 else {
3022 samp->get_samples = samp->sample_target;
3023 }
3024
3025 samp->get_dims = sample_get_dims;
3026 samp->get_texel = sample_get_texels;
3027 return samp;
3028 }
3029
3030
3031
3032 static void
3033 sp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler,
3034 const unsigned sview_index,
3035 int level, int dims[4])
3036 {
3037 const struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
3038
3039 assert(sp_samp->sp_sampler[sview_index]);
3040 sp_samp->sp_sampler[sview_index]->get_dims(sp_samp->sp_sampler[sview_index],
3041 level, dims);
3042 }
3043
3044
3045 static void
3046 sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
3047 const unsigned sview_index,
3048 const unsigned sampler_index,
3049 const float s[TGSI_QUAD_SIZE],
3050 const float t[TGSI_QUAD_SIZE],
3051 const float p[TGSI_QUAD_SIZE],
3052 const float c0[TGSI_QUAD_SIZE],
3053 const float lod[TGSI_QUAD_SIZE],
3054 enum tgsi_sampler_control control,
3055 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3056 {
3057 const struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
3058 assert(sview_index < PIPE_MAX_SAMPLERS);
3059 assert(sview_index == sampler_index);
3060 assert(sp_samp->sp_sampler[sampler_index]);
3061 sp_samp->sp_sampler[sview_index]->get_samples(sp_samp->sp_sampler[sampler_index],
3062 s, t, p, c0, lod, control, rgba);
3063 }
3064
3065
3066 static void
3067 sp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler,
3068 const unsigned sview_index,
3069 const int i[TGSI_QUAD_SIZE],
3070 const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
3071 const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
3072 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3073 {
3074 const struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
3075 assert(sview_index < PIPE_MAX_SAMPLERS);
3076 assert(sp_samp->sp_sampler[sview_index]);
3077 sp_samp->sp_sampler[sview_index]->get_texel(sp_samp->sp_sampler[sview_index],
3078 i, j, k, lod, offset, rgba);
3079 }
3080
3081
3082 struct sp_tgsi_sampler *
3083 sp_create_tgsi_sampler(void)
3084 {
3085 struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler);
3086 if (!samp)
3087 return NULL;
3088
3089 samp->base.get_dims = sp_tgsi_get_dims;
3090 samp->base.get_samples = sp_tgsi_get_samples;
3091 samp->base.get_texel = sp_tgsi_get_texel;
3092
3093 return samp;
3094 }
3095