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