sp_tex_sample.c revision b5b128b26841e7f947edd8f0cbcc91a530d6bb8f
1/**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 * Copyright 2008-2010 VMware, Inc.  All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29/**
30 * Texture sampling
31 *
32 * Authors:
33 *   Brian Paul
34 *   Keith Whitwell
35 */
36
37#include "pipe/p_context.h"
38#include "pipe/p_defines.h"
39#include "pipe/p_shader_tokens.h"
40#include "util/u_math.h"
41#include "util/u_memory.h"
42#include "sp_quad.h"   /* only for #define QUAD_* tokens */
43#include "sp_tex_sample.h"
44#include "sp_tex_tile_cache.h"
45
46
47
48/*
49 * Return fractional part of 'f'.  Used for computing interpolation weights.
50 * Need to be careful with negative values.
51 * Note, if this function isn't perfect you'll sometimes see 1-pixel bands
52 * of improperly weighted linear-filtered textures.
53 * The tests/texwrap.c demo is a good test.
54 */
55static INLINE float
56frac(float f)
57{
58   return f - floorf(f);
59}
60
61
62
63/**
64 * Linear interpolation macro
65 */
66static INLINE float
67lerp(float a, float v0, float v1)
68{
69   return v0 + a * (v1 - v0);
70}
71
72
73/**
74 * Do 2D/biliner interpolation of float values.
75 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
76 * a and b are the horizontal and vertical interpolants.
77 * It's important that this function is inlined when compiled with
78 * optimization!  If we find that's not true on some systems, convert
79 * to a macro.
80 */
81static INLINE float
82lerp_2d(float a, float b,
83        float v00, float v10, float v01, float v11)
84{
85   const float temp0 = lerp(a, v00, v10);
86   const float temp1 = lerp(a, v01, v11);
87   return lerp(b, temp0, temp1);
88}
89
90
91/**
92 * As above, but 3D interpolation of 8 values.
93 */
94static INLINE float
95lerp_3d(float a, float b, float c,
96        float v000, float v100, float v010, float v110,
97        float v001, float v101, float v011, float v111)
98{
99   const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
100   const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
101   return lerp(c, temp0, temp1);
102}
103
104
105
106/**
107 * Compute coord % size for repeat wrap modes.
108 * Note that if coord is a signed integer, coord % size doesn't give
109 * the right value for coord < 0 (in terms of texture repeat).  Just
110 * casting to unsigned fixes that.
111 */
112static INLINE int
113repeat(int coord, unsigned size)
114{
115   return (int) ((unsigned) coord % size);
116}
117
118
119/**
120 * Apply texture coord wrapping mode and return integer texture indexes
121 * for a vector of four texcoords (S or T or P).
122 * \param wrapMode  PIPE_TEX_WRAP_x
123 * \param s  the incoming texcoords
124 * \param size  the texture image size
125 * \param icoord  returns the integer texcoords
126 * \return  integer texture index
127 */
128static void
129wrap_nearest_repeat(const float s[4], unsigned size, int icoord[4])
130{
131   uint ch;
132   /* s limited to [0,1) */
133   /* i limited to [0,size-1] */
134   for (ch = 0; ch < 4; ch++) {
135      int i = util_ifloor(s[ch] * size);
136      icoord[ch] = repeat(i, size);
137   }
138}
139
140
141static void
142wrap_nearest_clamp(const float s[4], unsigned size, int icoord[4])
143{
144   uint ch;
145   /* s limited to [0,1] */
146   /* i limited to [0,size-1] */
147   for (ch = 0; ch < 4; ch++) {
148      if (s[ch] <= 0.0F)
149         icoord[ch] = 0;
150      else if (s[ch] >= 1.0F)
151         icoord[ch] = size - 1;
152      else
153         icoord[ch] = util_ifloor(s[ch] * size);
154   }
155}
156
157
158static void
159wrap_nearest_clamp_to_edge(const float s[4], unsigned size, int icoord[4])
160{
161   uint ch;
162   /* s limited to [min,max] */
163   /* i limited to [0, size-1] */
164   const float min = 1.0F / (2.0F * size);
165   const float max = 1.0F - min;
166   for (ch = 0; ch < 4; ch++) {
167      if (s[ch] < min)
168         icoord[ch] = 0;
169      else if (s[ch] > max)
170         icoord[ch] = size - 1;
171      else
172         icoord[ch] = util_ifloor(s[ch] * size);
173   }
174}
175
176
177static void
178wrap_nearest_clamp_to_border(const float s[4], unsigned size, int icoord[4])
179{
180   uint ch;
181   /* s limited to [min,max] */
182   /* i limited to [-1, size] */
183   const float min = -1.0F / (2.0F * size);
184   const float max = 1.0F - min;
185   for (ch = 0; ch < 4; ch++) {
186      if (s[ch] <= min)
187         icoord[ch] = -1;
188      else if (s[ch] >= max)
189         icoord[ch] = size;
190      else
191         icoord[ch] = util_ifloor(s[ch] * size);
192   }
193}
194
195
196static void
197wrap_nearest_mirror_repeat(const float s[4], unsigned size, int icoord[4])
198{
199   uint ch;
200   const float min = 1.0F / (2.0F * size);
201   const float max = 1.0F - min;
202   for (ch = 0; ch < 4; ch++) {
203      const int flr = util_ifloor(s[ch]);
204      float u = frac(s[ch]);
205      if (flr & 1)
206         u = 1.0F - u;
207      if (u < min)
208         icoord[ch] = 0;
209      else if (u > max)
210         icoord[ch] = size - 1;
211      else
212         icoord[ch] = util_ifloor(u * size);
213   }
214}
215
216
217static void
218wrap_nearest_mirror_clamp(const float s[4], unsigned size, int icoord[4])
219{
220   uint ch;
221   for (ch = 0; ch < 4; ch++) {
222      /* s limited to [0,1] */
223      /* i limited to [0,size-1] */
224      const float u = fabsf(s[ch]);
225      if (u <= 0.0F)
226         icoord[ch] = 0;
227      else if (u >= 1.0F)
228         icoord[ch] = size - 1;
229      else
230         icoord[ch] = util_ifloor(u * size);
231   }
232}
233
234
235static void
236wrap_nearest_mirror_clamp_to_edge(const float s[4], unsigned size,
237                                  int icoord[4])
238{
239   uint ch;
240   /* s limited to [min,max] */
241   /* i limited to [0, size-1] */
242   const float min = 1.0F / (2.0F * size);
243   const float max = 1.0F - min;
244   for (ch = 0; ch < 4; ch++) {
245      const float u = fabsf(s[ch]);
246      if (u < min)
247         icoord[ch] = 0;
248      else if (u > max)
249         icoord[ch] = size - 1;
250      else
251         icoord[ch] = util_ifloor(u * size);
252   }
253}
254
255
256static void
257wrap_nearest_mirror_clamp_to_border(const float s[4], unsigned size,
258                                    int icoord[4])
259{
260   uint ch;
261   /* s limited to [min,max] */
262   /* i limited to [0, size-1] */
263   const float min = -1.0F / (2.0F * size);
264   const float max = 1.0F - min;
265   for (ch = 0; ch < 4; ch++) {
266      const float u = fabsf(s[ch]);
267      if (u < min)
268         icoord[ch] = -1;
269      else if (u > max)
270         icoord[ch] = size;
271      else
272         icoord[ch] = util_ifloor(u * size);
273   }
274}
275
276
277/**
278 * Used to compute texel locations for linear sampling for four texcoords.
279 * \param wrapMode  PIPE_TEX_WRAP_x
280 * \param s  the texcoords
281 * \param size  the texture image size
282 * \param icoord0  returns first texture indexes
283 * \param icoord1  returns second texture indexes (usually icoord0 + 1)
284 * \param w  returns blend factor/weight between texture indexes
285 * \param icoord  returns the computed integer texture coords
286 */
287static void
288wrap_linear_repeat(const float s[4], unsigned size,
289                   int icoord0[4], int icoord1[4], float w[4])
290{
291   uint ch;
292   for (ch = 0; ch < 4; ch++) {
293      float u = s[ch] * size - 0.5F;
294      icoord0[ch] = repeat(util_ifloor(u), size);
295      icoord1[ch] = repeat(icoord0[ch] + 1, size);
296      w[ch] = frac(u);
297   }
298}
299
300
301static void
302wrap_linear_clamp(const float s[4], unsigned size,
303                  int icoord0[4], int icoord1[4], float w[4])
304{
305   uint ch;
306   for (ch = 0; ch < 4; ch++) {
307      float u = CLAMP(s[ch], 0.0F, 1.0F);
308      u = u * size - 0.5f;
309      icoord0[ch] = util_ifloor(u);
310      icoord1[ch] = icoord0[ch] + 1;
311      w[ch] = frac(u);
312   }
313}
314
315
316static void
317wrap_linear_clamp_to_edge(const float s[4], unsigned size,
318                          int icoord0[4], int icoord1[4], float w[4])
319{
320   uint ch;
321   for (ch = 0; ch < 4; ch++) {
322      float u = CLAMP(s[ch], 0.0F, 1.0F);
323      u = u * size - 0.5f;
324      icoord0[ch] = util_ifloor(u);
325      icoord1[ch] = icoord0[ch] + 1;
326      if (icoord0[ch] < 0)
327         icoord0[ch] = 0;
328      if (icoord1[ch] >= (int) size)
329         icoord1[ch] = size - 1;
330      w[ch] = frac(u);
331   }
332}
333
334
335static void
336wrap_linear_clamp_to_border(const float s[4], unsigned size,
337                            int icoord0[4], int icoord1[4], float w[4])
338{
339   const float min = -1.0F / (2.0F * size);
340   const float max = 1.0F - min;
341   uint ch;
342   for (ch = 0; ch < 4; ch++) {
343      float u = CLAMP(s[ch], min, max);
344      u = u * size - 0.5f;
345      icoord0[ch] = util_ifloor(u);
346      icoord1[ch] = icoord0[ch] + 1;
347      w[ch] = frac(u);
348   }
349}
350
351
352static void
353wrap_linear_mirror_repeat(const float s[4], unsigned size,
354                          int icoord0[4], int icoord1[4], float w[4])
355{
356   uint ch;
357   for (ch = 0; ch < 4; ch++) {
358      const int flr = util_ifloor(s[ch]);
359      float u = frac(s[ch]);
360      if (flr & 1)
361         u = 1.0F - u;
362      u = u * size - 0.5F;
363      icoord0[ch] = util_ifloor(u);
364      icoord1[ch] = icoord0[ch] + 1;
365      if (icoord0[ch] < 0)
366         icoord0[ch] = 0;
367      if (icoord1[ch] >= (int) size)
368         icoord1[ch] = size - 1;
369      w[ch] = frac(u);
370   }
371}
372
373
374static void
375wrap_linear_mirror_clamp(const float s[4], unsigned size,
376                         int icoord0[4], int icoord1[4], float w[4])
377{
378   uint ch;
379   for (ch = 0; ch < 4; ch++) {
380      float u = fabsf(s[ch]);
381      if (u >= 1.0F)
382         u = (float) size;
383      else
384         u *= size;
385      u -= 0.5F;
386      icoord0[ch] = util_ifloor(u);
387      icoord1[ch] = icoord0[ch] + 1;
388      w[ch] = frac(u);
389   }
390}
391
392
393static void
394wrap_linear_mirror_clamp_to_edge(const float s[4], unsigned size,
395                                 int icoord0[4], int icoord1[4], float w[4])
396{
397   uint ch;
398   for (ch = 0; ch < 4; ch++) {
399      float u = fabsf(s[ch]);
400      if (u >= 1.0F)
401         u = (float) size;
402      else
403         u *= size;
404      u -= 0.5F;
405      icoord0[ch] = util_ifloor(u);
406      icoord1[ch] = icoord0[ch] + 1;
407      if (icoord0[ch] < 0)
408         icoord0[ch] = 0;
409      if (icoord1[ch] >= (int) size)
410         icoord1[ch] = size - 1;
411      w[ch] = frac(u);
412   }
413}
414
415
416static void
417wrap_linear_mirror_clamp_to_border(const float s[4], unsigned size,
418                                   int icoord0[4], int icoord1[4], float w[4])
419{
420   const float min = -1.0F / (2.0F * size);
421   const float max = 1.0F - min;
422   uint ch;
423   for (ch = 0; ch < 4; ch++) {
424      float u = fabsf(s[ch]);
425      if (u <= min)
426         u = min * size;
427      else if (u >= max)
428         u = max * size;
429      else
430         u *= size;
431      u -= 0.5F;
432      icoord0[ch] = util_ifloor(u);
433      icoord1[ch] = icoord0[ch] + 1;
434      w[ch] = frac(u);
435   }
436}
437
438
439/**
440 * PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords.
441 */
442static void
443wrap_nearest_unorm_clamp(const float s[4], unsigned size, int icoord[4])
444{
445   uint ch;
446   for (ch = 0; ch < 4; ch++) {
447      int i = util_ifloor(s[ch]);
448      icoord[ch]= CLAMP(i, 0, (int) size-1);
449   }
450}
451
452
453/**
454 * PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords.
455 */
456static void
457wrap_nearest_unorm_clamp_to_border(const float s[4], unsigned size,
458                                   int icoord[4])
459{
460   uint ch;
461   for (ch = 0; ch < 4; ch++) {
462      icoord[ch]= util_ifloor( CLAMP(s[ch], -0.5F, (float) size + 0.5F) );
463   }
464}
465
466
467/**
468 * PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords.
469 */
470static void
471wrap_nearest_unorm_clamp_to_edge(const float s[4], unsigned size,
472                                 int icoord[4])
473{
474   uint ch;
475   for (ch = 0; ch < 4; ch++) {
476      icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) );
477   }
478}
479
480
481/**
482 * PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords.
483 */
484static void
485wrap_linear_unorm_clamp(const float s[4], unsigned size,
486                        int icoord0[4], int icoord1[4], float w[4])
487{
488   uint ch;
489   for (ch = 0; ch < 4; ch++) {
490      /* Not exactly what the spec says, but it matches NVIDIA output */
491      float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f);
492      icoord0[ch] = util_ifloor(u);
493      icoord1[ch] = icoord0[ch] + 1;
494      w[ch] = frac(u);
495   }
496}
497
498
499/**
500 * PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords.
501 */
502static void
503wrap_linear_unorm_clamp_to_border(const float s[4], unsigned size,
504                                  int icoord0[4], int icoord1[4], float w[4])
505{
506   uint ch;
507   for (ch = 0; ch < 4; ch++) {
508      float u = CLAMP(s[ch], -0.5F, (float) size + 0.5F);
509      u -= 0.5F;
510      icoord0[ch] = util_ifloor(u);
511      icoord1[ch] = icoord0[ch] + 1;
512      if (icoord1[ch] > (int) size - 1)
513         icoord1[ch] = size - 1;
514      w[ch] = frac(u);
515   }
516}
517
518
519/**
520 * PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords.
521 */
522static void
523wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size,
524                                int icoord0[4], int icoord1[4], float w[4])
525{
526   uint ch;
527   for (ch = 0; ch < 4; ch++) {
528      float u = CLAMP(s[ch], +0.5F, (float) size - 0.5F);
529      u -= 0.5F;
530      icoord0[ch] = util_ifloor(u);
531      icoord1[ch] = icoord0[ch] + 1;
532      if (icoord1[ch] > (int) size - 1)
533         icoord1[ch] = size - 1;
534      w[ch] = frac(u);
535   }
536}
537
538
539
540/**
541 * Examine the quad's texture coordinates to compute the partial
542 * derivatives w.r.t X and Y, then compute lambda (level of detail).
543 */
544static float
545compute_lambda_1d(const struct sp_sampler_varient *samp,
546                  const float s[QUAD_SIZE],
547                  const float t[QUAD_SIZE],
548                  const float p[QUAD_SIZE])
549{
550   const struct pipe_texture *texture = samp->texture;
551   float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
552   float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
553   float rho = MAX2(dsdx, dsdy) * texture->width0;
554
555   return util_fast_log2(rho);
556}
557
558
559static float
560compute_lambda_2d(const struct sp_sampler_varient *samp,
561                  const float s[QUAD_SIZE],
562                  const float t[QUAD_SIZE],
563                  const float p[QUAD_SIZE])
564{
565   const struct pipe_texture *texture = samp->texture;
566   float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
567   float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
568   float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
569   float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
570   float maxx = MAX2(dsdx, dsdy) * texture->width0;
571   float maxy = MAX2(dtdx, dtdy) * texture->height0;
572   float rho  = MAX2(maxx, maxy);
573
574   return util_fast_log2(rho);
575}
576
577
578static float
579compute_lambda_3d(const struct sp_sampler_varient *samp,
580                  const float s[QUAD_SIZE],
581                  const float t[QUAD_SIZE],
582                  const float p[QUAD_SIZE])
583{
584   const struct pipe_texture *texture = samp->texture;
585   float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
586   float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
587   float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
588   float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
589   float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
590   float dpdy = fabsf(p[QUAD_TOP_LEFT]     - p[QUAD_BOTTOM_LEFT]);
591   float maxx = MAX2(dsdx, dsdy) * texture->width0;
592   float maxy = MAX2(dtdx, dtdy) * texture->height0;
593   float maxz = MAX2(dpdx, dpdy) * texture->depth0;
594   float rho;
595
596   rho = MAX2(maxx, maxy);
597   rho = MAX2(rho, maxz);
598
599   return util_fast_log2(rho);
600}
601
602
603/**
604 * Compute lambda for a vertex texture sampler.
605 * Since there aren't derivatives to use, just return 0.
606 */
607static float
608compute_lambda_vert(const struct sp_sampler_varient *samp,
609                    const float s[QUAD_SIZE],
610                    const float t[QUAD_SIZE],
611                    const float p[QUAD_SIZE])
612{
613   return 0.0f;
614}
615
616
617
618/**
619 * Get a texel from a texture, using the texture tile cache.
620 *
621 * \param addr  the template tex address containing cube, z, face info.
622 * \param x  the x coord of texel within 2D image
623 * \param y  the y coord of texel within 2D image
624 * \param rgba  the quad to put the texel/color into
625 *
626 * XXX maybe move this into sp_tex_tile_cache.c and merge with the
627 * sp_get_cached_tile_tex() function.  Also, get 4 texels instead of 1...
628 */
629
630
631
632
633static INLINE const float *
634get_texel_2d_no_border(const struct sp_sampler_varient *samp,
635		       union tex_tile_address addr, int x, int y)
636{
637   const struct softpipe_tex_cached_tile *tile;
638
639   addr.bits.x = x / TILE_SIZE;
640   addr.bits.y = y / TILE_SIZE;
641   y %= TILE_SIZE;
642   x %= TILE_SIZE;
643
644   tile = sp_get_cached_tile_tex(samp->cache, addr);
645
646   return &tile->data.color[y][x][0];
647}
648
649
650static INLINE const float *
651get_texel_2d(const struct sp_sampler_varient *samp,
652	     union tex_tile_address addr, int x, int y)
653{
654   const struct pipe_texture *texture = samp->texture;
655   unsigned level = addr.bits.level;
656
657   if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
658       y < 0 || y >= (int) u_minify(texture->height0, level)) {
659      return samp->sampler->border_color;
660   }
661   else {
662      return get_texel_2d_no_border( samp, addr, x, y );
663   }
664}
665
666
667/* Gather a quad of adjacent texels within a tile:
668 */
669static INLINE void
670get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_varient *samp,
671					union tex_tile_address addr,
672					unsigned x, unsigned y,
673					const float *out[4])
674{
675   const struct softpipe_tex_cached_tile *tile;
676
677   addr.bits.x = x / TILE_SIZE;
678   addr.bits.y = y / TILE_SIZE;
679   y %= TILE_SIZE;
680   x %= TILE_SIZE;
681
682   tile = sp_get_cached_tile_tex(samp->cache, addr);
683
684   out[0] = &tile->data.color[y  ][x  ][0];
685   out[1] = &tile->data.color[y  ][x+1][0];
686   out[2] = &tile->data.color[y+1][x  ][0];
687   out[3] = &tile->data.color[y+1][x+1][0];
688}
689
690
691/* Gather a quad of potentially non-adjacent texels:
692 */
693static INLINE void
694get_texel_quad_2d_no_border(const struct sp_sampler_varient *samp,
695			    union tex_tile_address addr,
696			    int x0, int y0,
697			    int x1, int y1,
698			    const float *out[4])
699{
700   out[0] = get_texel_2d_no_border( samp, addr, x0, y0 );
701   out[1] = get_texel_2d_no_border( samp, addr, x1, y0 );
702   out[2] = get_texel_2d_no_border( samp, addr, x0, y1 );
703   out[3] = get_texel_2d_no_border( samp, addr, x1, y1 );
704}
705
706/* Can involve a lot of unnecessary checks for border color:
707 */
708static INLINE void
709get_texel_quad_2d(const struct sp_sampler_varient *samp,
710		  union tex_tile_address addr,
711		  int x0, int y0,
712		  int x1, int y1,
713		  const float *out[4])
714{
715   out[0] = get_texel_2d( samp, addr, x0, y0 );
716   out[1] = get_texel_2d( samp, addr, x1, y0 );
717   out[3] = get_texel_2d( samp, addr, x1, y1 );
718   out[2] = get_texel_2d( samp, addr, x0, y1 );
719}
720
721
722
723/* 3d varients:
724 */
725static INLINE const float *
726get_texel_3d_no_border(const struct sp_sampler_varient *samp,
727                       union tex_tile_address addr, int x, int y, int z)
728{
729   const struct softpipe_tex_cached_tile *tile;
730
731   addr.bits.x = x / TILE_SIZE;
732   addr.bits.y = y / TILE_SIZE;
733   addr.bits.z = z;
734   y %= TILE_SIZE;
735   x %= TILE_SIZE;
736
737   tile = sp_get_cached_tile_tex(samp->cache, addr);
738
739   return &tile->data.color[y][x][0];
740}
741
742
743static INLINE const float *
744get_texel_3d(const struct sp_sampler_varient *samp,
745	     union tex_tile_address addr, int x, int y, int z)
746{
747   const struct pipe_texture *texture = samp->texture;
748   unsigned level = addr.bits.level;
749
750   if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
751       y < 0 || y >= (int) u_minify(texture->height0, level) ||
752       z < 0 || z >= (int) u_minify(texture->depth0, level)) {
753      return samp->sampler->border_color;
754   }
755   else {
756      return get_texel_3d_no_border( samp, addr, x, y, z );
757   }
758}
759
760
761/**
762 * Given the logbase2 of a mipmap's base level size and a mipmap level,
763 * return the size (in texels) of that mipmap level.
764 * For example, if level[0].width = 256 then base_pot will be 8.
765 * If level = 2, then we'll return 64 (the width at level=2).
766 * Return 1 if level > base_pot.
767 */
768static INLINE unsigned
769pot_level_size(unsigned base_pot, unsigned level)
770{
771   return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
772}
773
774
775/* Some image-filter fastpaths:
776 */
777static INLINE void
778img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler,
779                                const float s[QUAD_SIZE],
780                                const float t[QUAD_SIZE],
781                                const float p[QUAD_SIZE],
782                                const float c0[QUAD_SIZE],
783                                enum tgsi_sampler_control control,
784                                float rgba[NUM_CHANNELS][QUAD_SIZE])
785{
786   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
787   unsigned  j;
788   unsigned level = samp->level;
789   unsigned xpot = pot_level_size(samp->xpot, level);
790   unsigned ypot = pot_level_size(samp->ypot, level);
791   unsigned xmax = (xpot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, xpot) - 1; */
792   unsigned ymax = (ypot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, ypot) - 1; */
793   union tex_tile_address addr;
794
795   addr.value = 0;
796   addr.bits.level = samp->level;
797
798   for (j = 0; j < QUAD_SIZE; j++) {
799      int c;
800
801      float u = s[j] * xpot - 0.5F;
802      float v = t[j] * ypot - 0.5F;
803
804      int uflr = util_ifloor(u);
805      int vflr = util_ifloor(v);
806
807      float xw = u - (float)uflr;
808      float yw = v - (float)vflr;
809
810      int x0 = uflr & (xpot - 1);
811      int y0 = vflr & (ypot - 1);
812
813      const float *tx[4];
814
815      /* Can we fetch all four at once:
816       */
817      if (x0 < xmax && y0 < ymax) {
818         get_texel_quad_2d_no_border_single_tile(samp, addr, x0, y0, tx);
819      }
820      else {
821         unsigned x1 = (x0 + 1) & (xpot - 1);
822         unsigned y1 = (y0 + 1) & (ypot - 1);
823         get_texel_quad_2d_no_border(samp, addr, x0, y0, x1, y1, tx);
824      }
825
826      /* interpolate R, G, B, A */
827      for (c = 0; c < 4; c++) {
828         rgba[c][j] = lerp_2d(xw, yw,
829                              tx[0][c], tx[1][c],
830                              tx[2][c], tx[3][c]);
831      }
832   }
833}
834
835
836static INLINE void
837img_filter_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler,
838                                 const float s[QUAD_SIZE],
839                                 const float t[QUAD_SIZE],
840                                 const float p[QUAD_SIZE],
841                                 const float c0[QUAD_SIZE],
842                                 enum tgsi_sampler_control control,
843                                 float rgba[NUM_CHANNELS][QUAD_SIZE])
844{
845   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
846   unsigned  j;
847   unsigned level = samp->level;
848   unsigned xpot = pot_level_size(samp->xpot, level);
849   unsigned ypot = pot_level_size(samp->ypot, level);
850   union tex_tile_address addr;
851
852   addr.value = 0;
853   addr.bits.level = samp->level;
854
855   for (j = 0; j < QUAD_SIZE; j++) {
856      int c;
857
858      float u = s[j] * xpot;
859      float v = t[j] * ypot;
860
861      int uflr = util_ifloor(u);
862      int vflr = util_ifloor(v);
863
864      int x0 = uflr & (xpot - 1);
865      int y0 = vflr & (ypot - 1);
866
867      const float *out = get_texel_2d_no_border(samp, addr, x0, y0);
868
869      for (c = 0; c < 4; c++) {
870         rgba[c][j] = out[c];
871      }
872   }
873}
874
875
876static INLINE void
877img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler,
878                                const float s[QUAD_SIZE],
879                                const float t[QUAD_SIZE],
880                                const float p[QUAD_SIZE],
881                                const float c0[QUAD_SIZE],
882                                enum tgsi_sampler_control control,
883                                float rgba[NUM_CHANNELS][QUAD_SIZE])
884{
885   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
886   unsigned  j;
887   unsigned level = samp->level;
888   unsigned xpot = pot_level_size(samp->xpot, level);
889   unsigned ypot = pot_level_size(samp->ypot, level);
890   union tex_tile_address addr;
891
892   addr.value = 0;
893   addr.bits.level = samp->level;
894
895   for (j = 0; j < QUAD_SIZE; j++) {
896      int c;
897
898      float u = s[j] * xpot;
899      float v = t[j] * ypot;
900
901      int x0, y0;
902      const float *out;
903
904      x0 = util_ifloor(u);
905      if (x0 < 0)
906         x0 = 0;
907      else if (x0 > xpot - 1)
908         x0 = xpot - 1;
909
910      y0 = util_ifloor(v);
911      if (y0 < 0)
912         y0 = 0;
913      else if (y0 > ypot - 1)
914         y0 = ypot - 1;
915
916      out = get_texel_2d_no_border(samp, addr, x0, y0);
917
918      for (c = 0; c < 4; c++) {
919         rgba[c][j] = out[c];
920      }
921   }
922}
923
924
925static void
926img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler,
927                        const float s[QUAD_SIZE],
928                        const float t[QUAD_SIZE],
929                        const float p[QUAD_SIZE],
930                        const float c0[QUAD_SIZE],
931                        enum tgsi_sampler_control control,
932                        float rgba[NUM_CHANNELS][QUAD_SIZE])
933{
934   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
935   const struct pipe_texture *texture = samp->texture;
936   unsigned level0, j;
937   int width;
938   int x[4];
939   union tex_tile_address addr;
940
941   level0 = samp->level;
942   width = u_minify(texture->width0, level0);
943
944   assert(width > 0);
945
946   addr.value = 0;
947   addr.bits.level = samp->level;
948
949   samp->nearest_texcoord_s(s, width, x);
950
951   for (j = 0; j < QUAD_SIZE; j++) {
952      const float *out = get_texel_2d(samp, addr, x[j], 0);
953      int c;
954      for (c = 0; c < 4; c++) {
955         rgba[c][j] = out[c];
956      }
957   }
958}
959
960
961static void
962img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
963                      const float s[QUAD_SIZE],
964                      const float t[QUAD_SIZE],
965                      const float p[QUAD_SIZE],
966                      const float c0[QUAD_SIZE],
967                      enum tgsi_sampler_control control,
968                      float rgba[NUM_CHANNELS][QUAD_SIZE])
969{
970   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
971   const struct pipe_texture *texture = samp->texture;
972   unsigned level0, j;
973   int width, height;
974   int x[4], y[4];
975   union tex_tile_address addr;
976
977
978   level0 = samp->level;
979   width = u_minify(texture->width0, level0);
980   height = u_minify(texture->height0, level0);
981
982   assert(width > 0);
983   assert(height > 0);
984
985   addr.value = 0;
986   addr.bits.level = samp->level;
987
988   samp->nearest_texcoord_s(s, width, x);
989   samp->nearest_texcoord_t(t, height, y);
990
991   for (j = 0; j < QUAD_SIZE; j++) {
992      const float *out = get_texel_2d(samp, addr, x[j], y[j]);
993      int c;
994      for (c = 0; c < 4; c++) {
995         rgba[c][j] = out[c];
996      }
997   }
998}
999
1000
1001static INLINE union tex_tile_address
1002face(union tex_tile_address addr, unsigned face )
1003{
1004   addr.bits.face = face;
1005   return addr;
1006}
1007
1008
1009static void
1010img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler,
1011                        const float s[QUAD_SIZE],
1012                        const float t[QUAD_SIZE],
1013                        const float p[QUAD_SIZE],
1014                        const float c0[QUAD_SIZE],
1015                        enum tgsi_sampler_control control,
1016                        float rgba[NUM_CHANNELS][QUAD_SIZE])
1017{
1018   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1019   const struct pipe_texture *texture = samp->texture;
1020   const unsigned *faces = samp->faces; /* zero when not cube-mapping */
1021   unsigned level0, j;
1022   int width, height;
1023   int x[4], y[4];
1024   union tex_tile_address addr;
1025
1026   level0 = samp->level;
1027   width = u_minify(texture->width0, level0);
1028   height = u_minify(texture->height0, level0);
1029
1030   assert(width > 0);
1031   assert(height > 0);
1032
1033   addr.value = 0;
1034   addr.bits.level = samp->level;
1035
1036   samp->nearest_texcoord_s(s, width, x);
1037   samp->nearest_texcoord_t(t, height, y);
1038
1039   for (j = 0; j < QUAD_SIZE; j++) {
1040      const float *out = get_texel_2d(samp, face(addr, faces[j]), x[j], y[j]);
1041      int c;
1042      for (c = 0; c < 4; c++) {
1043         rgba[c][j] = out[c];
1044      }
1045   }
1046}
1047
1048
1049static void
1050img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler,
1051                      const float s[QUAD_SIZE],
1052                      const float t[QUAD_SIZE],
1053                      const float p[QUAD_SIZE],
1054                      const float c0[QUAD_SIZE],
1055                      enum tgsi_sampler_control control,
1056                      float rgba[NUM_CHANNELS][QUAD_SIZE])
1057{
1058   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1059   const struct pipe_texture *texture = samp->texture;
1060   unsigned level0, j;
1061   int width, height, depth;
1062   int x[4], y[4], z[4];
1063   union tex_tile_address addr;
1064
1065   level0 = samp->level;
1066   width = u_minify(texture->width0, level0);
1067   height = u_minify(texture->height0, level0);
1068   depth = u_minify(texture->depth0, level0);
1069
1070   assert(width > 0);
1071   assert(height > 0);
1072   assert(depth > 0);
1073
1074   samp->nearest_texcoord_s(s, width,  x);
1075   samp->nearest_texcoord_t(t, height, y);
1076   samp->nearest_texcoord_p(p, depth,  z);
1077
1078   addr.value = 0;
1079   addr.bits.level = samp->level;
1080
1081   for (j = 0; j < QUAD_SIZE; j++) {
1082      const float *out = get_texel_3d(samp, addr, x[j], y[j], z[j]);
1083      int c;
1084      for (c = 0; c < 4; c++) {
1085         rgba[c][j] = out[c];
1086      }
1087   }
1088}
1089
1090
1091static void
1092img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler,
1093                     const float s[QUAD_SIZE],
1094                     const float t[QUAD_SIZE],
1095                     const float p[QUAD_SIZE],
1096                     const float c0[QUAD_SIZE],
1097                     enum tgsi_sampler_control control,
1098                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1099{
1100   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1101   const struct pipe_texture *texture = samp->texture;
1102   unsigned level0, j;
1103   int width;
1104   int x0[4], x1[4];
1105   float xw[4]; /* weights */
1106   union tex_tile_address addr;
1107
1108   level0 = samp->level;
1109   width = u_minify(texture->width0, level0);
1110
1111   assert(width > 0);
1112
1113   addr.value = 0;
1114   addr.bits.level = samp->level;
1115
1116   samp->linear_texcoord_s(s, width, x0, x1, xw);
1117
1118   for (j = 0; j < QUAD_SIZE; j++) {
1119      const float *tx0 = get_texel_2d(samp, addr, x0[j], 0);
1120      const float *tx1 = get_texel_2d(samp, addr, x1[j], 0);
1121      int c;
1122
1123      /* interpolate R, G, B, A */
1124      for (c = 0; c < 4; c++) {
1125         rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]);
1126      }
1127   }
1128}
1129
1130
1131static void
1132img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
1133                     const float s[QUAD_SIZE],
1134                     const float t[QUAD_SIZE],
1135                     const float p[QUAD_SIZE],
1136                     const float c0[QUAD_SIZE],
1137                     enum tgsi_sampler_control control,
1138                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1139{
1140   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1141   const struct pipe_texture *texture = samp->texture;
1142   unsigned level0, j;
1143   int width, height;
1144   int x0[4], y0[4], x1[4], y1[4];
1145   float xw[4], yw[4]; /* weights */
1146   union tex_tile_address addr;
1147
1148   level0 = samp->level;
1149   width = u_minify(texture->width0, level0);
1150   height = u_minify(texture->height0, level0);
1151
1152   assert(width > 0);
1153   assert(height > 0);
1154
1155   addr.value = 0;
1156   addr.bits.level = samp->level;
1157
1158   samp->linear_texcoord_s(s, width,  x0, x1, xw);
1159   samp->linear_texcoord_t(t, height, y0, y1, yw);
1160
1161   for (j = 0; j < QUAD_SIZE; j++) {
1162      const float *tx0 = get_texel_2d(samp, addr, x0[j], y0[j]);
1163      const float *tx1 = get_texel_2d(samp, addr, x1[j], y0[j]);
1164      const float *tx2 = get_texel_2d(samp, addr, x0[j], y1[j]);
1165      const float *tx3 = get_texel_2d(samp, addr, x1[j], y1[j]);
1166      int c;
1167
1168      /* interpolate R, G, B, A */
1169      for (c = 0; c < 4; c++) {
1170         rgba[c][j] = lerp_2d(xw[j], yw[j],
1171                              tx0[c], tx1[c],
1172                              tx2[c], tx3[c]);
1173      }
1174   }
1175}
1176
1177
1178static void
1179img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
1180                       const float s[QUAD_SIZE],
1181                       const float t[QUAD_SIZE],
1182                       const float p[QUAD_SIZE],
1183                       const float c0[QUAD_SIZE],
1184                       enum tgsi_sampler_control control,
1185                       float rgba[NUM_CHANNELS][QUAD_SIZE])
1186{
1187   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1188   const struct pipe_texture *texture = samp->texture;
1189   const unsigned *faces = samp->faces; /* zero when not cube-mapping */
1190   unsigned level0, j;
1191   int width, height;
1192   int x0[4], y0[4], x1[4], y1[4];
1193   float xw[4], yw[4]; /* weights */
1194   union tex_tile_address addr;
1195
1196   level0 = samp->level;
1197   width = u_minify(texture->width0, level0);
1198   height = u_minify(texture->height0, level0);
1199
1200   assert(width > 0);
1201   assert(height > 0);
1202
1203   addr.value = 0;
1204   addr.bits.level = samp->level;
1205
1206   samp->linear_texcoord_s(s, width,  x0, x1, xw);
1207   samp->linear_texcoord_t(t, height, y0, y1, yw);
1208
1209   for (j = 0; j < QUAD_SIZE; j++) {
1210      union tex_tile_address addrj = face(addr, faces[j]);
1211      const float *tx0 = get_texel_2d(samp, addrj, x0[j], y0[j]);
1212      const float *tx1 = get_texel_2d(samp, addrj, x1[j], y0[j]);
1213      const float *tx2 = get_texel_2d(samp, addrj, x0[j], y1[j]);
1214      const float *tx3 = get_texel_2d(samp, addrj, x1[j], y1[j]);
1215      int c;
1216
1217      /* interpolate R, G, B, A */
1218      for (c = 0; c < 4; c++) {
1219         rgba[c][j] = lerp_2d(xw[j], yw[j],
1220                              tx0[c], tx1[c],
1221                              tx2[c], tx3[c]);
1222      }
1223   }
1224}
1225
1226
1227static void
1228img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler,
1229                     const float s[QUAD_SIZE],
1230                     const float t[QUAD_SIZE],
1231                     const float p[QUAD_SIZE],
1232                     const float c0[QUAD_SIZE],
1233                     enum tgsi_sampler_control control,
1234                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1235{
1236   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1237   const struct pipe_texture *texture = samp->texture;
1238   unsigned level0, j;
1239   int width, height, depth;
1240   int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4];
1241   float xw[4], yw[4], zw[4]; /* interpolation weights */
1242   union tex_tile_address addr;
1243
1244   level0 = samp->level;
1245   width = u_minify(texture->width0, level0);
1246   height = u_minify(texture->height0, level0);
1247   depth = u_minify(texture->depth0, level0);
1248
1249   addr.value = 0;
1250   addr.bits.level = level0;
1251
1252   assert(width > 0);
1253   assert(height > 0);
1254   assert(depth > 0);
1255
1256   samp->linear_texcoord_s(s, width,  x0, x1, xw);
1257   samp->linear_texcoord_t(t, height, y0, y1, yw);
1258   samp->linear_texcoord_p(p, depth,  z0, z1, zw);
1259
1260   for (j = 0; j < QUAD_SIZE; j++) {
1261      int c;
1262
1263      const float *tx00 = get_texel_3d(samp, addr, x0[j], y0[j], z0[j]);
1264      const float *tx01 = get_texel_3d(samp, addr, x1[j], y0[j], z0[j]);
1265      const float *tx02 = get_texel_3d(samp, addr, x0[j], y1[j], z0[j]);
1266      const float *tx03 = get_texel_3d(samp, addr, x1[j], y1[j], z0[j]);
1267
1268      const float *tx10 = get_texel_3d(samp, addr, x0[j], y0[j], z1[j]);
1269      const float *tx11 = get_texel_3d(samp, addr, x1[j], y0[j], z1[j]);
1270      const float *tx12 = get_texel_3d(samp, addr, x0[j], y1[j], z1[j]);
1271      const float *tx13 = get_texel_3d(samp, addr, x1[j], y1[j], z1[j]);
1272
1273      /* interpolate R, G, B, A */
1274      for (c = 0; c < 4; c++) {
1275         rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j],
1276                              tx00[c], tx01[c],
1277                              tx02[c], tx03[c],
1278                              tx10[c], tx11[c],
1279                              tx12[c], tx13[c]);
1280      }
1281   }
1282}
1283
1284
1285/* Calculate level of detail for every fragment.
1286 * Note that lambda has already been biased by global LOD bias.
1287 */
1288static INLINE void
1289compute_lod(const struct pipe_sampler_state *sampler,
1290            const float biased_lambda,
1291            const float lodbias[QUAD_SIZE],
1292            float lod[QUAD_SIZE])
1293{
1294   uint i;
1295
1296   for (i = 0; i < QUAD_SIZE; i++) {
1297      lod[i] = biased_lambda + lodbias[i];
1298      lod[i] = CLAMP(lod[i], sampler->min_lod, sampler->max_lod);
1299   }
1300}
1301
1302
1303static void
1304mip_filter_linear(struct tgsi_sampler *tgsi_sampler,
1305                  const float s[QUAD_SIZE],
1306                  const float t[QUAD_SIZE],
1307                  const float p[QUAD_SIZE],
1308                  const float c0[QUAD_SIZE],
1309                  enum tgsi_sampler_control control,
1310                  float rgba[NUM_CHANNELS][QUAD_SIZE])
1311{
1312   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1313   const struct pipe_texture *texture = samp->texture;
1314   int level0;
1315   float lambda;
1316   float lod[QUAD_SIZE];
1317
1318   if (control == tgsi_sampler_lod_bias) {
1319      lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias;
1320      compute_lod(samp->sampler, lambda, c0, lod);
1321   } else {
1322      assert(control == tgsi_sampler_lod_explicit);
1323
1324      memcpy(lod, c0, sizeof(lod));
1325   }
1326
1327   /* XXX: Take into account all lod values.
1328    */
1329   lambda = lod[0];
1330   level0 = (int)lambda;
1331
1332   if (lambda < 0.0) {
1333      samp->level = 0;
1334      samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba);
1335   }
1336   else if (level0 >= texture->last_level) {
1337      samp->level = texture->last_level;
1338      samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba);
1339   }
1340   else {
1341      float levelBlend = lambda - level0;
1342      float rgba0[4][4];
1343      float rgba1[4][4];
1344      int c,j;
1345
1346      samp->level = level0;
1347      samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba0);
1348
1349      samp->level = level0+1;
1350      samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba1);
1351
1352      for (j = 0; j < QUAD_SIZE; j++) {
1353         for (c = 0; c < 4; c++) {
1354            rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
1355         }
1356      }
1357   }
1358}
1359
1360
1361/**
1362 * Compute nearest mipmap level from texcoords.
1363 * Then sample the texture level for four elements of a quad.
1364 * \param c0  the LOD bias factors, or absolute LODs (depending on control)
1365 */
1366static void
1367mip_filter_nearest(struct tgsi_sampler *tgsi_sampler,
1368                   const float s[QUAD_SIZE],
1369                   const float t[QUAD_SIZE],
1370                   const float p[QUAD_SIZE],
1371                   const float c0[QUAD_SIZE],
1372                   enum tgsi_sampler_control control,
1373                   float rgba[NUM_CHANNELS][QUAD_SIZE])
1374{
1375   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1376   const struct pipe_texture *texture = samp->texture;
1377   float lambda;
1378   float lod[QUAD_SIZE];
1379
1380   if (control == tgsi_sampler_lod_bias) {
1381      lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias;
1382      compute_lod(samp->sampler, lambda, c0, lod);
1383   } else {
1384      assert(control == tgsi_sampler_lod_explicit);
1385
1386      memcpy(lod, c0, sizeof(lod));
1387   }
1388
1389   /* XXX: Take into account all lod values.
1390    */
1391   lambda = lod[0];
1392
1393   if (lambda < 0.0) {
1394      samp->level = 0;
1395      samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba);
1396   }
1397   else {
1398      samp->level = (int)(lambda + 0.5) ;
1399      samp->level = MIN2(samp->level, (int)texture->last_level);
1400      samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba);
1401   }
1402
1403#if 0
1404   printf("RGBA %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
1405          rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
1406          rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
1407          rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
1408          rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
1409#endif
1410}
1411
1412
1413static void
1414mip_filter_none(struct tgsi_sampler *tgsi_sampler,
1415                const float s[QUAD_SIZE],
1416                const float t[QUAD_SIZE],
1417                const float p[QUAD_SIZE],
1418                const float c0[QUAD_SIZE],
1419                enum tgsi_sampler_control control,
1420                float rgba[NUM_CHANNELS][QUAD_SIZE])
1421{
1422   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1423   float lambda;
1424   float lod[QUAD_SIZE];
1425
1426   if (control == tgsi_sampler_lod_bias) {
1427      lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias;
1428      compute_lod(samp->sampler, lambda, c0, lod);
1429   } else {
1430      assert(control == tgsi_sampler_lod_explicit);
1431
1432      memcpy(lod, c0, sizeof(lod));
1433   }
1434
1435   /* XXX: Take into account all lod values.
1436    */
1437   lambda = lod[0];
1438
1439   if (lambda < 0.0) {
1440      samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba);
1441   }
1442   else {
1443      samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba);
1444   }
1445}
1446
1447
1448
1449/**
1450 * Specialized version of mip_filter_linear with hard-wired calls to
1451 * 2d lambda calculation and 2d_linear_repeat_POT img filters.
1452 */
1453static void
1454mip_filter_linear_2d_linear_repeat_POT(
1455   struct tgsi_sampler *tgsi_sampler,
1456   const float s[QUAD_SIZE],
1457   const float t[QUAD_SIZE],
1458   const float p[QUAD_SIZE],
1459   const float c0[QUAD_SIZE],
1460   enum tgsi_sampler_control control,
1461   float rgba[NUM_CHANNELS][QUAD_SIZE])
1462{
1463   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1464   const struct pipe_texture *texture = samp->texture;
1465   int level0;
1466   float lambda;
1467   float lod[QUAD_SIZE];
1468
1469   if (control == tgsi_sampler_lod_bias) {
1470      lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias;
1471      compute_lod(samp->sampler, lambda, c0, lod);
1472   } else {
1473      assert(control == tgsi_sampler_lod_explicit);
1474
1475      memcpy(lod, c0, sizeof(lod));
1476   }
1477
1478   /* XXX: Take into account all lod values.
1479    */
1480   lambda = lod[0];
1481   level0 = (int)lambda;
1482
1483   /* Catches both negative and large values of level0:
1484    */
1485   if ((unsigned)level0 >= texture->last_level) {
1486      if (level0 < 0)
1487         samp->level = 0;
1488      else
1489         samp->level = texture->last_level;
1490
1491      img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba);
1492   }
1493   else {
1494      float levelBlend = lambda - level0;
1495      float rgba0[4][4];
1496      float rgba1[4][4];
1497      int c,j;
1498
1499      samp->level = level0;
1500      img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba0);
1501
1502      samp->level = level0+1;
1503      img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba1);
1504
1505      for (j = 0; j < QUAD_SIZE; j++) {
1506         for (c = 0; c < 4; c++) {
1507            rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
1508         }
1509      }
1510   }
1511}
1512
1513
1514
1515/**
1516 * Do shadow/depth comparisons.
1517 */
1518static void
1519sample_compare(struct tgsi_sampler *tgsi_sampler,
1520               const float s[QUAD_SIZE],
1521               const float t[QUAD_SIZE],
1522               const float p[QUAD_SIZE],
1523               const float c0[QUAD_SIZE],
1524               enum tgsi_sampler_control control,
1525               float rgba[NUM_CHANNELS][QUAD_SIZE])
1526{
1527   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1528   const struct pipe_sampler_state *sampler = samp->sampler;
1529   int j, k0, k1, k2, k3;
1530   float val;
1531
1532   samp->mip_filter(tgsi_sampler, s, t, p, c0, control, rgba);
1533
1534   /**
1535    * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
1536    * When we sampled the depth texture, the depth value was put into all
1537    * RGBA channels.  We look at the red channel here.
1538    */
1539
1540   /* compare four texcoords vs. four texture samples */
1541   switch (sampler->compare_func) {
1542   case PIPE_FUNC_LESS:
1543      k0 = p[0] < rgba[0][0];
1544      k1 = p[1] < rgba[0][1];
1545      k2 = p[2] < rgba[0][2];
1546      k3 = p[3] < rgba[0][3];
1547      break;
1548   case PIPE_FUNC_LEQUAL:
1549      k0 = p[0] <= rgba[0][0];
1550      k1 = p[1] <= rgba[0][1];
1551      k2 = p[2] <= rgba[0][2];
1552      k3 = p[3] <= rgba[0][3];
1553      break;
1554   case PIPE_FUNC_GREATER:
1555      k0 = p[0] > rgba[0][0];
1556      k1 = p[1] > rgba[0][1];
1557      k2 = p[2] > rgba[0][2];
1558      k3 = p[3] > rgba[0][3];
1559      break;
1560   case PIPE_FUNC_GEQUAL:
1561      k0 = p[0] >= rgba[0][0];
1562      k1 = p[1] >= rgba[0][1];
1563      k2 = p[2] >= rgba[0][2];
1564      k3 = p[3] >= rgba[0][3];
1565      break;
1566   case PIPE_FUNC_EQUAL:
1567      k0 = p[0] == rgba[0][0];
1568      k1 = p[1] == rgba[0][1];
1569      k2 = p[2] == rgba[0][2];
1570      k3 = p[3] == rgba[0][3];
1571      break;
1572   case PIPE_FUNC_NOTEQUAL:
1573      k0 = p[0] != rgba[0][0];
1574      k1 = p[1] != rgba[0][1];
1575      k2 = p[2] != rgba[0][2];
1576      k3 = p[3] != rgba[0][3];
1577      break;
1578   case PIPE_FUNC_ALWAYS:
1579      k0 = k1 = k2 = k3 = 1;
1580      break;
1581   case PIPE_FUNC_NEVER:
1582      k0 = k1 = k2 = k3 = 0;
1583      break;
1584   default:
1585      k0 = k1 = k2 = k3 = 0;
1586      assert(0);
1587      break;
1588   }
1589
1590   /* convert four pass/fail values to an intensity in [0,1] */
1591   val = 0.25F * (k0 + k1 + k2 + k3);
1592
1593   /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
1594   for (j = 0; j < 4; j++) {
1595      rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
1596      rgba[3][j] = 1.0F;
1597   }
1598}
1599
1600
1601/**
1602 * Use 3D texcoords to choose a cube face, then sample the 2D cube faces.
1603 * Put face info into the sampler faces[] array.
1604 */
1605static void
1606sample_cube(struct tgsi_sampler *tgsi_sampler,
1607            const float s[QUAD_SIZE],
1608            const float t[QUAD_SIZE],
1609            const float p[QUAD_SIZE],
1610            const float c0[QUAD_SIZE],
1611            enum tgsi_sampler_control control,
1612            float rgba[NUM_CHANNELS][QUAD_SIZE])
1613{
1614   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1615   unsigned j;
1616   float ssss[4], tttt[4];
1617   unsigned face;
1618
1619   /*
1620     major axis
1621     direction    target                             sc     tc    ma
1622     ----------   -------------------------------    ---    ---   ---
1623     +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
1624     -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
1625     +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
1626     -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
1627     +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
1628     -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
1629   */
1630
1631   /* First choose the cube face.
1632    * Use the same cube face for all four pixels in the quad.
1633    *
1634    * This isn't ideal, but if we want to use a different cube face
1635    * per pixel in the quad, we'd have to also compute the per-face
1636    * LOD here too.  That's because the four post-face-selection
1637    * texcoords are no longer related to each other (they're
1638    * per-face!)  so we can't use subtraction to compute the partial
1639    * deriviates to compute the LOD.  Doing so (near cube edges
1640    * anyway) gives us pretty much random values.
1641    */
1642   {
1643      /* use the average of the four pixel's texcoords to choose the face */
1644      const float rx = 0.25 * (s[0] + s[1] + s[2] + s[3]);
1645      const float ry = 0.25 * (t[0] + t[1] + t[2] + t[3]);
1646      const float rz = 0.25 * (p[0] + p[1] + p[2] + p[3]);
1647      const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
1648
1649      if (arx >= ary && arx >= arz) {
1650         if (rx >= 0.0F) {
1651            face = PIPE_TEX_FACE_POS_X;
1652         }
1653         else {
1654            face = PIPE_TEX_FACE_NEG_X;
1655         }
1656      }
1657      else if (ary >= arx && ary >= arz) {
1658         if (ry >= 0.0F) {
1659            face = PIPE_TEX_FACE_POS_Y;
1660         }
1661         else {
1662            face = PIPE_TEX_FACE_NEG_Y;
1663         }
1664      }
1665      else {
1666         if (rz > 0.0F) {
1667            face = PIPE_TEX_FACE_POS_Z;
1668         }
1669         else {
1670            face = PIPE_TEX_FACE_NEG_Z;
1671         }
1672      }
1673   }
1674
1675   /* Now compute the 2D _face_ texture coords from the
1676    * 3D _cube_ texture coords.
1677    */
1678   for (j = 0; j < QUAD_SIZE; j++) {
1679      const float rx = s[j], ry = t[j], rz = p[j];
1680      const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
1681      float sc, tc, ma;
1682
1683      switch (face) {
1684      case PIPE_TEX_FACE_POS_X:
1685         sc = -rz;
1686         tc = -ry;
1687         ma = arx;
1688         break;
1689      case PIPE_TEX_FACE_NEG_X:
1690         sc = rz;
1691         tc = -ry;
1692         ma = arx;
1693         break;
1694      case PIPE_TEX_FACE_POS_Y:
1695         sc = rx;
1696         tc = rz;
1697         ma = ary;
1698         break;
1699      case PIPE_TEX_FACE_NEG_Y:
1700         sc = rx;
1701         tc = -rz;
1702         ma = ary;
1703         break;
1704      case PIPE_TEX_FACE_POS_Z:
1705         sc = rx;
1706         tc = -ry;
1707         ma = arz;
1708         break;
1709      case PIPE_TEX_FACE_NEG_Z:
1710         sc = -rx;
1711         tc = -ry;
1712         ma = arz;
1713         break;
1714      default:
1715         assert(0 && "bad cube face");
1716         sc = 0.0F;
1717         tc = 0.0F;
1718         ma = 0.0F;
1719      }
1720
1721      {
1722	 const float ima = 1.0 / ma;
1723	 ssss[j] = ( sc * ima + 1.0F ) * 0.5F;
1724	 tttt[j] = ( tc * ima + 1.0F ) * 0.5F;
1725	 samp->faces[j] = face;
1726      }
1727   }
1728
1729   /* In our little pipeline, the compare stage is next.  If compare
1730    * is not active, this will point somewhere deeper into the
1731    * pipeline, eg. to mip_filter or even img_filter.
1732    */
1733   samp->compare(tgsi_sampler, ssss, tttt, NULL, c0, control, rgba);
1734}
1735
1736
1737
1738static wrap_nearest_func
1739get_nearest_unorm_wrap(unsigned mode)
1740{
1741   switch (mode) {
1742   case PIPE_TEX_WRAP_CLAMP:
1743      return wrap_nearest_unorm_clamp;
1744   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1745      return wrap_nearest_unorm_clamp_to_edge;
1746   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1747      return wrap_nearest_unorm_clamp_to_border;
1748   default:
1749      assert(0);
1750      return wrap_nearest_unorm_clamp;
1751   }
1752}
1753
1754
1755static wrap_nearest_func
1756get_nearest_wrap(unsigned mode)
1757{
1758   switch (mode) {
1759   case PIPE_TEX_WRAP_REPEAT:
1760      return wrap_nearest_repeat;
1761   case PIPE_TEX_WRAP_CLAMP:
1762      return wrap_nearest_clamp;
1763   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1764      return wrap_nearest_clamp_to_edge;
1765   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1766      return wrap_nearest_clamp_to_border;
1767   case PIPE_TEX_WRAP_MIRROR_REPEAT:
1768      return wrap_nearest_mirror_repeat;
1769   case PIPE_TEX_WRAP_MIRROR_CLAMP:
1770      return wrap_nearest_mirror_clamp;
1771   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
1772      return wrap_nearest_mirror_clamp_to_edge;
1773   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
1774      return wrap_nearest_mirror_clamp_to_border;
1775   default:
1776      assert(0);
1777      return wrap_nearest_repeat;
1778   }
1779}
1780
1781
1782static wrap_linear_func
1783get_linear_unorm_wrap(unsigned mode)
1784{
1785   switch (mode) {
1786   case PIPE_TEX_WRAP_CLAMP:
1787      return wrap_linear_unorm_clamp;
1788   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1789      return wrap_linear_unorm_clamp_to_edge;
1790   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1791      return wrap_linear_unorm_clamp_to_border;
1792   default:
1793      assert(0);
1794      return wrap_linear_unorm_clamp;
1795   }
1796}
1797
1798
1799static wrap_linear_func
1800get_linear_wrap(unsigned mode)
1801{
1802   switch (mode) {
1803   case PIPE_TEX_WRAP_REPEAT:
1804      return wrap_linear_repeat;
1805   case PIPE_TEX_WRAP_CLAMP:
1806      return wrap_linear_clamp;
1807   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1808      return wrap_linear_clamp_to_edge;
1809   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1810      return wrap_linear_clamp_to_border;
1811   case PIPE_TEX_WRAP_MIRROR_REPEAT:
1812      return wrap_linear_mirror_repeat;
1813   case PIPE_TEX_WRAP_MIRROR_CLAMP:
1814      return wrap_linear_mirror_clamp;
1815   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
1816      return wrap_linear_mirror_clamp_to_edge;
1817   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
1818      return wrap_linear_mirror_clamp_to_border;
1819   default:
1820      assert(0);
1821      return wrap_linear_repeat;
1822   }
1823}
1824
1825
1826static compute_lambda_func
1827get_lambda_func(const union sp_sampler_key key)
1828{
1829   if (key.bits.processor == TGSI_PROCESSOR_VERTEX)
1830      return compute_lambda_vert;
1831
1832   switch (key.bits.target) {
1833   case PIPE_TEXTURE_1D:
1834      return compute_lambda_1d;
1835   case PIPE_TEXTURE_2D:
1836   case PIPE_TEXTURE_CUBE:
1837      return compute_lambda_2d;
1838   case PIPE_TEXTURE_3D:
1839      return compute_lambda_3d;
1840   default:
1841      assert(0);
1842      return compute_lambda_1d;
1843   }
1844}
1845
1846
1847static filter_func
1848get_img_filter(const union sp_sampler_key key,
1849               unsigned filter,
1850               const struct pipe_sampler_state *sampler)
1851{
1852   switch (key.bits.target) {
1853   case PIPE_TEXTURE_1D:
1854      if (filter == PIPE_TEX_FILTER_NEAREST)
1855         return img_filter_1d_nearest;
1856      else
1857         return img_filter_1d_linear;
1858      break;
1859   case PIPE_TEXTURE_2D:
1860      /* Try for fast path:
1861       */
1862      if (key.bits.is_pot &&
1863          sampler->wrap_s == sampler->wrap_t &&
1864          sampler->normalized_coords)
1865      {
1866         switch (sampler->wrap_s) {
1867         case PIPE_TEX_WRAP_REPEAT:
1868            switch (filter) {
1869            case PIPE_TEX_FILTER_NEAREST:
1870               return img_filter_2d_nearest_repeat_POT;
1871            case PIPE_TEX_FILTER_LINEAR:
1872               return img_filter_2d_linear_repeat_POT;
1873            default:
1874               break;
1875            }
1876            break;
1877         case PIPE_TEX_WRAP_CLAMP:
1878            switch (filter) {
1879            case PIPE_TEX_FILTER_NEAREST:
1880               return img_filter_2d_nearest_clamp_POT;
1881            default:
1882               break;
1883            }
1884         }
1885      }
1886      /* Otherwise use default versions:
1887       */
1888      if (filter == PIPE_TEX_FILTER_NEAREST)
1889         return img_filter_2d_nearest;
1890      else
1891         return img_filter_2d_linear;
1892      break;
1893   case PIPE_TEXTURE_CUBE:
1894      if (filter == PIPE_TEX_FILTER_NEAREST)
1895         return img_filter_cube_nearest;
1896      else
1897         return img_filter_cube_linear;
1898      break;
1899   case PIPE_TEXTURE_3D:
1900      if (filter == PIPE_TEX_FILTER_NEAREST)
1901         return img_filter_3d_nearest;
1902      else
1903         return img_filter_3d_linear;
1904      break;
1905   default:
1906      assert(0);
1907      return img_filter_1d_nearest;
1908   }
1909}
1910
1911
1912/**
1913 * Bind the given texture object and texture cache to the sampler varient.
1914 */
1915void
1916sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp,
1917                                 struct softpipe_tex_tile_cache *tex_cache,
1918                                 const struct pipe_texture *texture )
1919{
1920   const struct pipe_sampler_state *sampler = samp->sampler;
1921
1922   samp->texture = texture;
1923   samp->cache = tex_cache;
1924   samp->xpot = util_unsigned_logbase2( texture->width0 );
1925   samp->ypot = util_unsigned_logbase2( texture->height0 );
1926   samp->level = CLAMP((int) sampler->min_lod, 0, (int) texture->last_level);
1927}
1928
1929
1930void
1931sp_sampler_varient_destroy( struct sp_sampler_varient *samp )
1932{
1933   FREE(samp);
1934}
1935
1936
1937/**
1938 * Create a sampler varient for a given set of non-orthogonal state.
1939 */
1940struct sp_sampler_varient *
1941sp_create_sampler_varient( const struct pipe_sampler_state *sampler,
1942                           const union sp_sampler_key key )
1943{
1944   struct sp_sampler_varient *samp = CALLOC_STRUCT(sp_sampler_varient);
1945   if (!samp)
1946      return NULL;
1947
1948   samp->sampler = sampler;
1949   samp->key = key;
1950
1951   /* Note that (for instance) linear_texcoord_s and
1952    * nearest_texcoord_s may be active at the same time, if the
1953    * sampler min_img_filter differs from its mag_img_filter.
1954    */
1955   if (sampler->normalized_coords) {
1956      samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
1957      samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
1958      samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
1959
1960      samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
1961      samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
1962      samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
1963   }
1964   else {
1965      samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
1966      samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
1967      samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
1968
1969      samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
1970      samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
1971      samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
1972   }
1973
1974   samp->compute_lambda = get_lambda_func( key );
1975
1976   samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler);
1977   samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler);
1978
1979   switch (sampler->min_mip_filter) {
1980   case PIPE_TEX_MIPFILTER_NONE:
1981      if (sampler->min_img_filter == sampler->mag_img_filter)
1982         samp->mip_filter = samp->min_img_filter;
1983      else
1984         samp->mip_filter = mip_filter_none;
1985      break;
1986
1987   case PIPE_TEX_MIPFILTER_NEAREST:
1988      samp->mip_filter = mip_filter_nearest;
1989      break;
1990
1991   case PIPE_TEX_MIPFILTER_LINEAR:
1992      if (key.bits.is_pot &&
1993          sampler->min_img_filter == sampler->mag_img_filter &&
1994          sampler->normalized_coords &&
1995          sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
1996          sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
1997          sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR)
1998      {
1999         samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT;
2000      }
2001      else
2002      {
2003         samp->mip_filter = mip_filter_linear;
2004      }
2005      break;
2006   }
2007
2008   if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE) {
2009      samp->compare = sample_compare;
2010   }
2011   else {
2012      /* Skip compare operation by promoting the mip_filter function
2013       * pointer:
2014       */
2015      samp->compare = samp->mip_filter;
2016   }
2017
2018   if (key.bits.target == PIPE_TEXTURE_CUBE) {
2019      samp->base.get_samples = sample_cube;
2020   }
2021   else {
2022      samp->faces[0] = 0;
2023      samp->faces[1] = 0;
2024      samp->faces[2] = 0;
2025      samp->faces[3] = 0;
2026
2027      /* Skip cube face determination by promoting the compare
2028       * function pointer:
2029       */
2030      samp->base.get_samples = samp->compare;
2031   }
2032
2033   return samp;
2034}
2035