1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
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 VMWARE 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/format/u_format.h"
42 #include "util/u_memory.h"
43 #include "util/u_inlines.h"
44 #include "sp_quad.h"   /* only for #define QUAD_* tokens */
45 #include "sp_tex_sample.h"
46 #include "sp_texture.h"
47 #include "sp_tex_tile_cache.h"
48 
49 
50 /** Set to one to help debug texture sampling */
51 #define DEBUG_TEX 0
52 
53 
54 /*
55  * Return fractional part of 'f'.  Used for computing interpolation weights.
56  * Need to be careful with negative values.
57  * Note, if this function isn't perfect you'll sometimes see 1-pixel bands
58  * of improperly weighted linear-filtered textures.
59  * The tests/texwrap.c demo is a good test.
60  */
61 static inline float
frac(float f)62 frac(float f)
63 {
64    return f - floorf(f);
65 }
66 
67 
68 
69 /**
70  * Linear interpolation macro
71  */
72 static inline float
lerp(float a,float v0,float v1)73 lerp(float a, float v0, float v1)
74 {
75    return v0 + a * (v1 - v0);
76 }
77 
78 
79 /**
80  * Do 2D/bilinear interpolation of float values.
81  * v00, v10, v01 and v11 are typically four texture samples in a square/box.
82  * a and b are the horizontal and vertical interpolants.
83  * It's important that this function is inlined when compiled with
84  * optimization!  If we find that's not true on some systems, convert
85  * to a macro.
86  */
87 static inline float
lerp_2d(float a,float b,float v00,float v10,float v01,float v11)88 lerp_2d(float a, float b,
89         float v00, float v10, float v01, float v11)
90 {
91    const float temp0 = lerp(a, v00, v10);
92    const float temp1 = lerp(a, v01, v11);
93    return lerp(b, temp0, temp1);
94 }
95 
96 
97 /**
98  * As above, but 3D interpolation of 8 values.
99  */
100 static inline float
lerp_3d(float a,float b,float c,float v000,float v100,float v010,float v110,float v001,float v101,float v011,float v111)101 lerp_3d(float a, float b, float c,
102         float v000, float v100, float v010, float v110,
103         float v001, float v101, float v011, float v111)
104 {
105    const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
106    const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
107    return lerp(c, temp0, temp1);
108 }
109 
110 
111 
112 /**
113  * Compute coord % size for repeat wrap modes.
114  * Note that if coord is negative, coord % size doesn't give the right
115  * value.  To avoid that problem we add a large multiple of the size
116  * (rather than using a conditional).
117  */
118 static inline int
repeat(int coord,unsigned size)119 repeat(int coord, unsigned size)
120 {
121    return (coord + size * 1024) % size;
122 }
123 
124 
125 /**
126  * Apply texture coord wrapping mode and return integer texture indexes
127  * for a vector of four texcoords (S or T or P).
128  * \param wrapMode  PIPE_TEX_WRAP_x
129  * \param s  the incoming texcoords
130  * \param size  the texture image size
131  * \param icoord  returns the integer texcoords
132  */
133 static void
wrap_nearest_repeat(float s,unsigned size,int offset,int * icoord)134 wrap_nearest_repeat(float s, unsigned size, int offset, int *icoord)
135 {
136    /* s limited to [0,1) */
137    /* i limited to [0,size-1] */
138    const int i = util_ifloor(s * size);
139    *icoord = repeat(i + offset, size);
140 }
141 
142 
143 static void
wrap_nearest_clamp(float s,unsigned size,int offset,int * icoord)144 wrap_nearest_clamp(float s, unsigned size, int offset, int *icoord)
145 {
146    /* s limited to [0,1] */
147    /* i limited to [0,size-1] */
148    s *= size;
149    s += offset;
150    if (s <= 0.0F)
151       *icoord = 0;
152    else if (s >= size)
153       *icoord = size - 1;
154    else
155       *icoord = util_ifloor(s);
156 }
157 
158 
159 static void
wrap_nearest_clamp_to_edge(float s,unsigned size,int offset,int * icoord)160 wrap_nearest_clamp_to_edge(float s, unsigned size, int offset, int *icoord)
161 {
162    /* s limited to [min,max] */
163    /* i limited to [0, size-1] */
164    const float min = 0.5F;
165    const float max = (float)size - 0.5F;
166 
167    s *= size;
168    s += offset;
169 
170    if (s < min)
171       *icoord = 0;
172    else if (s > max)
173       *icoord = size - 1;
174    else
175       *icoord = util_ifloor(s);
176 }
177 
178 
179 static void
wrap_nearest_clamp_to_border(float s,unsigned size,int offset,int * icoord)180 wrap_nearest_clamp_to_border(float s, unsigned size, int offset, int *icoord)
181 {
182    /* s limited to [min,max] */
183    /* i limited to [-1, size] */
184    const float min = -0.5F;
185    const float max = size + 0.5F;
186 
187    s *= size;
188    s += offset;
189    if (s <= min)
190       *icoord = -1;
191    else if (s >= max)
192       *icoord = size;
193    else
194       *icoord = util_ifloor(s);
195 }
196 
197 static void
wrap_nearest_mirror_repeat(float s,unsigned size,int offset,int * icoord)198 wrap_nearest_mirror_repeat(float s, unsigned size, int offset, int *icoord)
199 {
200    const float min = 1.0F / (2.0F * size);
201    const float max = 1.0F - min;
202    int flr;
203    float u;
204 
205    s += (float)offset / size;
206    flr = util_ifloor(s);
207    u = frac(s);
208    if (flr & 1)
209       u = 1.0F - u;
210    if (u < min)
211       *icoord = 0;
212    else if (u > max)
213       *icoord = size - 1;
214    else
215       *icoord = util_ifloor(u * size);
216 }
217 
218 
219 static void
wrap_nearest_mirror_clamp(float s,unsigned size,int offset,int * icoord)220 wrap_nearest_mirror_clamp(float s, unsigned size, int offset, int *icoord)
221 {
222    /* s limited to [0,1] */
223    /* i limited to [0,size-1] */
224    const float u = fabsf(s * size + offset);
225    if (u <= 0.0F)
226       *icoord = 0;
227    else if (u >= size)
228       *icoord = size - 1;
229    else
230       *icoord = util_ifloor(u);
231 }
232 
233 
234 static void
wrap_nearest_mirror_clamp_to_edge(float s,unsigned size,int offset,int * icoord)235 wrap_nearest_mirror_clamp_to_edge(float s, unsigned size, int offset, int *icoord)
236 {
237    /* s limited to [min,max] */
238    /* i limited to [0, size-1] */
239    const float min = 0.5F;
240    const float max = (float)size - 0.5F;
241    const float u = fabsf(s * size + offset);
242 
243    if (u < min)
244       *icoord = 0;
245    else if (u > max)
246       *icoord = size - 1;
247    else
248       *icoord = util_ifloor(u);
249 }
250 
251 
252 static void
wrap_nearest_mirror_clamp_to_border(float s,unsigned size,int offset,int * icoord)253 wrap_nearest_mirror_clamp_to_border(float s, unsigned size, int offset, int *icoord)
254 {
255    /* u limited to [-0.5, size-0.5] */
256    const float min = -0.5F;
257    const float max = (float)size + 0.5F;
258    const float u = fabsf(s * size + offset);
259 
260    if (u < min)
261       *icoord = -1;
262    else if (u > max)
263       *icoord = size;
264    else
265       *icoord = util_ifloor(u);
266 }
267 
268 
269 /**
270  * Used to compute texel locations for linear sampling
271  * \param wrapMode  PIPE_TEX_WRAP_x
272  * \param s  the texcoord
273  * \param size  the texture image size
274  * \param icoord0  returns first texture index
275  * \param icoord1  returns second texture index (usually icoord0 + 1)
276  * \param w  returns blend factor/weight between texture indices
277  * \param icoord  returns the computed integer texture coord
278  */
279 static void
wrap_linear_repeat(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)280 wrap_linear_repeat(float s, unsigned size, int offset,
281                    int *icoord0, int *icoord1, float *w)
282 {
283    const float u = s * size - 0.5F;
284    *icoord0 = repeat(util_ifloor(u) + offset, size);
285    *icoord1 = repeat(*icoord0 + 1, size);
286    *w = frac(u);
287 }
288 
289 
290 static void
wrap_linear_clamp(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)291 wrap_linear_clamp(float s, unsigned size, int offset,
292                   int *icoord0, int *icoord1, float *w)
293 {
294    const float u = CLAMP(s * size + offset, 0.0F, (float)size) - 0.5f;
295 
296    *icoord0 = util_ifloor(u);
297    *icoord1 = *icoord0 + 1;
298    *w = frac(u);
299 }
300 
301 
302 static void
wrap_linear_clamp_to_edge(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)303 wrap_linear_clamp_to_edge(float s, unsigned size, int offset,
304                           int *icoord0, int *icoord1, float *w)
305 {
306    const float u = CLAMP(s * size + offset, 0.0F, (float)size) - 0.5f;
307    *icoord0 = util_ifloor(u);
308    *icoord1 = *icoord0 + 1;
309    if (*icoord0 < 0)
310       *icoord0 = 0;
311    if (*icoord1 >= (int) size)
312       *icoord1 = size - 1;
313    *w = frac(u);
314 }
315 
316 
317 static void
wrap_linear_clamp_to_border(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)318 wrap_linear_clamp_to_border(float s, unsigned size, int offset,
319                             int *icoord0, int *icoord1, float *w)
320 {
321    const float min = -1.0F;
322    const float max = (float)size + 0.5F;
323    const float u = CLAMP(s * size + offset, min, max) - 0.5f;
324    *icoord0 = util_ifloor(u);
325    *icoord1 = *icoord0 + 1;
326    *w = frac(u);
327 }
328 
329 
330 static void
wrap_linear_mirror_repeat(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)331 wrap_linear_mirror_repeat(float s, unsigned size, int offset,
332                           int *icoord0, int *icoord1, float *w)
333 {
334    int flr;
335    float u;
336    bool no_mirror;
337 
338    s += (float)offset / size;
339    flr = util_ifloor(s);
340    no_mirror = !(flr & 1);
341 
342    u = frac(s);
343    if (no_mirror) {
344       u = u * size - 0.5F;
345    } else {
346       u = 1.0F - u;
347       u = u * size + 0.5F;
348    }
349 
350    *icoord0 = util_ifloor(u);
351    *icoord1 = (no_mirror) ? *icoord0 + 1 : *icoord0 - 1;
352 
353    if (*icoord0 < 0)
354       *icoord0 = 1 + *icoord0;
355    if (*icoord0 >= (int) size)
356       *icoord0 = size - 1;
357 
358    if (*icoord1 >= (int) size)
359       *icoord1 = size - 1;
360    if (*icoord1 < 0)
361       *icoord1 = 1 + *icoord1;
362 
363    *w = (no_mirror) ? frac(u) : frac(1.0f - u);
364 }
365 
366 
367 static void
wrap_linear_mirror_clamp(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)368 wrap_linear_mirror_clamp(float s, unsigned size, int offset,
369                          int *icoord0, int *icoord1, float *w)
370 {
371    float u = fabsf(s * size + offset);
372    if (u >= size)
373       u = (float) size;
374    u -= 0.5F;
375    *icoord0 = util_ifloor(u);
376    *icoord1 = *icoord0 + 1;
377    *w = frac(u);
378 }
379 
380 
381 static void
wrap_linear_mirror_clamp_to_edge(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)382 wrap_linear_mirror_clamp_to_edge(float s, unsigned size, int offset,
383                                  int *icoord0, int *icoord1, float *w)
384 {
385    float u = fabsf(s * size + offset);
386    if (u >= size)
387       u = (float) size;
388    u -= 0.5F;
389    *icoord0 = util_ifloor(u);
390    *icoord1 = *icoord0 + 1;
391    if (*icoord0 < 0)
392       *icoord0 = 0;
393    if (*icoord1 >= (int) size)
394       *icoord1 = size - 1;
395    *w = frac(u);
396 }
397 
398 
399 static void
wrap_linear_mirror_clamp_to_border(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)400 wrap_linear_mirror_clamp_to_border(float s, unsigned size, int offset,
401                                    int *icoord0, int *icoord1, float *w)
402 {
403    const float min = -0.5F;
404    const float max = size + 0.5F;
405    const float t = fabsf(s * size + offset);
406    const float u = CLAMP(t, min, max) - 0.5F;
407    *icoord0 = util_ifloor(u);
408    *icoord1 = *icoord0 + 1;
409    *w = frac(u);
410 }
411 
412 
413 /**
414  * PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords.
415  */
416 static void
wrap_nearest_unorm_clamp(float s,unsigned size,int offset,int * icoord)417 wrap_nearest_unorm_clamp(float s, unsigned size, int offset, int *icoord)
418 {
419    const int i = util_ifloor(s);
420    *icoord = CLAMP(i + offset, 0, (int) size-1);
421 }
422 
423 
424 /**
425  * PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords.
426  */
427 static void
wrap_nearest_unorm_clamp_to_border(float s,unsigned size,int offset,int * icoord)428 wrap_nearest_unorm_clamp_to_border(float s, unsigned size, int offset, int *icoord)
429 {
430    *icoord = util_ifloor( CLAMP(s + offset, -0.5F, (float) size + 0.5F) );
431 }
432 
433 
434 /**
435  * PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords.
436  */
437 static void
wrap_nearest_unorm_clamp_to_edge(float s,unsigned size,int offset,int * icoord)438 wrap_nearest_unorm_clamp_to_edge(float s, unsigned size, int offset, int *icoord)
439 {
440    *icoord = util_ifloor( CLAMP(s + offset, 0.5F, (float) size - 0.5F) );
441 }
442 
443 
444 /**
445  * PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords.
446  */
447 static void
wrap_linear_unorm_clamp(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)448 wrap_linear_unorm_clamp(float s, unsigned size, int offset,
449                         int *icoord0, int *icoord1, float *w)
450 {
451    /* Not exactly what the spec says, but it matches NVIDIA output */
452    const float u = CLAMP(s + offset - 0.5F, 0.0f, (float) size - 1.0f);
453    *icoord0 = util_ifloor(u);
454    *icoord1 = *icoord0 + 1;
455    *w = frac(u);
456 }
457 
458 
459 /**
460  * PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords.
461  */
462 static void
wrap_linear_unorm_clamp_to_border(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)463 wrap_linear_unorm_clamp_to_border(float s, unsigned size, int offset,
464                                   int *icoord0, int *icoord1, float *w)
465 {
466    const float u = CLAMP(s + offset, -0.5F, (float) size + 0.5F) - 0.5F;
467    *icoord0 = util_ifloor(u);
468    *icoord1 = *icoord0 + 1;
469    if (*icoord1 > (int) size - 1)
470       *icoord1 = size - 1;
471    *w = frac(u);
472 }
473 
474 
475 /**
476  * PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords.
477  */
478 static void
wrap_linear_unorm_clamp_to_edge(float s,unsigned size,int offset,int * icoord0,int * icoord1,float * w)479 wrap_linear_unorm_clamp_to_edge(float s, unsigned size, int offset,
480                                 int *icoord0, int *icoord1, float *w)
481 {
482    const float u = CLAMP(s + offset, +0.5F, (float) size - 0.5F) - 0.5F;
483    *icoord0 = util_ifloor(u);
484    *icoord1 = *icoord0 + 1;
485    if (*icoord1 > (int) size - 1)
486       *icoord1 = size - 1;
487    *w = frac(u);
488 }
489 
490 
491 /**
492  * Do coordinate to array index conversion.  For array textures.
493  */
494 static inline int
coord_to_layer(float coord,unsigned first_layer,unsigned last_layer)495 coord_to_layer(float coord, unsigned first_layer, unsigned last_layer)
496 {
497    const int c = util_ifloor(coord + 0.5F);
498    return CLAMP(c, (int)first_layer, (int)last_layer);
499 }
500 
501 static void
compute_gradient_1d(const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],float derivs[3][2][TGSI_QUAD_SIZE])502 compute_gradient_1d(const float s[TGSI_QUAD_SIZE],
503                     const float t[TGSI_QUAD_SIZE],
504                     const float p[TGSI_QUAD_SIZE],
505                     float derivs[3][2][TGSI_QUAD_SIZE])
506 {
507    memset(derivs, 0, 6 * TGSI_QUAD_SIZE * sizeof(float));
508    derivs[0][0][0] = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
509    derivs[0][1][0] = s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT];
510 }
511 
512 static float
compute_lambda_1d_explicit_gradients(const struct sp_sampler_view * sview,const float derivs[3][2][TGSI_QUAD_SIZE],uint quad)513 compute_lambda_1d_explicit_gradients(const struct sp_sampler_view *sview,
514                                      const float derivs[3][2][TGSI_QUAD_SIZE],
515                                      uint quad)
516 {
517    const struct pipe_resource *texture = sview->base.texture;
518    const float dsdx = fabsf(derivs[0][0][quad]);
519    const float dsdy = fabsf(derivs[0][1][quad]);
520    const float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
521    return util_fast_log2(rho);
522 }
523 
524 
525 /**
526  * Examine the quad's texture coordinates to compute the partial
527  * derivatives w.r.t X and Y, then compute lambda (level of detail).
528  */
529 static float
compute_lambda_1d(const struct sp_sampler_view * sview,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE])530 compute_lambda_1d(const struct sp_sampler_view *sview,
531                   const float s[TGSI_QUAD_SIZE],
532                   const float t[TGSI_QUAD_SIZE],
533                   const float p[TGSI_QUAD_SIZE])
534 {
535    float derivs[3][2][TGSI_QUAD_SIZE];
536    compute_gradient_1d(s, t, p, derivs);
537    return compute_lambda_1d_explicit_gradients(sview, derivs, 0);
538 }
539 
540 
541 static void
compute_gradient_2d(const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],float derivs[3][2][TGSI_QUAD_SIZE])542 compute_gradient_2d(const float s[TGSI_QUAD_SIZE],
543                     const float t[TGSI_QUAD_SIZE],
544                     const float p[TGSI_QUAD_SIZE],
545                     float derivs[3][2][TGSI_QUAD_SIZE])
546 {
547    memset(derivs, 0, 6 * TGSI_QUAD_SIZE * sizeof(float));
548    derivs[0][0][0] = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
549    derivs[0][1][0] = s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT];
550    derivs[1][0][0] = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT];
551    derivs[1][1][0] = t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT];
552 }
553 
554 static float
compute_lambda_2d_explicit_gradients(const struct sp_sampler_view * sview,const float derivs[3][2][TGSI_QUAD_SIZE],uint quad)555 compute_lambda_2d_explicit_gradients(const struct sp_sampler_view *sview,
556                                      const float derivs[3][2][TGSI_QUAD_SIZE],
557                                      uint quad)
558 {
559    const struct pipe_resource *texture = sview->base.texture;
560    const float dsdx = fabsf(derivs[0][0][quad]);
561    const float dsdy = fabsf(derivs[0][1][quad]);
562    const float dtdx = fabsf(derivs[1][0][quad]);
563    const float dtdy = fabsf(derivs[1][1][quad]);
564    const float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
565    const float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
566    const float rho  = MAX2(maxx, maxy);
567    return util_fast_log2(rho);
568 }
569 
570 
571 static float
compute_lambda_2d(const struct sp_sampler_view * sview,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE])572 compute_lambda_2d(const struct sp_sampler_view *sview,
573                   const float s[TGSI_QUAD_SIZE],
574                   const float t[TGSI_QUAD_SIZE],
575                   const float p[TGSI_QUAD_SIZE])
576 {
577    float derivs[3][2][TGSI_QUAD_SIZE];
578    compute_gradient_2d(s, t, p, derivs);
579    return compute_lambda_2d_explicit_gradients(sview, derivs, 0);
580 }
581 
582 
583 static void
compute_gradient_3d(const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],float derivs[3][2][TGSI_QUAD_SIZE])584 compute_gradient_3d(const float s[TGSI_QUAD_SIZE],
585                     const float t[TGSI_QUAD_SIZE],
586                     const float p[TGSI_QUAD_SIZE],
587                     float derivs[3][2][TGSI_QUAD_SIZE])
588 {
589    memset(derivs, 0, 6 * TGSI_QUAD_SIZE * sizeof(float));
590    derivs[0][0][0] = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
591    derivs[0][1][0] = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
592    derivs[1][0][0] = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
593    derivs[1][1][0] = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
594    derivs[2][0][0] = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
595    derivs[2][1][0] = fabsf(p[QUAD_TOP_LEFT]     - p[QUAD_BOTTOM_LEFT]);
596 }
597 
598 static float
compute_lambda_3d_explicit_gradients(const struct sp_sampler_view * sview,const float derivs[3][2][TGSI_QUAD_SIZE],uint quad)599 compute_lambda_3d_explicit_gradients(const struct sp_sampler_view *sview,
600                                      const float derivs[3][2][TGSI_QUAD_SIZE],
601                                      uint quad)
602 {
603    const struct pipe_resource *texture = sview->base.texture;
604    const float dsdx = fabsf(derivs[0][0][quad]);
605    const float dsdy = fabsf(derivs[0][1][quad]);
606    const float dtdx = fabsf(derivs[1][0][quad]);
607    const float dtdy = fabsf(derivs[1][1][quad]);
608    const float dpdx = fabsf(derivs[2][0][quad]);
609    const float dpdy = fabsf(derivs[2][1][quad]);
610    const float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
611    const float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
612    const float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, sview->base.u.tex.first_level);
613    const float rho = MAX3(maxx, maxy, maxz);
614 
615    return util_fast_log2(rho);
616 }
617 
618 
619 static float
compute_lambda_3d(const struct sp_sampler_view * sview,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE])620 compute_lambda_3d(const struct sp_sampler_view *sview,
621                   const float s[TGSI_QUAD_SIZE],
622                   const float t[TGSI_QUAD_SIZE],
623                   const float p[TGSI_QUAD_SIZE])
624 {
625    float derivs[3][2][TGSI_QUAD_SIZE];
626    compute_gradient_3d(s, t, p, derivs);
627    return compute_lambda_3d_explicit_gradients(sview, derivs, 0);
628 }
629 
630 
631 static float
compute_lambda_cube_explicit_gradients(const struct sp_sampler_view * sview,const float derivs[3][2][TGSI_QUAD_SIZE],uint quad)632 compute_lambda_cube_explicit_gradients(const struct sp_sampler_view *sview,
633                                        const float derivs[3][2][TGSI_QUAD_SIZE],
634                                        uint quad)
635 {
636    const struct pipe_resource *texture = sview->base.texture;
637    const float dsdx = fabsf(derivs[0][0][quad]);
638    const float dsdy = fabsf(derivs[0][1][quad]);
639    const float dtdx = fabsf(derivs[1][0][quad]);
640    const float dtdy = fabsf(derivs[1][1][quad]);
641    const float dpdx = fabsf(derivs[2][0][quad]);
642    const float dpdy = fabsf(derivs[2][1][quad]);
643    const float maxx = MAX2(dsdx, dsdy);
644    const float maxy = MAX2(dtdx, dtdy);
645    const float maxz = MAX2(dpdx, dpdy);
646    const float rho = MAX3(maxx, maxy, maxz) * u_minify(texture->width0, sview->base.u.tex.first_level) / 2.0f;
647 
648    return util_fast_log2(rho);
649 }
650 
651 static float
compute_lambda_cube(const struct sp_sampler_view * sview,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE])652 compute_lambda_cube(const struct sp_sampler_view *sview,
653                     const float s[TGSI_QUAD_SIZE],
654                     const float t[TGSI_QUAD_SIZE],
655                     const float p[TGSI_QUAD_SIZE])
656 {
657    float derivs[3][2][TGSI_QUAD_SIZE];
658    compute_gradient_3d(s, t, p, derivs);
659    return compute_lambda_cube_explicit_gradients(sview, derivs, 0);
660 }
661 
662 /**
663  * Compute lambda for a vertex texture sampler.
664  * Since there aren't derivatives to use, just return 0.
665  */
666 static float
compute_lambda_vert(const struct sp_sampler_view * sview,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE])667 compute_lambda_vert(const struct sp_sampler_view *sview,
668                     const float s[TGSI_QUAD_SIZE],
669                     const float t[TGSI_QUAD_SIZE],
670                     const float p[TGSI_QUAD_SIZE])
671 {
672    return 0.0f;
673 }
674 
675 
676 compute_lambda_from_grad_func
softpipe_get_lambda_from_grad_func(const struct pipe_sampler_view * view,enum pipe_shader_type shader)677 softpipe_get_lambda_from_grad_func(const struct pipe_sampler_view *view,
678                                    enum pipe_shader_type shader)
679 {
680    switch (view->target) {
681    case PIPE_BUFFER:
682    case PIPE_TEXTURE_1D:
683    case PIPE_TEXTURE_1D_ARRAY:
684       return compute_lambda_1d_explicit_gradients;
685    case PIPE_TEXTURE_2D:
686    case PIPE_TEXTURE_2D_ARRAY:
687    case PIPE_TEXTURE_RECT:
688       return compute_lambda_2d_explicit_gradients;
689    case PIPE_TEXTURE_CUBE:
690    case PIPE_TEXTURE_CUBE_ARRAY:
691       return compute_lambda_cube_explicit_gradients;
692    case PIPE_TEXTURE_3D:
693       return compute_lambda_3d_explicit_gradients;
694    default:
695       assert(0);
696       return compute_lambda_1d_explicit_gradients;
697    }
698 }
699 
700 
701 /**
702  * Get a texel from a texture, using the texture tile cache.
703  *
704  * \param addr  the template tex address containing cube, z, face info.
705  * \param x  the x coord of texel within 2D image
706  * \param y  the y coord of texel within 2D image
707  * \param rgba  the quad to put the texel/color into
708  *
709  * XXX maybe move this into sp_tex_tile_cache.c and merge with the
710  * sp_get_cached_tile_tex() function.
711  */
712 
713 
714 
715 static inline const float *
get_texel_buffer_no_border(const struct sp_sampler_view * sp_sview,union tex_tile_address addr,int x,unsigned elmsize)716 get_texel_buffer_no_border(const struct sp_sampler_view *sp_sview,
717                            union tex_tile_address addr, int x, unsigned elmsize)
718 {
719    const struct softpipe_tex_cached_tile *tile;
720    addr.bits.x = x * elmsize / TEX_TILE_SIZE;
721    assert(x * elmsize / TEX_TILE_SIZE == addr.bits.x);
722 
723    x %= TEX_TILE_SIZE / elmsize;
724 
725    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
726 
727    return &tile->data.color[0][x][0];
728 }
729 
730 
731 static inline const float *
get_texel_2d_no_border(const struct sp_sampler_view * sp_sview,union tex_tile_address addr,int x,int y)732 get_texel_2d_no_border(const struct sp_sampler_view *sp_sview,
733                        union tex_tile_address addr, int x, int y)
734 {
735    const struct softpipe_tex_cached_tile *tile;
736    addr.bits.x = x / TEX_TILE_SIZE;
737    addr.bits.y = y / TEX_TILE_SIZE;
738    y %= TEX_TILE_SIZE;
739    x %= TEX_TILE_SIZE;
740 
741    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
742 
743    return &tile->data.color[y][x][0];
744 }
745 
746 
747 static inline const float *
get_texel_2d(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,union tex_tile_address addr,int x,int y)748 get_texel_2d(const struct sp_sampler_view *sp_sview,
749              const struct sp_sampler *sp_samp,
750              union tex_tile_address addr, int x, int y)
751 {
752    const struct pipe_resource *texture = sp_sview->base.texture;
753    const unsigned level = addr.bits.level;
754 
755    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
756        y < 0 || y >= (int) u_minify(texture->height0, level)) {
757       return sp_sview->border_color.f;
758    }
759    else {
760       return get_texel_2d_no_border( sp_sview, addr, x, y );
761    }
762 }
763 
764 
765 /*
766  * Here's the complete logic (HOLY CRAP) for finding next face and doing the
767  * corresponding coord wrapping, implemented by get_next_face,
768  * get_next_xcoord, get_next_ycoord.
769  * Read like that (first line):
770  * If face is +x and s coord is below zero, then
771  * new face is +z, new s is max , new t is old t
772  * (max is always cube size - 1).
773  *
774  * +x s- -> +z: s = max,   t = t
775  * +x s+ -> -z: s = 0,     t = t
776  * +x t- -> +y: s = max,   t = max-s
777  * +x t+ -> -y: s = max,   t = s
778  *
779  * -x s- -> -z: s = max,   t = t
780  * -x s+ -> +z: s = 0,     t = t
781  * -x t- -> +y: s = 0,     t = s
782  * -x t+ -> -y: s = 0,     t = max-s
783  *
784  * +y s- -> -x: s = t,     t = 0
785  * +y s+ -> +x: s = max-t, t = 0
786  * +y t- -> -z: s = max-s, t = 0
787  * +y t+ -> +z: s = s,     t = 0
788  *
789  * -y s- -> -x: s = max-t, t = max
790  * -y s+ -> +x: s = t,     t = max
791  * -y t- -> +z: s = s,     t = max
792  * -y t+ -> -z: s = max-s, t = max
793 
794  * +z s- -> -x: s = max,   t = t
795  * +z s+ -> +x: s = 0,     t = t
796  * +z t- -> +y: s = s,     t = max
797  * +z t+ -> -y: s = s,     t = 0
798 
799  * -z s- -> +x: s = max,   t = t
800  * -z s+ -> -x: s = 0,     t = t
801  * -z t- -> +y: s = max-s, t = 0
802  * -z t+ -> -y: s = max-s, t = max
803  */
804 
805 
806 /*
807  * seamless cubemap neighbour array.
808  * this array is used to find the adjacent face in each of 4 directions,
809  * left, right, up, down. (or -x, +x, -y, +y).
810  */
811 static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
812    /* pos X first then neg X is Z different, Y the same */
813    /* PIPE_TEX_FACE_POS_X,*/
814    { PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
815      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y },
816    /* PIPE_TEX_FACE_NEG_X */
817    { PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
818      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y },
819 
820    /* pos Y first then neg Y is X different, X the same */
821    /* PIPE_TEX_FACE_POS_Y */
822    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
823      PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
824 
825    /* PIPE_TEX_FACE_NEG_Y */
826    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
827      PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
828 
829    /* pos Z first then neg Y is X different, X the same */
830    /* PIPE_TEX_FACE_POS_Z */
831    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
832      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y },
833 
834    /* PIPE_TEX_FACE_NEG_Z */
835    { PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
836      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y }
837 };
838 
839 static inline unsigned
get_next_face(unsigned face,int idx)840 get_next_face(unsigned face, int idx)
841 {
842    return face_array[face][idx];
843 }
844 
845 /*
846  * return a new xcoord based on old face, old coords, cube size
847  * and fall_off_index (0 for x-, 1 for x+, 2 for y-, 3 for y+)
848  */
849 static inline int
get_next_xcoord(unsigned face,unsigned fall_off_index,int max,int xc,int yc)850 get_next_xcoord(unsigned face, unsigned fall_off_index, int max, int xc, int yc)
851 {
852    if ((face == 0 && fall_off_index != 1) ||
853        (face == 1 && fall_off_index == 0) ||
854        (face == 4 && fall_off_index == 0) ||
855        (face == 5 && fall_off_index == 0)) {
856       return max;
857    }
858    if ((face == 1 && fall_off_index != 0) ||
859        (face == 0 && fall_off_index == 1) ||
860        (face == 4 && fall_off_index == 1) ||
861        (face == 5 && fall_off_index == 1)) {
862       return 0;
863    }
864    if ((face == 4 && fall_off_index >= 2) ||
865        (face == 2 && fall_off_index == 3) ||
866        (face == 3 && fall_off_index == 2)) {
867       return xc;
868    }
869    if ((face == 5 && fall_off_index >= 2) ||
870        (face == 2 && fall_off_index == 2) ||
871        (face == 3 && fall_off_index == 3)) {
872       return max - xc;
873    }
874    if ((face == 2 && fall_off_index == 0) ||
875        (face == 3 && fall_off_index == 1)) {
876       return yc;
877    }
878    /* (face == 2 && fall_off_index == 1) ||
879       (face == 3 && fall_off_index == 0)) */
880    return max - yc;
881 }
882 
883 /*
884  * return a new ycoord based on old face, old coords, cube size
885  * and fall_off_index (0 for x-, 1 for x+, 2 for y-, 3 for y+)
886  */
887 static inline int
get_next_ycoord(unsigned face,unsigned fall_off_index,int max,int xc,int yc)888 get_next_ycoord(unsigned face, unsigned fall_off_index, int max, int xc, int yc)
889 {
890    if ((fall_off_index <= 1) && (face <= 1 || face >= 4)) {
891       return yc;
892    }
893    if (face == 2 ||
894        (face == 4 && fall_off_index == 3) ||
895        (face == 5 && fall_off_index == 2)) {
896       return 0;
897    }
898    if (face == 3 ||
899        (face == 4 && fall_off_index == 2) ||
900        (face == 5 && fall_off_index == 3)) {
901       return max;
902    }
903    if ((face == 0 && fall_off_index == 3) ||
904        (face == 1 && fall_off_index == 2)) {
905       return xc;
906    }
907    /* (face == 0 && fall_off_index == 2) ||
908       (face == 1 && fall_off_index == 3) */
909    return max - xc;
910 }
911 
912 
913 /* Gather a quad of adjacent texels within a tile:
914  */
915 static inline void
get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view * sp_sview,union tex_tile_address addr,unsigned x,unsigned y,const float * out[4])916 get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view *sp_sview,
917                                         union tex_tile_address addr,
918                                         unsigned x, unsigned y,
919                                         const float *out[4])
920 {
921     const struct softpipe_tex_cached_tile *tile;
922 
923    addr.bits.x = x / TEX_TILE_SIZE;
924    addr.bits.y = y / TEX_TILE_SIZE;
925    y %= TEX_TILE_SIZE;
926    x %= TEX_TILE_SIZE;
927 
928    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
929 
930    out[0] = &tile->data.color[y  ][x  ][0];
931    out[1] = &tile->data.color[y  ][x+1][0];
932    out[2] = &tile->data.color[y+1][x  ][0];
933    out[3] = &tile->data.color[y+1][x+1][0];
934 }
935 
936 
937 /* Gather a quad of potentially non-adjacent texels:
938  */
939 static inline void
get_texel_quad_2d_no_border(const struct sp_sampler_view * sp_sview,union tex_tile_address addr,int x0,int y0,int x1,int y1,const float * out[4])940 get_texel_quad_2d_no_border(const struct sp_sampler_view *sp_sview,
941                             union tex_tile_address addr,
942                             int x0, int y0,
943                             int x1, int y1,
944                             const float *out[4])
945 {
946    out[0] = get_texel_2d_no_border( sp_sview, addr, x0, y0 );
947    out[1] = get_texel_2d_no_border( sp_sview, addr, x1, y0 );
948    out[2] = get_texel_2d_no_border( sp_sview, addr, x0, y1 );
949    out[3] = get_texel_2d_no_border( sp_sview, addr, x1, y1 );
950 }
951 
952 
953 /* 3d variants:
954  */
955 static inline const float *
get_texel_3d_no_border(const struct sp_sampler_view * sp_sview,union tex_tile_address addr,int x,int y,int z)956 get_texel_3d_no_border(const struct sp_sampler_view *sp_sview,
957                        union tex_tile_address addr, int x, int y, int z)
958 {
959    const struct softpipe_tex_cached_tile *tile;
960 
961    addr.bits.x = x / TEX_TILE_SIZE;
962    addr.bits.y = y / TEX_TILE_SIZE;
963    addr.bits.z = z;
964    y %= TEX_TILE_SIZE;
965    x %= TEX_TILE_SIZE;
966 
967    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
968 
969    return &tile->data.color[y][x][0];
970 }
971 
972 
973 static inline const float *
get_texel_3d(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,union tex_tile_address addr,int x,int y,int z)974 get_texel_3d(const struct sp_sampler_view *sp_sview,
975              const struct sp_sampler *sp_samp,
976              union tex_tile_address addr, int x, int y, int z)
977 {
978    const struct pipe_resource *texture = sp_sview->base.texture;
979    const unsigned level = addr.bits.level;
980 
981    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
982        y < 0 || y >= (int) u_minify(texture->height0, level) ||
983        z < 0 || z >= (int) u_minify(texture->depth0, level)) {
984       return sp_sview->border_color.f;
985    }
986    else {
987       return get_texel_3d_no_border( sp_sview, addr, x, y, z );
988    }
989 }
990 
991 
992 /* Get texel pointer for 1D array texture */
993 static inline const float *
get_texel_1d_array(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,union tex_tile_address addr,int x,int y)994 get_texel_1d_array(const struct sp_sampler_view *sp_sview,
995                    const struct sp_sampler *sp_samp,
996                    union tex_tile_address addr, int x, int y)
997 {
998    const struct pipe_resource *texture = sp_sview->base.texture;
999    const unsigned level = addr.bits.level;
1000 
1001    if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
1002       return sp_sview->border_color.f;
1003    }
1004    else {
1005       return get_texel_2d_no_border(sp_sview, addr, x, y);
1006    }
1007 }
1008 
1009 
1010 /* Get texel pointer for 2D array texture */
1011 static inline const float *
get_texel_2d_array(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,union tex_tile_address addr,int x,int y,int layer)1012 get_texel_2d_array(const struct sp_sampler_view *sp_sview,
1013                    const struct sp_sampler *sp_samp,
1014                    union tex_tile_address addr, int x, int y, int layer)
1015 {
1016    const struct pipe_resource *texture = sp_sview->base.texture;
1017    const unsigned level = addr.bits.level;
1018 
1019    assert(layer < (int) texture->array_size);
1020    assert(layer >= 0);
1021 
1022    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
1023        y < 0 || y >= (int) u_minify(texture->height0, level)) {
1024       return sp_sview->border_color.f;
1025    }
1026    else {
1027       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
1028    }
1029 }
1030 
1031 
1032 static inline const float *
get_texel_cube_seamless(const struct sp_sampler_view * sp_sview,union tex_tile_address addr,int x,int y,float * corner,int layer,unsigned face)1033 get_texel_cube_seamless(const struct sp_sampler_view *sp_sview,
1034                         union tex_tile_address addr, int x, int y,
1035                         float *corner, int layer, unsigned face)
1036 {
1037    const struct pipe_resource *texture = sp_sview->base.texture;
1038    const unsigned level = addr.bits.level;
1039    int new_x, new_y, max_x;
1040 
1041    max_x = (int) u_minify(texture->width0, level);
1042 
1043    assert(texture->width0 == texture->height0);
1044    new_x = x;
1045    new_y = y;
1046 
1047    /* change the face */
1048    if (x < 0) {
1049       /*
1050        * Cheat with corners. They are difficult and I believe because we don't get
1051        * per-pixel faces we can actually have multiple corner texels per pixel,
1052        * which screws things up majorly in any case (as the per spec behavior is
1053        * to average the 3 remaining texels, which we might not have).
1054        * Hence just make sure that the 2nd coord is clamped, will simply pick the
1055        * sample which would have fallen off the x coord, but not y coord.
1056        * So the filter weight of the samples will be wrong, but at least this
1057        * ensures that only valid texels near the corner are used.
1058        */
1059       if (y < 0 || y >= max_x) {
1060          y = CLAMP(y, 0, max_x - 1);
1061       }
1062       new_x = get_next_xcoord(face, 0, max_x -1, x, y);
1063       new_y = get_next_ycoord(face, 0, max_x -1, x, y);
1064       face = get_next_face(face, 0);
1065    } else if (x >= max_x) {
1066       if (y < 0 || y >= max_x) {
1067          y = CLAMP(y, 0, max_x - 1);
1068       }
1069       new_x = get_next_xcoord(face, 1, max_x -1, x, y);
1070       new_y = get_next_ycoord(face, 1, max_x -1, x, y);
1071       face = get_next_face(face, 1);
1072    } else if (y < 0) {
1073       new_x = get_next_xcoord(face, 2, max_x -1, x, y);
1074       new_y = get_next_ycoord(face, 2, max_x -1, x, y);
1075       face = get_next_face(face, 2);
1076    } else if (y >= max_x) {
1077       new_x = get_next_xcoord(face, 3, max_x -1, x, y);
1078       new_y = get_next_ycoord(face, 3, max_x -1, x, y);
1079       face = get_next_face(face, 3);
1080    }
1081 
1082    return get_texel_3d_no_border(sp_sview, addr, new_x, new_y, layer + face);
1083 }
1084 
1085 
1086 /* Get texel pointer for cube array texture */
1087 static inline const float *
get_texel_cube_array(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,union tex_tile_address addr,int x,int y,int layer)1088 get_texel_cube_array(const struct sp_sampler_view *sp_sview,
1089                      const struct sp_sampler *sp_samp,
1090                      union tex_tile_address addr, int x, int y, int layer)
1091 {
1092    const struct pipe_resource *texture = sp_sview->base.texture;
1093    const unsigned level = addr.bits.level;
1094 
1095    assert(layer < (int) texture->array_size);
1096    assert(layer >= 0);
1097 
1098    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
1099        y < 0 || y >= (int) u_minify(texture->height0, level)) {
1100       return sp_sview->border_color.f;
1101    }
1102    else {
1103       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
1104    }
1105 }
1106 /**
1107  * Given the logbase2 of a mipmap's base level size and a mipmap level,
1108  * return the size (in texels) of that mipmap level.
1109  * For example, if level[0].width = 256 then base_pot will be 8.
1110  * If level = 2, then we'll return 64 (the width at level=2).
1111  * Return 1 if level > base_pot.
1112  */
1113 static inline unsigned
pot_level_size(unsigned base_pot,unsigned level)1114 pot_level_size(unsigned base_pot, unsigned level)
1115 {
1116    return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
1117 }
1118 
1119 
1120 static void
print_sample(const char * function,const float * rgba)1121 print_sample(const char *function, const float *rgba)
1122 {
1123    debug_printf("%s %g %g %g %g\n",
1124                 function,
1125                 rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]);
1126 }
1127 
1128 
1129 static void
print_sample_4(const char * function,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])1130 print_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1131 {
1132    debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
1133                 function,
1134                 rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
1135                 rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
1136                 rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
1137                 rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
1138 }
1139 
1140 
1141 /* Some image-filter fastpaths:
1142  */
1143 static inline void
img_filter_2d_linear_repeat_POT(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1144 img_filter_2d_linear_repeat_POT(const struct sp_sampler_view *sp_sview,
1145                                 const struct sp_sampler *sp_samp,
1146                                 const struct img_filter_args *args,
1147                                 float *rgba)
1148 {
1149    const unsigned xpot = pot_level_size(sp_sview->xpot, args->level);
1150    const unsigned ypot = pot_level_size(sp_sview->ypot, args->level);
1151    const int xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */
1152    const int ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */
1153    union tex_tile_address addr;
1154    int c;
1155 
1156    const float u = (args->s * xpot - 0.5F) + args->offset[0];
1157    const float v = (args->t * ypot - 0.5F) + args->offset[1];
1158 
1159    const int uflr = util_ifloor(u);
1160    const int vflr = util_ifloor(v);
1161 
1162    const float xw = u - (float)uflr;
1163    const float yw = v - (float)vflr;
1164 
1165    const int x0 = uflr & (xpot - 1);
1166    const int y0 = vflr & (ypot - 1);
1167 
1168    const float *tx[4];
1169 
1170    addr.value = 0;
1171    addr.bits.level = args->level;
1172    addr.bits.z = sp_sview->base.u.tex.first_layer;
1173 
1174    /* Can we fetch all four at once:
1175     */
1176    if (x0 < xmax && y0 < ymax) {
1177       get_texel_quad_2d_no_border_single_tile(sp_sview, addr, x0, y0, tx);
1178    }
1179    else {
1180       const unsigned x1 = (x0 + 1) & (xpot - 1);
1181       const unsigned y1 = (y0 + 1) & (ypot - 1);
1182       get_texel_quad_2d_no_border(sp_sview, addr, x0, y0, x1, y1, tx);
1183    }
1184 
1185    /* interpolate R, G, B, A */
1186    for (c = 0; c < TGSI_NUM_CHANNELS; c++) {
1187       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1188                                        tx[0][c], tx[1][c],
1189                                        tx[2][c], tx[3][c]);
1190    }
1191 
1192    if (DEBUG_TEX) {
1193       print_sample(__FUNCTION__, rgba);
1194    }
1195 }
1196 
1197 
1198 static inline void
img_filter_2d_nearest_repeat_POT(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1199 img_filter_2d_nearest_repeat_POT(const struct sp_sampler_view *sp_sview,
1200                                  const struct sp_sampler *sp_samp,
1201                                  const struct img_filter_args *args,
1202                                  float *rgba)
1203 {
1204    const unsigned xpot = pot_level_size(sp_sview->xpot, args->level);
1205    const unsigned ypot = pot_level_size(sp_sview->ypot, args->level);
1206    const float *out;
1207    union tex_tile_address addr;
1208    int c;
1209 
1210    const float u = args->s * xpot + args->offset[0];
1211    const float v = args->t * ypot + args->offset[1];
1212 
1213    const int uflr = util_ifloor(u);
1214    const int vflr = util_ifloor(v);
1215 
1216    const int x0 = uflr & (xpot - 1);
1217    const int y0 = vflr & (ypot - 1);
1218 
1219    addr.value = 0;
1220    addr.bits.level = args->level;
1221    addr.bits.z = sp_sview->base.u.tex.first_layer;
1222 
1223    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
1224    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1225       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1226 
1227    if (DEBUG_TEX) {
1228       print_sample(__FUNCTION__, rgba);
1229    }
1230 }
1231 
1232 
1233 static inline void
img_filter_2d_nearest_clamp_POT(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1234 img_filter_2d_nearest_clamp_POT(const struct sp_sampler_view *sp_sview,
1235                                 const struct sp_sampler *sp_samp,
1236                                 const struct img_filter_args *args,
1237                                 float *rgba)
1238 {
1239    const unsigned xpot = pot_level_size(sp_sview->xpot, args->level);
1240    const unsigned ypot = pot_level_size(sp_sview->ypot, args->level);
1241    union tex_tile_address addr;
1242    int c;
1243 
1244    const float u = args->s * xpot + args->offset[0];
1245    const float v = args->t * ypot + args->offset[1];
1246 
1247    int x0, y0;
1248    const float *out;
1249 
1250    addr.value = 0;
1251    addr.bits.level = args->level;
1252    addr.bits.z = sp_sview->base.u.tex.first_layer;
1253 
1254    x0 = util_ifloor(u);
1255    if (x0 < 0)
1256       x0 = 0;
1257    else if (x0 > (int) xpot - 1)
1258       x0 = xpot - 1;
1259 
1260    y0 = util_ifloor(v);
1261    if (y0 < 0)
1262       y0 = 0;
1263    else if (y0 > (int) ypot - 1)
1264       y0 = ypot - 1;
1265 
1266    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
1267    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1268       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1269 
1270    if (DEBUG_TEX) {
1271       print_sample(__FUNCTION__, rgba);
1272    }
1273 }
1274 
1275 
1276 static void
img_filter_1d_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1277 img_filter_1d_nearest(const struct sp_sampler_view *sp_sview,
1278                       const struct sp_sampler *sp_samp,
1279                       const struct img_filter_args *args,
1280                       float *rgba)
1281 {
1282    const struct pipe_resource *texture = sp_sview->base.texture;
1283    const int width = u_minify(texture->width0, args->level);
1284    int x;
1285    union tex_tile_address addr;
1286    const float *out;
1287    int c;
1288 
1289    assert(width > 0);
1290 
1291    addr.value = 0;
1292    addr.bits.level = args->level;
1293 
1294    sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x);
1295 
1296    out = get_texel_1d_array(sp_sview, sp_samp, addr, x,
1297                             sp_sview->base.u.tex.first_layer);
1298    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1299       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1300 
1301    if (DEBUG_TEX) {
1302       print_sample(__FUNCTION__, rgba);
1303    }
1304 }
1305 
1306 
1307 static void
img_filter_1d_array_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1308 img_filter_1d_array_nearest(const struct sp_sampler_view *sp_sview,
1309                             const struct sp_sampler *sp_samp,
1310                             const struct img_filter_args *args,
1311                             float *rgba)
1312 {
1313    const struct pipe_resource *texture = sp_sview->base.texture;
1314    const int width = u_minify(texture->width0, args->level);
1315    const int layer = coord_to_layer(args->t, sp_sview->base.u.tex.first_layer,
1316                                     sp_sview->base.u.tex.last_layer);
1317    int x;
1318    union tex_tile_address addr;
1319    const float *out;
1320    int c;
1321 
1322    assert(width > 0);
1323 
1324    addr.value = 0;
1325    addr.bits.level = args->level;
1326 
1327    sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x);
1328 
1329    out = get_texel_1d_array(sp_sview, sp_samp, addr, x, layer);
1330    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1331       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1332 
1333    if (DEBUG_TEX) {
1334       print_sample(__FUNCTION__, rgba);
1335    }
1336 }
1337 
1338 
1339 static void
img_filter_2d_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1340 img_filter_2d_nearest(const struct sp_sampler_view *sp_sview,
1341                       const struct sp_sampler *sp_samp,
1342                       const struct img_filter_args *args,
1343                       float *rgba)
1344 {
1345    const struct pipe_resource *texture = sp_sview->base.texture;
1346    const int width = u_minify(texture->width0, args->level);
1347    const int height = u_minify(texture->height0, args->level);
1348    int x, y;
1349    union tex_tile_address addr;
1350    const float *out;
1351    int c;
1352 
1353    assert(width > 0);
1354    assert(height > 0);
1355 
1356    addr.value = 0;
1357    addr.bits.level = args->level;
1358    addr.bits.z = sp_sview->base.u.tex.first_layer;
1359 
1360    sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x);
1361    sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y);
1362 
1363    out = get_texel_2d(sp_sview, sp_samp, addr, x, y);
1364    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1365       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1366 
1367    if (DEBUG_TEX) {
1368       print_sample(__FUNCTION__, rgba);
1369    }
1370 }
1371 
1372 
1373 static void
img_filter_2d_array_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1374 img_filter_2d_array_nearest(const struct sp_sampler_view *sp_sview,
1375                             const struct sp_sampler *sp_samp,
1376                             const struct img_filter_args *args,
1377                             float *rgba)
1378 {
1379    const struct pipe_resource *texture = sp_sview->base.texture;
1380    const int width = u_minify(texture->width0, args->level);
1381    const int height = u_minify(texture->height0, args->level);
1382    const int layer = coord_to_layer(args->p, sp_sview->base.u.tex.first_layer,
1383                                     sp_sview->base.u.tex.last_layer);
1384    int x, y;
1385    union tex_tile_address addr;
1386    const float *out;
1387    int c;
1388 
1389    assert(width > 0);
1390    assert(height > 0);
1391 
1392    addr.value = 0;
1393    addr.bits.level = args->level;
1394 
1395    sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x);
1396    sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y);
1397 
1398    out = get_texel_2d_array(sp_sview, sp_samp, addr, x, y, layer);
1399    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1400       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1401 
1402    if (DEBUG_TEX) {
1403       print_sample(__FUNCTION__, rgba);
1404    }
1405 }
1406 
1407 
1408 static void
img_filter_cube_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1409 img_filter_cube_nearest(const struct sp_sampler_view *sp_sview,
1410                         const struct sp_sampler *sp_samp,
1411                         const struct img_filter_args *args,
1412                         float *rgba)
1413 {
1414    const struct pipe_resource *texture = sp_sview->base.texture;
1415    const int width = u_minify(texture->width0, args->level);
1416    const int height = u_minify(texture->height0, args->level);
1417    const int layerface = args->face_id + sp_sview->base.u.tex.first_layer;
1418    int x, y;
1419    union tex_tile_address addr;
1420    const float *out;
1421    int c;
1422 
1423    assert(width > 0);
1424    assert(height > 0);
1425 
1426    addr.value = 0;
1427    addr.bits.level = args->level;
1428 
1429    /*
1430     * If NEAREST filtering is done within a miplevel, always apply wrap
1431     * mode CLAMP_TO_EDGE.
1432     */
1433    if (sp_samp->base.seamless_cube_map) {
1434       wrap_nearest_clamp_to_edge(args->s, width, args->offset[0], &x);
1435       wrap_nearest_clamp_to_edge(args->t, height, args->offset[1], &y);
1436    } else {
1437       /* Would probably make sense to ignore mode and just do edge clamp */
1438       sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x);
1439       sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y);
1440    }
1441 
1442    out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layerface);
1443    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1444       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1445 
1446    if (DEBUG_TEX) {
1447       print_sample(__FUNCTION__, rgba);
1448    }
1449 }
1450 
1451 static void
img_filter_cube_array_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1452 img_filter_cube_array_nearest(const struct sp_sampler_view *sp_sview,
1453                               const struct sp_sampler *sp_samp,
1454                               const struct img_filter_args *args,
1455                               float *rgba)
1456 {
1457    const struct pipe_resource *texture = sp_sview->base.texture;
1458    const int width = u_minify(texture->width0, args->level);
1459    const int height = u_minify(texture->height0, args->level);
1460    const int layerface = CLAMP(6 * util_ifloor(args->p + 0.5f) + sp_sview->base.u.tex.first_layer,
1461                                sp_sview->base.u.tex.first_layer,
1462                                sp_sview->base.u.tex.last_layer - 5) + args->face_id;
1463    int x, y;
1464    union tex_tile_address addr;
1465    const float *out;
1466    int c;
1467 
1468    assert(width > 0);
1469    assert(height > 0);
1470 
1471    addr.value = 0;
1472    addr.bits.level = args->level;
1473 
1474    sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x);
1475    sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y);
1476 
1477    out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layerface);
1478    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1479       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1480 
1481    if (DEBUG_TEX) {
1482       print_sample(__FUNCTION__, rgba);
1483    }
1484 }
1485 
1486 static void
img_filter_3d_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1487 img_filter_3d_nearest(const struct sp_sampler_view *sp_sview,
1488                       const struct sp_sampler *sp_samp,
1489                       const struct img_filter_args *args,
1490                       float *rgba)
1491 {
1492    const struct pipe_resource *texture = sp_sview->base.texture;
1493    const int width = u_minify(texture->width0, args->level);
1494    const int height = u_minify(texture->height0, args->level);
1495    const int depth = u_minify(texture->depth0, args->level);
1496    int x, y, z;
1497    union tex_tile_address addr;
1498    const float *out;
1499    int c;
1500 
1501    assert(width > 0);
1502    assert(height > 0);
1503    assert(depth > 0);
1504 
1505    sp_samp->nearest_texcoord_s(args->s, width,  args->offset[0], &x);
1506    sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y);
1507    sp_samp->nearest_texcoord_p(args->p, depth,  args->offset[2], &z);
1508 
1509    addr.value = 0;
1510    addr.bits.level = args->level;
1511 
1512    out = get_texel_3d(sp_sview, sp_samp, addr, x, y, z);
1513    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1514       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1515 }
1516 
1517 
1518 static void
img_filter_1d_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1519 img_filter_1d_linear(const struct sp_sampler_view *sp_sview,
1520                      const struct sp_sampler *sp_samp,
1521                      const struct img_filter_args *args,
1522                      float *rgba)
1523 {
1524    const struct pipe_resource *texture = sp_sview->base.texture;
1525    const int width = u_minify(texture->width0, args->level);
1526    int x0, x1;
1527    float xw; /* weights */
1528    union tex_tile_address addr;
1529    const float *tx0, *tx1;
1530    int c;
1531 
1532    assert(width > 0);
1533 
1534    addr.value = 0;
1535    addr.bits.level = args->level;
1536 
1537    sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw);
1538 
1539    tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0,
1540                             sp_sview->base.u.tex.first_layer);
1541    tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1,
1542                             sp_sview->base.u.tex.first_layer);
1543 
1544    /* interpolate R, G, B, A */
1545    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1546       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
1547 }
1548 
1549 
1550 static void
img_filter_1d_array_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1551 img_filter_1d_array_linear(const struct sp_sampler_view *sp_sview,
1552                            const struct sp_sampler *sp_samp,
1553                            const struct img_filter_args *args,
1554                            float *rgba)
1555 {
1556    const struct pipe_resource *texture = sp_sview->base.texture;
1557    const int width = u_minify(texture->width0, args->level);
1558    const int layer = coord_to_layer(args->t, sp_sview->base.u.tex.first_layer,
1559                                     sp_sview->base.u.tex.last_layer);
1560    int x0, x1;
1561    float xw; /* weights */
1562    union tex_tile_address addr;
1563    const float *tx0, *tx1;
1564    int c;
1565 
1566    assert(width > 0);
1567 
1568    addr.value = 0;
1569    addr.bits.level = args->level;
1570 
1571    sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw);
1572 
1573    tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, layer);
1574    tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, layer);
1575 
1576    /* interpolate R, G, B, A */
1577    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1578       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
1579 }
1580 
1581 /*
1582  * Retrieve the gathered value, need to convert to the
1583  * TGSI expected interface, and take component select
1584  * and swizzling into account.
1585  */
1586 static float
get_gather_value(const struct sp_sampler_view * sp_sview,int chan_in,int comp_sel,const float * tx[4])1587 get_gather_value(const struct sp_sampler_view *sp_sview,
1588                  int chan_in, int comp_sel,
1589                  const float *tx[4])
1590 {
1591    int chan;
1592    unsigned swizzle;
1593 
1594    /*
1595     * softpipe samples in a different order
1596     * to TGSI expects, so we need to swizzle,
1597     * the samples into the correct slots.
1598     */
1599    switch (chan_in) {
1600    case 0:
1601       chan = 2;
1602       break;
1603    case 1:
1604       chan = 3;
1605       break;
1606    case 2:
1607       chan = 1;
1608       break;
1609    case 3:
1610       chan = 0;
1611       break;
1612    default:
1613       assert(0);
1614       return 0.0;
1615    }
1616 
1617    /* pick which component to use for the swizzle */
1618    switch (comp_sel) {
1619    case 0:
1620       swizzle = sp_sview->base.swizzle_r;
1621       break;
1622    case 1:
1623       swizzle = sp_sview->base.swizzle_g;
1624       break;
1625    case 2:
1626       swizzle = sp_sview->base.swizzle_b;
1627       break;
1628    case 3:
1629       swizzle = sp_sview->base.swizzle_a;
1630       break;
1631    default:
1632       assert(0);
1633       return 0.0;
1634    }
1635 
1636    /* get correct result using the channel and swizzle */
1637    switch (swizzle) {
1638    case PIPE_SWIZZLE_0:
1639       return 0.0;
1640    case PIPE_SWIZZLE_1:
1641       return sp_sview->oneval;
1642    default:
1643       return tx[chan][swizzle];
1644    }
1645 }
1646 
1647 
1648 static void
img_filter_2d_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1649 img_filter_2d_linear(const struct sp_sampler_view *sp_sview,
1650                      const struct sp_sampler *sp_samp,
1651                      const struct img_filter_args *args,
1652                      float *rgba)
1653 {
1654    const struct pipe_resource *texture = sp_sview->base.texture;
1655    const int width = u_minify(texture->width0, args->level);
1656    const int height = u_minify(texture->height0, args->level);
1657    int x0, y0, x1, y1;
1658    float xw, yw; /* weights */
1659    union tex_tile_address addr;
1660    const float *tx[4];
1661    int c;
1662 
1663    assert(width > 0);
1664    assert(height > 0);
1665 
1666    addr.value = 0;
1667    addr.bits.level = args->level;
1668    addr.bits.z = sp_sview->base.u.tex.first_layer;
1669 
1670    sp_samp->linear_texcoord_s(args->s, width,  args->offset[0], &x0, &x1, &xw);
1671    sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw);
1672 
1673    tx[0] = get_texel_2d(sp_sview, sp_samp, addr, x0, y0);
1674    tx[1] = get_texel_2d(sp_sview, sp_samp, addr, x1, y0);
1675    tx[2] = get_texel_2d(sp_sview, sp_samp, addr, x0, y1);
1676    tx[3] = get_texel_2d(sp_sview, sp_samp, addr, x1, y1);
1677 
1678    if (args->gather_only) {
1679       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1680          rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c,
1681                                                       args->gather_comp,
1682                                                       tx);
1683    } else {
1684       /* interpolate R, G, B, A */
1685       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1686          rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1687                                              tx[0][c], tx[1][c],
1688                                              tx[2][c], tx[3][c]);
1689    }
1690 }
1691 
1692 
1693 static void
img_filter_2d_array_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1694 img_filter_2d_array_linear(const struct sp_sampler_view *sp_sview,
1695                            const struct sp_sampler *sp_samp,
1696                            const struct img_filter_args *args,
1697                            float *rgba)
1698 {
1699    const struct pipe_resource *texture = sp_sview->base.texture;
1700    const int width = u_minify(texture->width0, args->level);
1701    const int height = u_minify(texture->height0, args->level);
1702    const int layer = coord_to_layer(args->p, sp_sview->base.u.tex.first_layer,
1703                                     sp_sview->base.u.tex.last_layer);
1704    int x0, y0, x1, y1;
1705    float xw, yw; /* weights */
1706    union tex_tile_address addr;
1707    const float *tx[4];
1708    int c;
1709 
1710    assert(width > 0);
1711    assert(height > 0);
1712 
1713    addr.value = 0;
1714    addr.bits.level = args->level;
1715 
1716    sp_samp->linear_texcoord_s(args->s, width,  args->offset[0], &x0, &x1, &xw);
1717    sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw);
1718 
1719    tx[0] = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y0, layer);
1720    tx[1] = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y0, layer);
1721    tx[2] = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y1, layer);
1722    tx[3] = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y1, layer);
1723 
1724    if (args->gather_only) {
1725       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1726          rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c,
1727                                                       args->gather_comp,
1728                                                       tx);
1729    } else {
1730       /* interpolate R, G, B, A */
1731       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1732          rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1733                                              tx[0][c], tx[1][c],
1734                                              tx[2][c], tx[3][c]);
1735    }
1736 }
1737 
1738 
1739 static void
img_filter_cube_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1740 img_filter_cube_linear(const struct sp_sampler_view *sp_sview,
1741                        const struct sp_sampler *sp_samp,
1742                        const struct img_filter_args *args,
1743                        float *rgba)
1744 {
1745    const struct pipe_resource *texture = sp_sview->base.texture;
1746    const int width = u_minify(texture->width0, args->level);
1747    const int height = u_minify(texture->height0, args->level);
1748    const int layer = sp_sview->base.u.tex.first_layer;
1749    int x0, y0, x1, y1;
1750    float xw, yw; /* weights */
1751    union tex_tile_address addr;
1752    const float *tx[4];
1753    float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
1754          corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
1755    int c;
1756 
1757    assert(width > 0);
1758    assert(height > 0);
1759 
1760    addr.value = 0;
1761    addr.bits.level = args->level;
1762 
1763    /*
1764     * For seamless if LINEAR filtering is done within a miplevel,
1765     * always apply wrap mode CLAMP_TO_BORDER.
1766     */
1767    if (sp_samp->base.seamless_cube_map) {
1768       /* Note this is a bit overkill, actual clamping is not required */
1769       wrap_linear_clamp_to_border(args->s, width, args->offset[0], &x0, &x1, &xw);
1770       wrap_linear_clamp_to_border(args->t, height, args->offset[1], &y0, &y1, &yw);
1771    } else {
1772       /* Would probably make sense to ignore mode and just do edge clamp */
1773       sp_samp->linear_texcoord_s(args->s, width,  args->offset[0], &x0, &x1, &xw);
1774       sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw);
1775    }
1776 
1777    if (sp_samp->base.seamless_cube_map) {
1778       tx[0] = get_texel_cube_seamless(sp_sview, addr, x0, y0, corner0, layer, args->face_id);
1779       tx[1] = get_texel_cube_seamless(sp_sview, addr, x1, y0, corner1, layer, args->face_id);
1780       tx[2] = get_texel_cube_seamless(sp_sview, addr, x0, y1, corner2, layer, args->face_id);
1781       tx[3] = get_texel_cube_seamless(sp_sview, addr, x1, y1, corner3, layer, args->face_id);
1782    } else {
1783       tx[0] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer + args->face_id);
1784       tx[1] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer + args->face_id);
1785       tx[2] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer + args->face_id);
1786       tx[3] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer + args->face_id);
1787    }
1788 
1789    if (args->gather_only) {
1790       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1791          rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c,
1792                                                       args->gather_comp,
1793                                                       tx);
1794    } else {
1795       /* interpolate R, G, B, A */
1796       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1797          rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1798                                              tx[0][c], tx[1][c],
1799                                              tx[2][c], tx[3][c]);
1800    }
1801 }
1802 
1803 
1804 static void
img_filter_cube_array_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1805 img_filter_cube_array_linear(const struct sp_sampler_view *sp_sview,
1806                              const struct sp_sampler *sp_samp,
1807                              const struct img_filter_args *args,
1808                              float *rgba)
1809 {
1810    const struct pipe_resource *texture = sp_sview->base.texture;
1811    const int width = u_minify(texture->width0, args->level);
1812    const int height = u_minify(texture->height0, args->level);
1813 
1814    const int layer = CLAMP(6 * util_ifloor(args->p + 0.5f) + sp_sview->base.u.tex.first_layer,
1815                            sp_sview->base.u.tex.first_layer,
1816                            sp_sview->base.u.tex.last_layer - 5);
1817 
1818    int x0, y0, x1, y1;
1819    float xw, yw; /* weights */
1820    union tex_tile_address addr;
1821    const float *tx[4];
1822    float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
1823          corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
1824    int c;
1825 
1826    assert(width > 0);
1827    assert(height > 0);
1828 
1829    addr.value = 0;
1830    addr.bits.level = args->level;
1831 
1832    /*
1833     * For seamless if LINEAR filtering is done within a miplevel,
1834     * always apply wrap mode CLAMP_TO_BORDER.
1835     */
1836    if (sp_samp->base.seamless_cube_map) {
1837       /* Note this is a bit overkill, actual clamping is not required */
1838       wrap_linear_clamp_to_border(args->s, width, args->offset[0], &x0, &x1, &xw);
1839       wrap_linear_clamp_to_border(args->t, height, args->offset[1], &y0, &y1, &yw);
1840    } else {
1841       /* Would probably make sense to ignore mode and just do edge clamp */
1842       sp_samp->linear_texcoord_s(args->s, width,  args->offset[0], &x0, &x1, &xw);
1843       sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw);
1844    }
1845 
1846    if (sp_samp->base.seamless_cube_map) {
1847       tx[0] = get_texel_cube_seamless(sp_sview, addr, x0, y0, corner0, layer, args->face_id);
1848       tx[1] = get_texel_cube_seamless(sp_sview, addr, x1, y0, corner1, layer, args->face_id);
1849       tx[2] = get_texel_cube_seamless(sp_sview, addr, x0, y1, corner2, layer, args->face_id);
1850       tx[3] = get_texel_cube_seamless(sp_sview, addr, x1, y1, corner3, layer, args->face_id);
1851    } else {
1852       tx[0] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer + args->face_id);
1853       tx[1] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer + args->face_id);
1854       tx[2] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer + args->face_id);
1855       tx[3] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer + args->face_id);
1856    }
1857 
1858    if (args->gather_only) {
1859       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1860          rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c,
1861                                                       args->gather_comp,
1862                                                       tx);
1863    } else {
1864       /* interpolate R, G, B, A */
1865       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1866          rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1867                                              tx[0][c], tx[1][c],
1868                                              tx[2][c], tx[3][c]);
1869    }
1870 }
1871 
1872 static void
img_filter_3d_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const struct img_filter_args * args,float * rgba)1873 img_filter_3d_linear(const struct sp_sampler_view *sp_sview,
1874                      const struct sp_sampler *sp_samp,
1875                      const struct img_filter_args *args,
1876                      float *rgba)
1877 {
1878    const struct pipe_resource *texture = sp_sview->base.texture;
1879    const int width = u_minify(texture->width0, args->level);
1880    const int height = u_minify(texture->height0, args->level);
1881    const int depth = u_minify(texture->depth0, args->level);
1882    int x0, x1, y0, y1, z0, z1;
1883    float xw, yw, zw; /* interpolation weights */
1884    union tex_tile_address addr;
1885    const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13;
1886    int c;
1887 
1888    addr.value = 0;
1889    addr.bits.level = args->level;
1890 
1891    assert(width > 0);
1892    assert(height > 0);
1893    assert(depth > 0);
1894 
1895    sp_samp->linear_texcoord_s(args->s, width,  args->offset[0], &x0, &x1, &xw);
1896    sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw);
1897    sp_samp->linear_texcoord_p(args->p, depth,  args->offset[2], &z0, &z1, &zw);
1898 
1899    tx00 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z0);
1900    tx01 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z0);
1901    tx02 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z0);
1902    tx03 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z0);
1903 
1904    tx10 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z1);
1905    tx11 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z1);
1906    tx12 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z1);
1907    tx13 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z1);
1908 
1909       /* interpolate R, G, B, A */
1910    for (c = 0; c < TGSI_NUM_CHANNELS; c++)
1911       rgba[TGSI_NUM_CHANNELS*c] =  lerp_3d(xw, yw, zw,
1912                                            tx00[c], tx01[c],
1913                                            tx02[c], tx03[c],
1914                                            tx10[c], tx11[c],
1915                                            tx12[c], tx13[c]);
1916 }
1917 
1918 
1919 /* Calculate level of detail for every fragment,
1920  * with lambda already computed.
1921  * Note that lambda has already been biased by global LOD bias.
1922  * \param biased_lambda per-quad lambda.
1923  * \param lod_in per-fragment lod_bias or explicit_lod.
1924  * \param lod returns the per-fragment lod.
1925  */
1926 static inline void
compute_lod(const struct pipe_sampler_state * sampler,enum tgsi_sampler_control control,const float biased_lambda,const float lod_in[TGSI_QUAD_SIZE],float lod[TGSI_QUAD_SIZE])1927 compute_lod(const struct pipe_sampler_state *sampler,
1928             enum tgsi_sampler_control control,
1929             const float biased_lambda,
1930             const float lod_in[TGSI_QUAD_SIZE],
1931             float lod[TGSI_QUAD_SIZE])
1932 {
1933    const float min_lod = sampler->min_lod;
1934    const float max_lod = sampler->max_lod;
1935    uint i;
1936 
1937    switch (control) {
1938    case TGSI_SAMPLER_LOD_NONE:
1939    case TGSI_SAMPLER_LOD_ZERO:
1940       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
1941       break;
1942    case TGSI_SAMPLER_DERIVS_EXPLICIT:
1943       for (i = 0; i < TGSI_QUAD_SIZE; i++)
1944          lod[i] = lod_in[i];
1945       break;
1946    case TGSI_SAMPLER_LOD_BIAS:
1947       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1948          lod[i] = biased_lambda + lod_in[i];
1949          lod[i] = CLAMP(lod[i], min_lod, max_lod);
1950       }
1951       break;
1952    case TGSI_SAMPLER_LOD_EXPLICIT:
1953       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1954          lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
1955       }
1956       break;
1957    default:
1958       assert(0);
1959       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
1960    }
1961 }
1962 
1963 
1964 /* Calculate level of detail for every fragment. The computed value is not
1965  * clamped to lod_min and lod_max.
1966  * \param lod_in per-fragment lod_bias or explicit_lod.
1967  * \param lod results per-fragment lod.
1968  */
1969 static inline void
compute_lambda_lod_unclamped(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],const float derivs[3][2][TGSI_QUAD_SIZE],const float lod_in[TGSI_QUAD_SIZE],enum tgsi_sampler_control control,float lod[TGSI_QUAD_SIZE])1970 compute_lambda_lod_unclamped(const struct sp_sampler_view *sp_sview,
1971                              const struct sp_sampler *sp_samp,
1972                              const float s[TGSI_QUAD_SIZE],
1973                              const float t[TGSI_QUAD_SIZE],
1974                              const float p[TGSI_QUAD_SIZE],
1975                              const float derivs[3][2][TGSI_QUAD_SIZE],
1976                              const float lod_in[TGSI_QUAD_SIZE],
1977                              enum tgsi_sampler_control control,
1978                              float lod[TGSI_QUAD_SIZE])
1979 {
1980    const struct pipe_sampler_state *sampler = &sp_samp->base;
1981    const float lod_bias = sampler->lod_bias;
1982    float lambda;
1983    uint i;
1984 
1985    switch (control) {
1986    case TGSI_SAMPLER_LOD_NONE:
1987       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
1988       lod[0] = lod[1] = lod[2] = lod[3] = lambda;
1989       break;
1990    case TGSI_SAMPLER_DERIVS_EXPLICIT:
1991       for (i = 0; i < TGSI_QUAD_SIZE; i++)
1992          lod[i] = sp_sview->compute_lambda_from_grad(sp_sview, derivs, i);
1993       break;
1994    case TGSI_SAMPLER_LOD_BIAS:
1995       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
1996       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1997          lod[i] = lambda + lod_in[i];
1998       }
1999       break;
2000    case TGSI_SAMPLER_LOD_EXPLICIT:
2001       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
2002          lod[i] = lod_in[i] + lod_bias;
2003       }
2004       break;
2005    case TGSI_SAMPLER_LOD_ZERO:
2006    case TGSI_SAMPLER_GATHER:
2007       lod[0] = lod[1] = lod[2] = lod[3] = lod_bias;
2008       break;
2009    default:
2010       assert(0);
2011       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
2012    }
2013 }
2014 
2015 /* Calculate level of detail for every fragment.
2016  * \param lod_in per-fragment lod_bias or explicit_lod.
2017  * \param lod results per-fragment lod.
2018  */
2019 static inline void
compute_lambda_lod(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],float derivs[3][2][TGSI_QUAD_SIZE],const float lod_in[TGSI_QUAD_SIZE],enum tgsi_sampler_control control,float lod[TGSI_QUAD_SIZE])2020 compute_lambda_lod(const struct sp_sampler_view *sp_sview,
2021                    const struct sp_sampler *sp_samp,
2022                    const float s[TGSI_QUAD_SIZE],
2023                    const float t[TGSI_QUAD_SIZE],
2024                    const float p[TGSI_QUAD_SIZE],
2025                    float derivs[3][2][TGSI_QUAD_SIZE],
2026                    const float lod_in[TGSI_QUAD_SIZE],
2027                    enum tgsi_sampler_control control,
2028                    float lod[TGSI_QUAD_SIZE])
2029 {
2030    const struct pipe_sampler_state *sampler = &sp_samp->base;
2031    const float min_lod = sampler->min_lod;
2032    const float max_lod = sampler->max_lod;
2033    int i;
2034 
2035    compute_lambda_lod_unclamped(sp_sview, sp_samp,
2036                                 s, t, p, derivs, lod_in, control, lod);
2037    for (i = 0; i < TGSI_QUAD_SIZE; i++) {
2038       lod[i] = CLAMP(lod[i], min_lod, max_lod);
2039    }
2040 }
2041 
2042 static inline unsigned
get_gather_component(const float lod_in[TGSI_QUAD_SIZE])2043 get_gather_component(const float lod_in[TGSI_QUAD_SIZE])
2044 {
2045    /* gather component is stored in lod_in slot as unsigned */
2046    return (*(unsigned int *)lod_in) & 0x3;
2047 }
2048 
2049 /**
2050  * Clamps given lod to both lod limits and mip level limits. Clamping to the
2051  * latter limits is done so that lod is relative to the first (base) level.
2052  */
2053 static void
clamp_lod(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float lod[TGSI_QUAD_SIZE],float clamped[TGSI_QUAD_SIZE])2054 clamp_lod(const struct sp_sampler_view *sp_sview,
2055           const struct sp_sampler *sp_samp,
2056           const float lod[TGSI_QUAD_SIZE],
2057           float clamped[TGSI_QUAD_SIZE])
2058 {
2059    const float min_lod = sp_samp->base.min_lod;
2060    const float max_lod = sp_samp->base.max_lod;
2061    const float min_level = sp_sview->base.u.tex.first_level;
2062    const float max_level = sp_sview->base.u.tex.last_level;
2063    int i;
2064 
2065    for (i = 0; i < TGSI_QUAD_SIZE; i++) {
2066       float cl = lod[i];
2067 
2068       cl = CLAMP(cl, min_lod, max_lod);
2069       cl = CLAMP(cl, 0, max_level - min_level);
2070       clamped[i] = cl;
2071    }
2072 }
2073 
2074 /**
2075  * Get mip level relative to base level for linear mip filter
2076  */
2077 static void
mip_rel_level_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float lod[TGSI_QUAD_SIZE],float level[TGSI_QUAD_SIZE])2078 mip_rel_level_linear(const struct sp_sampler_view *sp_sview,
2079                      const struct sp_sampler *sp_samp,
2080                      const float lod[TGSI_QUAD_SIZE],
2081                      float level[TGSI_QUAD_SIZE])
2082 {
2083    clamp_lod(sp_sview, sp_samp, lod, level);
2084 }
2085 
2086 static void
mip_filter_linear(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,img_filter_func min_filter,img_filter_func mag_filter,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],int gather_comp,const float lod[TGSI_QUAD_SIZE],const struct filter_args * filt_args,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2087 mip_filter_linear(const struct sp_sampler_view *sp_sview,
2088                   const struct sp_sampler *sp_samp,
2089                   img_filter_func min_filter,
2090                   img_filter_func mag_filter,
2091                   const float s[TGSI_QUAD_SIZE],
2092                   const float t[TGSI_QUAD_SIZE],
2093                   const float p[TGSI_QUAD_SIZE],
2094                   int gather_comp,
2095                   const float lod[TGSI_QUAD_SIZE],
2096                   const struct filter_args *filt_args,
2097                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2098 {
2099    const struct pipe_sampler_view *psview = &sp_sview->base;
2100    int j;
2101    struct img_filter_args args;
2102 
2103    args.offset = filt_args->offset;
2104    args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER;
2105    args.gather_comp = gather_comp;
2106 
2107    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2108       const int level0 = psview->u.tex.first_level + (int)lod[j];
2109 
2110       args.s = s[j];
2111       args.t = t[j];
2112       args.p = p[j];
2113       args.face_id = filt_args->faces[j];
2114 
2115       if (lod[j] <= 0.0 && !args.gather_only) {
2116          args.level = psview->u.tex.first_level;
2117          mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2118       }
2119       else if (level0 >= (int) psview->u.tex.last_level) {
2120          args.level = psview->u.tex.last_level;
2121          min_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2122       }
2123       else {
2124          float levelBlend = frac(lod[j]);
2125          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2126          int c;
2127 
2128          args.level = level0;
2129          min_filter(sp_sview, sp_samp, &args, &rgbax[0][0]);
2130          args.level = level0+1;
2131          min_filter(sp_sview, sp_samp, &args, &rgbax[0][1]);
2132 
2133          for (c = 0; c < 4; c++) {
2134             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
2135          }
2136       }
2137    }
2138 
2139    if (DEBUG_TEX) {
2140       print_sample_4(__FUNCTION__, rgba);
2141    }
2142 }
2143 
2144 
2145 /**
2146  * Get mip level relative to base level for nearest mip filter
2147  */
2148 static void
mip_rel_level_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float lod[TGSI_QUAD_SIZE],float level[TGSI_QUAD_SIZE])2149 mip_rel_level_nearest(const struct sp_sampler_view *sp_sview,
2150                       const struct sp_sampler *sp_samp,
2151                       const float lod[TGSI_QUAD_SIZE],
2152                       float level[TGSI_QUAD_SIZE])
2153 {
2154    int j;
2155 
2156    clamp_lod(sp_sview, sp_samp, lod, level);
2157    for (j = 0; j < TGSI_QUAD_SIZE; j++)
2158       /* TODO: It should rather be:
2159        * level[j] = ceil(level[j] + 0.5F) - 1.0F;
2160        */
2161       level[j] = (int)(level[j] + 0.5F);
2162 }
2163 
2164 /**
2165  * Compute nearest mipmap level from texcoords.
2166  * Then sample the texture level for four elements of a quad.
2167  * \param c0  the LOD bias factors, or absolute LODs (depending on control)
2168  */
2169 static void
mip_filter_nearest(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,img_filter_func min_filter,img_filter_func mag_filter,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],int gather_component,const float lod[TGSI_QUAD_SIZE],const struct filter_args * filt_args,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2170 mip_filter_nearest(const struct sp_sampler_view *sp_sview,
2171                    const struct sp_sampler *sp_samp,
2172                    img_filter_func min_filter,
2173                    img_filter_func mag_filter,
2174                    const float s[TGSI_QUAD_SIZE],
2175                    const float t[TGSI_QUAD_SIZE],
2176                    const float p[TGSI_QUAD_SIZE],
2177                    int gather_component,
2178                    const float lod[TGSI_QUAD_SIZE],
2179                    const struct filter_args *filt_args,
2180                    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2181 {
2182    const struct pipe_sampler_view *psview = &sp_sview->base;
2183    int j;
2184    struct img_filter_args args;
2185 
2186    args.offset = filt_args->offset;
2187    args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER;
2188    args.gather_comp = gather_component;
2189 
2190    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2191       args.s = s[j];
2192       args.t = t[j];
2193       args.p = p[j];
2194       args.face_id = filt_args->faces[j];
2195 
2196       if (lod[j] <= 0.0f && !args.gather_only) {
2197          args.level = psview->u.tex.first_level;
2198          mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2199       } else {
2200          const int level = psview->u.tex.first_level + (int)(lod[j] + 0.5F);
2201          args.level = MIN2(level, (int)psview->u.tex.last_level);
2202          min_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2203       }
2204    }
2205 
2206    if (DEBUG_TEX) {
2207       print_sample_4(__FUNCTION__, rgba);
2208    }
2209 }
2210 
2211 
2212 /**
2213  * Get mip level relative to base level for none mip filter
2214  */
2215 static void
mip_rel_level_none(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float lod[TGSI_QUAD_SIZE],float level[TGSI_QUAD_SIZE])2216 mip_rel_level_none(const struct sp_sampler_view *sp_sview,
2217                    const struct sp_sampler *sp_samp,
2218                    const float lod[TGSI_QUAD_SIZE],
2219                    float level[TGSI_QUAD_SIZE])
2220 {
2221    int j;
2222 
2223    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2224       level[j] = 0;
2225    }
2226 }
2227 
2228 static void
mip_filter_none(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,img_filter_func min_filter,img_filter_func mag_filter,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],int gather_component,const float lod[TGSI_QUAD_SIZE],const struct filter_args * filt_args,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2229 mip_filter_none(const struct sp_sampler_view *sp_sview,
2230                 const struct sp_sampler *sp_samp,
2231                 img_filter_func min_filter,
2232                 img_filter_func mag_filter,
2233                 const float s[TGSI_QUAD_SIZE],
2234                 const float t[TGSI_QUAD_SIZE],
2235                 const float p[TGSI_QUAD_SIZE],
2236                 int gather_component,
2237                 const float lod[TGSI_QUAD_SIZE],
2238                 const struct filter_args *filt_args,
2239                 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2240 {
2241    int j;
2242    struct img_filter_args args;
2243 
2244    args.level = sp_sview->base.u.tex.first_level;
2245    args.offset = filt_args->offset;
2246    args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER;
2247    args.gather_comp = gather_component;
2248 
2249    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2250       args.s = s[j];
2251       args.t = t[j];
2252       args.p = p[j];
2253       args.face_id = filt_args->faces[j];
2254       if (lod[j] <= 0.0f && !args.gather_only) {
2255          mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2256       }
2257       else {
2258          min_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2259       }
2260    }
2261 }
2262 
2263 
2264 /**
2265  * Get mip level relative to base level for none mip filter
2266  */
2267 static void
mip_rel_level_none_no_filter_select(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float lod[TGSI_QUAD_SIZE],float level[TGSI_QUAD_SIZE])2268 mip_rel_level_none_no_filter_select(const struct sp_sampler_view *sp_sview,
2269                                     const struct sp_sampler *sp_samp,
2270                                     const float lod[TGSI_QUAD_SIZE],
2271                                     float level[TGSI_QUAD_SIZE])
2272 {
2273    mip_rel_level_none(sp_sview, sp_samp, lod, level);
2274 }
2275 
2276 static void
mip_filter_none_no_filter_select(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,img_filter_func min_filter,img_filter_func mag_filter,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],int gather_comp,const float lod_in[TGSI_QUAD_SIZE],const struct filter_args * filt_args,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2277 mip_filter_none_no_filter_select(const struct sp_sampler_view *sp_sview,
2278                                  const struct sp_sampler *sp_samp,
2279                                  img_filter_func min_filter,
2280                                  img_filter_func mag_filter,
2281                                  const float s[TGSI_QUAD_SIZE],
2282                                  const float t[TGSI_QUAD_SIZE],
2283                                  const float p[TGSI_QUAD_SIZE],
2284                                  int gather_comp,
2285                                  const float lod_in[TGSI_QUAD_SIZE],
2286                                  const struct filter_args *filt_args,
2287                                  float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2288 {
2289    int j;
2290    struct img_filter_args args;
2291    args.level = sp_sview->base.u.tex.first_level;
2292    args.offset = filt_args->offset;
2293    args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER;
2294    args.gather_comp = gather_comp;
2295    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2296       args.s = s[j];
2297       args.t = t[j];
2298       args.p = p[j];
2299       args.face_id = filt_args->faces[j];
2300       mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2301    }
2302 }
2303 
2304 
2305 /* For anisotropic filtering */
2306 #define WEIGHT_LUT_SIZE 1024
2307 
2308 static const float *weightLut = NULL;
2309 
2310 /**
2311  * Creates the look-up table used to speed-up EWA sampling
2312  */
2313 static void
create_filter_table(void)2314 create_filter_table(void)
2315 {
2316    unsigned i;
2317    if (!weightLut) {
2318       float *lut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float));
2319 
2320       for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
2321          const float alpha = 2;
2322          const float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1);
2323          const float weight = (float) expf(-alpha * r2);
2324          lut[i] = weight;
2325       }
2326       weightLut = lut;
2327    }
2328 }
2329 
2330 
2331 /**
2332  * Elliptical weighted average (EWA) filter for producing high quality
2333  * anisotropic filtered results.
2334  * Based on the Higher Quality Elliptical Weighted Average Filter
2335  * published by Paul S. Heckbert in his Master's Thesis
2336  * "Fundamentals of Texture Mapping and Image Warping" (1989)
2337  */
2338 static void
img_filter_2d_ewa(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,img_filter_func min_filter,img_filter_func mag_filter,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],const uint faces[TGSI_QUAD_SIZE],const int8_t * offset,unsigned level,const float dudx,const float dvdx,const float dudy,const float dvdy,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2339 img_filter_2d_ewa(const struct sp_sampler_view *sp_sview,
2340                   const struct sp_sampler *sp_samp,
2341                   img_filter_func min_filter,
2342                   img_filter_func mag_filter,
2343                   const float s[TGSI_QUAD_SIZE],
2344                   const float t[TGSI_QUAD_SIZE],
2345                   const float p[TGSI_QUAD_SIZE],
2346                   const uint faces[TGSI_QUAD_SIZE],
2347                   const int8_t *offset,
2348                   unsigned level,
2349                   const float dudx, const float dvdx,
2350                   const float dudy, const float dvdy,
2351                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2352 {
2353    const struct pipe_resource *texture = sp_sview->base.texture;
2354 
2355    // ??? Won't the image filters blow up if level is negative?
2356    const unsigned level0 = level > 0 ? level : 0;
2357    const float scaling = 1.0f / (1 << level0);
2358    const int width = u_minify(texture->width0, level0);
2359    const int height = u_minify(texture->height0, level0);
2360    struct img_filter_args args;
2361    const float ux = dudx * scaling;
2362    const float vx = dvdx * scaling;
2363    const float uy = dudy * scaling;
2364    const float vy = dvdy * scaling;
2365 
2366    /* compute ellipse coefficients to bound the region:
2367     * A*x*x + B*x*y + C*y*y = F.
2368     */
2369    float A = vx*vx+vy*vy+1;
2370    float B = -2*(ux*vx+uy*vy);
2371    float C = ux*ux+uy*uy+1;
2372    float F = A*C-B*B/4.0f;
2373 
2374    /* check if it is an ellipse */
2375    /* assert(F > 0.0); */
2376 
2377    /* Compute the ellipse's (u,v) bounding box in texture space */
2378    const float d = -B*B+4.0f*C*A;
2379    const float box_u = 2.0f / d * sqrtf(d*C*F); /* box_u -> half of bbox with   */
2380    const float box_v = 2.0f / d * sqrtf(A*d*F); /* box_v -> half of bbox height */
2381 
2382    float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2383    float s_buffer[TGSI_QUAD_SIZE];
2384    float t_buffer[TGSI_QUAD_SIZE];
2385    float weight_buffer[TGSI_QUAD_SIZE];
2386    int j;
2387 
2388    /* Scale ellipse formula to directly index the Filter Lookup Table.
2389     * i.e. scale so that F = WEIGHT_LUT_SIZE-1
2390     */
2391    const double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
2392    A *= formScale;
2393    B *= formScale;
2394    C *= formScale;
2395    /* F *= formScale; */ /* no need to scale F as we don't use it below here */
2396 
2397    /* For each quad, the du and dx values are the same and so the ellipse is
2398     * also the same. Note that texel/image access can only be performed using
2399     * a quad, i.e. it is not possible to get the pixel value for a single
2400     * tex coord. In order to have a better performance, the access is buffered
2401     * using the s_buffer/t_buffer and weight_buffer. Only when the buffer is
2402     * full, then the pixel values are read from the image.
2403     */
2404    const float ddq = 2 * A;
2405 
2406    args.level = level;
2407    args.offset = offset;
2408 
2409    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2410       /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
2411        * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
2412        * value, q, is less than F, we're inside the ellipse
2413        */
2414       const float tex_u = -0.5F + s[j] * texture->width0 * scaling;
2415       const float tex_v = -0.5F + t[j] * texture->height0 * scaling;
2416 
2417       const int u0 = (int) floorf(tex_u - box_u);
2418       const int u1 = (int) ceilf(tex_u + box_u);
2419       const int v0 = (int) floorf(tex_v - box_v);
2420       const int v1 = (int) ceilf(tex_v + box_v);
2421       const float U = u0 - tex_u;
2422 
2423       float num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
2424       unsigned buffer_next = 0;
2425       float den = 0;
2426       int v;
2427       args.face_id = faces[j];
2428 
2429       for (v = v0; v <= v1; ++v) {
2430          const float V = v - tex_v;
2431          float dq = A * (2 * U + 1) + B * V;
2432          float q = (C * V + B * U) * V + A * U * U;
2433 
2434          int u;
2435          for (u = u0; u <= u1; ++u) {
2436             /* Note that the ellipse has been pre-scaled so F =
2437              * WEIGHT_LUT_SIZE - 1
2438              */
2439             if (q < WEIGHT_LUT_SIZE) {
2440                /* as a LUT is used, q must never be negative;
2441                 * should not happen, though
2442                 */
2443                const int qClamped = q >= 0.0F ? q : 0;
2444                const float weight = weightLut[qClamped];
2445 
2446                weight_buffer[buffer_next] = weight;
2447                s_buffer[buffer_next] = u / ((float) width);
2448                t_buffer[buffer_next] = v / ((float) height);
2449 
2450                buffer_next++;
2451                if (buffer_next == TGSI_QUAD_SIZE) {
2452                   /* 4 texel coords are in the buffer -> read it now */
2453                   unsigned jj;
2454                   /* it is assumed that samp->min_img_filter is set to
2455                    * img_filter_2d_nearest or one of the
2456                    * accelerated img_filter_2d_nearest_XXX functions.
2457                    */
2458                   for (jj = 0; jj < buffer_next; jj++) {
2459                      args.s = s_buffer[jj];
2460                      args.t = t_buffer[jj];
2461                      args.p = p[jj];
2462                      min_filter(sp_sview, sp_samp, &args, &rgba_temp[0][jj]);
2463                      num[0] += weight_buffer[jj] * rgba_temp[0][jj];
2464                      num[1] += weight_buffer[jj] * rgba_temp[1][jj];
2465                      num[2] += weight_buffer[jj] * rgba_temp[2][jj];
2466                      num[3] += weight_buffer[jj] * rgba_temp[3][jj];
2467                   }
2468 
2469                   buffer_next = 0;
2470                }
2471 
2472                den += weight;
2473             }
2474             q += dq;
2475             dq += ddq;
2476          }
2477       }
2478 
2479       /* if the tex coord buffer contains unread values, we will read
2480        * them now.
2481        */
2482       if (buffer_next > 0) {
2483          unsigned jj;
2484          /* it is assumed that samp->min_img_filter is set to
2485           * img_filter_2d_nearest or one of the
2486           * accelerated img_filter_2d_nearest_XXX functions.
2487           */
2488          for (jj = 0; jj < buffer_next; jj++) {
2489             args.s = s_buffer[jj];
2490             args.t = t_buffer[jj];
2491             args.p = p[jj];
2492             min_filter(sp_sview, sp_samp, &args, &rgba_temp[0][jj]);
2493             num[0] += weight_buffer[jj] * rgba_temp[0][jj];
2494             num[1] += weight_buffer[jj] * rgba_temp[1][jj];
2495             num[2] += weight_buffer[jj] * rgba_temp[2][jj];
2496             num[3] += weight_buffer[jj] * rgba_temp[3][jj];
2497          }
2498       }
2499 
2500       if (den <= 0.0F) {
2501          /* Reaching this place would mean that no pixels intersected
2502           * the ellipse.  This should never happen because the filter
2503           * we use always intersects at least one pixel.
2504           */
2505 
2506          /*rgba[0]=0;
2507          rgba[1]=0;
2508          rgba[2]=0;
2509          rgba[3]=0;*/
2510          /* not enough pixels in resampling, resort to direct interpolation */
2511          args.s = s[j];
2512          args.t = t[j];
2513          args.p = p[j];
2514          min_filter(sp_sview, sp_samp, &args, &rgba_temp[0][j]);
2515          den = 1;
2516          num[0] = rgba_temp[0][j];
2517          num[1] = rgba_temp[1][j];
2518          num[2] = rgba_temp[2][j];
2519          num[3] = rgba_temp[3][j];
2520       }
2521 
2522       rgba[0][j] = num[0] / den;
2523       rgba[1][j] = num[1] / den;
2524       rgba[2][j] = num[2] / den;
2525       rgba[3][j] = num[3] / den;
2526    }
2527 }
2528 
2529 
2530 /**
2531  * Get mip level relative to base level for linear mip filter
2532  */
2533 static void
mip_rel_level_linear_aniso(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float lod[TGSI_QUAD_SIZE],float level[TGSI_QUAD_SIZE])2534 mip_rel_level_linear_aniso(const struct sp_sampler_view *sp_sview,
2535                            const struct sp_sampler *sp_samp,
2536                            const float lod[TGSI_QUAD_SIZE],
2537                            float level[TGSI_QUAD_SIZE])
2538 {
2539    mip_rel_level_linear(sp_sview, sp_samp, lod, level);
2540 }
2541 
2542 /**
2543  * Sample 2D texture using an anisotropic filter.
2544  */
2545 static void
mip_filter_linear_aniso(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,img_filter_func min_filter,img_filter_func mag_filter,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],UNUSED int gather_comp,const float lod_in[TGSI_QUAD_SIZE],const struct filter_args * filt_args,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2546 mip_filter_linear_aniso(const struct sp_sampler_view *sp_sview,
2547                         const struct sp_sampler *sp_samp,
2548                         img_filter_func min_filter,
2549                         img_filter_func mag_filter,
2550                         const float s[TGSI_QUAD_SIZE],
2551                         const float t[TGSI_QUAD_SIZE],
2552                         const float p[TGSI_QUAD_SIZE],
2553                         UNUSED int gather_comp,
2554                         const float lod_in[TGSI_QUAD_SIZE],
2555                         const struct filter_args *filt_args,
2556                         float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2557 {
2558    const struct pipe_resource *texture = sp_sview->base.texture;
2559    const struct pipe_sampler_view *psview = &sp_sview->base;
2560    int level0;
2561    float lambda;
2562    float lod[TGSI_QUAD_SIZE];
2563 
2564    const float s_to_u = u_minify(texture->width0, psview->u.tex.first_level);
2565    const float t_to_v = u_minify(texture->height0, psview->u.tex.first_level);
2566    const float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
2567    const float dudy = (s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]) * s_to_u;
2568    const float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
2569    const float dvdy = (t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]) * t_to_v;
2570    struct img_filter_args args;
2571 
2572    args.offset = filt_args->offset;
2573 
2574    if (filt_args->control == TGSI_SAMPLER_LOD_BIAS ||
2575        filt_args->control == TGSI_SAMPLER_LOD_NONE ||
2576        /* XXX FIXME */
2577        filt_args->control == TGSI_SAMPLER_DERIVS_EXPLICIT) {
2578       /* note: instead of working with Px and Py, we will use the
2579        * squared length instead, to avoid sqrt.
2580        */
2581       const float Px2 = dudx * dudx + dvdx * dvdx;
2582       const float Py2 = dudy * dudy + dvdy * dvdy;
2583 
2584       float Pmax2;
2585       float Pmin2;
2586       float e;
2587       const float maxEccentricity = sp_samp->base.max_anisotropy * sp_samp->base.max_anisotropy;
2588 
2589       if (Px2 < Py2) {
2590          Pmax2 = Py2;
2591          Pmin2 = Px2;
2592       }
2593       else {
2594          Pmax2 = Px2;
2595          Pmin2 = Py2;
2596       }
2597 
2598       /* if the eccentricity of the ellipse is too big, scale up the shorter
2599        * of the two vectors to limit the maximum amount of work per pixel
2600        */
2601       e = Pmax2 / Pmin2;
2602       if (e > maxEccentricity) {
2603          /* float s=e / maxEccentricity;
2604             minor[0] *= s;
2605             minor[1] *= s;
2606             Pmin2 *= s; */
2607          Pmin2 = Pmax2 / maxEccentricity;
2608       }
2609 
2610       /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
2611        * this since 0.5*log(x) = log(sqrt(x))
2612        */
2613       lambda = 0.5F * util_fast_log2(Pmin2) + sp_samp->base.lod_bias;
2614       compute_lod(&sp_samp->base, filt_args->control, lambda, lod_in, lod);
2615    }
2616    else {
2617       assert(filt_args->control == TGSI_SAMPLER_LOD_EXPLICIT ||
2618              filt_args->control == TGSI_SAMPLER_LOD_ZERO);
2619       compute_lod(&sp_samp->base, filt_args->control, sp_samp->base.lod_bias, lod_in, lod);
2620    }
2621 
2622    /* XXX: Take into account all lod values.
2623     */
2624    lambda = lod[0];
2625    level0 = psview->u.tex.first_level + (int)lambda;
2626 
2627    /* If the ellipse covers the whole image, we can
2628     * simply return the average of the whole image.
2629     */
2630    if (level0 >= (int) psview->u.tex.last_level) {
2631       int j;
2632       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2633          args.s = s[j];
2634          args.t = t[j];
2635          args.p = p[j];
2636          args.level = psview->u.tex.last_level;
2637          args.face_id = filt_args->faces[j];
2638          /*
2639           * XXX: we overwrote any linear filter with nearest, so this
2640           * isn't right (albeit if last level is 1x1 and no border it
2641           * will work just the same).
2642           */
2643          min_filter(sp_sview, sp_samp, &args, &rgba[0][j]);
2644       }
2645    }
2646    else {
2647       /* don't bother interpolating between multiple LODs; it doesn't
2648        * seem to be worth the extra running time.
2649        */
2650       img_filter_2d_ewa(sp_sview, sp_samp, min_filter, mag_filter,
2651                         s, t, p, filt_args->faces, filt_args->offset,
2652                         level0, dudx, dvdx, dudy, dvdy, rgba);
2653    }
2654 
2655    if (DEBUG_TEX) {
2656       print_sample_4(__FUNCTION__, rgba);
2657    }
2658 }
2659 
2660 /**
2661  * Get mip level relative to base level for linear mip filter
2662  */
2663 static void
mip_rel_level_linear_2d_linear_repeat_POT(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float lod[TGSI_QUAD_SIZE],float level[TGSI_QUAD_SIZE])2664 mip_rel_level_linear_2d_linear_repeat_POT(
2665    const struct sp_sampler_view *sp_sview,
2666    const struct sp_sampler *sp_samp,
2667    const float lod[TGSI_QUAD_SIZE],
2668    float level[TGSI_QUAD_SIZE])
2669 {
2670    mip_rel_level_linear(sp_sview, sp_samp, lod, level);
2671 }
2672 
2673 /**
2674  * Specialized version of mip_filter_linear with hard-wired calls to
2675  * 2d lambda calculation and 2d_linear_repeat_POT img filters.
2676  */
2677 static void
mip_filter_linear_2d_linear_repeat_POT(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,img_filter_func min_filter,img_filter_func mag_filter,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],int gather_comp,const float lod[TGSI_QUAD_SIZE],const struct filter_args * filt_args,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2678 mip_filter_linear_2d_linear_repeat_POT(
2679    const struct sp_sampler_view *sp_sview,
2680    const struct sp_sampler *sp_samp,
2681    img_filter_func min_filter,
2682    img_filter_func mag_filter,
2683    const float s[TGSI_QUAD_SIZE],
2684    const float t[TGSI_QUAD_SIZE],
2685    const float p[TGSI_QUAD_SIZE],
2686    int gather_comp,
2687    const float lod[TGSI_QUAD_SIZE],
2688    const struct filter_args *filt_args,
2689    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2690 {
2691    const struct pipe_sampler_view *psview = &sp_sview->base;
2692    int j;
2693 
2694    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2695       const int level0 = psview->u.tex.first_level + (int)lod[j];
2696       struct img_filter_args args;
2697       /* Catches both negative and large values of level0:
2698        */
2699       args.s = s[j];
2700       args.t = t[j];
2701       args.p = p[j];
2702       args.face_id = filt_args->faces[j];
2703       args.offset = filt_args->offset;
2704       args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER;
2705       args.gather_comp = gather_comp;
2706       if ((unsigned)level0 >= psview->u.tex.last_level) {
2707          if (level0 < 0)
2708             args.level = psview->u.tex.first_level;
2709          else
2710             args.level = psview->u.tex.last_level;
2711          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, &args,
2712                                          &rgba[0][j]);
2713 
2714       }
2715       else {
2716          const float levelBlend = frac(lod[j]);
2717          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2718          int c;
2719 
2720          args.level = level0;
2721          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, &args, &rgbax[0][0]);
2722          args.level = level0+1;
2723          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, &args, &rgbax[0][1]);
2724 
2725          for (c = 0; c < TGSI_NUM_CHANNELS; c++)
2726             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
2727       }
2728    }
2729 
2730    if (DEBUG_TEX) {
2731       print_sample_4(__FUNCTION__, rgba);
2732    }
2733 }
2734 
2735 static const struct sp_filter_funcs funcs_linear = {
2736    mip_rel_level_linear,
2737    mip_filter_linear
2738 };
2739 
2740 static const struct sp_filter_funcs funcs_nearest = {
2741    mip_rel_level_nearest,
2742    mip_filter_nearest
2743 };
2744 
2745 static const struct sp_filter_funcs funcs_none = {
2746    mip_rel_level_none,
2747    mip_filter_none
2748 };
2749 
2750 static const struct sp_filter_funcs funcs_none_no_filter_select = {
2751    mip_rel_level_none_no_filter_select,
2752    mip_filter_none_no_filter_select
2753 };
2754 
2755 static const struct sp_filter_funcs funcs_linear_aniso = {
2756    mip_rel_level_linear_aniso,
2757    mip_filter_linear_aniso
2758 };
2759 
2760 static const struct sp_filter_funcs funcs_linear_2d_linear_repeat_POT = {
2761    mip_rel_level_linear_2d_linear_repeat_POT,
2762    mip_filter_linear_2d_linear_repeat_POT
2763 };
2764 
2765 /**
2766  * Do shadow/depth comparisons.
2767  */
2768 static void
sample_compare(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float c0[TGSI_QUAD_SIZE],enum tgsi_sampler_control control,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2769 sample_compare(const struct sp_sampler_view *sp_sview,
2770                const struct sp_sampler *sp_samp,
2771                const float c0[TGSI_QUAD_SIZE],
2772                enum tgsi_sampler_control control,
2773                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2774 {
2775    const struct pipe_sampler_state *sampler = &sp_samp->base;
2776    int j, v;
2777    int k[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2778    float pc[4];
2779    const struct util_format_description *format_desc =
2780       util_format_description(sp_sview->base.format);
2781    /* not entirely sure we couldn't end up with non-valid swizzle here */
2782    const unsigned chan_type =
2783       format_desc->swizzle[0] <= PIPE_SWIZZLE_W ?
2784       format_desc->channel[format_desc->swizzle[0]].type :
2785       UTIL_FORMAT_TYPE_FLOAT;
2786    const bool is_gather = (control == TGSI_SAMPLER_GATHER);
2787 
2788    /**
2789     * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
2790     * for 2D Array texture we need to use the 'c0' (aka Q).
2791     * When we sampled the depth texture, the depth value was put into all
2792     * RGBA channels.  We look at the red channel here.
2793     */
2794 
2795 
2796 
2797    if (chan_type != UTIL_FORMAT_TYPE_FLOAT) {
2798       /*
2799        * clamping is a result of conversion to texture format, hence
2800        * doesn't happen with floats. Technically also should do comparison
2801        * in texture format (quantization!).
2802        */
2803       pc[0] = CLAMP(c0[0], 0.0F, 1.0F);
2804       pc[1] = CLAMP(c0[1], 0.0F, 1.0F);
2805       pc[2] = CLAMP(c0[2], 0.0F, 1.0F);
2806       pc[3] = CLAMP(c0[3], 0.0F, 1.0F);
2807    } else {
2808       pc[0] = c0[0];
2809       pc[1] = c0[1];
2810       pc[2] = c0[2];
2811       pc[3] = c0[3];
2812    }
2813 
2814    for (v = 0; v < (is_gather ? TGSI_NUM_CHANNELS : 1); v++) {
2815       /* compare four texcoords vs. four texture samples */
2816       switch (sampler->compare_func) {
2817       case PIPE_FUNC_LESS:
2818          k[v][0] = pc[0] < rgba[v][0];
2819          k[v][1] = pc[1] < rgba[v][1];
2820          k[v][2] = pc[2] < rgba[v][2];
2821          k[v][3] = pc[3] < rgba[v][3];
2822          break;
2823       case PIPE_FUNC_LEQUAL:
2824          k[v][0] = pc[0] <= rgba[v][0];
2825          k[v][1] = pc[1] <= rgba[v][1];
2826          k[v][2] = pc[2] <= rgba[v][2];
2827          k[v][3] = pc[3] <= rgba[v][3];
2828          break;
2829       case PIPE_FUNC_GREATER:
2830          k[v][0] = pc[0] > rgba[v][0];
2831          k[v][1] = pc[1] > rgba[v][1];
2832          k[v][2] = pc[2] > rgba[v][2];
2833          k[v][3] = pc[3] > rgba[v][3];
2834          break;
2835       case PIPE_FUNC_GEQUAL:
2836          k[v][0] = pc[0] >= rgba[v][0];
2837          k[v][1] = pc[1] >= rgba[v][1];
2838          k[v][2] = pc[2] >= rgba[v][2];
2839          k[v][3] = pc[3] >= rgba[v][3];
2840          break;
2841       case PIPE_FUNC_EQUAL:
2842          k[v][0] = pc[0] == rgba[v][0];
2843          k[v][1] = pc[1] == rgba[v][1];
2844          k[v][2] = pc[2] == rgba[v][2];
2845          k[v][3] = pc[3] == rgba[v][3];
2846          break;
2847       case PIPE_FUNC_NOTEQUAL:
2848          k[v][0] = pc[0] != rgba[v][0];
2849          k[v][1] = pc[1] != rgba[v][1];
2850          k[v][2] = pc[2] != rgba[v][2];
2851          k[v][3] = pc[3] != rgba[v][3];
2852          break;
2853       case PIPE_FUNC_ALWAYS:
2854          k[v][0] = k[v][1] = k[v][2] = k[v][3] = 1;
2855          break;
2856       case PIPE_FUNC_NEVER:
2857          k[v][0] = k[v][1] = k[v][2] = k[v][3] = 0;
2858          break;
2859       default:
2860          k[v][0] = k[v][1] = k[v][2] = k[v][3] = 0;
2861          assert(0);
2862          break;
2863       }
2864    }
2865 
2866    if (is_gather) {
2867       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2868          for (v = 0; v < TGSI_NUM_CHANNELS; v++) {
2869             rgba[v][j] = k[v][j];
2870          }
2871       }
2872    } else {
2873       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2874          rgba[0][j] = k[0][j];
2875          rgba[1][j] = k[0][j];
2876          rgba[2][j] = k[0][j];
2877          rgba[3][j] = 1.0F;
2878       }
2879    }
2880 }
2881 
2882 static void
do_swizzling(const struct pipe_sampler_view * sview,float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])2883 do_swizzling(const struct pipe_sampler_view *sview,
2884              float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
2885              float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2886 {
2887    struct sp_sampler_view *sp_sview = (struct sp_sampler_view *)sview;
2888    int j;
2889    const unsigned swizzle_r = sview->swizzle_r;
2890    const unsigned swizzle_g = sview->swizzle_g;
2891    const unsigned swizzle_b = sview->swizzle_b;
2892    const unsigned swizzle_a = sview->swizzle_a;
2893 
2894    switch (swizzle_r) {
2895    case PIPE_SWIZZLE_0:
2896       for (j = 0; j < 4; j++)
2897          out[0][j] = 0.0f;
2898       break;
2899    case PIPE_SWIZZLE_1:
2900       for (j = 0; j < 4; j++)
2901          out[0][j] = sp_sview->oneval;
2902       break;
2903    default:
2904       assert(swizzle_r < 4);
2905       for (j = 0; j < 4; j++)
2906          out[0][j] = in[swizzle_r][j];
2907    }
2908 
2909    switch (swizzle_g) {
2910    case PIPE_SWIZZLE_0:
2911       for (j = 0; j < 4; j++)
2912          out[1][j] = 0.0f;
2913       break;
2914    case PIPE_SWIZZLE_1:
2915       for (j = 0; j < 4; j++)
2916          out[1][j] = sp_sview->oneval;
2917       break;
2918    default:
2919       assert(swizzle_g < 4);
2920       for (j = 0; j < 4; j++)
2921          out[1][j] = in[swizzle_g][j];
2922    }
2923 
2924    switch (swizzle_b) {
2925    case PIPE_SWIZZLE_0:
2926       for (j = 0; j < 4; j++)
2927          out[2][j] = 0.0f;
2928       break;
2929    case PIPE_SWIZZLE_1:
2930       for (j = 0; j < 4; j++)
2931          out[2][j] = sp_sview->oneval;
2932       break;
2933    default:
2934       assert(swizzle_b < 4);
2935       for (j = 0; j < 4; j++)
2936          out[2][j] = in[swizzle_b][j];
2937    }
2938 
2939    switch (swizzle_a) {
2940    case PIPE_SWIZZLE_0:
2941       for (j = 0; j < 4; j++)
2942          out[3][j] = 0.0f;
2943       break;
2944    case PIPE_SWIZZLE_1:
2945       for (j = 0; j < 4; j++)
2946          out[3][j] = sp_sview->oneval;
2947       break;
2948    default:
2949       assert(swizzle_a < 4);
2950       for (j = 0; j < 4; j++)
2951          out[3][j] = in[swizzle_a][j];
2952    }
2953 }
2954 
2955 
2956 static wrap_nearest_func
get_nearest_unorm_wrap(unsigned mode)2957 get_nearest_unorm_wrap(unsigned mode)
2958 {
2959    switch (mode) {
2960    case PIPE_TEX_WRAP_CLAMP:
2961       return wrap_nearest_unorm_clamp;
2962    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2963       return wrap_nearest_unorm_clamp_to_edge;
2964    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2965       return wrap_nearest_unorm_clamp_to_border;
2966    default:
2967       debug_printf("illegal wrap mode %d with non-normalized coords\n", mode);
2968       return wrap_nearest_unorm_clamp;
2969    }
2970 }
2971 
2972 
2973 static wrap_nearest_func
get_nearest_wrap(unsigned mode)2974 get_nearest_wrap(unsigned mode)
2975 {
2976    switch (mode) {
2977    case PIPE_TEX_WRAP_REPEAT:
2978       return wrap_nearest_repeat;
2979    case PIPE_TEX_WRAP_CLAMP:
2980       return wrap_nearest_clamp;
2981    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2982       return wrap_nearest_clamp_to_edge;
2983    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2984       return wrap_nearest_clamp_to_border;
2985    case PIPE_TEX_WRAP_MIRROR_REPEAT:
2986       return wrap_nearest_mirror_repeat;
2987    case PIPE_TEX_WRAP_MIRROR_CLAMP:
2988       return wrap_nearest_mirror_clamp;
2989    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
2990       return wrap_nearest_mirror_clamp_to_edge;
2991    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
2992       return wrap_nearest_mirror_clamp_to_border;
2993    default:
2994       assert(0);
2995       return wrap_nearest_repeat;
2996    }
2997 }
2998 
2999 
3000 static wrap_linear_func
get_linear_unorm_wrap(unsigned mode)3001 get_linear_unorm_wrap(unsigned mode)
3002 {
3003    switch (mode) {
3004    case PIPE_TEX_WRAP_CLAMP:
3005       return wrap_linear_unorm_clamp;
3006    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
3007       return wrap_linear_unorm_clamp_to_edge;
3008    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
3009       return wrap_linear_unorm_clamp_to_border;
3010    default:
3011       debug_printf("illegal wrap mode %d with non-normalized coords\n", mode);
3012       return wrap_linear_unorm_clamp;
3013    }
3014 }
3015 
3016 
3017 static wrap_linear_func
get_linear_wrap(unsigned mode)3018 get_linear_wrap(unsigned mode)
3019 {
3020    switch (mode) {
3021    case PIPE_TEX_WRAP_REPEAT:
3022       return wrap_linear_repeat;
3023    case PIPE_TEX_WRAP_CLAMP:
3024       return wrap_linear_clamp;
3025    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
3026       return wrap_linear_clamp_to_edge;
3027    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
3028       return wrap_linear_clamp_to_border;
3029    case PIPE_TEX_WRAP_MIRROR_REPEAT:
3030       return wrap_linear_mirror_repeat;
3031    case PIPE_TEX_WRAP_MIRROR_CLAMP:
3032       return wrap_linear_mirror_clamp;
3033    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
3034       return wrap_linear_mirror_clamp_to_edge;
3035    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
3036       return wrap_linear_mirror_clamp_to_border;
3037    default:
3038       assert(0);
3039       return wrap_linear_repeat;
3040    }
3041 }
3042 
3043 
3044 /**
3045  * Is swizzling needed for the given state key?
3046  */
3047 static inline bool
any_swizzle(const struct pipe_sampler_view * view)3048 any_swizzle(const struct pipe_sampler_view *view)
3049 {
3050    return (view->swizzle_r != PIPE_SWIZZLE_X ||
3051            view->swizzle_g != PIPE_SWIZZLE_Y ||
3052            view->swizzle_b != PIPE_SWIZZLE_Z ||
3053            view->swizzle_a != PIPE_SWIZZLE_W);
3054 }
3055 
3056 
3057 static img_filter_func
get_img_filter(const struct sp_sampler_view * sp_sview,const struct pipe_sampler_state * sampler,unsigned filter,bool gather)3058 get_img_filter(const struct sp_sampler_view *sp_sview,
3059                const struct pipe_sampler_state *sampler,
3060                unsigned filter, bool gather)
3061 {
3062    switch (sp_sview->base.target) {
3063    case PIPE_BUFFER:
3064    case PIPE_TEXTURE_1D:
3065       if (filter == PIPE_TEX_FILTER_NEAREST)
3066          return img_filter_1d_nearest;
3067       else
3068          return img_filter_1d_linear;
3069       break;
3070    case PIPE_TEXTURE_1D_ARRAY:
3071       if (filter == PIPE_TEX_FILTER_NEAREST)
3072          return img_filter_1d_array_nearest;
3073       else
3074          return img_filter_1d_array_linear;
3075       break;
3076    case PIPE_TEXTURE_2D:
3077    case PIPE_TEXTURE_RECT:
3078       /* Try for fast path:
3079        */
3080       if (!gather && sp_sview->pot2d &&
3081           sampler->wrap_s == sampler->wrap_t &&
3082           sampler->normalized_coords)
3083       {
3084          switch (sampler->wrap_s) {
3085          case PIPE_TEX_WRAP_REPEAT:
3086             switch (filter) {
3087             case PIPE_TEX_FILTER_NEAREST:
3088                return img_filter_2d_nearest_repeat_POT;
3089             case PIPE_TEX_FILTER_LINEAR:
3090                return img_filter_2d_linear_repeat_POT;
3091             default:
3092                break;
3093             }
3094             break;
3095          case PIPE_TEX_WRAP_CLAMP:
3096             switch (filter) {
3097             case PIPE_TEX_FILTER_NEAREST:
3098                return img_filter_2d_nearest_clamp_POT;
3099             default:
3100                break;
3101             }
3102          }
3103       }
3104       /* Otherwise use default versions:
3105        */
3106       if (filter == PIPE_TEX_FILTER_NEAREST)
3107          return img_filter_2d_nearest;
3108       else
3109          return img_filter_2d_linear;
3110       break;
3111    case PIPE_TEXTURE_2D_ARRAY:
3112       if (filter == PIPE_TEX_FILTER_NEAREST)
3113          return img_filter_2d_array_nearest;
3114       else
3115          return img_filter_2d_array_linear;
3116       break;
3117    case PIPE_TEXTURE_CUBE:
3118       if (filter == PIPE_TEX_FILTER_NEAREST)
3119          return img_filter_cube_nearest;
3120       else
3121          return img_filter_cube_linear;
3122       break;
3123    case PIPE_TEXTURE_CUBE_ARRAY:
3124       if (filter == PIPE_TEX_FILTER_NEAREST)
3125          return img_filter_cube_array_nearest;
3126       else
3127          return img_filter_cube_array_linear;
3128       break;
3129    case PIPE_TEXTURE_3D:
3130       if (filter == PIPE_TEX_FILTER_NEAREST)
3131          return img_filter_3d_nearest;
3132       else
3133          return img_filter_3d_linear;
3134       break;
3135    default:
3136       assert(0);
3137       return img_filter_1d_nearest;
3138    }
3139 }
3140 
3141 /**
3142  * Get mip filter funcs, and optionally both img min filter and img mag
3143  * filter. Note that both img filter function pointers must be either non-NULL
3144  * or NULL.
3145  */
3146 static void
get_filters(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const enum tgsi_sampler_control control,const struct sp_filter_funcs ** funcs,img_filter_func * min,img_filter_func * mag)3147 get_filters(const struct sp_sampler_view *sp_sview,
3148             const struct sp_sampler *sp_samp,
3149             const enum tgsi_sampler_control control,
3150             const struct sp_filter_funcs **funcs,
3151             img_filter_func *min,
3152             img_filter_func *mag)
3153 {
3154    assert(funcs);
3155    if (control == TGSI_SAMPLER_GATHER) {
3156       *funcs = &funcs_nearest;
3157       if (min) {
3158          *min = get_img_filter(sp_sview, &sp_samp->base,
3159                                PIPE_TEX_FILTER_LINEAR, true);
3160       }
3161    } else if (sp_sview->pot2d & sp_samp->min_mag_equal_repeat_linear) {
3162       *funcs = &funcs_linear_2d_linear_repeat_POT;
3163    } else {
3164       *funcs = sp_samp->filter_funcs;
3165       if (min) {
3166          assert(mag);
3167          *min = get_img_filter(sp_sview, &sp_samp->base,
3168                                sp_samp->min_img_filter, false);
3169          if (sp_samp->min_mag_equal) {
3170             *mag = *min;
3171          } else {
3172             *mag = get_img_filter(sp_sview, &sp_samp->base,
3173                                   sp_samp->base.mag_img_filter, false);
3174          }
3175       }
3176    }
3177 }
3178 
3179 static void
sample_mip(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],const float c0[TGSI_QUAD_SIZE],int gather_comp,const float lod[TGSI_QUAD_SIZE],const struct filter_args * filt_args,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])3180 sample_mip(const struct sp_sampler_view *sp_sview,
3181            const struct sp_sampler *sp_samp,
3182            const float s[TGSI_QUAD_SIZE],
3183            const float t[TGSI_QUAD_SIZE],
3184            const float p[TGSI_QUAD_SIZE],
3185            const float c0[TGSI_QUAD_SIZE],
3186            int gather_comp,
3187            const float lod[TGSI_QUAD_SIZE],
3188            const struct filter_args *filt_args,
3189            float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3190 {
3191    const struct sp_filter_funcs *funcs = NULL;
3192    img_filter_func min_img_filter = NULL;
3193    img_filter_func mag_img_filter = NULL;
3194 
3195    get_filters(sp_sview, sp_samp, filt_args->control,
3196                &funcs, &min_img_filter, &mag_img_filter);
3197 
3198    funcs->filter(sp_sview, sp_samp, min_img_filter, mag_img_filter,
3199                  s, t, p, gather_comp, lod, filt_args, rgba);
3200 
3201    if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) {
3202       sample_compare(sp_sview, sp_samp, c0, filt_args->control, rgba);
3203    }
3204 
3205    if (sp_sview->need_swizzle && filt_args->control != TGSI_SAMPLER_GATHER) {
3206       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
3207       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
3208       do_swizzling(&sp_sview->base, rgba_temp, rgba);
3209    }
3210 
3211 }
3212 
3213 
3214 /**
3215  * This function uses cube texture coordinates to choose a face of a cube and
3216  * computes the 2D cube face coordinates. Puts face info into the sampler
3217  * faces[] array.
3218  */
3219 static void
convert_cube(const struct sp_sampler_view * sp_sview,const struct sp_sampler * sp_samp,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],const float c0[TGSI_QUAD_SIZE],float ssss[TGSI_QUAD_SIZE],float tttt[TGSI_QUAD_SIZE],float pppp[TGSI_QUAD_SIZE],uint faces[TGSI_QUAD_SIZE])3220 convert_cube(const struct sp_sampler_view *sp_sview,
3221              const struct sp_sampler *sp_samp,
3222              const float s[TGSI_QUAD_SIZE],
3223              const float t[TGSI_QUAD_SIZE],
3224              const float p[TGSI_QUAD_SIZE],
3225              const float c0[TGSI_QUAD_SIZE],
3226              float ssss[TGSI_QUAD_SIZE],
3227              float tttt[TGSI_QUAD_SIZE],
3228              float pppp[TGSI_QUAD_SIZE],
3229              uint faces[TGSI_QUAD_SIZE])
3230 {
3231    unsigned j;
3232 
3233    pppp[0] = c0[0];
3234    pppp[1] = c0[1];
3235    pppp[2] = c0[2];
3236    pppp[3] = c0[3];
3237    /*
3238      major axis
3239      direction    target                             sc     tc    ma
3240      ----------   -------------------------------    ---    ---   ---
3241      +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
3242      -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
3243      +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
3244      -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
3245      +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
3246      -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
3247    */
3248 
3249    /* Choose the cube face and compute new s/t coords for the 2D face.
3250     *
3251     * Use the same cube face for all four pixels in the quad.
3252     *
3253     * This isn't ideal, but if we want to use a different cube face
3254     * per pixel in the quad, we'd have to also compute the per-face
3255     * LOD here too.  That's because the four post-face-selection
3256     * texcoords are no longer related to each other (they're
3257     * per-face!)  so we can't use subtraction to compute the partial
3258     * deriviates to compute the LOD.  Doing so (near cube edges
3259     * anyway) gives us pretty much random values.
3260     */
3261    for (j = 0; j < TGSI_QUAD_SIZE; j++)  {
3262       const float rx = s[j], ry = t[j], rz = p[j];
3263       const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
3264 
3265       if (arx >= ary && arx >= arz) {
3266          const float sign = (rx >= 0.0F) ? 1.0F : -1.0F;
3267          const uint face = (rx >= 0.0F) ?
3268             PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X;
3269          const float ima = -0.5F / fabsf(s[j]);
3270          ssss[j] = sign *  p[j] * ima + 0.5F;
3271          tttt[j] =         t[j] * ima + 0.5F;
3272          faces[j] = face;
3273       }
3274       else if (ary >= arx && ary >= arz) {
3275          const float sign = (ry >= 0.0F) ? 1.0F : -1.0F;
3276          const uint face = (ry >= 0.0F) ?
3277             PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y;
3278          const float ima = -0.5F / fabsf(t[j]);
3279          ssss[j] =        -s[j] * ima + 0.5F;
3280          tttt[j] = sign * -p[j] * ima + 0.5F;
3281          faces[j] = face;
3282       }
3283       else {
3284          const float sign = (rz >= 0.0F) ? 1.0F : -1.0F;
3285          const uint face = (rz >= 0.0F) ?
3286             PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z;
3287          const float ima = -0.5F / fabsf(p[j]);
3288          ssss[j] = sign * -s[j] * ima + 0.5F;
3289          tttt[j] =         t[j] * ima + 0.5F;
3290          faces[j] = face;
3291       }
3292    }
3293 }
3294 
3295 
3296 static void
sp_get_dims(const struct sp_sampler_view * sp_sview,int level,int dims[4])3297 sp_get_dims(const struct sp_sampler_view *sp_sview,
3298             int level,
3299             int dims[4])
3300 {
3301    const struct pipe_sampler_view *view = &sp_sview->base;
3302    const struct pipe_resource *texture = view->texture;
3303 
3304    if (view->target == PIPE_BUFFER) {
3305       dims[0] = view->u.buf.size / util_format_get_blocksize(view->format);
3306       /* the other values are undefined, but let's avoid potential valgrind
3307        * warnings.
3308        */
3309       dims[1] = dims[2] = dims[3] = 0;
3310       return;
3311    }
3312 
3313    /* undefined according to EXT_gpu_program */
3314    level += view->u.tex.first_level;
3315    if (level > view->u.tex.last_level)
3316       return;
3317 
3318    dims[3] = view->u.tex.last_level - view->u.tex.first_level + 1;
3319    dims[0] = u_minify(texture->width0, level);
3320 
3321    switch (view->target) {
3322    case PIPE_TEXTURE_1D_ARRAY:
3323       dims[1] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
3324       FALLTHROUGH;
3325    case PIPE_TEXTURE_1D:
3326       return;
3327    case PIPE_TEXTURE_2D_ARRAY:
3328       dims[2] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
3329       FALLTHROUGH;
3330    case PIPE_TEXTURE_2D:
3331    case PIPE_TEXTURE_CUBE:
3332    case PIPE_TEXTURE_RECT:
3333       dims[1] = u_minify(texture->height0, level);
3334       return;
3335    case PIPE_TEXTURE_3D:
3336       dims[1] = u_minify(texture->height0, level);
3337       dims[2] = u_minify(texture->depth0, level);
3338       return;
3339    case PIPE_TEXTURE_CUBE_ARRAY:
3340       dims[1] = u_minify(texture->height0, level);
3341       dims[2] = (view->u.tex.last_layer - view->u.tex.first_layer + 1) / 6;
3342       break;
3343    default:
3344       assert(!"unexpected texture target in sp_get_dims()");
3345       return;
3346    }
3347 }
3348 
3349 /**
3350  * This function is only used for getting unfiltered texels via the
3351  * TXF opcode.  The GL spec says that out-of-bounds texel fetches
3352  * produce undefined results.  Instead of crashing, lets just clamp
3353  * coords to the texture image size.
3354  */
3355 static void
sp_get_texels(const struct sp_sampler_view * sp_sview,const int v_i[TGSI_QUAD_SIZE],const int v_j[TGSI_QUAD_SIZE],const int v_k[TGSI_QUAD_SIZE],const int lod[TGSI_QUAD_SIZE],const int8_t offset[3],float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])3356 sp_get_texels(const struct sp_sampler_view *sp_sview,
3357               const int v_i[TGSI_QUAD_SIZE],
3358               const int v_j[TGSI_QUAD_SIZE],
3359               const int v_k[TGSI_QUAD_SIZE],
3360               const int lod[TGSI_QUAD_SIZE],
3361               const int8_t offset[3],
3362               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3363 {
3364    union tex_tile_address addr;
3365    const struct pipe_resource *texture = sp_sview->base.texture;
3366    int j, c;
3367    const float *tx;
3368    /* TODO write a better test for LOD */
3369    const unsigned level =
3370       sp_sview->base.target == PIPE_BUFFER ? 0 :
3371       CLAMP(lod[0] + sp_sview->base.u.tex.first_level,
3372             sp_sview->base.u.tex.first_level,
3373             sp_sview->base.u.tex.last_level);
3374    const int width = u_minify(texture->width0, level);
3375    const int height = u_minify(texture->height0, level);
3376    const int depth = u_minify(texture->depth0, level);
3377    unsigned elem_size, first_element, last_element;
3378 
3379    addr.value = 0;
3380    addr.bits.level = level;
3381 
3382    switch (sp_sview->base.target) {
3383    case PIPE_BUFFER:
3384       elem_size = util_format_get_blocksize(sp_sview->base.format);
3385       first_element = sp_sview->base.u.buf.offset / elem_size;
3386       last_element = (sp_sview->base.u.buf.offset +
3387                       sp_sview->base.u.buf.size) / elem_size - 1;
3388       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
3389          const int x = CLAMP(v_i[j] + offset[0] +
3390                              first_element,
3391                              first_element,
3392                              last_element);
3393          tx = get_texel_buffer_no_border(sp_sview, addr, x, elem_size);
3394          for (c = 0; c < 4; c++) {
3395             rgba[c][j] = tx[c];
3396          }
3397       }
3398       break;
3399    case PIPE_TEXTURE_1D:
3400       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
3401          const int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
3402          tx = get_texel_2d_no_border(sp_sview, addr, x,
3403                                      sp_sview->base.u.tex.first_layer);
3404          for (c = 0; c < 4; c++) {
3405             rgba[c][j] = tx[c];
3406          }
3407       }
3408       break;
3409    case PIPE_TEXTURE_1D_ARRAY:
3410       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
3411          const int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
3412          const int y = CLAMP(v_j[j], sp_sview->base.u.tex.first_layer,
3413                              sp_sview->base.u.tex.last_layer);
3414          tx = get_texel_2d_no_border(sp_sview, addr, x, y);
3415          for (c = 0; c < 4; c++) {
3416             rgba[c][j] = tx[c];
3417          }
3418       }
3419       break;
3420    case PIPE_TEXTURE_2D:
3421    case PIPE_TEXTURE_RECT:
3422       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
3423          const int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
3424          const int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
3425          tx = get_texel_3d_no_border(sp_sview, addr, x, y,
3426                                      sp_sview->base.u.tex.first_layer);
3427          for (c = 0; c < 4; c++) {
3428             rgba[c][j] = tx[c];
3429          }
3430       }
3431       break;
3432    case PIPE_TEXTURE_2D_ARRAY:
3433       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
3434          const int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
3435          const int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
3436          const int layer = CLAMP(v_k[j], sp_sview->base.u.tex.first_layer,
3437                                  sp_sview->base.u.tex.last_layer);
3438          tx = get_texel_3d_no_border(sp_sview, addr, x, y, layer);
3439          for (c = 0; c < 4; c++) {
3440             rgba[c][j] = tx[c];
3441          }
3442       }
3443       break;
3444    case PIPE_TEXTURE_3D:
3445       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
3446          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
3447          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
3448          int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
3449          tx = get_texel_3d_no_border(sp_sview, addr, x, y, z);
3450          for (c = 0; c < 4; c++) {
3451             rgba[c][j] = tx[c];
3452          }
3453       }
3454       break;
3455    case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */
3456    case PIPE_TEXTURE_CUBE_ARRAY:
3457    default:
3458       assert(!"Unknown or CUBE texture type in TXF processing\n");
3459       break;
3460    }
3461 
3462    if (sp_sview->need_swizzle) {
3463       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
3464       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
3465       do_swizzling(&sp_sview->base, rgba_temp, rgba);
3466    }
3467 }
3468 
3469 
3470 void *
softpipe_create_sampler_state(struct pipe_context * pipe,const struct pipe_sampler_state * sampler)3471 softpipe_create_sampler_state(struct pipe_context *pipe,
3472                               const struct pipe_sampler_state *sampler)
3473 {
3474    struct sp_sampler *samp = CALLOC_STRUCT(sp_sampler);
3475 
3476    samp->base = *sampler;
3477 
3478    /* Note that (for instance) linear_texcoord_s and
3479     * nearest_texcoord_s may be active at the same time, if the
3480     * sampler min_img_filter differs from its mag_img_filter.
3481     */
3482    if (sampler->normalized_coords) {
3483       samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
3484       samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
3485       samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
3486 
3487       samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
3488       samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
3489       samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
3490    }
3491    else {
3492       samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
3493       samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
3494       samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
3495 
3496       samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
3497       samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
3498       samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
3499    }
3500 
3501    samp->min_img_filter = sampler->min_img_filter;
3502 
3503    switch (sampler->min_mip_filter) {
3504    case PIPE_TEX_MIPFILTER_NONE:
3505       if (sampler->min_img_filter == sampler->mag_img_filter)
3506          samp->filter_funcs = &funcs_none_no_filter_select;
3507       else
3508          samp->filter_funcs = &funcs_none;
3509       break;
3510 
3511    case PIPE_TEX_MIPFILTER_NEAREST:
3512       samp->filter_funcs = &funcs_nearest;
3513       break;
3514 
3515    case PIPE_TEX_MIPFILTER_LINEAR:
3516       if (sampler->min_img_filter == sampler->mag_img_filter &&
3517           sampler->normalized_coords &&
3518           sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
3519           sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
3520           sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
3521           sampler->max_anisotropy <= 1) {
3522          samp->min_mag_equal_repeat_linear = TRUE;
3523       }
3524       samp->filter_funcs = &funcs_linear;
3525 
3526       /* Anisotropic filtering extension. */
3527       if (sampler->max_anisotropy > 1) {
3528          samp->filter_funcs = &funcs_linear_aniso;
3529 
3530          /* Override min_img_filter:
3531           * min_img_filter needs to be set to NEAREST since we need to access
3532           * each texture pixel as it is and weight it later; using linear
3533           * filters will have incorrect results.
3534           * By setting the filter to NEAREST here, we can avoid calling the
3535           * generic img_filter_2d_nearest in the anisotropic filter function,
3536           * making it possible to use one of the accelerated implementations
3537           */
3538          samp->min_img_filter = PIPE_TEX_FILTER_NEAREST;
3539 
3540          /* on first access create the lookup table containing the filter weights. */
3541         if (!weightLut) {
3542            create_filter_table();
3543         }
3544       }
3545       break;
3546    }
3547    if (samp->min_img_filter == sampler->mag_img_filter) {
3548       samp->min_mag_equal = TRUE;
3549    }
3550 
3551    return (void *)samp;
3552 }
3553 
3554 
3555 compute_lambda_func
softpipe_get_lambda_func(const struct pipe_sampler_view * view,enum pipe_shader_type shader)3556 softpipe_get_lambda_func(const struct pipe_sampler_view *view,
3557                          enum pipe_shader_type shader)
3558 {
3559    if (shader != PIPE_SHADER_FRAGMENT)
3560       return compute_lambda_vert;
3561 
3562    switch (view->target) {
3563    case PIPE_BUFFER:
3564    case PIPE_TEXTURE_1D:
3565    case PIPE_TEXTURE_1D_ARRAY:
3566       return compute_lambda_1d;
3567    case PIPE_TEXTURE_2D:
3568    case PIPE_TEXTURE_2D_ARRAY:
3569    case PIPE_TEXTURE_RECT:
3570       return compute_lambda_2d;
3571    case PIPE_TEXTURE_CUBE:
3572    case PIPE_TEXTURE_CUBE_ARRAY:
3573       return compute_lambda_cube;
3574    case PIPE_TEXTURE_3D:
3575       return compute_lambda_3d;
3576    default:
3577       assert(0);
3578       return compute_lambda_1d;
3579    }
3580 }
3581 
3582 
3583 struct pipe_sampler_view *
softpipe_create_sampler_view(struct pipe_context * pipe,struct pipe_resource * resource,const struct pipe_sampler_view * templ)3584 softpipe_create_sampler_view(struct pipe_context *pipe,
3585                              struct pipe_resource *resource,
3586                              const struct pipe_sampler_view *templ)
3587 {
3588    struct sp_sampler_view *sview = CALLOC_STRUCT(sp_sampler_view);
3589    const struct softpipe_resource *spr = (struct softpipe_resource *)resource;
3590 
3591    if (sview) {
3592       struct pipe_sampler_view *view = &sview->base;
3593       *view = *templ;
3594       view->reference.count = 1;
3595       view->texture = NULL;
3596       pipe_resource_reference(&view->texture, resource);
3597       view->context = pipe;
3598 
3599 #ifdef DEBUG
3600      /*
3601       * This is possibly too lenient, but the primary reason is just
3602       * to catch gallium frontends which forget to initialize this, so
3603       * it only catches clearly impossible view targets.
3604       */
3605       if (view->target != resource->target) {
3606          if (view->target == PIPE_TEXTURE_1D)
3607             assert(resource->target == PIPE_TEXTURE_1D_ARRAY);
3608          else if (view->target == PIPE_TEXTURE_1D_ARRAY)
3609             assert(resource->target == PIPE_TEXTURE_1D);
3610          else if (view->target == PIPE_TEXTURE_2D)
3611             assert(resource->target == PIPE_TEXTURE_2D_ARRAY ||
3612                    resource->target == PIPE_TEXTURE_CUBE ||
3613                    resource->target == PIPE_TEXTURE_CUBE_ARRAY);
3614          else if (view->target == PIPE_TEXTURE_2D_ARRAY)
3615             assert(resource->target == PIPE_TEXTURE_2D ||
3616                    resource->target == PIPE_TEXTURE_CUBE ||
3617                    resource->target == PIPE_TEXTURE_CUBE_ARRAY);
3618          else if (view->target == PIPE_TEXTURE_CUBE)
3619             assert(resource->target == PIPE_TEXTURE_CUBE_ARRAY ||
3620                    resource->target == PIPE_TEXTURE_2D_ARRAY);
3621          else if (view->target == PIPE_TEXTURE_CUBE_ARRAY)
3622             assert(resource->target == PIPE_TEXTURE_CUBE ||
3623                    resource->target == PIPE_TEXTURE_2D_ARRAY);
3624          else
3625             assert(0);
3626       }
3627 #endif
3628 
3629       if (any_swizzle(view)) {
3630          sview->need_swizzle = TRUE;
3631       }
3632 
3633       sview->need_cube_convert = (view->target == PIPE_TEXTURE_CUBE ||
3634                                   view->target == PIPE_TEXTURE_CUBE_ARRAY);
3635       sview->pot2d = spr->pot &&
3636                      (view->target == PIPE_TEXTURE_2D ||
3637                       view->target == PIPE_TEXTURE_RECT);
3638 
3639       sview->xpot = util_logbase2( resource->width0 );
3640       sview->ypot = util_logbase2( resource->height0 );
3641 
3642       sview->oneval = util_format_is_pure_integer(view->format) ? uif(1) : 1.0f;
3643    }
3644 
3645    return (struct pipe_sampler_view *) sview;
3646 }
3647 
3648 
3649 static inline const struct sp_tgsi_sampler *
sp_tgsi_sampler_cast_c(const struct tgsi_sampler * sampler)3650 sp_tgsi_sampler_cast_c(const struct tgsi_sampler *sampler)
3651 {
3652    return (const struct sp_tgsi_sampler *)sampler;
3653 }
3654 
3655 
3656 static void
sp_tgsi_get_dims(struct tgsi_sampler * tgsi_sampler,const unsigned sview_index,int level,int dims[4])3657 sp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler,
3658                  const unsigned sview_index,
3659                  int level, int dims[4])
3660 {
3661    const struct sp_tgsi_sampler *sp_samp =
3662       sp_tgsi_sampler_cast_c(tgsi_sampler);
3663 
3664    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
3665    /* always have a view here but texture is NULL if no sampler view was set. */
3666    if (!sp_samp->sp_sview[sview_index].base.texture) {
3667       dims[0] = dims[1] = dims[2] = dims[3] = 0;
3668       return;
3669    }
3670    sp_get_dims(&sp_samp->sp_sview[sview_index], level, dims);
3671 }
3672 
3673 
prepare_compare_values(enum pipe_texture_target target,const float p[TGSI_QUAD_SIZE],const float c0[TGSI_QUAD_SIZE],const float c1[TGSI_QUAD_SIZE],float pc[TGSI_QUAD_SIZE])3674 static void prepare_compare_values(enum pipe_texture_target target,
3675                                    const float p[TGSI_QUAD_SIZE],
3676                                    const float c0[TGSI_QUAD_SIZE],
3677                                    const float c1[TGSI_QUAD_SIZE],
3678                                    float pc[TGSI_QUAD_SIZE])
3679 {
3680    if (target == PIPE_TEXTURE_2D_ARRAY ||
3681        target == PIPE_TEXTURE_CUBE) {
3682       pc[0] = c0[0];
3683       pc[1] = c0[1];
3684       pc[2] = c0[2];
3685       pc[3] = c0[3];
3686    } else if (target == PIPE_TEXTURE_CUBE_ARRAY) {
3687       pc[0] = c1[0];
3688       pc[1] = c1[1];
3689       pc[2] = c1[2];
3690       pc[3] = c1[3];
3691    } else {
3692       pc[0] = p[0];
3693       pc[1] = p[1];
3694       pc[2] = p[2];
3695       pc[3] = p[3];
3696    }
3697 }
3698 
3699 static void
sp_tgsi_get_samples(struct tgsi_sampler * tgsi_sampler,const unsigned sview_index,const unsigned sampler_index,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],const float c0[TGSI_QUAD_SIZE],const float lod_in[TGSI_QUAD_SIZE],float derivs[3][2][TGSI_QUAD_SIZE],const int8_t offset[3],enum tgsi_sampler_control control,float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])3700 sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
3701                     const unsigned sview_index,
3702                     const unsigned sampler_index,
3703                     const float s[TGSI_QUAD_SIZE],
3704                     const float t[TGSI_QUAD_SIZE],
3705                     const float p[TGSI_QUAD_SIZE],
3706                     const float c0[TGSI_QUAD_SIZE],
3707                     const float lod_in[TGSI_QUAD_SIZE],
3708                     float derivs[3][2][TGSI_QUAD_SIZE],
3709                     const int8_t offset[3],
3710                     enum tgsi_sampler_control control,
3711                     float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3712 {
3713    const struct sp_tgsi_sampler *sp_tgsi_samp =
3714       sp_tgsi_sampler_cast_c(tgsi_sampler);
3715    struct sp_sampler_view sp_sview;
3716    const struct sp_sampler *sp_samp;
3717    struct filter_args filt_args;
3718    float compare_values[TGSI_QUAD_SIZE];
3719    float lod[TGSI_QUAD_SIZE];
3720    int c;
3721 
3722    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
3723    assert(sampler_index < PIPE_MAX_SAMPLERS);
3724    assert(sp_tgsi_samp->sp_sampler[sampler_index]);
3725 
3726    memcpy(&sp_sview, &sp_tgsi_samp->sp_sview[sview_index],
3727           sizeof(struct sp_sampler_view));
3728    sp_samp = sp_tgsi_samp->sp_sampler[sampler_index];
3729 
3730    if (util_format_is_unorm(sp_sview.base.format)) {
3731       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
3732           sp_sview.border_color.f[c] = CLAMP(sp_samp->base.border_color.f[c],
3733                                               0.0f, 1.0f);
3734    } else if (util_format_is_snorm(sp_sview.base.format)) {
3735       for (c = 0; c < TGSI_NUM_CHANNELS; c++)
3736           sp_sview.border_color.f[c] = CLAMP(sp_samp->base.border_color.f[c],
3737                                               -1.0f, 1.0f);
3738    } else {
3739       memcpy(sp_sview.border_color.f, sp_samp->base.border_color.f,
3740              TGSI_NUM_CHANNELS * sizeof(float));
3741    }
3742 
3743    /* always have a view here but texture is NULL if no sampler view was set. */
3744    if (!sp_sview.base.texture) {
3745       int i, j;
3746       for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
3747          for (i = 0; i < TGSI_QUAD_SIZE; i++) {
3748             rgba[j][i] = 0.0f;
3749          }
3750       }
3751       return;
3752    }
3753 
3754    if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE)
3755       prepare_compare_values(sp_sview.base.target, p, c0, lod_in, compare_values);
3756 
3757    filt_args.control = control;
3758    filt_args.offset = offset;
3759    int gather_comp = get_gather_component(lod_in);
3760 
3761    compute_lambda_lod(&sp_sview, sp_samp, s, t, p, derivs, lod_in, control, lod);
3762 
3763    if (sp_sview.need_cube_convert) {
3764       float cs[TGSI_QUAD_SIZE];
3765       float ct[TGSI_QUAD_SIZE];
3766       float cp[TGSI_QUAD_SIZE];
3767       uint faces[TGSI_QUAD_SIZE];
3768 
3769       convert_cube(&sp_sview, sp_samp, s, t, p, c0, cs, ct, cp, faces);
3770 
3771       filt_args.faces = faces;
3772       sample_mip(&sp_sview, sp_samp, cs, ct, cp, compare_values, gather_comp, lod, &filt_args, rgba);
3773    } else {
3774       static const uint zero_faces[TGSI_QUAD_SIZE] = {0, 0, 0, 0};
3775 
3776       filt_args.faces = zero_faces;
3777       sample_mip(&sp_sview, sp_samp, s, t, p, compare_values, gather_comp, lod, &filt_args, rgba);
3778    }
3779 }
3780 
3781 static void
sp_tgsi_query_lod(const struct tgsi_sampler * tgsi_sampler,const unsigned sview_index,const unsigned sampler_index,const float s[TGSI_QUAD_SIZE],const float t[TGSI_QUAD_SIZE],const float p[TGSI_QUAD_SIZE],const float c0[TGSI_QUAD_SIZE],const enum tgsi_sampler_control control,float mipmap[TGSI_QUAD_SIZE],float lod[TGSI_QUAD_SIZE])3782 sp_tgsi_query_lod(const struct tgsi_sampler *tgsi_sampler,
3783                   const unsigned sview_index,
3784                   const unsigned sampler_index,
3785                   const float s[TGSI_QUAD_SIZE],
3786                   const float t[TGSI_QUAD_SIZE],
3787                   const float p[TGSI_QUAD_SIZE],
3788                   const float c0[TGSI_QUAD_SIZE],
3789                   const enum tgsi_sampler_control control,
3790                   float mipmap[TGSI_QUAD_SIZE],
3791                   float lod[TGSI_QUAD_SIZE])
3792 {
3793    static const float lod_in[TGSI_QUAD_SIZE] = { 0.0, 0.0, 0.0, 0.0 };
3794    static const float dummy_grad[3][2][TGSI_QUAD_SIZE];
3795 
3796    const struct sp_tgsi_sampler *sp_tgsi_samp =
3797       sp_tgsi_sampler_cast_c(tgsi_sampler);
3798    const struct sp_sampler_view *sp_sview;
3799    const struct sp_sampler *sp_samp;
3800    const struct sp_filter_funcs *funcs;
3801    int i;
3802 
3803    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
3804    assert(sampler_index < PIPE_MAX_SAMPLERS);
3805    assert(sp_tgsi_samp->sp_sampler[sampler_index]);
3806 
3807    sp_sview = &sp_tgsi_samp->sp_sview[sview_index];
3808    sp_samp = sp_tgsi_samp->sp_sampler[sampler_index];
3809    /* always have a view here but texture is NULL if no sampler view was
3810     * set. */
3811    if (!sp_sview->base.texture) {
3812       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
3813          mipmap[i] = 0.0f;
3814          lod[i] = 0.0f;
3815       }
3816       return;
3817    }
3818    compute_lambda_lod_unclamped(sp_sview, sp_samp,
3819                                 s, t, p, dummy_grad, lod_in, control, lod);
3820 
3821    get_filters(sp_sview, sp_samp, control, &funcs, NULL, NULL);
3822    funcs->relative_level(sp_sview, sp_samp, lod, mipmap);
3823 }
3824 
3825 static void
sp_tgsi_get_texel(struct tgsi_sampler * tgsi_sampler,const unsigned sview_index,const int i[TGSI_QUAD_SIZE],const int j[TGSI_QUAD_SIZE],const int k[TGSI_QUAD_SIZE],const int lod[TGSI_QUAD_SIZE],const int8_t offset[3],float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])3826 sp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler,
3827                   const unsigned sview_index,
3828                   const int i[TGSI_QUAD_SIZE],
3829                   const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
3830                   const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
3831                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3832 {
3833    const struct sp_tgsi_sampler *sp_samp =
3834       sp_tgsi_sampler_cast_c(tgsi_sampler);
3835 
3836    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
3837    /* always have a view here but texture is NULL if no sampler view was set. */
3838    if (!sp_samp->sp_sview[sview_index].base.texture) {
3839       int i, j;
3840       for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
3841          for (i = 0; i < TGSI_QUAD_SIZE; i++) {
3842             rgba[j][i] = 0.0f;
3843          }
3844       }
3845       return;
3846    }
3847    sp_get_texels(&sp_samp->sp_sview[sview_index], i, j, k, lod, offset, rgba);
3848 }
3849 
3850 
3851 struct sp_tgsi_sampler *
sp_create_tgsi_sampler(void)3852 sp_create_tgsi_sampler(void)
3853 {
3854    struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler);
3855    if (!samp)
3856       return NULL;
3857 
3858    samp->base.get_dims = sp_tgsi_get_dims;
3859    samp->base.get_samples = sp_tgsi_get_samples;
3860    samp->base.get_texel = sp_tgsi_get_texel;
3861    samp->base.query_lod = sp_tgsi_query_lod;
3862 
3863    return samp;
3864 }
3865