sp_tex_sample.c revision 75276ea316610a5737f2115326482024aa09d02a
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_tex_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 addr  the template tex address containing cube, z, face info.
596 * \param x  the x coord of texel within 2D image
597 * \param y  the y coord of texel within 2D image
598 * \param rgba  the quad to put the texel/color into
599 *
600 * XXX maybe move this into sp_tex_tile_cache.c and merge with the
601 * sp_get_cached_tile_tex() function.  Also, get 4 texels instead of 1...
602 */
603
604
605
606
607static INLINE const float *
608get_texel_2d_no_border(const struct sp_sampler_varient *samp,
609		       union tex_tile_address addr, int x, int y)
610{
611   const struct softpipe_tex_cached_tile *tile;
612
613   addr.bits.x = x / TILE_SIZE;
614   addr.bits.y = y / TILE_SIZE;
615   y %= TILE_SIZE;
616   x %= TILE_SIZE;
617
618   tile = sp_get_cached_tile_tex(samp->cache, addr);
619
620   return &tile->data.color[y][x][0];
621}
622
623
624static INLINE const float *
625get_texel_2d(const struct sp_sampler_varient *samp,
626	     union tex_tile_address addr, int x, int y)
627{
628   const struct pipe_texture *texture = samp->texture;
629   unsigned level = addr.bits.level;
630
631   if (x < 0 || x >= (int) texture->width[level] ||
632       y < 0 || y >= (int) texture->height[level]) {
633      return samp->sampler->border_color;
634   }
635   else {
636      return get_texel_2d_no_border( samp, addr, x, y );
637   }
638}
639
640
641/* Gather a quad of adjacent texels within a tile:
642 */
643static INLINE void
644get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_varient *samp,
645					union tex_tile_address addr,
646					unsigned x, unsigned y,
647					const float *out[4])
648{
649   const struct softpipe_tex_cached_tile *tile;
650
651   addr.bits.x = x / TILE_SIZE;
652   addr.bits.y = y / TILE_SIZE;
653   y %= TILE_SIZE;
654   x %= TILE_SIZE;
655
656   tile = sp_get_cached_tile_tex(samp->cache, addr);
657
658   out[0] = &tile->data.color[y  ][x  ][0];
659   out[1] = &tile->data.color[y  ][x+1][0];
660   out[2] = &tile->data.color[y+1][x  ][0];
661   out[3] = &tile->data.color[y+1][x+1][0];
662}
663
664
665/* Gather a quad of potentially non-adjacent texels:
666 */
667static INLINE void
668get_texel_quad_2d_no_border(const struct sp_sampler_varient *samp,
669			    union tex_tile_address addr,
670			    int x0, int y0,
671			    int x1, int y1,
672			    const float *out[4])
673{
674   out[0] = get_texel_2d_no_border( samp, addr, x0, y0 );
675   out[1] = get_texel_2d_no_border( samp, addr, x1, y0 );
676   out[2] = get_texel_2d_no_border( samp, addr, x0, y1 );
677   out[3] = get_texel_2d_no_border( samp, addr, x1, y1 );
678}
679
680/* Can involve a lot of unnecessary checks for border color:
681 */
682static INLINE void
683get_texel_quad_2d(const struct sp_sampler_varient *samp,
684		  union tex_tile_address addr,
685		  int x0, int y0,
686		  int x1, int y1,
687		  const float *out[4])
688{
689   out[0] = get_texel_2d( samp, addr, x0, y0 );
690   out[1] = get_texel_2d( samp, addr, x1, y0 );
691   out[3] = get_texel_2d( samp, addr, x1, y1 );
692   out[2] = get_texel_2d( samp, addr, x0, y1 );
693}
694
695
696
697/* 3d varients:
698 */
699static INLINE const float *
700get_texel_3d_no_border(const struct sp_sampler_varient *samp,
701		    union tex_tile_address addr, int x, int y, int z)
702{
703   const struct softpipe_tex_cached_tile *tile;
704
705   addr.bits.x = x / TILE_SIZE;
706   addr.bits.y = y / TILE_SIZE;
707   addr.bits.z = z;
708   y %= TILE_SIZE;
709   x %= TILE_SIZE;
710
711   tile = sp_get_cached_tile_tex(samp->cache, addr);
712
713   return &tile->data.color[y][x][0];
714}
715
716
717static INLINE const float *
718get_texel_3d(const struct sp_sampler_varient *samp,
719	     union tex_tile_address addr, int x, int y, int z )
720{
721   const struct pipe_texture *texture = samp->texture;
722   unsigned level = addr.bits.level;
723
724   if (x < 0 || x >= (int) texture->width[level] ||
725       y < 0 || y >= (int) texture->height[level] ||
726       z < 0 || z >= (int) texture->depth[level]) {
727      return samp->sampler->border_color;
728   }
729   else {
730      return get_texel_3d_no_border( samp, addr, x, y, z );
731   }
732}
733
734
735/**
736 * Given the logbase2 of a mipmap's base level size and a mipmap level,
737 * return the size (in texels) of that mipmap level.
738 * For example, if level[0].width = 256 then base_pot will be 8.
739 * If level = 2, then we'll return 64 (the width at level=2).
740 * Return 1 if level > base_pot.
741 */
742static INLINE unsigned
743pot_level_size(unsigned base_pot, unsigned level)
744{
745   return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
746}
747
748
749/* Some image-filter fastpaths:
750 */
751static INLINE void
752img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler,
753                                  const float s[QUAD_SIZE],
754                                  const float t[QUAD_SIZE],
755                                  const float p[QUAD_SIZE],
756                                  float lodbias,
757                                  float rgba[NUM_CHANNELS][QUAD_SIZE])
758{
759   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
760   unsigned  j;
761   unsigned level = samp->level;
762   unsigned xpot = pot_level_size(samp->xpot, level);
763   unsigned ypot = pot_level_size(samp->ypot, level);
764   unsigned xmax = (xpot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, xpot) - 1; */
765   unsigned ymax = (ypot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, ypot) - 1; */
766   union tex_tile_address addr;
767
768   addr.value = 0;
769   addr.bits.level = samp->level;
770
771
772   for (j = 0; j < QUAD_SIZE; j++) {
773      int c;
774
775      float u = s[j] * xpot - 0.5F;
776      float v = t[j] * ypot - 0.5F;
777
778      int uflr = util_ifloor(u);
779      int vflr = util_ifloor(v);
780
781      float xw = u - (float)uflr;
782      float yw = v - (float)vflr;
783
784      int x0 = uflr & (xpot - 1);
785      int y0 = vflr & (ypot - 1);
786
787      const float *tx[4];
788
789      /* Can we fetch all four at once:
790       */
791      if (x0 < xmax && y0 < ymax)
792      {
793         get_texel_quad_2d_no_border_single_tile(samp, addr, x0, y0, tx);
794      }
795      else
796      {
797         unsigned x1 = (x0 + 1) & (xpot - 1);
798         unsigned y1 = (y0 + 1) & (ypot - 1);
799         get_texel_quad_2d_no_border(samp, addr, x0, y0, x1, y1, tx);
800      }
801
802
803      /* interpolate R, G, B, A */
804      for (c = 0; c < 4; c++) {
805         rgba[c][j] = lerp_2d(xw, yw,
806                              tx[0][c], tx[1][c],
807                              tx[2][c], tx[3][c]);
808      }
809   }
810}
811
812
813static INLINE void
814img_filter_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler,
815                                 const float s[QUAD_SIZE],
816                                 const float t[QUAD_SIZE],
817                                 const float p[QUAD_SIZE],
818                                 float lodbias,
819                                 float rgba[NUM_CHANNELS][QUAD_SIZE])
820{
821   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
822   unsigned  j;
823   unsigned level = samp->level;
824   unsigned xpot = pot_level_size(samp->xpot, level);
825   unsigned ypot = pot_level_size(samp->ypot, level);
826   union tex_tile_address addr;
827
828   addr.value = 0;
829   addr.bits.level = samp->level;
830
831   for (j = 0; j < QUAD_SIZE; j++) {
832      int c;
833
834      float u = s[j] * xpot;
835      float v = t[j] * ypot;
836
837      int uflr = util_ifloor(u);
838      int vflr = util_ifloor(v);
839
840      int x0 = uflr & (xpot - 1);
841      int y0 = vflr & (ypot - 1);
842
843      const float *out = get_texel_2d_no_border(samp, addr, x0, y0);
844
845      for (c = 0; c < 4; c++) {
846         rgba[c][j] = out[c];
847      }
848   }
849}
850
851
852static INLINE void
853img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler,
854                                const float s[QUAD_SIZE],
855                                const float t[QUAD_SIZE],
856                                const float p[QUAD_SIZE],
857                                float lodbias,
858                                float rgba[NUM_CHANNELS][QUAD_SIZE])
859{
860   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
861   unsigned  j;
862   unsigned level = samp->level;
863   unsigned xpot = pot_level_size(samp->xpot, level);
864   unsigned ypot = pot_level_size(samp->ypot, level);
865   union tex_tile_address addr;
866
867   addr.value = 0;
868   addr.bits.level = samp->level;
869
870   for (j = 0; j < QUAD_SIZE; j++) {
871      int c;
872
873      float u = s[j] * xpot;
874      float v = t[j] * ypot;
875
876      int x0, y0;
877      const float *out;
878
879      x0 = util_ifloor(u);
880      if (x0 < 0)
881         x0 = 0;
882      else if (x0 > xpot - 1)
883         x0 = xpot - 1;
884
885      y0 = util_ifloor(v);
886      if (y0 < 0)
887         y0 = 0;
888      else if (y0 > ypot - 1)
889         y0 = ypot - 1;
890
891      out = get_texel_2d_no_border(samp, addr, x0, y0);
892
893      for (c = 0; c < 4; c++) {
894         rgba[c][j] = out[c];
895      }
896   }
897}
898
899static void
900img_filter_1d_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;
911   int x[4];
912   union tex_tile_address addr;
913
914   level0 = samp->level;
915   width = texture->width[level0];
916
917   assert(width > 0);
918
919   addr.value = 0;
920   addr.bits.level = samp->level;
921
922   samp->nearest_texcoord_s(s, width, x);
923
924   for (j = 0; j < QUAD_SIZE; j++) {
925      const float *out = get_texel_2d(samp, addr, x[j], 0);
926      int c;
927      for (c = 0; c < 4; c++) {
928         rgba[c][j] = out[c];
929      }
930   }
931}
932
933
934static void
935img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
936                      const float s[QUAD_SIZE],
937                      const float t[QUAD_SIZE],
938                      const float p[QUAD_SIZE],
939                      float lodbias,
940                      float rgba[NUM_CHANNELS][QUAD_SIZE])
941{
942   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
943   const struct pipe_texture *texture = samp->texture;
944   unsigned level0, j;
945   int width, height;
946   int x[4], y[4];
947   union tex_tile_address addr;
948
949
950   level0 = samp->level;
951   width = texture->width[level0];
952   height = texture->height[level0];
953
954   assert(width > 0);
955   assert(height > 0);
956
957   addr.value = 0;
958   addr.bits.level = samp->level;
959
960   samp->nearest_texcoord_s(s, width, x);
961   samp->nearest_texcoord_t(t, height, y);
962
963   for (j = 0; j < QUAD_SIZE; j++) {
964      const float *out = get_texel_2d(samp, addr, x[j], y[j]);
965      int c;
966      for (c = 0; c < 4; c++) {
967         rgba[c][j] = out[c];
968      }
969   }
970}
971
972static inline union tex_tile_address face( union tex_tile_address addr,
973					   unsigned face )
974{
975   addr.bits.face = face;
976   return addr;
977}
978
979static void
980img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler,
981                      const float s[QUAD_SIZE],
982                      const float t[QUAD_SIZE],
983                      const float p[QUAD_SIZE],
984                      float lodbias,
985                      float rgba[NUM_CHANNELS][QUAD_SIZE])
986{
987   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
988   const struct pipe_texture *texture = samp->texture;
989   const unsigned *faces = samp->faces; /* zero when not cube-mapping */
990   unsigned level0, j;
991   int width, height;
992   int x[4], y[4];
993   union tex_tile_address addr;
994
995
996   level0 = samp->level;
997   width = texture->width[level0];
998   height = texture->height[level0];
999
1000   assert(width > 0);
1001   assert(height > 0);
1002
1003   addr.value = 0;
1004   addr.bits.level = samp->level;
1005
1006   samp->nearest_texcoord_s(s, width, x);
1007   samp->nearest_texcoord_t(t, height, y);
1008
1009   for (j = 0; j < QUAD_SIZE; j++) {
1010      const float *out = get_texel_2d(samp, face(addr, faces[j]), x[j], y[j]);
1011      int c;
1012      for (c = 0; c < 4; c++) {
1013         rgba[c][j] = out[c];
1014      }
1015   }
1016}
1017
1018
1019static void
1020img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler,
1021                      const float s[QUAD_SIZE],
1022                      const float t[QUAD_SIZE],
1023                      const float p[QUAD_SIZE],
1024                      float lodbias,
1025                      float rgba[NUM_CHANNELS][QUAD_SIZE])
1026{
1027   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1028   const struct pipe_texture *texture = samp->texture;
1029   unsigned level0, j;
1030   int width, height, depth;
1031   int x[4], y[4], z[4];
1032   union tex_tile_address addr;
1033
1034   level0 = samp->level;
1035   width = texture->width[level0];
1036   height = texture->height[level0];
1037   depth = texture->depth[level0];
1038
1039   assert(width > 0);
1040   assert(height > 0);
1041   assert(depth > 0);
1042
1043   samp->nearest_texcoord_s(s, width,  x);
1044   samp->nearest_texcoord_t(t, height, y);
1045   samp->nearest_texcoord_p(p, depth,  z);
1046
1047   addr.value = 0;
1048   addr.bits.level = samp->level;
1049
1050   for (j = 0; j < QUAD_SIZE; j++) {
1051      const float *out = get_texel_3d(samp, addr, x[j], y[j], z[j]);
1052      int c;
1053      for (c = 0; c < 4; c++) {
1054         rgba[c][j] = out[c];
1055      }
1056   }
1057}
1058
1059
1060static void
1061img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler,
1062                     const float s[QUAD_SIZE],
1063                     const float t[QUAD_SIZE],
1064                     const float p[QUAD_SIZE],
1065                     float lodbias,
1066                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1067{
1068   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1069   const struct pipe_texture *texture = samp->texture;
1070   unsigned level0, j;
1071   int width;
1072   int x0[4], x1[4];
1073   float xw[4]; /* weights */
1074   union tex_tile_address addr;
1075
1076
1077   level0 = samp->level;
1078   width = texture->width[level0];
1079
1080   assert(width > 0);
1081
1082   addr.value = 0;
1083   addr.bits.level = samp->level;
1084
1085   samp->linear_texcoord_s(s, width, x0, x1, xw);
1086
1087
1088   for (j = 0; j < QUAD_SIZE; j++) {
1089      const float *tx0 = get_texel_2d(samp, addr, x0[j], 0);
1090      const float *tx1 = get_texel_2d(samp, addr, x1[j], 0);
1091      int c;
1092
1093      /* interpolate R, G, B, A */
1094      for (c = 0; c < 4; c++) {
1095         rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]);
1096      }
1097   }
1098}
1099
1100
1101static void
1102img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
1103                     const float s[QUAD_SIZE],
1104                     const float t[QUAD_SIZE],
1105                     const float p[QUAD_SIZE],
1106                     float lodbias,
1107                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1108{
1109   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1110   const struct pipe_texture *texture = samp->texture;
1111   unsigned level0, j;
1112   int width, height;
1113   int x0[4], y0[4], x1[4], y1[4];
1114   float xw[4], yw[4]; /* weights */
1115   union tex_tile_address addr;
1116
1117
1118   level0 = samp->level;
1119   width = texture->width[level0];
1120   height = texture->height[level0];
1121
1122   assert(width > 0);
1123   assert(height > 0);
1124
1125   addr.value = 0;
1126   addr.bits.level = samp->level;
1127
1128   samp->linear_texcoord_s(s, width,  x0, x1, xw);
1129   samp->linear_texcoord_t(t, height, y0, y1, yw);
1130
1131   for (j = 0; j < QUAD_SIZE; j++) {
1132      const float *tx0 = get_texel_2d(samp, addr, x0[j], y0[j]);
1133      const float *tx1 = get_texel_2d(samp, addr, x1[j], y0[j]);
1134      const float *tx2 = get_texel_2d(samp, addr, x0[j], y1[j]);
1135      const float *tx3 = get_texel_2d(samp, addr, x1[j], y1[j]);
1136      int c;
1137
1138      /* interpolate R, G, B, A */
1139      for (c = 0; c < 4; c++) {
1140         rgba[c][j] = lerp_2d(xw[j], yw[j],
1141                              tx0[c], tx1[c],
1142                              tx2[c], tx3[c]);
1143      }
1144   }
1145}
1146
1147
1148static void
1149img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
1150                     const float s[QUAD_SIZE],
1151                     const float t[QUAD_SIZE],
1152                     const float p[QUAD_SIZE],
1153                     float lodbias,
1154                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1155{
1156   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1157   const struct pipe_texture *texture = samp->texture;
1158   const unsigned *faces = samp->faces; /* zero when not cube-mapping */
1159   unsigned level0, j;
1160   int width, height;
1161   int x0[4], y0[4], x1[4], y1[4];
1162   float xw[4], yw[4]; /* weights */
1163   union tex_tile_address addr;
1164
1165
1166   level0 = samp->level;
1167   width = texture->width[level0];
1168   height = texture->height[level0];
1169
1170   assert(width > 0);
1171   assert(height > 0);
1172
1173   addr.value = 0;
1174   addr.bits.level = samp->level;
1175
1176   samp->linear_texcoord_s(s, width,  x0, x1, xw);
1177   samp->linear_texcoord_t(t, height, y0, y1, yw);
1178
1179   for (j = 0; j < QUAD_SIZE; j++) {
1180      union tex_tile_address addrj = face(addr, faces[j]);
1181      const float *tx0 = get_texel_2d(samp, addrj, x0[j], y0[j]);
1182      const float *tx1 = get_texel_2d(samp, addrj, x1[j], y0[j]);
1183      const float *tx2 = get_texel_2d(samp, addrj, x0[j], y1[j]);
1184      const float *tx3 = get_texel_2d(samp, addrj, x1[j], y1[j]);
1185      int c;
1186
1187      /* interpolate R, G, B, A */
1188      for (c = 0; c < 4; c++) {
1189         rgba[c][j] = lerp_2d(xw[j], yw[j],
1190                              tx0[c], tx1[c],
1191                              tx2[c], tx3[c]);
1192      }
1193   }
1194}
1195
1196
1197static void
1198img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler,
1199                     const float s[QUAD_SIZE],
1200                     const float t[QUAD_SIZE],
1201                     const float p[QUAD_SIZE],
1202                     float lodbias,
1203                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1204{
1205   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1206   const struct pipe_texture *texture = samp->texture;
1207   unsigned level0, j;
1208   int width, height, depth;
1209   int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4];
1210   float xw[4], yw[4], zw[4]; /* interpolation weights */
1211   union tex_tile_address addr;
1212
1213   level0 = samp->level;
1214   width = texture->width[level0];
1215   height = texture->height[level0];
1216   depth = texture->depth[level0];
1217
1218   addr.value = 0;
1219   addr.bits.level = level0;
1220
1221   assert(width > 0);
1222   assert(height > 0);
1223   assert(depth > 0);
1224
1225   samp->linear_texcoord_s(s, width,  x0, x1, xw);
1226   samp->linear_texcoord_t(t, height, y0, y1, yw);
1227   samp->linear_texcoord_p(p, depth,  z0, z1, zw);
1228
1229   for (j = 0; j < QUAD_SIZE; j++) {
1230      int c;
1231
1232      const float *tx00 = get_texel_3d(samp, addr, x0[j], y0[j], z0[j]);
1233      const float *tx01 = get_texel_3d(samp, addr, x1[j], y0[j], z0[j]);
1234      const float *tx02 = get_texel_3d(samp, addr, x0[j], y1[j], z0[j]);
1235      const float *tx03 = get_texel_3d(samp, addr, x1[j], y1[j], z0[j]);
1236
1237      const float *tx10 = get_texel_3d(samp, addr, x0[j], y0[j], z1[j]);
1238      const float *tx11 = get_texel_3d(samp, addr, x1[j], y0[j], z1[j]);
1239      const float *tx12 = get_texel_3d(samp, addr, x0[j], y1[j], z1[j]);
1240      const float *tx13 = get_texel_3d(samp, addr, x1[j], y1[j], z1[j]);
1241
1242      /* interpolate R, G, B, A */
1243      for (c = 0; c < 4; c++) {
1244         rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j],
1245                              tx00[c], tx01[c],
1246                              tx02[c], tx03[c],
1247                              tx10[c], tx11[c],
1248                              tx12[c], tx13[c]);
1249      }
1250   }
1251}
1252
1253
1254
1255
1256
1257
1258
1259static void
1260mip_filter_linear(struct tgsi_sampler *tgsi_sampler,
1261                     const float s[QUAD_SIZE],
1262                     const float t[QUAD_SIZE],
1263                     const float p[QUAD_SIZE],
1264                     float lodbias,
1265                     float rgba[NUM_CHANNELS][QUAD_SIZE])
1266{
1267   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1268   const struct pipe_texture *texture = samp->texture;
1269   int level0;
1270   float lambda;
1271
1272   lambda = samp->compute_lambda(samp, s, t, p, lodbias);
1273   level0 = (int)lambda;
1274
1275   if (lambda < 0.0) {
1276      samp->level = 0;
1277      samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1278   }
1279   else if (level0 >= texture->last_level) {
1280      samp->level = texture->last_level;
1281      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1282   }
1283   else {
1284      float levelBlend = lambda - level0;
1285      float rgba0[4][4];
1286      float rgba1[4][4];
1287      int c,j;
1288
1289      samp->level = level0;
1290      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba0 );
1291
1292      samp->level = level0+1;
1293      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba1 );
1294
1295      for (j = 0; j < QUAD_SIZE; j++) {
1296         for (c = 0; c < 4; c++) {
1297            rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
1298         }
1299      }
1300   }
1301}
1302
1303
1304
1305static void
1306mip_filter_nearest(struct tgsi_sampler *tgsi_sampler,
1307                   const float s[QUAD_SIZE],
1308                   const float t[QUAD_SIZE],
1309                   const float p[QUAD_SIZE],
1310                   float lodbias,
1311                   float rgba[NUM_CHANNELS][QUAD_SIZE])
1312{
1313   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1314   const struct pipe_texture *texture = samp->texture;
1315   float lambda;
1316
1317   lambda = samp->compute_lambda(samp, s, t, p, lodbias);
1318
1319   if (lambda < 0.0) {
1320      samp->level = 0;
1321      samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1322   }
1323   else {
1324      samp->level = (int)(lambda + 0.5) ;
1325      samp->level = MIN2(samp->level, (int)texture->last_level);
1326      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1327   }
1328
1329#if 0
1330   printf("RGBA %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
1331          rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
1332          rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
1333          rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
1334          rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
1335#endif
1336}
1337
1338
1339static void
1340mip_filter_none(struct tgsi_sampler *tgsi_sampler,
1341                const float s[QUAD_SIZE],
1342                const float t[QUAD_SIZE],
1343                const float p[QUAD_SIZE],
1344                float lodbias,
1345                float rgba[NUM_CHANNELS][QUAD_SIZE])
1346{
1347   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1348   float lambda = samp->compute_lambda(samp, s, t, p, lodbias);
1349
1350   if (lambda < 0.0) {
1351      samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1352   }
1353   else {
1354      samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba );
1355   }
1356}
1357
1358
1359
1360/* Specialized version of mip_filter_linear with hard-wired calls to
1361 * 2d lambda calculation and 2d_linear_repeat_POT img filters.
1362 */
1363static void
1364mip_filter_linear_2d_linear_repeat_POT(
1365   struct tgsi_sampler *tgsi_sampler,
1366   const float s[QUAD_SIZE],
1367   const float t[QUAD_SIZE],
1368   const float p[QUAD_SIZE],
1369   float lodbias,
1370   float rgba[NUM_CHANNELS][QUAD_SIZE])
1371{
1372   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1373   const struct pipe_texture *texture = samp->texture;
1374   int level0;
1375   float lambda;
1376
1377   lambda = compute_lambda_2d(samp, s, t, p, lodbias);
1378   level0 = (int)lambda;
1379
1380   /* Catches both negative and large values of level0:
1381    */
1382   if ((unsigned)level0 >= texture->last_level) {
1383      if (level0 < 0)
1384         samp->level = 0;
1385      else
1386         samp->level = texture->last_level;
1387
1388      img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba );
1389   }
1390   else {
1391      float levelBlend = lambda - level0;
1392      float rgba0[4][4];
1393      float rgba1[4][4];
1394      int c,j;
1395
1396      samp->level = level0;
1397      img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba0 );
1398
1399      samp->level = level0+1;
1400      img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba1 );
1401
1402      for (j = 0; j < QUAD_SIZE; j++) {
1403         for (c = 0; c < 4; c++) {
1404            rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
1405         }
1406      }
1407   }
1408}
1409
1410
1411
1412/* Compare stage in the little sampling pipeline.
1413 */
1414static void
1415sample_compare(struct tgsi_sampler *tgsi_sampler,
1416               const float s[QUAD_SIZE],
1417               const float t[QUAD_SIZE],
1418               const float p[QUAD_SIZE],
1419               float lodbias,
1420               float rgba[NUM_CHANNELS][QUAD_SIZE])
1421{
1422   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1423   const struct pipe_sampler_state *sampler = samp->sampler;
1424   int j, k0, k1, k2, k3;
1425   float val;
1426
1427   samp->mip_filter( tgsi_sampler, s, t, p, lodbias, rgba );
1428
1429
1430   /**
1431    * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
1432    * When we sampled the depth texture, the depth value was put into all
1433    * RGBA channels.  We look at the red channel here.
1434    */
1435
1436   /* compare four texcoords vs. four texture samples */
1437   switch (sampler->compare_func) {
1438   case PIPE_FUNC_LESS:
1439      k0 = p[0] < rgba[0][0];
1440      k1 = p[1] < rgba[0][1];
1441      k2 = p[2] < rgba[0][2];
1442      k3 = p[3] < rgba[0][3];
1443      break;
1444   case PIPE_FUNC_LEQUAL:
1445      k0 = p[0] <= rgba[0][0];
1446      k1 = p[1] <= rgba[0][1];
1447      k2 = p[2] <= rgba[0][2];
1448      k3 = p[3] <= rgba[0][3];
1449      break;
1450   case PIPE_FUNC_GREATER:
1451      k0 = p[0] > rgba[0][0];
1452      k1 = p[1] > rgba[0][1];
1453      k2 = p[2] > rgba[0][2];
1454      k3 = p[3] > rgba[0][3];
1455      break;
1456   case PIPE_FUNC_GEQUAL:
1457      k0 = p[0] >= rgba[0][0];
1458      k1 = p[1] >= rgba[0][1];
1459      k2 = p[2] >= rgba[0][2];
1460      k3 = p[3] >= rgba[0][3];
1461      break;
1462   case PIPE_FUNC_EQUAL:
1463      k0 = p[0] == rgba[0][0];
1464      k1 = p[1] == rgba[0][1];
1465      k2 = p[2] == rgba[0][2];
1466      k3 = p[3] == rgba[0][3];
1467      break;
1468   case PIPE_FUNC_NOTEQUAL:
1469      k0 = p[0] != rgba[0][0];
1470      k1 = p[1] != rgba[0][1];
1471      k2 = p[2] != rgba[0][2];
1472      k3 = p[3] != rgba[0][3];
1473      break;
1474   case PIPE_FUNC_ALWAYS:
1475      k0 = k1 = k2 = k3 = 1;
1476      break;
1477   case PIPE_FUNC_NEVER:
1478      k0 = k1 = k2 = k3 = 0;
1479      break;
1480   default:
1481      k0 = k1 = k2 = k3 = 0;
1482      assert(0);
1483      break;
1484   }
1485
1486   /* convert four pass/fail values to an intensity in [0,1] */
1487   val = 0.25F * (k0 + k1 + k2 + k3);
1488
1489   /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
1490   for (j = 0; j < 4; j++) {
1491      rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
1492      rgba[3][j] = 1.0F;
1493   }
1494}
1495
1496/* Calculate cube faces.
1497 */
1498static void
1499sample_cube(struct tgsi_sampler *tgsi_sampler,
1500            const float s[QUAD_SIZE],
1501            const float t[QUAD_SIZE],
1502            const float p[QUAD_SIZE],
1503            float lodbias,
1504            float rgba[NUM_CHANNELS][QUAD_SIZE])
1505{
1506   struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
1507   unsigned j;
1508   float ssss[4], tttt[4];
1509
1510   /*
1511     major axis
1512     direction     target                             sc     tc    ma
1513     ----------    -------------------------------    ---    ---   ---
1514     +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
1515     -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
1516     +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
1517     -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
1518     +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
1519     -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
1520   */
1521   for (j = 0; j < QUAD_SIZE; j++) {
1522      float rx = s[j];
1523      float ry = t[j];
1524      float rz = p[j];
1525      const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
1526      unsigned face;
1527      float sc, tc, ma;
1528
1529      if (arx > ary && arx > arz) {
1530         if (rx >= 0.0F) {
1531            face = PIPE_TEX_FACE_POS_X;
1532            sc = -rz;
1533            tc = -ry;
1534            ma = arx;
1535         }
1536         else {
1537            face = PIPE_TEX_FACE_NEG_X;
1538            sc = rz;
1539            tc = -ry;
1540            ma = arx;
1541         }
1542      }
1543      else if (ary > arx && ary > arz) {
1544         if (ry >= 0.0F) {
1545            face = PIPE_TEX_FACE_POS_Y;
1546            sc = rx;
1547            tc = rz;
1548            ma = ary;
1549         }
1550         else {
1551            face = PIPE_TEX_FACE_NEG_Y;
1552            sc = rx;
1553            tc = -rz;
1554            ma = ary;
1555         }
1556      }
1557      else {
1558         if (rz > 0.0F) {
1559            face = PIPE_TEX_FACE_POS_Z;
1560            sc = rx;
1561            tc = -ry;
1562            ma = arz;
1563         }
1564         else {
1565            face = PIPE_TEX_FACE_NEG_Z;
1566            sc = -rx;
1567            tc = -ry;
1568            ma = arz;
1569         }
1570      }
1571
1572      {
1573	 const float ima = 1.0 / ma;
1574	 ssss[j] = ( sc * ima + 1.0F ) * 0.5F;
1575	 tttt[j] = ( tc * ima + 1.0F ) * 0.5F;
1576	 samp->faces[j] = face;
1577      }
1578   }
1579
1580   /* In our little pipeline, the compare stage is next.  If compare
1581    * is not active, this will point somewhere deeper into the
1582    * pipeline, eg. to mip_filter or even img_filter.
1583    */
1584   samp->compare(tgsi_sampler, ssss, tttt, NULL, lodbias, rgba);
1585}
1586
1587
1588
1589
1590static wrap_nearest_func get_nearest_unorm_wrap( unsigned mode )
1591{
1592   switch (mode) {
1593   case PIPE_TEX_WRAP_CLAMP:
1594      return wrap_nearest_unorm_clamp;
1595   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1596   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1597      return wrap_nearest_unorm_clamp_to_border;
1598   default:
1599      assert(0);
1600      return wrap_nearest_unorm_clamp;
1601   }
1602}
1603
1604
1605static wrap_nearest_func get_nearest_wrap( unsigned mode )
1606{
1607   switch (mode) {
1608   case PIPE_TEX_WRAP_REPEAT:
1609      return wrap_nearest_repeat;
1610   case PIPE_TEX_WRAP_CLAMP:
1611      return wrap_nearest_clamp;
1612   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1613      return wrap_nearest_clamp_to_edge;
1614   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1615      return wrap_nearest_clamp_to_border;
1616   case PIPE_TEX_WRAP_MIRROR_REPEAT:
1617      return wrap_nearest_mirror_repeat;
1618   case PIPE_TEX_WRAP_MIRROR_CLAMP:
1619      return wrap_nearest_mirror_clamp;
1620   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
1621      return wrap_nearest_mirror_clamp_to_edge;
1622   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
1623      return wrap_nearest_mirror_clamp_to_border;
1624   default:
1625      assert(0);
1626      return wrap_nearest_repeat;
1627   }
1628}
1629
1630static wrap_linear_func get_linear_unorm_wrap( unsigned mode )
1631{
1632   switch (mode) {
1633   case PIPE_TEX_WRAP_CLAMP:
1634      return wrap_linear_unorm_clamp;
1635   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1636   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1637      return wrap_linear_unorm_clamp_to_border;
1638   default:
1639      assert(0);
1640      return wrap_linear_unorm_clamp;
1641   }
1642}
1643
1644static wrap_linear_func get_linear_wrap( unsigned mode )
1645{
1646   switch (mode) {
1647   case PIPE_TEX_WRAP_REPEAT:
1648      return wrap_linear_repeat;
1649   case PIPE_TEX_WRAP_CLAMP:
1650      return wrap_linear_clamp;
1651   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
1652      return wrap_linear_clamp_to_edge;
1653   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
1654      return wrap_linear_clamp_to_border;
1655   case PIPE_TEX_WRAP_MIRROR_REPEAT:
1656      return wrap_linear_mirror_repeat;
1657   case PIPE_TEX_WRAP_MIRROR_CLAMP:
1658      return wrap_linear_mirror_clamp;
1659   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
1660      return wrap_linear_mirror_clamp_to_edge;
1661   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
1662      return wrap_linear_mirror_clamp_to_border;
1663   default:
1664      assert(0);
1665      return wrap_linear_repeat;
1666   }
1667}
1668
1669static compute_lambda_func get_lambda_func( const union sp_sampler_key key )
1670{
1671   if (key.bits.processor == TGSI_PROCESSOR_VERTEX)
1672      return compute_lambda_vert;
1673
1674   switch (key.bits.target) {
1675   case PIPE_TEXTURE_1D:
1676      return compute_lambda_1d;
1677   case PIPE_TEXTURE_2D:
1678   case PIPE_TEXTURE_CUBE:
1679      return compute_lambda_2d;
1680   case PIPE_TEXTURE_3D:
1681      return compute_lambda_3d;
1682   default:
1683      assert(0);
1684      return compute_lambda_1d;
1685   }
1686}
1687
1688static filter_func get_img_filter( const union sp_sampler_key key,
1689                                   unsigned filter,
1690                                   const struct pipe_sampler_state *sampler )
1691{
1692   switch (key.bits.target) {
1693   case PIPE_TEXTURE_1D:
1694      if (filter == PIPE_TEX_FILTER_NEAREST)
1695         return img_filter_1d_nearest;
1696      else
1697         return img_filter_1d_linear;
1698      break;
1699   case PIPE_TEXTURE_2D:
1700      /* Try for fast path:
1701       */
1702      if (key.bits.is_pot &&
1703          sampler->wrap_s == sampler->wrap_t &&
1704          sampler->normalized_coords)
1705      {
1706         switch (sampler->wrap_s) {
1707         case PIPE_TEX_WRAP_REPEAT:
1708            switch (filter) {
1709            case PIPE_TEX_FILTER_NEAREST:
1710               return img_filter_2d_nearest_repeat_POT;
1711            case PIPE_TEX_FILTER_LINEAR:
1712               return img_filter_2d_linear_repeat_POT;
1713            default:
1714               break;
1715            }
1716            break;
1717         case PIPE_TEX_WRAP_CLAMP:
1718            switch (filter) {
1719            case PIPE_TEX_FILTER_NEAREST:
1720               return img_filter_2d_nearest_clamp_POT;
1721            default:
1722               break;
1723            }
1724         }
1725      }
1726      /* Otherwise use default versions:
1727       */
1728      if (filter == PIPE_TEX_FILTER_NEAREST)
1729         return img_filter_2d_nearest;
1730      else
1731         return img_filter_2d_linear;
1732      break;
1733   case PIPE_TEXTURE_CUBE:
1734      if (filter == PIPE_TEX_FILTER_NEAREST)
1735         return img_filter_cube_nearest;
1736      else
1737         return img_filter_cube_linear;
1738      break;
1739   case PIPE_TEXTURE_3D:
1740      if (filter == PIPE_TEX_FILTER_NEAREST)
1741         return img_filter_3d_nearest;
1742      else
1743         return img_filter_3d_linear;
1744      break;
1745   default:
1746      assert(0);
1747      return img_filter_1d_nearest;
1748   }
1749}
1750
1751
1752/**
1753 * Bind the given texture object and texture cache to the sampler varient.
1754 */
1755void
1756sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp,
1757                                 struct softpipe_tex_tile_cache *tex_cache,
1758                                 const struct pipe_texture *texture )
1759{
1760   const struct pipe_sampler_state *sampler = samp->sampler;
1761
1762   samp->texture = texture;
1763   samp->cache = tex_cache;
1764   samp->xpot = util_unsigned_logbase2( texture->width[0] );
1765   samp->ypot = util_unsigned_logbase2( texture->height[0] );
1766   samp->level = CLAMP((int) sampler->min_lod, 0, (int) texture->last_level);
1767}
1768
1769
1770void
1771sp_sampler_varient_destroy( struct sp_sampler_varient *samp )
1772{
1773   FREE(samp);
1774}
1775
1776
1777/* Create a sampler varient for a given set of non-orthogonal state.  Currently the
1778 */
1779struct sp_sampler_varient *
1780sp_create_sampler_varient( const struct pipe_sampler_state *sampler,
1781                           const union sp_sampler_key key )
1782{
1783   struct sp_sampler_varient *samp = CALLOC_STRUCT(sp_sampler_varient);
1784   if (!samp)
1785      return NULL;
1786
1787   samp->sampler = sampler;
1788   samp->key = key;
1789
1790   /* Note that (for instance) linear_texcoord_s and
1791    * nearest_texcoord_s may be active at the same time, if the
1792    * sampler min_img_filter differs from its mag_img_filter.
1793    */
1794   if (sampler->normalized_coords) {
1795      samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
1796      samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
1797      samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
1798
1799      samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
1800      samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
1801      samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
1802   }
1803   else {
1804      samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
1805      samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
1806      samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
1807
1808      samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
1809      samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
1810      samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
1811   }
1812
1813   samp->compute_lambda = get_lambda_func( key );
1814
1815   samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler);
1816   samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler);
1817
1818   switch (sampler->min_mip_filter) {
1819   case PIPE_TEX_MIPFILTER_NONE:
1820      if (sampler->min_img_filter == sampler->mag_img_filter)
1821         samp->mip_filter = samp->min_img_filter;
1822      else
1823         samp->mip_filter = mip_filter_none;
1824      break;
1825
1826   case PIPE_TEX_MIPFILTER_NEAREST:
1827      samp->mip_filter = mip_filter_nearest;
1828      break;
1829
1830   case PIPE_TEX_MIPFILTER_LINEAR:
1831      if (key.bits.is_pot &&
1832          sampler->min_img_filter == sampler->mag_img_filter &&
1833          sampler->normalized_coords &&
1834          sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
1835          sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
1836          sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR)
1837      {
1838         samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT;
1839      }
1840      else
1841      {
1842         samp->mip_filter = mip_filter_linear;
1843      }
1844      break;
1845   }
1846
1847   if (sampler->compare_mode != FALSE) {
1848      samp->compare = sample_compare;
1849   }
1850   else {
1851      /* Skip compare operation by promoting the mip_filter function
1852       * pointer:
1853       */
1854      samp->compare = samp->mip_filter;
1855   }
1856
1857   if (key.bits.target == PIPE_TEXTURE_CUBE) {
1858      samp->base.get_samples = sample_cube;
1859   }
1860   else {
1861      samp->faces[0] = 0;
1862      samp->faces[1] = 0;
1863      samp->faces[2] = 0;
1864      samp->faces[3] = 0;
1865
1866      /* Skip cube face determination by promoting the compare
1867       * function pointer:
1868       */
1869      samp->base.get_samples = samp->compare;
1870   }
1871
1872   return samp;
1873}
1874
1875
1876
1877
1878
1879
1880