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