sp_tex_sample.c revision d204659c8c725c02212ad4a49275c7447f2d02a6
1/**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 * Copyright 2008 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_tile_cache.h"
45
46
47
48/*
49 * Note, the FRAC macro has to work perfectly.  Otherwise you'll sometimes
50 * see 1-pixel bands of improperly weighted linear-filtered textures.
51 * The tests/texwrap.c demo is a good test.
52 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
53 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
54 */
55#define FRAC(f)  ((f) - util_ifloor(f))
56
57
58/**
59 * Linear interpolation macro
60 */
61static INLINE float
62lerp(float a, float v0, float v1)
63{
64   return v0 + a * (v1 - v0);
65}
66
67
68/**
69 * Do 2D/biliner interpolation of float values.
70 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
71 * a and b are the horizontal and vertical interpolants.
72 * It's important that this function is inlined when compiled with
73 * optimization!  If we find that's not true on some systems, convert
74 * to a macro.
75 */
76static INLINE float
77lerp_2d(float a, float b,
78        float v00, float v10, float v01, float v11)
79{
80   const float temp0 = lerp(a, v00, v10);
81   const float temp1 = lerp(a, v01, v11);
82   return lerp(b, temp0, temp1);
83}
84
85
86/**
87 * As above, but 3D interpolation of 8 values.
88 */
89static INLINE float
90lerp_3d(float a, float b, float c,
91        float v000, float v100, float v010, float v110,
92        float v001, float v101, float v011, float v111)
93{
94   const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
95   const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
96   return lerp(c, temp0, temp1);
97}
98
99
100
101/**
102 * If A is a signed integer, A % B doesn't give the right value for A < 0
103 * (in terms of texture repeat).  Just casting to unsigned fixes that.
104 */
105#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
106
107
108/**
109 * Apply texture coord wrapping mode and return integer texture indexes
110 * for a vector of four texcoords (S or T or P).
111 * \param wrapMode  PIPE_TEX_WRAP_x
112 * \param s  the incoming texcoords
113 * \param size  the texture image size
114 * \param icoord  returns the integer texcoords
115 * \return  integer texture index
116 */
117static void
118wrap_nearest_repeat(const float s[4], unsigned size,
119                        int icoord[4])
120{
121   uint ch;
122
123   /* s limited to [0,1) */
124   /* i limited to [0,size-1] */
125   for (ch = 0; ch < 4; ch++) {
126      int i = util_ifloor(s[ch] * size);
127      icoord[ch] = REMAINDER(i, size);
128   }
129}
130
131
132static void
133wrap_nearest_clamp(const float s[4], unsigned size,
134                   int icoord[4])
135{
136   uint ch;
137   /* s limited to [0,1] */
138   /* i limited to [0,size-1] */
139   for (ch = 0; ch < 4; ch++) {
140      if (s[ch] <= 0.0F)
141         icoord[ch] = 0;
142      else if (s[ch] >= 1.0F)
143         icoord[ch] = size - 1;
144      else
145         icoord[ch] = util_ifloor(s[ch] * size);
146   }
147}
148
149
150static void
151wrap_nearest_clamp_to_edge(const float s[4], unsigned size,
152                           int icoord[4])
153{
154   uint ch;
155   /* s limited to [min,max] */
156   /* i limited to [0, size-1] */
157   const float min = 1.0F / (2.0F * size);
158   const float max = 1.0F - min;
159   for (ch = 0; ch < 4; ch++) {
160      if (s[ch] < min)
161         icoord[ch] = 0;
162      else if (s[ch] > max)
163         icoord[ch] = size - 1;
164      else
165         icoord[ch] = util_ifloor(s[ch] * size);
166   }
167}
168
169
170static void
171wrap_nearest_clamp_to_border(const float s[4], unsigned size,
172                             int icoord[4])
173{
174   uint ch;
175   /* s limited to [min,max] */
176   /* i limited to [-1, size] */
177   const float min = -1.0F / (2.0F * size);
178   const float max = 1.0F - min;
179   for (ch = 0; ch < 4; ch++) {
180      if (s[ch] <= min)
181         icoord[ch] = -1;
182      else if (s[ch] >= max)
183         icoord[ch] = size;
184      else
185         icoord[ch] = util_ifloor(s[ch] * size);
186   }
187}
188
189static void
190wrap_nearest_mirror_repeat(const float s[4], unsigned size,
191                           int icoord[4])
192{
193   uint ch;
194   const float min = 1.0F / (2.0F * size);
195   const float max = 1.0F - min;
196   for (ch = 0; ch < 4; ch++) {
197      const int flr = util_ifloor(s[ch]);
198      float u;
199      if (flr & 1)
200         u = 1.0F - (s[ch] - (float) flr);
201      else
202         u = s[ch] - (float) flr;
203      if (u < min)
204         icoord[ch] = 0;
205      else if (u > max)
206         icoord[ch] = size - 1;
207      else
208         icoord[ch] = util_ifloor(u * size);
209   }
210}
211
212static void
213wrap_nearest_mirror_clamp(const float s[4], unsigned size,
214                          int icoord[4])
215{
216   uint ch;
217   for (ch = 0; ch < 4; ch++) {
218      /* s limited to [0,1] */
219      /* i limited to [0,size-1] */
220      const float u = fabsf(s[ch]);
221      if (u <= 0.0F)
222         icoord[ch] = 0;
223      else if (u >= 1.0F)
224         icoord[ch] = size - 1;
225      else
226         icoord[ch] = util_ifloor(u * size);
227   }
228}
229
230static void
231wrap_nearest_mirror_clamp_to_edge(const float s[4], unsigned size,
232                           int icoord[4])
233{
234   uint ch;
235   /* s limited to [min,max] */
236   /* i limited to [0, size-1] */
237   const float min = 1.0F / (2.0F * size);
238   const float max = 1.0F - min;
239   for (ch = 0; ch < 4; ch++) {
240      const float u = fabsf(s[ch]);
241      if (u < min)
242         icoord[ch] = 0;
243      else if (u > max)
244         icoord[ch] = size - 1;
245      else
246         icoord[ch] = util_ifloor(u * size);
247   }
248}
249
250
251static void
252wrap_nearest_mirror_clamp_to_border(const float s[4], unsigned size,
253                                    int icoord[4])
254{
255   uint ch;
256   /* s limited to [min,max] */
257   /* i limited to [0, size-1] */
258   const float min = -1.0F / (2.0F * size);
259   const float max = 1.0F - min;
260   for (ch = 0; ch < 4; ch++) {
261      const float u = fabsf(s[ch]);
262      if (u < min)
263         icoord[ch] = -1;
264      else if (u > max)
265         icoord[ch] = size;
266      else
267         icoord[ch] = util_ifloor(u * size);
268   }
269}
270
271
272/**
273 * Used to compute texel locations for linear sampling for four texcoords.
274 * \param wrapMode  PIPE_TEX_WRAP_x
275 * \param s  the texcoords
276 * \param size  the texture image size
277 * \param icoord0  returns first texture indexes
278 * \param icoord1  returns second texture indexes (usually icoord0 + 1)
279 * \param w  returns blend factor/weight between texture indexes
280 * \param icoord  returns the computed integer texture coords
281 */
282static void
283wrap_linear_repeat(const float s[4], unsigned size,
284                   int icoord0[4], int icoord1[4], float w[4])
285{
286   uint ch;
287
288   for (ch = 0; ch < 4; ch++) {
289      float u = s[ch] * size - 0.5F;
290      icoord0[ch] = REMAINDER(util_ifloor(u), size);
291      icoord1[ch] = REMAINDER(icoord0[ch] + 1, size);
292      w[ch] = FRAC(u);
293   }
294}
295
296static void
297wrap_linear_clamp(const float s[4], unsigned size,
298                  int icoord0[4], int icoord1[4], float w[4])
299{
300   uint ch;
301   for (ch = 0; ch < 4; ch++) {
302      float u = CLAMP(s[ch], 0.0F, 1.0F);
303      u = u * size - 0.5f;
304      icoord0[ch] = util_ifloor(u);
305      icoord1[ch] = icoord0[ch] + 1;
306      w[ch] = FRAC(u);
307   }
308}
309
310static void
311wrap_linear_clamp_to_edge(const float s[4], unsigned size,
312                          int icoord0[4], int icoord1[4], float w[4])
313{
314   uint ch;
315   for (ch = 0; ch < 4; ch++) {
316      float u = CLAMP(s[ch], 0.0F, 1.0F);
317      u = u * size - 0.5f;
318      icoord0[ch] = util_ifloor(u);
319      icoord1[ch] = icoord0[ch] + 1;
320      if (icoord0[ch] < 0)
321         icoord0[ch] = 0;
322      if (icoord1[ch] >= (int) size)
323         icoord1[ch] = size - 1;
324      w[ch] = FRAC(u);
325   }
326}
327
328static void
329wrap_linear_clamp_to_border(const float s[4], unsigned size,
330                            int icoord0[4], int icoord1[4], float w[4])
331{
332   const float min = -1.0F / (2.0F * size);
333   const float max = 1.0F - min;
334   uint ch;
335   for (ch = 0; ch < 4; ch++) {
336      float u = CLAMP(s[ch], min, max);
337      u = u * size - 0.5f;
338      icoord0[ch] = util_ifloor(u);
339      icoord1[ch] = icoord0[ch] + 1;
340      w[ch] = FRAC(u);
341   }
342}
343
344
345static void
346wrap_linear_mirror_repeat(const float s[4], unsigned size,
347                          int icoord0[4], int icoord1[4], float w[4])
348{
349   uint ch;
350   for (ch = 0; ch < 4; ch++) {
351      const int flr = util_ifloor(s[ch]);
352      float u;
353      if (flr & 1)
354         u = 1.0F - (s[ch] - (float) flr);
355      else
356         u = s[ch] - (float) flr;
357      u = u * size - 0.5F;
358      icoord0[ch] = util_ifloor(u);
359      icoord1[ch] = icoord0[ch] + 1;
360      if (icoord0[ch] < 0)
361         icoord0[ch] = 0;
362      if (icoord1[ch] >= (int) size)
363         icoord1[ch] = size - 1;
364      w[ch] = FRAC(u);
365   }
366}
367
368static void
369wrap_linear_mirror_clamp(const float s[4], unsigned size,
370                         int icoord0[4], int icoord1[4], float w[4])
371{
372   uint ch;
373   for (ch = 0; ch < 4; ch++) {
374      float u = fabsf(s[ch]);
375      if (u >= 1.0F)
376         u = (float) size;
377      else
378         u *= size;
379      u -= 0.5F;
380      icoord0[ch] = util_ifloor(u);
381      icoord1[ch] = icoord0[ch] + 1;
382      w[ch] = FRAC(u);
383   }
384}
385
386static void
387wrap_linear_mirror_clamp_to_edge(const float s[4], unsigned size,
388                                 int icoord0[4], int icoord1[4], float w[4])
389{
390   uint ch;
391   for (ch = 0; ch < 4; ch++) {
392      float u = fabsf(s[ch]);
393      if (u >= 1.0F)
394         u = (float) size;
395      else
396         u *= size;
397      u -= 0.5F;
398      icoord0[ch] = util_ifloor(u);
399      icoord1[ch] = icoord0[ch] + 1;
400      if (icoord0[ch] < 0)
401         icoord0[ch] = 0;
402      if (icoord1[ch] >= (int) size)
403         icoord1[ch] = size - 1;
404      w[ch] = FRAC(u);
405   }
406}
407
408static void
409wrap_linear_mirror_clamp_to_border(const float s[4], unsigned size,
410                                   int icoord0[4], int icoord1[4], float w[4])
411{
412   const float min = -1.0F / (2.0F * size);
413   const float max = 1.0F - min;
414   uint ch;
415   for (ch = 0; ch < 4; ch++) {
416      float u = fabsf(s[ch]);
417      if (u <= min)
418         u = min * size;
419      else if (u >= max)
420         u = max * size;
421      else
422         u *= size;
423      u -= 0.5F;
424      icoord0[ch] = util_ifloor(u);
425      icoord1[ch] = icoord0[ch] + 1;
426      w[ch] = FRAC(u);
427   }
428}
429
430
431/**
432 * For RECT textures / unnormalized texcoords
433 * Only a subset of wrap modes supported.
434 */
435static void
436wrap_nearest_unorm_clamp(const float s[4], unsigned size,
437                          int icoord[4])
438{
439   uint ch;
440   for (ch = 0; ch < 4; ch++) {
441      int i = util_ifloor(s[ch]);
442      icoord[ch]= CLAMP(i, 0, (int) size-1);
443   }
444}
445
446/* Handles clamp_to_edge and clamp_to_border:
447 */
448static void
449wrap_nearest_unorm_clamp_to_border(const float s[4], unsigned size,
450                               int icoord[4])
451{
452   uint ch;
453   for (ch = 0; ch < 4; ch++) {
454      icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) );
455   }
456}
457
458
459/**
460 * For RECT textures / unnormalized texcoords.
461 * Only a subset of wrap modes supported.
462 */
463static void
464wrap_linear_unorm_clamp(const float s[4], unsigned size,
465                         int icoord0[4], int icoord1[4], float w[4])
466{
467   uint ch;
468   for (ch = 0; ch < 4; ch++) {
469      /* Not exactly what the spec says, but it matches NVIDIA output */
470      float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f);
471      icoord0[ch] = util_ifloor(u);
472      icoord1[ch] = icoord0[ch] + 1;
473      w[ch] = FRAC(u);
474   }
475}
476
477static void
478wrap_linear_unorm_clamp_to_border( const float s[4], unsigned size,
479                                   int icoord0[4], int icoord1[4], float w[4])
480{
481   uint ch;
482   for (ch = 0; ch < 4; ch++) {
483      float u = CLAMP(s[ch], 0.5F, (float) size - 0.5F);
484      u -= 0.5F;
485      icoord0[ch] = util_ifloor(u);
486      icoord1[ch] = icoord0[ch] + 1;
487      if (icoord1[ch] > (int) size - 1)
488         icoord1[ch] = size - 1;
489      w[ch] = FRAC(u);
490   }
491}
492
493
494
495
496
497/**
498 * Examine the quad's texture coordinates to compute the partial
499 * derivatives w.r.t X and Y, then compute lambda (level of detail).
500 */
501static float
502compute_lambda_1d(const struct sp_sampler_varient *samp,
503                  const float s[QUAD_SIZE],
504                  const float t[QUAD_SIZE],
505                  const float p[QUAD_SIZE],
506                  float lodbias)
507{
508   const struct pipe_texture *texture = samp->texture;
509   const struct pipe_sampler_state *sampler = samp->sampler;
510   float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
511   float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
512   float rho = MAX2(dsdx, dsdy) * texture->width[0];
513   float lambda;
514
515   lambda = util_fast_log2(rho);
516   lambda += lodbias + sampler->lod_bias;
517   lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod);
518
519   return lambda;
520}
521
522static float
523compute_lambda_2d(const struct sp_sampler_varient *samp,
524                  const float s[QUAD_SIZE],
525                  const float t[QUAD_SIZE],
526                  const float p[QUAD_SIZE],
527                  float lodbias)
528{
529   const struct pipe_texture *texture = samp->texture;
530   const struct pipe_sampler_state *sampler = samp->sampler;
531   float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
532   float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
533   float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
534   float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
535   float maxx = MAX2(dsdx, dsdy) * texture->width[0];
536   float maxy = MAX2(dtdx, dtdy) * texture->height[0];
537   float rho  = MAX2(maxx, maxy);
538   float lambda;
539
540   lambda = util_fast_log2(rho);
541   lambda += lodbias + sampler->lod_bias;
542   lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod);
543
544   return lambda;
545}
546
547
548static float
549compute_lambda_3d(const struct sp_sampler_varient *samp,
550                  const float s[QUAD_SIZE],
551                  const float t[QUAD_SIZE],
552                  const float p[QUAD_SIZE],
553                  float lodbias)
554{
555   const struct pipe_texture *texture = samp->texture;
556   const struct pipe_sampler_state *sampler = samp->sampler;
557   float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
558   float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
559   float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
560   float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
561   float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
562   float dpdy = fabsf(p[QUAD_TOP_LEFT]     - p[QUAD_BOTTOM_LEFT]);
563   float maxx = MAX2(dsdx, dsdy) * texture->width[0];
564   float maxy = MAX2(dtdx, dtdy) * texture->height[0];
565   float maxz = MAX2(dpdx, dpdy) * texture->depth[0];
566   float rho, lambda;
567
568   rho = MAX2(maxx, maxy);
569   rho = MAX2(rho, maxz);
570
571   lambda = util_fast_log2(rho);
572   lambda += lodbias + sampler->lod_bias;
573   lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod);
574
575   return lambda;
576}
577
578
579
580static float
581compute_lambda_vert(const struct sp_sampler_varient *samp,
582                    const float s[QUAD_SIZE],
583                    const float t[QUAD_SIZE],
584                    const float p[QUAD_SIZE],
585                    float lodbias)
586{
587   return lodbias;
588}
589
590
591
592/**
593 * Get a texel from a texture, using the texture tile cache.
594 *
595 * \param face  the cube face in 0..5
596 * \param level  the mipmap level
597 * \param x  the x coord of texel within 2D image
598 * \param y  the y coord of texel within 2D image
599 * \param z  which slice of a 3D texture
600 * \param rgba  the quad to put the texel/color into
601 * \param j  which element of the rgba quad to write to
602 *
603 * XXX maybe move this into sp_tile_cache.c and merge with the
604 * sp_get_cached_tile_tex() function.  Also, get 4 texels instead of 1...
605 */
606static INLINE void
607get_texel_quad_2d(const struct tgsi_sampler *tgsi_sampler,
608                  unsigned face, unsigned level, int x, int y,
609                  const float *out[4])
610{
611   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
612
613   const struct softpipe_cached_tile *tile
614      = sp_get_cached_tile_tex(samp->cache,
615                               tile_address(x, y, 0, face, level));
616
617   y %= TILE_SIZE;
618   x %= TILE_SIZE;
619
620   out[0] = &tile->data.color[y  ][x  ][0];
621   out[1] = &tile->data.color[y  ][x+1][0];
622   out[2] = &tile->data.color[y+1][x  ][0];
623   out[3] = &tile->data.color[y+1][x+1][0];
624}
625
626static INLINE const float *
627get_texel_2d_ptr(const struct tgsi_sampler *tgsi_sampler,
628                 unsigned face, unsigned level, int x, int y)
629{
630   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
631
632   const struct softpipe_cached_tile *tile
633      = sp_get_cached_tile_tex(samp->cache,
634                               tile_address(x, y, 0, face, level));
635
636   y %= TILE_SIZE;
637   x %= TILE_SIZE;
638
639   return &tile->data.color[y][x][0];
640}
641
642
643static INLINE void
644get_texel_quad_2d_mt(const struct tgsi_sampler *tgsi_sampler,
645                     unsigned face, unsigned level,
646                     int x0, int y0,
647                     int x1, int y1,
648                     const float *out[4])
649{
650   unsigned i;
651
652   for (i = 0; i < 4; i++) {
653      unsigned tx = (i & 1) ? x1 : x0;
654      unsigned ty = (i >> 1) ? y1 : y0;
655
656      out[i] = get_texel_2d_ptr( tgsi_sampler, face, level, tx, ty );
657   }
658}
659
660static INLINE void
661get_texel(const struct tgsi_sampler *tgsi_sampler,
662                 unsigned face, unsigned level, int x, int y, int z,
663                 float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
664{
665   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
666   const struct pipe_texture *texture = samp->texture;
667   const struct pipe_sampler_state *sampler = samp->sampler;
668
669   if (x < 0 || x >= (int) texture->width[level] ||
670       y < 0 || y >= (int) texture->height[level] ||
671       z < 0 || z >= (int) texture->depth[level]) {
672      rgba[0][j] = sampler->border_color[0];
673      rgba[1][j] = sampler->border_color[1];
674      rgba[2][j] = sampler->border_color[2];
675      rgba[3][j] = sampler->border_color[3];
676   }
677   else {
678      const unsigned tx = x % TILE_SIZE;
679      const unsigned ty = y % TILE_SIZE;
680      const struct softpipe_cached_tile *tile;
681
682      tile = sp_get_cached_tile_tex(samp->cache,
683                                    tile_address(x, y, z, face, level));
684
685      rgba[0][j] = tile->data.color[ty][tx][0];
686      rgba[1][j] = tile->data.color[ty][tx][1];
687      rgba[2][j] = tile->data.color[ty][tx][2];
688      rgba[3][j] = tile->data.color[ty][tx][3];
689      if (0)
690      {
691         debug_printf("Get texel %f %f %f %f from %s\n",
692                      rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j],
693                      pf_name(texture->format));
694      }
695   }
696}
697
698
699
700
701
702static INLINE void
703img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler,
704                                  const float s[QUAD_SIZE],
705                                  const float t[QUAD_SIZE],
706                                  const float p[QUAD_SIZE],
707                                  float lodbias,
708                                  float rgba[NUM_CHANNELS][QUAD_SIZE])
709{
710   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
711   unsigned  j;
712   unsigned level = samp->level;
713   unsigned xpot = 1 << (samp->xpot - level);
714   unsigned ypot = 1 << (samp->ypot - level);
715   unsigned xmax = (xpot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, xpot) - 1; */
716   unsigned ymax = (ypot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, ypot) - 1; */
717
718   for (j = 0; j < QUAD_SIZE; j++) {
719      int c;
720
721      float u = s[j] * xpot - 0.5F;
722      float v = t[j] * ypot - 0.5F;
723
724      int uflr = util_ifloor(u);
725      int vflr = util_ifloor(v);
726
727      float xw = u - (float)uflr;
728      float yw = v - (float)vflr;
729
730      int x0 = uflr & (xpot - 1);
731      int y0 = vflr & (ypot - 1);
732
733      const float *tx[4];
734
735
736      /* Can we fetch all four at once:
737       */
738      if (x0 < xmax && y0 < ymax)
739      {
740         get_texel_quad_2d(tgsi_sampler, 0, level, x0, y0, tx);
741      }
742      else
743      {
744         unsigned x1 = (x0 + 1) & (xpot - 1);
745         unsigned y1 = (y0 + 1) & (ypot - 1);
746         get_texel_quad_2d_mt(tgsi_sampler, 0, level,
747                              x0, y0, x1, y1, tx);
748      }
749
750
751      /* interpolate R, G, B, A */
752      for (c = 0; c < 4; c++) {
753         rgba[c][j] = lerp_2d(xw, yw,
754                              tx[0][c], tx[1][c],
755                              tx[2][c], tx[3][c]);
756      }
757   }
758}
759
760
761static INLINE void
762img_filter_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler,
763                                 const float s[QUAD_SIZE],
764                                 const float t[QUAD_SIZE],
765                                 const float p[QUAD_SIZE],
766                                 float lodbias,
767                                 float rgba[NUM_CHANNELS][QUAD_SIZE])
768{
769   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
770   unsigned  j;
771   unsigned level = samp->level;
772   unsigned xpot = 1 << (samp->xpot - level);
773   unsigned ypot = 1 << (samp->ypot - level);
774
775   for (j = 0; j < QUAD_SIZE; j++) {
776      int c;
777
778      float u = s[j] * xpot;
779      float v = t[j] * ypot;
780
781      int uflr = util_ifloor(u);
782      int vflr = util_ifloor(v);
783
784      int x0 = uflr & (xpot - 1);
785      int y0 = vflr & (ypot - 1);
786
787      const float *out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0);
788
789      for (c = 0; c < 4; c++) {
790         rgba[c][j] = out[c];
791      }
792   }
793}
794
795
796static INLINE void
797img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler,
798                                const float s[QUAD_SIZE],
799                                const float t[QUAD_SIZE],
800                                const float p[QUAD_SIZE],
801                                float lodbias,
802                                float rgba[NUM_CHANNELS][QUAD_SIZE])
803{
804   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
805   unsigned  j;
806   unsigned level = samp->level;
807   unsigned xpot = 1 << (samp->xpot - level);
808   unsigned ypot = 1 << (samp->ypot - level);
809
810   for (j = 0; j < QUAD_SIZE; j++) {
811      int c;
812
813      float u = s[j] * xpot;
814      float v = t[j] * ypot;
815
816      int x0, y0;
817      const float *out;
818
819      x0 = util_ifloor(u);
820      if (x0 < 0)
821         x0 = 0;
822      else if (x0 > xpot - 1)
823         x0 = xpot - 1;
824
825      y0 = util_ifloor(v);
826      if (y0 < 0)
827         y0 = 0;
828      else if (y0 > ypot - 1)
829         y0 = ypot - 1;
830
831      out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0);
832
833      for (c = 0; c < 4; c++) {
834         rgba[c][j] = out[c];
835      }
836   }
837}
838
839static void
840img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler,
841                        const float s[QUAD_SIZE],
842                        const float t[QUAD_SIZE],
843                        const float p[QUAD_SIZE],
844                        float lodbias,
845                        float rgba[NUM_CHANNELS][QUAD_SIZE])
846{
847   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
848   const struct pipe_texture *texture = samp->texture;
849   unsigned level0, j;
850   int width;
851   int x[4];
852
853   level0 = samp->level;
854   width = texture->width[level0];
855
856   assert(width > 0);
857
858   samp->nearest_texcoord_s(s, width, x);
859
860   for (j = 0; j < QUAD_SIZE; j++) {
861      get_texel(tgsi_sampler, 0, level0, x[j], 0, 0, rgba, j);
862   }
863}
864
865
866static void
867img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
868                      const float s[QUAD_SIZE],
869                      const float t[QUAD_SIZE],
870                      const float p[QUAD_SIZE],
871                      float lodbias,
872                      float rgba[NUM_CHANNELS][QUAD_SIZE])
873{
874   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
875   const struct pipe_texture *texture = samp->texture;
876   const unsigned *faces = samp->faces; /* zero when not cube-mapping */
877   unsigned level0, j;
878   int width, height;
879   int x[4], y[4];
880
881   level0 = samp->level;
882   width = texture->width[level0];
883   height = texture->height[level0];
884
885   assert(width > 0);
886
887   samp->nearest_texcoord_s(s, width, x);
888   samp->nearest_texcoord_t(t, height, y);
889
890   for (j = 0; j < QUAD_SIZE; j++) {
891      get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j);
892   }
893}
894
895
896static void
897img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler,
898                      const float s[QUAD_SIZE],
899                      const float t[QUAD_SIZE],
900                      const float p[QUAD_SIZE],
901                      float lodbias,
902                      float rgba[NUM_CHANNELS][QUAD_SIZE])
903{
904   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
905   const struct pipe_texture *texture = samp->texture;
906   unsigned level0, j;
907   int width, height, depth;
908   int x[4], y[4], z[4];
909
910   level0 = samp->level;
911   width = texture->width[level0];
912   height = texture->height[level0];
913   depth = texture->depth[level0];
914
915   assert(width > 0);
916   assert(height > 0);
917   assert(depth > 0);
918
919   samp->nearest_texcoord_s(s, width,  x);
920   samp->nearest_texcoord_t(t, height, y);
921   samp->nearest_texcoord_p(p, depth,  z);
922
923   for (j = 0; j < QUAD_SIZE; j++) {
924      get_texel(tgsi_sampler, 0, level0, x[j], y[j], z[j], rgba, j);
925   }
926}
927
928
929static void
930img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler,
931                     const float s[QUAD_SIZE],
932                     const float t[QUAD_SIZE],
933                     const float p[QUAD_SIZE],
934                     float lodbias,
935                     float rgba[NUM_CHANNELS][QUAD_SIZE])
936{
937   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
938   const struct pipe_texture *texture = samp->texture;
939   unsigned level0, j;
940   int width;
941   int x0[4], x1[4];
942   float xw[4]; /* weights */
943
944
945   level0 = samp->level;
946   width = texture->width[level0];
947
948   assert(width > 0);
949
950   samp->linear_texcoord_s(s, width, x0, x1, xw);
951
952
953   for (j = 0; j < QUAD_SIZE; j++) {
954      float tx[4][4]; /* texels */
955      int c;
956      get_texel(tgsi_sampler, 0, level0, x0[j], 0, 0, tx, 0);
957      get_texel(tgsi_sampler, 0, level0, x1[j], 0, 0, tx, 1);
958
959      /* interpolate R, G, B, A */
960      for (c = 0; c < 4; c++) {
961         rgba[c][j] = lerp(xw[j], tx[c][0], tx[c][1]);
962      }
963   }
964}
965
966static void
967img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
968                     const float s[QUAD_SIZE],
969                     const float t[QUAD_SIZE],
970                     const float p[QUAD_SIZE],
971                     float lodbias,
972                     float rgba[NUM_CHANNELS][QUAD_SIZE])
973{
974   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
975   const struct pipe_texture *texture = samp->texture;
976   const unsigned *faces = samp->faces; /* zero when not cube-mapping */
977   unsigned level0, j;
978   int width, height;
979   int x0[4], y0[4], x1[4], y1[4];
980   float xw[4], yw[4]; /* weights */
981
982
983   level0 = samp->level;
984   width = texture->width[level0];
985   height = texture->height[level0];
986
987   assert(width > 0);
988
989   samp->linear_texcoord_s(s, width,  x0, x1, xw);
990   samp->linear_texcoord_t(t, height, y0, y1, yw);
991
992   for (j = 0; j < QUAD_SIZE; j++) {
993      float tx[4][4]; /* texels */
994      int c;
995      get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0);
996      get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1);
997      get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2);
998      get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3);
999
1000      /* interpolate R, G, B, A */
1001      for (c = 0; c < 4; c++) {
1002         rgba[c][j] = lerp_2d(xw[j], yw[j],
1003                              tx[c][0], tx[c][1],
1004                              tx[c][2], tx[c][3]);
1005      }
1006   }
1007}
1008
1009
1010static void
1011img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler,
1012                     const float s[QUAD_SIZE],
1013                     const float t[QUAD_SIZE],
1014                     const float p[QUAD_SIZE],
1015                     float lodbias,
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   unsigned level0, j;
1021   int width, height, depth;
1022   int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4];
1023   float xw[4], yw[4], zw[4]; /* interpolation weights */
1024
1025   level0 = samp->level;
1026   width = texture->width[level0];
1027   height = texture->height[level0];
1028   depth = texture->depth[level0];
1029
1030   assert(width > 0);
1031   assert(height > 0);
1032   assert(depth > 0);
1033
1034   samp->linear_texcoord_s(s, width,  x0, x1, xw);
1035   samp->linear_texcoord_t(t, height, y0, y1, yw);
1036   samp->linear_texcoord_p(p, depth,  z0, z1, zw);
1037
1038   for (j = 0; j < QUAD_SIZE; j++) {
1039      float tx0[4][4], tx1[4][4];
1040      int c;
1041
1042      get_texel(tgsi_sampler, 0, level0, x0[j], y0[j], z0[j], tx0, 0);
1043      get_texel(tgsi_sampler, 0, level0, x1[j], y0[j], z0[j], tx0, 1);
1044      get_texel(tgsi_sampler, 0, level0, x0[j], y1[j], z0[j], tx0, 2);
1045      get_texel(tgsi_sampler, 0, level0, x1[j], y1[j], z0[j], tx0, 3);
1046      get_texel(tgsi_sampler, 0, level0, x0[j], y0[j], z1[j], tx1, 0);
1047      get_texel(tgsi_sampler, 0, level0, x1[j], y0[j], z1[j], tx1, 1);
1048      get_texel(tgsi_sampler, 0, level0, x0[j], y1[j], z1[j], tx1, 2);
1049      get_texel(tgsi_sampler, 0, level0, x1[j], y1[j], z1[j], tx1, 3);
1050
1051      /* interpolate R, G, B, A */
1052      for (c = 0; c < 4; c++) {
1053         rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j],
1054                              tx0[c][0], tx0[c][1],
1055                              tx0[c][2], tx0[c][3],
1056                              tx1[c][0], tx1[c][1],
1057                              tx1[c][2], tx1[c][3]);
1058      }
1059   }
1060}
1061
1062
1063
1064
1065
1066
1067
1068static void
1069mip_filter_linear(struct tgsi_sampler *tgsi_sampler,
1070                     const float s[QUAD_SIZE],
1071                     const float t[QUAD_SIZE],
1072                     const float p[QUAD_SIZE],
1073                     float lodbias,
1074                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1075{
1076   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1077   const struct pipe_texture *texture = samp->texture;
1078   int level0;
1079   float lambda;
1080
1081   lambda = samp->compute_lambda(samp, s, t, p, lodbias);
1082   level0 = (int)lambda;
1083
1084   if (lambda < 0.0) {
1085      samp->level = 0;
1086      samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1087   }
1088   else if (level0 >= texture->last_level) {
1089      samp->level = texture->last_level;
1090      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1091   }
1092   else {
1093      float levelBlend = lambda - level0;
1094      float rgba0[4][4];
1095      float rgba1[4][4];
1096      int c,j;
1097
1098      samp->level = level0;
1099      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba0 );
1100
1101      samp->level = level0+1;
1102      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba1 );
1103
1104      for (j = 0; j < QUAD_SIZE; j++) {
1105         for (c = 0; c < 4; c++) {
1106            rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
1107         }
1108      }
1109   }
1110}
1111
1112
1113
1114static void
1115mip_filter_nearest(struct tgsi_sampler *tgsi_sampler,
1116                   const float s[QUAD_SIZE],
1117                   const float t[QUAD_SIZE],
1118                   const float p[QUAD_SIZE],
1119                   float lodbias,
1120                   float rgba[NUM_CHANNELS][QUAD_SIZE])
1121{
1122   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1123   const struct pipe_texture *texture = samp->texture;
1124   float lambda;
1125
1126   lambda = samp->compute_lambda(samp, s, t, p, lodbias);
1127
1128   if (lambda < 0.0) {
1129      samp->level = 0;
1130      samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1131   }
1132   else {
1133      samp->level = (int)(lambda + 0.5) ;
1134      samp->level = MIN2(samp->level, (int)texture->last_level);
1135      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1136   }
1137}
1138
1139
1140static void
1141mip_filter_none(struct tgsi_sampler *tgsi_sampler,
1142                const float s[QUAD_SIZE],
1143                const float t[QUAD_SIZE],
1144                const float p[QUAD_SIZE],
1145                float lodbias,
1146                float rgba[NUM_CHANNELS][QUAD_SIZE])
1147{
1148   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1149   float lambda = samp->compute_lambda(samp, s, t, p, lodbias);
1150
1151   if (lambda < 0.0) {
1152      samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1153   }
1154   else {
1155      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1156   }
1157}
1158
1159
1160
1161/* Specialized version of mip_filter_linear with hard-wired calls to
1162 * 2d lambda calculation and 2d_linear_repeat_POT img filters.
1163 */
1164static void
1165mip_filter_linear_2d_linear_repeat_POT(
1166   struct tgsi_sampler *tgsi_sampler,
1167   const float s[QUAD_SIZE],
1168   const float t[QUAD_SIZE],
1169   const float p[QUAD_SIZE],
1170   float lodbias,
1171   float rgba[NUM_CHANNELS][QUAD_SIZE])
1172{
1173   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1174   const struct pipe_texture *texture = samp->texture;
1175   int level0;
1176   float lambda;
1177
1178   lambda = compute_lambda_2d(samp, s, t, p, lodbias);
1179   level0 = (int)lambda;
1180
1181   /* Catches both negative and large values of level0:
1182    */
1183   if ((unsigned)level0 >= texture->last_level) {
1184      if (level0 < 0)
1185         samp->level = 0;
1186      else
1187         samp->level = texture->last_level;
1188
1189      img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba );
1190   }
1191   else {
1192      float levelBlend = lambda - level0;
1193      float rgba0[4][4];
1194      float rgba1[4][4];
1195      int c,j;
1196
1197      samp->level = level0;
1198      img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba0 );
1199
1200      samp->level = level0+1;
1201      img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba1 );
1202
1203      for (j = 0; j < QUAD_SIZE; j++) {
1204         for (c = 0; c < 4; c++) {
1205            rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
1206         }
1207      }
1208   }
1209}
1210
1211
1212
1213/* Compare stage in the little sampling pipeline.
1214 */
1215static void
1216sample_compare(struct tgsi_sampler *tgsi_sampler,
1217               const float s[QUAD_SIZE],
1218               const float t[QUAD_SIZE],
1219               const float p[QUAD_SIZE],
1220               float lodbias,
1221               float rgba[NUM_CHANNELS][QUAD_SIZE])
1222{
1223   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1224   const struct pipe_sampler_state *sampler = samp->sampler;
1225   int j, k0, k1, k2, k3;
1226   float val;
1227
1228   samp->mip_filter( tgsi_sampler, s, t, p, lodbias, rgba );
1229
1230
1231   /**
1232    * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
1233    * When we sampled the depth texture, the depth value was put into all
1234    * RGBA channels.  We look at the red channel here.
1235    */
1236
1237   /* compare four texcoords vs. four texture samples */
1238   switch (sampler->compare_func) {
1239   case PIPE_FUNC_LESS:
1240      k0 = p[0] < rgba[0][0];
1241      k1 = p[1] < rgba[0][1];
1242      k2 = p[2] < rgba[0][2];
1243      k3 = p[3] < rgba[0][3];
1244      break;
1245   case PIPE_FUNC_LEQUAL:
1246      k0 = p[0] <= rgba[0][0];
1247      k1 = p[1] <= rgba[0][1];
1248      k2 = p[2] <= rgba[0][2];
1249      k3 = p[3] <= rgba[0][3];
1250      break;
1251   case PIPE_FUNC_GREATER:
1252      k0 = p[0] > rgba[0][0];
1253      k1 = p[1] > rgba[0][1];
1254      k2 = p[2] > rgba[0][2];
1255      k3 = p[3] > rgba[0][3];
1256      break;
1257   case PIPE_FUNC_GEQUAL:
1258      k0 = p[0] >= rgba[0][0];
1259      k1 = p[1] >= rgba[0][1];
1260      k2 = p[2] >= rgba[0][2];
1261      k3 = p[3] >= rgba[0][3];
1262      break;
1263   case PIPE_FUNC_EQUAL:
1264      k0 = p[0] == rgba[0][0];
1265      k1 = p[1] == rgba[0][1];
1266      k2 = p[2] == rgba[0][2];
1267      k3 = p[3] == rgba[0][3];
1268      break;
1269   case PIPE_FUNC_NOTEQUAL:
1270      k0 = p[0] != rgba[0][0];
1271      k1 = p[1] != rgba[0][1];
1272      k2 = p[2] != rgba[0][2];
1273      k3 = p[3] != rgba[0][3];
1274      break;
1275   case PIPE_FUNC_ALWAYS:
1276      k0 = k1 = k2 = k3 = 1;
1277      break;
1278   case PIPE_FUNC_NEVER:
1279      k0 = k1 = k2 = k3 = 0;
1280      break;
1281   default:
1282      k0 = k1 = k2 = k3 = 0;
1283      assert(0);
1284      break;
1285   }
1286
1287   /* convert four pass/fail values to an intensity in [0,1] */
1288   val = 0.25F * (k0 + k1 + k2 + k3);
1289
1290   /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
1291   for (j = 0; j < 4; j++) {
1292      rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
1293      rgba[3][j] = 1.0F;
1294   }
1295}
1296
1297/* Calculate cube faces.
1298 */
1299static void
1300sample_cube(struct tgsi_sampler *tgsi_sampler,
1301            const float s[QUAD_SIZE],
1302            const float t[QUAD_SIZE],
1303            const float p[QUAD_SIZE],
1304            float lodbias,
1305            float rgba[NUM_CHANNELS][QUAD_SIZE])
1306{
1307   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1308   unsigned j;
1309   float ssss[4], tttt[4];
1310
1311   /*
1312     major axis
1313     direction     target                             sc     tc    ma
1314     ----------    -------------------------------    ---    ---   ---
1315     +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
1316     -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
1317     +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
1318     -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
1319     +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
1320     -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
1321   */
1322   for (j = 0; j < QUAD_SIZE; j++) {
1323      float rx = s[j];
1324      float ry = t[j];
1325      float rz = p[j];
1326      const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
1327      unsigned face;
1328      float sc, tc, ma;
1329
1330      if (arx > ary && arx > arz) {
1331         if (rx >= 0.0F) {
1332            face = PIPE_TEX_FACE_POS_X;
1333            sc = -rz;
1334            tc = -ry;
1335            ma = arx;
1336         }
1337         else {
1338            face = PIPE_TEX_FACE_NEG_X;
1339            sc = rz;
1340            tc = -ry;
1341            ma = arx;
1342         }
1343      }
1344      else if (ary > arx && ary > arz) {
1345         if (ry >= 0.0F) {
1346            face = PIPE_TEX_FACE_POS_Y;
1347            sc = rx;
1348            tc = rz;
1349            ma = ary;
1350         }
1351         else {
1352            face = PIPE_TEX_FACE_NEG_Y;
1353            sc = rx;
1354            tc = -rz;
1355            ma = ary;
1356         }
1357      }
1358      else {
1359         if (rz > 0.0F) {
1360            face = PIPE_TEX_FACE_POS_Z;
1361            sc = rx;
1362            tc = -ry;
1363            ma = arz;
1364         }
1365         else {
1366            face = PIPE_TEX_FACE_NEG_Z;
1367            sc = -rx;
1368            tc = -ry;
1369            ma = arz;
1370         }
1371      }
1372
1373      ssss[j] = ( sc / ma + 1.0F ) * 0.5F;
1374      tttt[j] = ( tc / ma + 1.0F ) * 0.5F;
1375      samp->faces[j] = face;
1376   }
1377
1378   /* In our little pipeline, the compare stage is next.  If compare
1379    * is not active, this will point somewhere deeper into the
1380    * pipeline, eg. to mip_filter or even img_filter.
1381    */
1382   samp->compare(tgsi_sampler, ssss, tttt, NULL, lodbias, rgba);
1383}
1384
1385
1386
1387
1388static wrap_nearest_func get_nearest_unorm_wrap( unsigned mode )
1389{
1390   switch (mode) {
1391   case PIPE_TEX_WRAP_CLAMP:
1392      return wrap_nearest_unorm_clamp;
1393   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1394   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1395      return wrap_nearest_unorm_clamp_to_border;
1396   default:
1397      assert(0);
1398      return wrap_nearest_unorm_clamp;
1399   }
1400}
1401
1402
1403static wrap_nearest_func get_nearest_wrap( unsigned mode )
1404{
1405   switch (mode) {
1406   case PIPE_TEX_WRAP_REPEAT:
1407      return wrap_nearest_repeat;
1408   case PIPE_TEX_WRAP_CLAMP:
1409      return wrap_nearest_clamp;
1410   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1411      return wrap_nearest_clamp_to_edge;
1412   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1413      return wrap_nearest_clamp_to_border;
1414   case PIPE_TEX_WRAP_MIRROR_REPEAT:
1415      return wrap_nearest_mirror_repeat;
1416   case PIPE_TEX_WRAP_MIRROR_CLAMP:
1417      return wrap_nearest_mirror_clamp;
1418   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
1419      return wrap_nearest_mirror_clamp_to_edge;
1420   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
1421      return wrap_nearest_mirror_clamp_to_border;
1422   default:
1423      assert(0);
1424      return wrap_nearest_repeat;
1425   }
1426}
1427
1428static wrap_linear_func get_linear_unorm_wrap( unsigned mode )
1429{
1430   switch (mode) {
1431   case PIPE_TEX_WRAP_CLAMP:
1432      return wrap_linear_unorm_clamp;
1433   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1434   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1435      return wrap_linear_unorm_clamp_to_border;
1436   default:
1437      assert(0);
1438      return wrap_linear_unorm_clamp;
1439   }
1440}
1441
1442static wrap_linear_func get_linear_wrap( unsigned mode )
1443{
1444   switch (mode) {
1445   case PIPE_TEX_WRAP_REPEAT:
1446      return wrap_linear_repeat;
1447   case PIPE_TEX_WRAP_CLAMP:
1448      return wrap_linear_clamp;
1449   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1450      return wrap_linear_clamp_to_edge;
1451   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1452      return wrap_linear_clamp_to_border;
1453   case PIPE_TEX_WRAP_MIRROR_REPEAT:
1454      return wrap_linear_mirror_repeat;
1455   case PIPE_TEX_WRAP_MIRROR_CLAMP:
1456      return wrap_linear_mirror_clamp;
1457   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
1458      return wrap_linear_mirror_clamp_to_edge;
1459   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
1460      return wrap_linear_mirror_clamp_to_border;
1461   default:
1462      assert(0);
1463      return wrap_linear_repeat;
1464   }
1465}
1466
1467static compute_lambda_func get_lambda_func( const union sp_sampler_key key )
1468{
1469   if (key.bits.processor == TGSI_PROCESSOR_VERTEX)
1470      return compute_lambda_vert;
1471
1472   switch (key.bits.target) {
1473   case PIPE_TEXTURE_1D:
1474      return compute_lambda_1d;
1475   case PIPE_TEXTURE_2D:
1476   case PIPE_TEXTURE_CUBE:
1477      return compute_lambda_2d;
1478   case PIPE_TEXTURE_3D:
1479      return compute_lambda_3d;
1480   default:
1481      assert(0);
1482      return compute_lambda_1d;
1483   }
1484}
1485
1486static filter_func get_img_filter( const union sp_sampler_key key,
1487                                   unsigned filter,
1488                                   const struct pipe_sampler_state *sampler )
1489{
1490   switch (key.bits.target) {
1491   case PIPE_TEXTURE_1D:
1492      if (filter == PIPE_TEX_FILTER_NEAREST)
1493         return img_filter_1d_nearest;
1494      else
1495         return img_filter_1d_linear;
1496      break;
1497   case PIPE_TEXTURE_2D:
1498      /* Try for fast path:
1499       */
1500      if (key.bits.is_pot &&
1501          sampler->wrap_s == sampler->wrap_t &&
1502          sampler->normalized_coords)
1503      {
1504         switch (sampler->wrap_s) {
1505         case PIPE_TEX_WRAP_REPEAT:
1506            switch (filter) {
1507            case PIPE_TEX_FILTER_NEAREST:
1508               return img_filter_2d_nearest_repeat_POT;
1509            case PIPE_TEX_FILTER_LINEAR:
1510               return img_filter_2d_linear_repeat_POT;
1511            default:
1512               break;
1513            }
1514            break;
1515         case PIPE_TEX_WRAP_CLAMP:
1516            switch (filter) {
1517            case PIPE_TEX_FILTER_NEAREST:
1518               return img_filter_2d_nearest_clamp_POT;
1519            default:
1520               break;
1521            }
1522         }
1523      }
1524      /* Fallthrough to default versions:
1525       */
1526   case PIPE_TEXTURE_CUBE:
1527      if (filter == PIPE_TEX_FILTER_NEAREST)
1528         return img_filter_2d_nearest;
1529      else
1530         return img_filter_2d_linear;
1531      break;
1532   case PIPE_TEXTURE_3D:
1533      if (filter == PIPE_TEX_FILTER_NEAREST)
1534         return img_filter_3d_nearest;
1535      else
1536         return img_filter_3d_linear;
1537      break;
1538   default:
1539      assert(0);
1540      return img_filter_1d_nearest;
1541   }
1542}
1543
1544
1545/**
1546 * Bind the given texture object and texture cache to the sampler varient.
1547 */
1548void
1549sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp,
1550                                 struct softpipe_tile_cache *tex_cache,
1551                                 const struct pipe_texture *texture )
1552{
1553   const struct pipe_sampler_state *sampler = samp->sampler;
1554
1555   samp->texture = texture;
1556   samp->cache = tex_cache;
1557   samp->xpot = util_unsigned_logbase2( texture->width[0] );
1558   samp->ypot = util_unsigned_logbase2( texture->height[0] );
1559   samp->level = CLAMP((int) sampler->min_lod, 0, (int) texture->last_level);
1560}
1561
1562
1563void
1564sp_sampler_varient_destroy( struct sp_sampler_varient *samp )
1565{
1566   FREE(samp);
1567}
1568
1569
1570/* Create a sampler varient for a given set of non-orthogonal state.  Currently the
1571 */
1572struct sp_sampler_varient *
1573sp_create_sampler_varient( const struct pipe_sampler_state *sampler,
1574                           const union sp_sampler_key key )
1575{
1576   struct sp_sampler_varient *samp = CALLOC_STRUCT(sp_sampler_varient);
1577   if (!samp)
1578      return NULL;
1579
1580   samp->sampler = sampler;
1581   samp->key = key;
1582
1583   /* Note that (for instance) linear_texcoord_s and
1584    * nearest_texcoord_s may be active at the same time, if the
1585    * sampler min_img_filter differs from its mag_img_filter.
1586    */
1587   if (sampler->normalized_coords) {
1588      samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
1589      samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
1590      samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
1591
1592      samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
1593      samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
1594      samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
1595   }
1596   else {
1597      samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
1598      samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
1599      samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
1600
1601      samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
1602      samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
1603      samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
1604   }
1605
1606   samp->compute_lambda = get_lambda_func( key );
1607
1608   samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler);
1609   samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler);
1610
1611   switch (sampler->min_mip_filter) {
1612   case PIPE_TEX_MIPFILTER_NONE:
1613      if (sampler->min_img_filter == sampler->mag_img_filter)
1614         samp->mip_filter = samp->min_img_filter;
1615      else
1616         samp->mip_filter = mip_filter_none;
1617      break;
1618
1619   case PIPE_TEX_MIPFILTER_NEAREST:
1620      samp->mip_filter = mip_filter_nearest;
1621      break;
1622
1623   case PIPE_TEX_MIPFILTER_LINEAR:
1624      if (key.bits.is_pot &&
1625          sampler->min_img_filter == sampler->mag_img_filter &&
1626          sampler->normalized_coords &&
1627          sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
1628          sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
1629          sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR)
1630      {
1631         samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT;
1632      }
1633      else
1634      {
1635         samp->mip_filter = mip_filter_linear;
1636      }
1637      break;
1638   }
1639
1640   if (sampler->compare_mode != FALSE) {
1641      samp->compare = sample_compare;
1642   }
1643   else {
1644      /* Skip compare operation by promoting the mip_filter function
1645       * pointer:
1646       */
1647      samp->compare = samp->mip_filter;
1648   }
1649
1650   if (key.bits.target == PIPE_TEXTURE_CUBE) {
1651      samp->base.get_samples = sample_cube;
1652   }
1653   else {
1654      samp->faces[0] = 0;
1655      samp->faces[1] = 0;
1656      samp->faces[2] = 0;
1657      samp->faces[3] = 0;
1658
1659      /* Skip cube face determination by promoting the compare
1660       * function pointer:
1661       */
1662      samp->base.get_samples = samp->compare;
1663   }
1664
1665   return samp;
1666}
1667
1668
1669
1670
1671
1672
1673