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