OSDN Git Service

15501994acc4f865d9913f4e05d770cb619ee030
[android-x86/external-mesa.git] / src / gallium / drivers / softpipe / sp_tex_sample.c
1 /**************************************************************************
2  * 
3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  * Copyright 2008-2010 VMware, Inc.  All rights reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  * 
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  * 
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  * 
27  **************************************************************************/
28
29 /**
30  * Texture sampling
31  *
32  * Authors:
33  *   Brian Paul
34  *   Keith Whitwell
35  */
36
37 #include "pipe/p_context.h"
38 #include "pipe/p_defines.h"
39 #include "pipe/p_shader_tokens.h"
40 #include "util/u_math.h"
41 #include "util/u_format.h"
42 #include "util/u_memory.h"
43 #include "util/u_inlines.h"
44 #include "sp_quad.h"   /* only for #define QUAD_* tokens */
45 #include "sp_tex_sample.h"
46 #include "sp_texture.h"
47 #include "sp_tex_tile_cache.h"
48
49
50 /** Set to one to help debug texture sampling */
51 #define DEBUG_TEX 0
52
53
54 /*
55  * Return fractional part of 'f'.  Used for computing interpolation weights.
56  * Need to be careful with negative values.
57  * Note, if this function isn't perfect you'll sometimes see 1-pixel bands
58  * of improperly weighted linear-filtered textures.
59  * The tests/texwrap.c demo is a good test.
60  */
61 static INLINE float
62 frac(float f)
63 {
64    return f - floorf(f);
65 }
66
67
68
69 /**
70  * Linear interpolation macro
71  */
72 static INLINE float
73 lerp(float a, float v0, float v1)
74 {
75    return v0 + a * (v1 - v0);
76 }
77
78
79 /**
80  * Do 2D/bilinear interpolation of float values.
81  * v00, v10, v01 and v11 are typically four texture samples in a square/box.
82  * a and b are the horizontal and vertical interpolants.
83  * It's important that this function is inlined when compiled with
84  * optimization!  If we find that's not true on some systems, convert
85  * to a macro.
86  */
87 static INLINE float
88 lerp_2d(float a, float b,
89         float v00, float v10, float v01, float v11)
90 {
91    const float temp0 = lerp(a, v00, v10);
92    const float temp1 = lerp(a, v01, v11);
93    return lerp(b, temp0, temp1);
94 }
95
96
97 /**
98  * As above, but 3D interpolation of 8 values.
99  */
100 static INLINE float
101 lerp_3d(float a, float b, float c,
102         float v000, float v100, float v010, float v110,
103         float v001, float v101, float v011, float v111)
104 {
105    const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
106    const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
107    return lerp(c, temp0, temp1);
108 }
109
110
111
112 /**
113  * Compute coord % size for repeat wrap modes.
114  * Note that if coord is negative, coord % size doesn't give the right
115  * value.  To avoid that problem we add a large multiple of the size
116  * (rather than using a conditional).
117  */
118 static INLINE int
119 repeat(int coord, unsigned size)
120 {
121    return (coord + size * 1024) % size;
122 }
123
124
125 /**
126  * Apply texture coord wrapping mode and return integer texture indexes
127  * for a vector of four texcoords (S or T or P).
128  * \param wrapMode  PIPE_TEX_WRAP_x
129  * \param s  the incoming texcoords
130  * \param size  the texture image size
131  * \param icoord  returns the integer texcoords
132  */
133 static void
134 wrap_nearest_repeat(float s, unsigned size, int *icoord)
135 {
136    /* s limited to [0,1) */
137    /* i limited to [0,size-1] */
138    int i = util_ifloor(s * size);
139    *icoord = repeat(i, size);
140 }
141
142
143 static void
144 wrap_nearest_clamp(float s, unsigned size, int *icoord)
145 {
146    /* s limited to [0,1] */
147    /* i limited to [0,size-1] */
148    if (s <= 0.0F)
149       *icoord = 0;
150    else if (s >= 1.0F)
151       *icoord = size - 1;
152    else
153       *icoord = util_ifloor(s * size);
154 }
155
156
157 static void
158 wrap_nearest_clamp_to_edge(float s, unsigned size, int *icoord)
159 {
160    /* s limited to [min,max] */
161    /* i limited to [0, size-1] */
162    const float min = 1.0F / (2.0F * size);
163    const float max = 1.0F - min;
164    if (s < min)
165       *icoord = 0;
166    else if (s > max)
167       *icoord = size - 1;
168    else
169       *icoord = util_ifloor(s * size);
170 }
171
172
173 static void
174 wrap_nearest_clamp_to_border(float s, unsigned size, int *icoord)
175 {
176    /* s limited to [min,max] */
177    /* i limited to [-1, size] */
178    const float min = -1.0F / (2.0F * size);
179    const float max = 1.0F - min;
180    if (s <= min)
181       *icoord = -1;
182    else if (s >= max)
183       *icoord = size;
184    else
185       *icoord = util_ifloor(s * size);
186 }
187
188
189 static void
190 wrap_nearest_mirror_repeat(float s, unsigned size, int *icoord)
191 {
192    const float min = 1.0F / (2.0F * size);
193    const float max = 1.0F - min;
194    const int flr = util_ifloor(s);
195    float u = frac(s);
196    if (flr & 1)
197       u = 1.0F - u;
198    if (u < min)
199       *icoord = 0;
200    else if (u > max)
201       *icoord = size - 1;
202    else
203       *icoord = util_ifloor(u * size);
204 }
205
206
207 static void
208 wrap_nearest_mirror_clamp(float s, unsigned size, int *icoord)
209 {
210    /* s limited to [0,1] */
211    /* i limited to [0,size-1] */
212    const float u = fabsf(s);
213    if (u <= 0.0F)
214       *icoord = 0;
215    else if (u >= 1.0F)
216       *icoord = size - 1;
217    else
218       *icoord = util_ifloor(u * size);
219 }
220
221
222 static void
223 wrap_nearest_mirror_clamp_to_edge(float s, unsigned size, int *icoord)
224 {
225    /* s limited to [min,max] */
226    /* i limited to [0, size-1] */
227    const float min = 1.0F / (2.0F * size);
228    const float max = 1.0F - min;
229    const float u = fabsf(s);
230    if (u < min)
231       *icoord = 0;
232    else if (u > max)
233       *icoord = size - 1;
234    else
235       *icoord = util_ifloor(u * size);
236 }
237
238
239 static void
240 wrap_nearest_mirror_clamp_to_border(float s, unsigned size, int *icoord)
241 {
242    /* s limited to [min,max] */
243    /* i limited to [0, size-1] */
244    const float min = -1.0F / (2.0F * size);
245    const float max = 1.0F - min;
246    const float u = fabsf(s);
247    if (u < min)
248       *icoord = -1;
249    else if (u > max)
250       *icoord = size;
251    else
252       *icoord = util_ifloor(u * size);
253 }
254
255
256 /**
257  * Used to compute texel locations for linear sampling
258  * \param wrapMode  PIPE_TEX_WRAP_x
259  * \param s  the texcoord
260  * \param size  the texture image size
261  * \param icoord0  returns first texture index
262  * \param icoord1  returns second texture index (usually icoord0 + 1)
263  * \param w  returns blend factor/weight between texture indices
264  * \param icoord  returns the computed integer texture coord
265  */
266 static void
267 wrap_linear_repeat(float s, unsigned size,
268                    int *icoord0, int *icoord1, float *w)
269 {
270    float u = s * size - 0.5F;
271    *icoord0 = repeat(util_ifloor(u), size);
272    *icoord1 = repeat(*icoord0 + 1, size);
273    *w = frac(u);
274 }
275
276
277 static void
278 wrap_linear_clamp(float s, unsigned size,
279                   int *icoord0, int *icoord1, float *w)
280 {
281    float u = CLAMP(s, 0.0F, 1.0F);
282    u = u * size - 0.5f;
283    *icoord0 = util_ifloor(u);
284    *icoord1 = *icoord0 + 1;
285    *w = frac(u);
286 }
287
288
289 static void
290 wrap_linear_clamp_to_edge(float s, unsigned size,
291                           int *icoord0, int *icoord1, float *w)
292 {
293    float u = CLAMP(s, 0.0F, 1.0F);
294    u = u * size - 0.5f;
295    *icoord0 = util_ifloor(u);
296    *icoord1 = *icoord0 + 1;
297    if (*icoord0 < 0)
298       *icoord0 = 0;
299    if (*icoord1 >= (int) size)
300       *icoord1 = size - 1;
301    *w = frac(u);
302 }
303
304
305 static void
306 wrap_linear_clamp_to_border(float s, unsigned size,
307                             int *icoord0, int *icoord1, float *w)
308 {
309    const float min = -1.0F / (2.0F * size);
310    const float max = 1.0F - min;
311    float u = CLAMP(s, min, max);
312    u = u * size - 0.5f;
313    *icoord0 = util_ifloor(u);
314    *icoord1 = *icoord0 + 1;
315    *w = frac(u);
316 }
317
318
319 static void
320 wrap_linear_mirror_repeat(float s, unsigned size,
321                           int *icoord0, int *icoord1, float *w)
322 {
323    const int flr = util_ifloor(s);
324    float u = frac(s);
325    if (flr & 1)
326       u = 1.0F - u;
327    u = u * size - 0.5F;
328    *icoord0 = util_ifloor(u);
329    *icoord1 = *icoord0 + 1;
330    if (*icoord0 < 0)
331       *icoord0 = 0;
332    if (*icoord1 >= (int) size)
333       *icoord1 = size - 1;
334    *w = frac(u);
335 }
336
337
338 static void
339 wrap_linear_mirror_clamp(float s, unsigned size,
340                          int *icoord0, int *icoord1, float *w)
341 {
342    float u = fabsf(s);
343    if (u >= 1.0F)
344       u = (float) size;
345    else
346       u *= size;
347    u -= 0.5F;
348    *icoord0 = util_ifloor(u);
349    *icoord1 = *icoord0 + 1;
350    *w = frac(u);
351 }
352
353
354 static void
355 wrap_linear_mirror_clamp_to_edge(float s, unsigned size,
356                                  int *icoord0, int *icoord1, float *w)
357 {
358    float u = fabsf(s);
359    if (u >= 1.0F)
360       u = (float) size;
361    else
362       u *= size;
363    u -= 0.5F;
364    *icoord0 = util_ifloor(u);
365    *icoord1 = *icoord0 + 1;
366    if (*icoord0 < 0)
367       *icoord0 = 0;
368    if (*icoord1 >= (int) size)
369       *icoord1 = size - 1;
370    *w = frac(u);
371 }
372
373
374 static void
375 wrap_linear_mirror_clamp_to_border(float s, unsigned size,
376                                    int *icoord0, int *icoord1, float *w)
377 {
378    const float min = -1.0F / (2.0F * size);
379    const float max = 1.0F - min;
380    float u = fabsf(s);
381    if (u <= min)
382       u = min * size;
383    else if (u >= max)
384       u = max * size;
385    else
386       u *= size;
387    u -= 0.5F;
388    *icoord0 = util_ifloor(u);
389    *icoord1 = *icoord0 + 1;
390    *w = frac(u);
391 }
392
393
394 /**
395  * PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords.
396  */
397 static void
398 wrap_nearest_unorm_clamp(float s, unsigned size, int *icoord)
399 {
400    int i = util_ifloor(s);
401    *icoord = CLAMP(i, 0, (int) size-1);
402 }
403
404
405 /**
406  * PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords.
407  */
408 static void
409 wrap_nearest_unorm_clamp_to_border(float s, unsigned size, int *icoord)
410 {
411    *icoord = util_ifloor( CLAMP(s, -0.5F, (float) size + 0.5F) );
412 }
413
414
415 /**
416  * PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords.
417  */
418 static void
419 wrap_nearest_unorm_clamp_to_edge(float s, unsigned size, int *icoord)
420 {
421    *icoord = util_ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) );
422 }
423
424
425 /**
426  * PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords.
427  */
428 static void
429 wrap_linear_unorm_clamp(float s, unsigned size,
430                         int *icoord0, int *icoord1, float *w)
431 {
432    /* Not exactly what the spec says, but it matches NVIDIA output */
433    float u = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f);
434    *icoord0 = util_ifloor(u);
435    *icoord1 = *icoord0 + 1;
436    *w = frac(u);
437 }
438
439
440 /**
441  * PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords.
442  */
443 static void
444 wrap_linear_unorm_clamp_to_border(float s, unsigned size,
445                                   int *icoord0, int *icoord1, float *w)
446 {
447    float u = CLAMP(s, -0.5F, (float) size + 0.5F);
448    u -= 0.5F;
449    *icoord0 = util_ifloor(u);
450    *icoord1 = *icoord0 + 1;
451    if (*icoord1 > (int) size - 1)
452       *icoord1 = size - 1;
453    *w = frac(u);
454 }
455
456
457 /**
458  * PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords.
459  */
460 static void
461 wrap_linear_unorm_clamp_to_edge(float s, unsigned size,
462                                 int *icoord0, int *icoord1, float *w)
463 {
464    float u = CLAMP(s, +0.5F, (float) size - 0.5F);
465    u -= 0.5F;
466    *icoord0 = util_ifloor(u);
467    *icoord1 = *icoord0 + 1;
468    if (*icoord1 > (int) size - 1)
469       *icoord1 = size - 1;
470    *w = frac(u);
471 }
472
473
474 /**
475  * Do coordinate to array index conversion.  For array textures.
476  */
477 static INLINE void
478 wrap_array_layer(float coord, unsigned size, int *layer)
479 {
480    int c = util_ifloor(coord + 0.5F);
481    *layer = CLAMP(c, 0, (int) size - 1);
482 }
483
484
485 /**
486  * Examine the quad's texture coordinates to compute the partial
487  * derivatives w.r.t X and Y, then compute lambda (level of detail).
488  */
489 static float
490 compute_lambda_1d(const struct sp_sampler_view *sview,
491                   const float s[TGSI_QUAD_SIZE],
492                   const float t[TGSI_QUAD_SIZE],
493                   const float p[TGSI_QUAD_SIZE])
494 {
495    const struct pipe_resource *texture = sview->base.texture;
496    float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
497    float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
498    float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
499
500    return util_fast_log2(rho);
501 }
502
503
504 static float
505 compute_lambda_2d(const struct sp_sampler_view *sview,
506                   const float s[TGSI_QUAD_SIZE],
507                   const float t[TGSI_QUAD_SIZE],
508                   const float p[TGSI_QUAD_SIZE])
509 {
510    const struct pipe_resource *texture = sview->base.texture;
511    float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
512    float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
513    float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
514    float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
515    float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
516    float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
517    float rho  = MAX2(maxx, maxy);
518
519    return util_fast_log2(rho);
520 }
521
522
523 static float
524 compute_lambda_3d(const struct sp_sampler_view *sview,
525                   const float s[TGSI_QUAD_SIZE],
526                   const float t[TGSI_QUAD_SIZE],
527                   const float p[TGSI_QUAD_SIZE])
528 {
529    const struct pipe_resource *texture = sview->base.texture;
530    float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
531    float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
532    float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
533    float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
534    float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
535    float dpdy = fabsf(p[QUAD_TOP_LEFT]     - p[QUAD_BOTTOM_LEFT]);
536    float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
537    float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
538    float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, sview->base.u.tex.first_level);
539    float rho;
540
541    rho = MAX2(maxx, maxy);
542    rho = MAX2(rho, maxz);
543
544    return util_fast_log2(rho);
545 }
546
547
548 /**
549  * Compute lambda for a vertex texture sampler.
550  * Since there aren't derivatives to use, just return 0.
551  */
552 static float
553 compute_lambda_vert(const struct sp_sampler_view *sview,
554                     const float s[TGSI_QUAD_SIZE],
555                     const float t[TGSI_QUAD_SIZE],
556                     const float p[TGSI_QUAD_SIZE])
557 {
558    return 0.0f;
559 }
560
561
562
563 /**
564  * Get a texel from a texture, using the texture tile cache.
565  *
566  * \param addr  the template tex address containing cube, z, face info.
567  * \param x  the x coord of texel within 2D image
568  * \param y  the y coord of texel within 2D image
569  * \param rgba  the quad to put the texel/color into
570  *
571  * XXX maybe move this into sp_tex_tile_cache.c and merge with the
572  * sp_get_cached_tile_tex() function.
573  */
574
575
576
577
578 static INLINE const float *
579 get_texel_2d_no_border(const struct sp_sampler_view *sp_sview,
580                        union tex_tile_address addr, int x, int y)
581 {
582    const struct softpipe_tex_cached_tile *tile;
583    addr.bits.x = x / TILE_SIZE;
584    addr.bits.y = y / TILE_SIZE;
585    y %= TILE_SIZE;
586    x %= TILE_SIZE;
587
588    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
589
590    return &tile->data.color[y][x][0];
591 }
592
593
594 static INLINE const float *
595 get_texel_2d(const struct sp_sampler_view *sp_sview,
596              const struct sp_sampler *sp_samp,
597              union tex_tile_address addr, int x, int y)
598 {
599    const struct pipe_resource *texture = sp_sview->base.texture;
600    unsigned level = addr.bits.level;
601
602    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
603        y < 0 || y >= (int) u_minify(texture->height0, level)) {
604       return sp_samp->base.border_color.f;
605    }
606    else {
607       return get_texel_2d_no_border( sp_sview, addr, x, y );
608    }
609 }
610
611 /*
612  * seamless cubemap neighbour array.
613  * this array is used to find the adjacent face in each of 4 directions,
614  * left, right, up, down. (or -x, +x, -y, +y).
615  */
616 static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
617    /* pos X first then neg X is Z different, Y the same */
618    /* PIPE_TEX_FACE_POS_X,*/
619    { PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
620      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
621    /* PIPE_TEX_FACE_NEG_X */
622    { PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
623      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
624
625    /* pos Y first then neg Y is X different, X the same */
626    /* PIPE_TEX_FACE_POS_Y */
627    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
628      PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
629
630    /* PIPE_TEX_FACE_NEG_Y */
631    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
632      PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
633
634    /* pos Z first then neg Y is X different, X the same */
635    /* PIPE_TEX_FACE_POS_Z */
636    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
637      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
638
639    /* PIPE_TEX_FACE_NEG_Z */
640    { PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
641      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y }
642 };
643
644 static INLINE unsigned
645 get_next_face(unsigned face, int x, int y)
646 {
647    int idx = 0;
648
649    if (x == 0 && y == 0)
650       return face;
651    if (x == -1)
652       idx = 0;
653    else if (x == 1)
654       idx = 1;
655    else if (y == -1)
656       idx = 2;
657    else if (y == 1)
658       idx = 3;
659
660    return face_array[face][idx];
661 }
662
663 static INLINE const float *
664 get_texel_cube_seamless(const struct sp_sampler_view *sp_sview,
665                         union tex_tile_address addr, int x, int y,
666                         float *corner)
667 {
668    const struct pipe_resource *texture = sp_sview->base.texture;
669    unsigned level = addr.bits.level;
670    unsigned face = addr.bits.face;
671    int new_x, new_y;
672    int max_x, max_y;
673    int c;
674
675    max_x = (int) u_minify(texture->width0, level);
676    max_y = (int) u_minify(texture->height0, level);
677    new_x = x;
678    new_y = y;
679
680    /* the corner case */
681    if ((x < 0 || x >= max_x) &&
682        (y < 0 || y >= max_y)) {
683       const float *c1, *c2, *c3;
684       int fx = x < 0 ? 0 : max_x - 1;
685       int fy = y < 0 ? 0 : max_y - 1;
686       c1 = get_texel_2d_no_border( sp_sview, addr, fx, fy);
687       addr.bits.face = get_next_face(face, (x < 0) ? -1 : 1, 0);
688       c2 = get_texel_2d_no_border( sp_sview, addr, (x < 0) ? max_x - 1 : 0, fy);
689       addr.bits.face = get_next_face(face, 0, (y < 0) ? -1 : 1);
690       c3 = get_texel_2d_no_border( sp_sview, addr, fx, (y < 0) ?  max_y - 1 : 0);
691       for (c = 0; c < TGSI_QUAD_SIZE; c++)
692          corner[c] = CLAMP((c1[c] + c2[c] + c3[c]), 0.0F, 1.0F) / 3;
693
694       return corner;
695    }
696    /* change the face */
697    if (x < 0) {
698       new_x = max_x - 1;
699       face = get_next_face(face, -1, 0);
700    } else if (x >= max_x) {
701       new_x = 0;
702       face = get_next_face(face, 1, 0);
703    } else if (y < 0) {
704       new_y = max_y - 1;
705       face = get_next_face(face, 0, -1);
706    } else if (y >= max_y) {
707       new_y = 0;
708       face = get_next_face(face, 0, 1);
709    }
710
711    addr.bits.face = face;
712    return get_texel_2d_no_border( sp_sview, addr, new_x, new_y );
713 }
714
715 /* Gather a quad of adjacent texels within a tile:
716  */
717 static INLINE void
718 get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view *sp_sview,
719                                         union tex_tile_address addr,
720                                         unsigned x, unsigned y,
721                                         const float *out[4])
722 {
723     const struct softpipe_tex_cached_tile *tile;
724
725    addr.bits.x = x / TILE_SIZE;
726    addr.bits.y = y / TILE_SIZE;
727    y %= TILE_SIZE;
728    x %= TILE_SIZE;
729
730    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
731       
732    out[0] = &tile->data.color[y  ][x  ][0];
733    out[1] = &tile->data.color[y  ][x+1][0];
734    out[2] = &tile->data.color[y+1][x  ][0];
735    out[3] = &tile->data.color[y+1][x+1][0];
736 }
737
738
739 /* Gather a quad of potentially non-adjacent texels:
740  */
741 static INLINE void
742 get_texel_quad_2d_no_border(const struct sp_sampler_view *sp_sview,
743                             union tex_tile_address addr,
744                             int x0, int y0,
745                             int x1, int y1,
746                             const float *out[4])
747 {
748    out[0] = get_texel_2d_no_border( sp_sview, addr, x0, y0 );
749    out[1] = get_texel_2d_no_border( sp_sview, addr, x1, y0 );
750    out[2] = get_texel_2d_no_border( sp_sview, addr, x0, y1 );
751    out[3] = get_texel_2d_no_border( sp_sview, addr, x1, y1 );
752 }
753
754 /* Can involve a lot of unnecessary checks for border color:
755  */
756 static INLINE void
757 get_texel_quad_2d(const struct sp_sampler_view *sp_sview,
758                   const struct sp_sampler *sp_samp,
759                   union tex_tile_address addr,
760                   int x0, int y0,
761                   int x1, int y1,
762                   const float *out[4])
763 {
764    out[0] = get_texel_2d( sp_sview, sp_samp, addr, x0, y0 );
765    out[1] = get_texel_2d( sp_sview, sp_samp, addr, x1, y0 );
766    out[3] = get_texel_2d( sp_sview, sp_samp, addr, x1, y1 );
767    out[2] = get_texel_2d( sp_sview, sp_samp, addr, x0, y1 );
768 }
769
770
771
772 /* 3d variants:
773  */
774 static INLINE const float *
775 get_texel_3d_no_border(const struct sp_sampler_view *sp_sview,
776                        union tex_tile_address addr, int x, int y, int z)
777 {
778    const struct softpipe_tex_cached_tile *tile;
779
780    addr.bits.x = x / TILE_SIZE;
781    addr.bits.y = y / TILE_SIZE;
782    addr.bits.z = z;
783    y %= TILE_SIZE;
784    x %= TILE_SIZE;
785
786    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
787
788    return &tile->data.color[y][x][0];
789 }
790
791
792 static INLINE const float *
793 get_texel_3d(const struct sp_sampler_view *sp_sview,
794              const struct sp_sampler *sp_samp,
795              union tex_tile_address addr, int x, int y, int z)
796 {
797    const struct pipe_resource *texture = sp_sview->base.texture;
798    unsigned level = addr.bits.level;
799
800    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
801        y < 0 || y >= (int) u_minify(texture->height0, level) ||
802        z < 0 || z >= (int) u_minify(texture->depth0, level)) {
803       return sp_samp->base.border_color.f;
804    }
805    else {
806       return get_texel_3d_no_border( sp_sview, addr, x, y, z );
807    }
808 }
809
810
811 /* Get texel pointer for 1D array texture */
812 static INLINE const float *
813 get_texel_1d_array(const struct sp_sampler_view *sp_sview,
814                    const struct sp_sampler *sp_samp,
815                    union tex_tile_address addr, int x, int y)
816 {
817    const struct pipe_resource *texture = sp_sview->base.texture;
818    unsigned level = addr.bits.level;
819
820    if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
821       return sp_samp->base.border_color.f;
822    }
823    else {
824       return get_texel_2d_no_border(sp_sview, addr, x, y);
825    }
826 }
827
828
829 /* Get texel pointer for 2D array texture */
830 static INLINE const float *
831 get_texel_2d_array(const struct sp_sampler_view *sp_sview,
832                    const struct sp_sampler *sp_samp,
833                    union tex_tile_address addr, int x, int y, int layer)
834 {
835    const struct pipe_resource *texture = sp_sview->base.texture;
836    unsigned level = addr.bits.level;
837
838    assert(layer < (int) texture->array_size);
839    assert(layer >= 0);
840
841    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
842        y < 0 || y >= (int) u_minify(texture->height0, level)) {
843       return sp_samp->base.border_color.f;
844    }
845    else {
846       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
847    }
848 }
849
850
851 /* Get texel pointer for cube array texture */
852 static INLINE const float *
853 get_texel_cube_array(const struct sp_sampler_view *sp_sview,
854                      const struct sp_sampler *sp_samp,
855                      union tex_tile_address addr, int x, int y, int layer)
856 {
857    const struct pipe_resource *texture = sp_sview->base.texture;
858    unsigned level = addr.bits.level;
859
860    assert(layer < (int) texture->array_size);
861    assert(layer >= 0);
862
863    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
864        y < 0 || y >= (int) u_minify(texture->height0, level)) {
865       return sp_samp->base.border_color.f;
866    }
867    else {
868       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
869    }
870 }
871 /**
872  * Given the logbase2 of a mipmap's base level size and a mipmap level,
873  * return the size (in texels) of that mipmap level.
874  * For example, if level[0].width = 256 then base_pot will be 8.
875  * If level = 2, then we'll return 64 (the width at level=2).
876  * Return 1 if level > base_pot.
877  */
878 static INLINE unsigned
879 pot_level_size(unsigned base_pot, unsigned level)
880 {
881    return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
882 }
883
884
885 static void
886 print_sample(const char *function, const float *rgba)
887 {
888    debug_printf("%s %g %g %g %g\n",
889                 function,
890                 rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]);
891 }
892
893
894 static void
895 print_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
896 {
897    debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
898                 function,
899                 rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
900                 rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
901                 rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
902                 rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
903 }
904
905
906 /* Some image-filter fastpaths:
907  */
908 static INLINE void
909 img_filter_2d_linear_repeat_POT(struct sp_sampler_view *sp_sview,
910                                 struct sp_sampler *sp_samp,
911                                 float s,
912                                 float t,
913                                 float p,
914                                 unsigned level,
915                                 unsigned face_id,
916                                 float *rgba)
917 {
918    unsigned xpot = pot_level_size(sp_sview->xpot, level);
919    unsigned ypot = pot_level_size(sp_sview->ypot, level);
920    unsigned xmax = (xpot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, xpot) - 1; */
921    unsigned ymax = (ypot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, ypot) - 1; */
922    union tex_tile_address addr;
923    int c;
924
925    float u = s * xpot - 0.5F;
926    float v = t * ypot - 0.5F;
927
928    int uflr = util_ifloor(u);
929    int vflr = util_ifloor(v);
930
931    float xw = u - (float)uflr;
932    float yw = v - (float)vflr;
933
934    int x0 = uflr & (xpot - 1);
935    int y0 = vflr & (ypot - 1);
936
937    const float *tx[4];
938       
939    addr.value = 0;
940    addr.bits.level = level;
941
942    /* Can we fetch all four at once:
943     */
944    if (x0 < xmax && y0 < ymax) {
945       get_texel_quad_2d_no_border_single_tile(sp_sview, addr, x0, y0, tx);
946    }
947    else {
948       unsigned x1 = (x0 + 1) & (xpot - 1);
949       unsigned y1 = (y0 + 1) & (ypot - 1);
950       get_texel_quad_2d_no_border(sp_sview, addr, x0, y0, x1, y1, tx);
951    }
952
953    /* interpolate R, G, B, A */
954    for (c = 0; c < TGSI_QUAD_SIZE; c++) {
955       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw, 
956                                        tx[0][c], tx[1][c], 
957                                        tx[2][c], tx[3][c]);
958    }
959
960    if (DEBUG_TEX) {
961       print_sample(__FUNCTION__, rgba);
962    }
963 }
964
965
966 static INLINE void
967 img_filter_2d_nearest_repeat_POT(struct sp_sampler_view *sp_sview,
968                                  struct sp_sampler *sp_samp,
969                                  float s,
970                                  float t,
971                                  float p,
972                                  unsigned level,
973                                  unsigned face_id,
974                                  float rgba[TGSI_QUAD_SIZE])
975 {
976    unsigned xpot = pot_level_size(sp_sview->xpot, level);
977    unsigned ypot = pot_level_size(sp_sview->ypot, level);
978    const float *out;
979    union tex_tile_address addr;
980    int c;
981
982    float u = s * xpot;
983    float v = t * ypot;
984
985    int uflr = util_ifloor(u);
986    int vflr = util_ifloor(v);
987
988    int x0 = uflr & (xpot - 1);
989    int y0 = vflr & (ypot - 1);
990
991    addr.value = 0;
992    addr.bits.level = level;
993
994    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
995    for (c = 0; c < TGSI_QUAD_SIZE; c++)
996       rgba[TGSI_NUM_CHANNELS*c] = out[c];
997
998    if (DEBUG_TEX) {
999       print_sample(__FUNCTION__, rgba);
1000    }
1001 }
1002
1003
1004 static INLINE void
1005 img_filter_2d_nearest_clamp_POT(struct sp_sampler_view *sp_sview,
1006                                 struct sp_sampler *sp_samp,
1007                                 float s,
1008                                 float t,
1009                                 float p,
1010                                 unsigned level,
1011                                 unsigned face_id,
1012                                 float rgba[TGSI_QUAD_SIZE])
1013 {
1014    unsigned xpot = pot_level_size(sp_sview->xpot, level);
1015    unsigned ypot = pot_level_size(sp_sview->ypot, level);
1016    union tex_tile_address addr;
1017    int c;
1018
1019    float u = s * xpot;
1020    float v = t * ypot;
1021
1022    int x0, y0;
1023    const float *out;
1024
1025    addr.value = 0;
1026    addr.bits.level = level;
1027
1028    x0 = util_ifloor(u);
1029    if (x0 < 0) 
1030       x0 = 0;
1031    else if (x0 > xpot - 1)
1032       x0 = xpot - 1;
1033
1034    y0 = util_ifloor(v);
1035    if (y0 < 0) 
1036       y0 = 0;
1037    else if (y0 > ypot - 1)
1038       y0 = ypot - 1;
1039    
1040    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
1041    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1042       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1043
1044    if (DEBUG_TEX) {
1045       print_sample(__FUNCTION__, rgba);
1046    }
1047 }
1048
1049
1050 static void
1051 img_filter_1d_nearest(struct sp_sampler_view *sp_sview,
1052                       struct sp_sampler *sp_samp,
1053                       float s,
1054                       float t,
1055                       float p,
1056                       unsigned level,
1057                       unsigned face_id,
1058                       float rgba[TGSI_QUAD_SIZE])
1059 {
1060    const struct pipe_resource *texture = sp_sview->base.texture;
1061    int width;
1062    int x;
1063    union tex_tile_address addr;
1064    const float *out;
1065    int c;
1066
1067    width = u_minify(texture->width0, level);
1068
1069    assert(width > 0);
1070
1071    addr.value = 0;
1072    addr.bits.level = level;
1073
1074    sp_samp->nearest_texcoord_s(s, width, &x);
1075
1076    out = get_texel_2d(sp_sview, sp_samp, addr, x, 0);
1077    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1078       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1079
1080    if (DEBUG_TEX) {
1081       print_sample(__FUNCTION__, rgba);
1082    }
1083 }
1084
1085
1086 static void
1087 img_filter_1d_array_nearest(struct sp_sampler_view *sp_sview,
1088                             struct sp_sampler *sp_samp,
1089                             float s,
1090                             float t,
1091                             float p,
1092                             unsigned level,
1093                             unsigned face_id,
1094                             float *rgba)
1095 {
1096    const struct pipe_resource *texture = sp_sview->base.texture;
1097    int width;
1098    int x, layer;
1099    union tex_tile_address addr;
1100    const float *out;
1101    int c;
1102
1103    width = u_minify(texture->width0, level);
1104
1105    assert(width > 0);
1106
1107    addr.value = 0;
1108    addr.bits.level = level;
1109
1110    sp_samp->nearest_texcoord_s(s, width, &x);
1111    wrap_array_layer(t, texture->array_size, &layer);
1112
1113    out = get_texel_1d_array(sp_sview, sp_samp, addr, x, layer);
1114    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1115       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1116
1117    if (DEBUG_TEX) {
1118       print_sample(__FUNCTION__, rgba);
1119    }
1120 }
1121
1122
1123 static void
1124 img_filter_2d_nearest(struct sp_sampler_view *sp_sview,
1125                       struct sp_sampler *sp_samp,
1126                       float s,
1127                       float t,
1128                       float p,
1129                       unsigned level,
1130                       unsigned face_id,
1131                       float *rgba)
1132 {
1133    const struct pipe_resource *texture = sp_sview->base.texture;
1134    int width, height;
1135    int x, y;
1136    union tex_tile_address addr;
1137    const float *out;
1138    int c;
1139
1140    width = u_minify(texture->width0, level);
1141    height = u_minify(texture->height0, level);
1142
1143    assert(width > 0);
1144    assert(height > 0);
1145  
1146    addr.value = 0;
1147    addr.bits.level = level;
1148
1149    sp_samp->nearest_texcoord_s(s, width, &x);
1150    sp_samp->nearest_texcoord_t(t, height, &y);
1151
1152    out = get_texel_2d(sp_sview, sp_samp, addr, x, y);
1153    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1154       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1155
1156    if (DEBUG_TEX) {
1157       print_sample(__FUNCTION__, rgba);
1158    }
1159 }
1160
1161
1162 static void
1163 img_filter_2d_array_nearest(struct sp_sampler_view *sp_sview,
1164                             struct sp_sampler *sp_samp,
1165                             float s,
1166                             float t,
1167                             float p,
1168                             unsigned level,
1169                             unsigned face_id,
1170                             float *rgba)
1171 {
1172    const struct pipe_resource *texture = sp_sview->base.texture;
1173    int width, height;
1174    int x, y, layer;
1175    union tex_tile_address addr;
1176    const float *out;
1177    int c;
1178
1179    width = u_minify(texture->width0, level);
1180    height = u_minify(texture->height0, level);
1181
1182    assert(width > 0);
1183    assert(height > 0);
1184  
1185    addr.value = 0;
1186    addr.bits.level = level;
1187
1188    sp_samp->nearest_texcoord_s(s, width, &x);
1189    sp_samp->nearest_texcoord_t(t, height, &y);
1190    wrap_array_layer(p, texture->array_size, &layer);
1191
1192    out = get_texel_2d_array(sp_sview, sp_samp, addr, x, y, layer);
1193    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1194       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1195
1196    if (DEBUG_TEX) {
1197       print_sample(__FUNCTION__, rgba);
1198    }
1199 }
1200
1201
1202 static INLINE union tex_tile_address
1203 face(union tex_tile_address addr, unsigned face )
1204 {
1205    addr.bits.face = face;
1206    return addr;
1207 }
1208
1209
1210 static void
1211 img_filter_cube_nearest(struct sp_sampler_view *sp_sview,
1212                         struct sp_sampler *sp_samp,
1213                         float s,
1214                         float t,
1215                         float p,
1216                         unsigned level,
1217                         unsigned face_id,
1218                         float *rgba)
1219 {
1220    const struct pipe_resource *texture = sp_sview->base.texture;
1221    int width, height;
1222    int x, y;
1223    union tex_tile_address addr;
1224    const float *out;
1225    int c;
1226
1227    width = u_minify(texture->width0, level);
1228    height = u_minify(texture->height0, level);
1229
1230    assert(width > 0);
1231    assert(height > 0);
1232  
1233    addr.value = 0;
1234    addr.bits.level = level;
1235
1236    /*
1237     * If NEAREST filtering is done within a miplevel, always apply wrap
1238     * mode CLAMP_TO_EDGE.
1239     */
1240    if (sp_samp->base.seamless_cube_map) {
1241       wrap_nearest_clamp_to_edge(s, width, &x);
1242       wrap_nearest_clamp_to_edge(t, height, &y);
1243    } else {
1244       sp_samp->nearest_texcoord_s(s, width, &x);
1245       sp_samp->nearest_texcoord_t(t, height, &y);
1246    }
1247
1248    out = get_texel_2d(sp_sview, sp_samp, face(addr, face_id), x, y);
1249    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1250       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1251
1252    if (DEBUG_TEX) {
1253       print_sample(__FUNCTION__, rgba);
1254    }
1255 }
1256
1257 static void
1258 img_filter_cube_array_nearest(struct sp_sampler_view *sp_sview,
1259                               struct sp_sampler *sp_samp,
1260                               float s,
1261                               float t,
1262                               float p,
1263                               unsigned level,
1264                               unsigned face_id,
1265                               float *rgba)
1266 {
1267    const struct pipe_resource *texture = sp_sview->base.texture;
1268    int width, height;
1269    int x, y, layer;
1270    union tex_tile_address addr;
1271    const float *out;
1272    int c;
1273
1274    width = u_minify(texture->width0, level);
1275    height = u_minify(texture->height0, level);
1276
1277    assert(width > 0);
1278    assert(height > 0);
1279  
1280    addr.value = 0;
1281    addr.bits.level = level;
1282
1283    sp_samp->nearest_texcoord_s(s, width, &x);
1284    sp_samp->nearest_texcoord_t(t, height, &y);
1285    wrap_array_layer(p, texture->array_size, &layer);
1286
1287    out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layer * 6 + face_id);
1288    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1289       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1290
1291    if (DEBUG_TEX) {
1292       print_sample(__FUNCTION__, rgba);
1293    }
1294 }
1295
1296 static void
1297 img_filter_3d_nearest(struct sp_sampler_view *sp_sview,
1298                       struct sp_sampler *sp_samp,
1299                       float s,
1300                       float t,
1301                       float p,
1302                       unsigned level,
1303                       unsigned face_id,
1304                       float *rgba)
1305 {
1306    const struct pipe_resource *texture = sp_sview->base.texture;
1307    int width, height, depth;
1308    int x, y, z;
1309    union tex_tile_address addr;
1310    const float *out;
1311    int c;
1312
1313    width = u_minify(texture->width0, level);
1314    height = u_minify(texture->height0, level);
1315    depth = u_minify(texture->depth0, level);
1316
1317    assert(width > 0);
1318    assert(height > 0);
1319    assert(depth > 0);
1320
1321    sp_samp->nearest_texcoord_s(s, width,  &x);
1322    sp_samp->nearest_texcoord_t(t, height, &y);
1323    sp_samp->nearest_texcoord_p(p, depth,  &z);
1324
1325    addr.value = 0;
1326    addr.bits.level = level;
1327
1328    out = get_texel_3d(sp_sview, sp_samp, addr, x, y, z);
1329    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1330       rgba[TGSI_NUM_CHANNELS*c] = out[c];
1331 }
1332
1333
1334 static void
1335 img_filter_1d_linear(struct sp_sampler_view *sp_sview,
1336                      struct sp_sampler *sp_samp,
1337                      float s,
1338                      float t,
1339                      float p,
1340                      unsigned level,
1341                      unsigned face_id,
1342                      float *rgba)
1343 {
1344    const struct pipe_resource *texture = sp_sview->base.texture;
1345    int width;
1346    int x0, x1;
1347    float xw; /* weights */
1348    union tex_tile_address addr;
1349    const float *tx0, *tx1;
1350    int c;
1351
1352    width = u_minify(texture->width0, level);
1353
1354    assert(width > 0);
1355
1356    addr.value = 0;
1357    addr.bits.level = level;
1358
1359    sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1360
1361    tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, 0);
1362    tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, 0);
1363
1364    /* interpolate R, G, B, A */
1365    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1366       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
1367 }
1368
1369
1370 static void
1371 img_filter_1d_array_linear(struct sp_sampler_view *sp_sview,
1372                            struct sp_sampler *sp_samp,
1373                            float s,
1374                            float t,
1375                            float p,
1376                            unsigned level,
1377                            unsigned face_id,
1378                            float *rgba)
1379 {
1380    const struct pipe_resource *texture = sp_sview->base.texture;
1381    int width;
1382    int x0, x1, layer;
1383    float xw; /* weights */
1384    union tex_tile_address addr;
1385    const float *tx0, *tx1;
1386    int c;
1387
1388    width = u_minify(texture->width0, level);
1389
1390    assert(width > 0);
1391
1392    addr.value = 0;
1393    addr.bits.level = level;
1394
1395    sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
1396    wrap_array_layer(t, texture->array_size, &layer);
1397
1398    tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, layer);
1399    tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, layer);
1400
1401    /* interpolate R, G, B, A */
1402    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1403       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
1404 }
1405
1406
1407 static void
1408 img_filter_2d_linear(struct sp_sampler_view *sp_sview,
1409                      struct sp_sampler *sp_samp,
1410                      float s,
1411                      float t,
1412                      float p,
1413                      unsigned level,
1414                      unsigned face_id,
1415                      float *rgba)
1416 {
1417    const struct pipe_resource *texture = sp_sview->base.texture;
1418    int width, height;
1419    int x0, y0, x1, y1;
1420    float xw, yw; /* weights */
1421    union tex_tile_address addr;
1422    const float *tx0, *tx1, *tx2, *tx3;
1423    int c;
1424
1425    width = u_minify(texture->width0, level);
1426    height = u_minify(texture->height0, level);
1427
1428    assert(width > 0);
1429    assert(height > 0);
1430
1431    addr.value = 0;
1432    addr.bits.level = level;
1433
1434    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
1435    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1436
1437    tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, y0);
1438    tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, y0);
1439    tx2 = get_texel_2d(sp_sview, sp_samp, addr, x0, y1);
1440    tx3 = get_texel_2d(sp_sview, sp_samp, addr, x1, y1);
1441
1442    /* interpolate R, G, B, A */
1443    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1444       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1445                                           tx0[c], tx1[c],
1446                                           tx2[c], tx3[c]);
1447 }
1448
1449
1450 static void
1451 img_filter_2d_array_linear(struct sp_sampler_view *sp_sview,
1452                            struct sp_sampler *sp_samp,
1453                            float s,
1454                            float t,
1455                            float p,
1456                            unsigned level,
1457                            unsigned face_id,
1458                            float *rgba)
1459 {
1460    const struct pipe_resource *texture = sp_sview->base.texture;
1461    int width, height;
1462    int x0, y0, x1, y1, layer;
1463    float xw, yw; /* weights */
1464    union tex_tile_address addr;
1465    const float *tx0, *tx1, *tx2, *tx3;
1466    int c;
1467
1468    width = u_minify(texture->width0, level);
1469    height = u_minify(texture->height0, level);
1470
1471    assert(width > 0);
1472    assert(height > 0);
1473
1474    addr.value = 0;
1475    addr.bits.level = level;
1476
1477    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
1478    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1479    wrap_array_layer(p, texture->array_size, &layer);
1480
1481    tx0 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y0, layer);
1482    tx1 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y0, layer);
1483    tx2 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y1, layer);
1484    tx3 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y1, layer);
1485
1486    /* interpolate R, G, B, A */
1487    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1488       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1489                                           tx0[c], tx1[c],
1490                                           tx2[c], tx3[c]);
1491 }
1492
1493
1494 static void
1495 img_filter_cube_linear(struct sp_sampler_view *sp_sview,
1496                        struct sp_sampler *sp_samp,
1497                        float s,
1498                        float t,
1499                        float p,
1500                        unsigned level,
1501                        unsigned face_id,
1502                        float *rgba)
1503 {
1504    const struct pipe_resource *texture = sp_sview->base.texture;
1505    int width, height;
1506    int x0, y0, x1, y1;
1507    float xw, yw; /* weights */
1508    union tex_tile_address addr, addrj;
1509    const float *tx0, *tx1, *tx2, *tx3;
1510    float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
1511          corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
1512    int c;
1513
1514    width = u_minify(texture->width0, level);
1515    height = u_minify(texture->height0, level);
1516
1517    assert(width > 0);
1518    assert(height > 0);
1519
1520    addr.value = 0;
1521    addr.bits.level = level;
1522
1523    /*
1524     * For seamless if LINEAR filtering is done within a miplevel,
1525     * always apply wrap mode CLAMP_TO_BORDER.
1526     */
1527    if (sp_samp->base.seamless_cube_map) {
1528       wrap_linear_clamp_to_border(s, width, &x0, &x1, &xw);
1529       wrap_linear_clamp_to_border(t, height, &y0, &y1, &yw);
1530    } else {
1531       sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
1532       sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1533    }
1534
1535    addrj = face(addr, face_id);
1536
1537    if (sp_samp->base.seamless_cube_map) {
1538       tx0 = get_texel_cube_seamless(sp_sview, addrj, x0, y0, corner0);
1539       tx1 = get_texel_cube_seamless(sp_sview, addrj, x1, y0, corner1);
1540       tx2 = get_texel_cube_seamless(sp_sview, addrj, x0, y1, corner2);
1541       tx3 = get_texel_cube_seamless(sp_sview, addrj, x1, y1, corner3);
1542    } else {
1543       tx0 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y0);
1544       tx1 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y0);
1545       tx2 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y1);
1546       tx3 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y1);
1547    }
1548    /* interpolate R, G, B, A */
1549    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1550       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1551                                           tx0[c], tx1[c],
1552                                           tx2[c], tx3[c]);
1553 }
1554
1555
1556 static void
1557 img_filter_cube_array_linear(struct sp_sampler_view *sp_sview,
1558                              struct sp_sampler *sp_samp,
1559                              float s,
1560                              float t,
1561                              float p,
1562                              unsigned level,
1563                              unsigned face_id,
1564                              float *rgba)
1565 {
1566    const struct pipe_resource *texture = sp_sview->base.texture;
1567    int width, height;
1568    int x0, y0, x1, y1, layer;
1569    float xw, yw; /* weights */
1570    union tex_tile_address addr;
1571    const float *tx0, *tx1, *tx2, *tx3;
1572    int c;
1573
1574    width = u_minify(texture->width0, level);
1575    height = u_minify(texture->height0, level);
1576
1577    assert(width > 0);
1578    assert(height > 0);
1579
1580    addr.value = 0;
1581    addr.bits.level = level;
1582
1583    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
1584    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1585    wrap_array_layer(p, texture->array_size, &layer);
1586
1587    tx0 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer * 6 + face_id);
1588    tx1 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer * 6 + face_id);
1589    tx2 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer * 6 + face_id);
1590    tx3 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer * 6 + face_id);
1591
1592    /* interpolate R, G, B, A */
1593    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1594       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
1595                                           tx0[c], tx1[c],
1596                                           tx2[c], tx3[c]);
1597 }
1598
1599 static void
1600 img_filter_3d_linear(struct sp_sampler_view *sp_sview,
1601                      struct sp_sampler *sp_samp,
1602                      float s,
1603                      float t,
1604                      float p,
1605                      unsigned level,
1606                      unsigned face_id,
1607                      float *rgba)
1608 {
1609    const struct pipe_resource *texture = sp_sview->base.texture;
1610    int width, height, depth;
1611    int x0, x1, y0, y1, z0, z1;
1612    float xw, yw, zw; /* interpolation weights */
1613    union tex_tile_address addr;
1614    const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13;
1615    int c;
1616
1617    width = u_minify(texture->width0, level);
1618    height = u_minify(texture->height0, level);
1619    depth = u_minify(texture->depth0, level);
1620
1621    addr.value = 0;
1622    addr.bits.level = level;
1623
1624    assert(width > 0);
1625    assert(height > 0);
1626    assert(depth > 0);
1627
1628    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
1629    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
1630    sp_samp->linear_texcoord_p(p, depth,  &z0, &z1, &zw);
1631
1632
1633    tx00 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z0);
1634    tx01 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z0);
1635    tx02 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z0);
1636    tx03 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z0);
1637       
1638    tx10 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z1);
1639    tx11 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z1);
1640    tx12 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z1);
1641    tx13 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z1);
1642       
1643       /* interpolate R, G, B, A */
1644    for (c = 0; c < TGSI_QUAD_SIZE; c++)
1645       rgba[TGSI_NUM_CHANNELS*c] =  lerp_3d(xw, yw, zw,
1646                                            tx00[c], tx01[c],
1647                                            tx02[c], tx03[c],
1648                                            tx10[c], tx11[c],
1649                                            tx12[c], tx13[c]);
1650 }
1651
1652
1653 /* Calculate level of detail for every fragment,
1654  * with lambda already computed.
1655  * Note that lambda has already been biased by global LOD bias.
1656  * \param biased_lambda per-quad lambda.
1657  * \param lod_in per-fragment lod_bias or explicit_lod.
1658  * \param lod returns the per-fragment lod.
1659  */
1660 static INLINE void
1661 compute_lod(const struct pipe_sampler_state *sampler,
1662             enum tgsi_sampler_control control,
1663             const float biased_lambda,
1664             const float lod_in[TGSI_QUAD_SIZE],
1665             float lod[TGSI_QUAD_SIZE])
1666 {
1667    float min_lod = sampler->min_lod;
1668    float max_lod = sampler->max_lod;
1669    uint i;
1670
1671    switch (control) {
1672    case tgsi_sampler_lod_none:
1673    case tgsi_sampler_lod_zero:
1674    /* XXX FIXME */
1675    case tgsi_sampler_derivs_explicit:
1676       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
1677       break;
1678    case tgsi_sampler_lod_bias:
1679       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1680          lod[i] = biased_lambda + lod_in[i];
1681          lod[i] = CLAMP(lod[i], min_lod, max_lod);
1682       }
1683       break;
1684    case tgsi_sampler_lod_explicit:
1685       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1686          lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
1687       }
1688       break;
1689    default:
1690       assert(0);
1691       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
1692    }
1693 }
1694
1695
1696 /* Calculate level of detail for every fragment.
1697  * \param lod_in per-fragment lod_bias or explicit_lod.
1698  * \param lod results per-fragment lod.
1699  */
1700 static INLINE void
1701 compute_lambda_lod(struct sp_sampler_view *sp_sview,
1702                    struct sp_sampler *sp_samp,
1703                    const float s[TGSI_QUAD_SIZE],
1704                    const float t[TGSI_QUAD_SIZE],
1705                    const float p[TGSI_QUAD_SIZE],
1706                    const float lod_in[TGSI_QUAD_SIZE],
1707                    enum tgsi_sampler_control control,
1708                    float lod[TGSI_QUAD_SIZE])
1709 {
1710    const struct pipe_sampler_state *sampler = &sp_samp->base;
1711    float lod_bias = sampler->lod_bias;
1712    float min_lod = sampler->min_lod;
1713    float max_lod = sampler->max_lod;
1714    float lambda;
1715    uint i;
1716
1717    switch (control) {
1718    case tgsi_sampler_lod_none:
1719       /* XXX FIXME */
1720    case tgsi_sampler_derivs_explicit:
1721       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
1722       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lambda, min_lod, max_lod);
1723       break;
1724    case tgsi_sampler_lod_bias:
1725       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
1726       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1727          lod[i] = lambda + lod_in[i];
1728          lod[i] = CLAMP(lod[i], min_lod, max_lod);
1729       }
1730       break;
1731    case tgsi_sampler_lod_explicit:
1732       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
1733          lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
1734       }
1735       break;
1736    case tgsi_sampler_lod_zero:
1737       /* this is all static state in the sampler really need clamp here? */
1738       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lod_bias, min_lod, max_lod);
1739       break;
1740    default:
1741       assert(0);
1742       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
1743    }
1744 }
1745
1746
1747 static void
1748 mip_filter_linear(struct sp_sampler_view *sp_sview,
1749                   struct sp_sampler *sp_samp,
1750                   img_filter_func min_filter,
1751                   img_filter_func mag_filter,
1752                   const float s[TGSI_QUAD_SIZE],
1753                   const float t[TGSI_QUAD_SIZE],
1754                   const float p[TGSI_QUAD_SIZE],
1755                   const float c0[TGSI_QUAD_SIZE],
1756                   const float lod_in[TGSI_QUAD_SIZE],
1757                   enum tgsi_sampler_control control,
1758                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1759 {
1760    const struct pipe_resource *texture = sp_sview->base.texture;
1761    int j;
1762    float lod[TGSI_QUAD_SIZE];
1763
1764    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
1765
1766    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
1767       int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
1768
1769       if (lod[j] < 0.0)
1770          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
1771                     sp_sview->base.u.tex.first_level,
1772                     sp_sview->faces[j], &rgba[0][j]);
1773
1774       else if (level0 >= texture->last_level)
1775          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
1776                     sp_sview->faces[j], &rgba[0][j]);
1777
1778       else {
1779          float levelBlend = frac(lod[j]);
1780          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
1781          int c;
1782
1783          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0,
1784                     sp_sview->faces[j], &rgbax[0][0]);
1785          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
1786                     sp_sview->faces[j], &rgbax[0][1]);
1787
1788          for (c = 0; c < 4; c++) {
1789             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
1790          }
1791       }
1792    }
1793
1794    if (DEBUG_TEX) {
1795       print_sample_4(__FUNCTION__, rgba);
1796    }
1797 }
1798
1799
1800 /**
1801  * Compute nearest mipmap level from texcoords.
1802  * Then sample the texture level for four elements of a quad.
1803  * \param c0  the LOD bias factors, or absolute LODs (depending on control)
1804  */
1805 static void
1806 mip_filter_nearest(struct sp_sampler_view *sp_sview,
1807                    struct sp_sampler *sp_samp,
1808                    img_filter_func min_filter,
1809                    img_filter_func mag_filter,
1810                    const float s[TGSI_QUAD_SIZE],
1811                    const float t[TGSI_QUAD_SIZE],
1812                    const float p[TGSI_QUAD_SIZE],
1813                    const float c0[TGSI_QUAD_SIZE],
1814                    const float lod_in[TGSI_QUAD_SIZE],
1815                    enum tgsi_sampler_control control,
1816                    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1817 {
1818    const struct pipe_resource *texture = sp_sview->base.texture;
1819    float lod[TGSI_QUAD_SIZE];
1820    int j;
1821
1822    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
1823
1824    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
1825       if (lod[j] < 0.0)
1826          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
1827                     sp_sview->base.u.tex.first_level,
1828                     sp_sview->faces[j], &rgba[0][j]);
1829       else {
1830          float level = sp_sview->base.u.tex.first_level + (int)(lod[j] + 0.5F) ;
1831          level = MIN2(level, (int)texture->last_level);
1832          min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
1833                     level, sp_sview->faces[j], &rgba[0][j]);
1834       }
1835    }
1836
1837    if (DEBUG_TEX) {
1838       print_sample_4(__FUNCTION__, rgba);
1839    }
1840 }
1841
1842
1843 static void
1844 mip_filter_none(struct sp_sampler_view *sp_sview,
1845                 struct sp_sampler *sp_samp,
1846                 img_filter_func min_filter,
1847                 img_filter_func mag_filter,
1848                 const float s[TGSI_QUAD_SIZE],
1849                 const float t[TGSI_QUAD_SIZE],
1850                 const float p[TGSI_QUAD_SIZE],
1851                 const float c0[TGSI_QUAD_SIZE],
1852                 const float lod_in[TGSI_QUAD_SIZE],
1853                 enum tgsi_sampler_control control,
1854                 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1855 {
1856    float lod[TGSI_QUAD_SIZE];
1857    int j;
1858
1859    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
1860
1861    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
1862       if (lod[j] < 0.0) { 
1863          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
1864                     sp_sview->base.u.tex.first_level,
1865                     sp_sview->faces[j], &rgba[0][j]);
1866       }
1867       else {
1868          min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
1869                     sp_sview->base.u.tex.first_level,
1870                     sp_sview->faces[j], &rgba[0][j]);
1871       }
1872    }
1873 }
1874
1875
1876 static void
1877 mip_filter_none_no_filter_select(struct sp_sampler_view *sp_sview,
1878                                  struct sp_sampler *sp_samp,
1879                                  img_filter_func min_filter,
1880                                  img_filter_func mag_filter,
1881                                  const float s[TGSI_QUAD_SIZE],
1882                                  const float t[TGSI_QUAD_SIZE],
1883                                  const float p[TGSI_QUAD_SIZE],
1884                                  const float c0[TGSI_QUAD_SIZE],
1885                                  const float lod_in[TGSI_QUAD_SIZE],
1886                                  enum tgsi_sampler_control control,
1887                                  float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1888 {
1889    int j;
1890
1891    for (j = 0; j < TGSI_QUAD_SIZE; j++)
1892       mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
1893                  sp_sview->base.u.tex.first_level,
1894                  sp_sview->faces[j], &rgba[0][j]);
1895 }
1896
1897
1898 /* For anisotropic filtering */
1899 #define WEIGHT_LUT_SIZE 1024
1900
1901 static float *weightLut = NULL;
1902
1903 /**
1904  * Creates the look-up table used to speed-up EWA sampling
1905  */
1906 static void
1907 create_filter_table(void)
1908 {
1909    unsigned i;
1910    if (!weightLut) {
1911       weightLut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float));
1912
1913       for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
1914          float alpha = 2;
1915          float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1);
1916          float weight = (float) exp(-alpha * r2);
1917          weightLut[i] = weight;
1918       }
1919    }
1920 }
1921
1922
1923 /**
1924  * Elliptical weighted average (EWA) filter for producing high quality
1925  * anisotropic filtered results.
1926  * Based on the Higher Quality Elliptical Weighted Average Filter
1927  * published by Paul S. Heckbert in his Master's Thesis
1928  * "Fundamentals of Texture Mapping and Image Warping" (1989)
1929  */
1930 static void
1931 img_filter_2d_ewa(struct sp_sampler_view *sp_sview,
1932                   struct sp_sampler *sp_samp,
1933                   img_filter_func min_filter,
1934                   img_filter_func mag_filter,
1935                   const float s[TGSI_QUAD_SIZE],
1936                   const float t[TGSI_QUAD_SIZE],
1937                   const float p[TGSI_QUAD_SIZE],
1938                   unsigned level,
1939                   const float dudx, const float dvdx,
1940                   const float dudy, const float dvdy,
1941                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
1942 {
1943    const struct pipe_resource *texture = sp_sview->base.texture;
1944
1945    // ??? Won't the image filters blow up if level is negative?
1946    unsigned level0 = level > 0 ? level : 0;
1947    float scaling = 1.0f / (1 << level0);
1948    int width = u_minify(texture->width0, level0);
1949    int height = u_minify(texture->height0, level0);
1950
1951    float ux = dudx * scaling;
1952    float vx = dvdx * scaling;
1953    float uy = dudy * scaling;
1954    float vy = dvdy * scaling;
1955
1956    /* compute ellipse coefficients to bound the region: 
1957     * A*x*x + B*x*y + C*y*y = F.
1958     */
1959    float A = vx*vx+vy*vy+1;
1960    float B = -2*(ux*vx+uy*vy);
1961    float C = ux*ux+uy*uy+1;
1962    float F = A*C-B*B/4.0f;
1963
1964    /* check if it is an ellipse */
1965    /* ASSERT(F > 0.0); */
1966
1967    /* Compute the ellipse's (u,v) bounding box in texture space */
1968    float d = -B*B+4.0f*C*A;
1969    float box_u = 2.0f / d * sqrt(d*C*F); /* box_u -> half of bbox with   */
1970    float box_v = 2.0f / d * sqrt(A*d*F); /* box_v -> half of bbox height */
1971
1972    float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
1973    float s_buffer[TGSI_QUAD_SIZE];
1974    float t_buffer[TGSI_QUAD_SIZE];
1975    float weight_buffer[TGSI_QUAD_SIZE];
1976    unsigned buffer_next;
1977    int j;
1978    float den; /* = 0.0F; */
1979    float ddq;
1980    float U; /* = u0 - tex_u; */
1981    int v;
1982
1983    /* Scale ellipse formula to directly index the Filter Lookup Table.
1984     * i.e. scale so that F = WEIGHT_LUT_SIZE-1
1985     */
1986    double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
1987    A *= formScale;
1988    B *= formScale;
1989    C *= formScale;
1990    /* F *= formScale; */ /* no need to scale F as we don't use it below here */
1991
1992    /* For each quad, the du and dx values are the same and so the ellipse is
1993     * also the same. Note that texel/image access can only be performed using
1994     * a quad, i.e. it is not possible to get the pixel value for a single
1995     * tex coord. In order to have a better performance, the access is buffered
1996     * using the s_buffer/t_buffer and weight_buffer. Only when the buffer is
1997     * full, then the pixel values are read from the image.
1998     */
1999    ddq = 2 * A;
2000    
2001    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2002       /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
2003        * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
2004        * value, q, is less than F, we're inside the ellipse
2005        */
2006       float tex_u = -0.5F + s[j] * texture->width0 * scaling;
2007       float tex_v = -0.5F + t[j] * texture->height0 * scaling;
2008
2009       int u0 = (int) floorf(tex_u - box_u);
2010       int u1 = (int) ceilf(tex_u + box_u);
2011       int v0 = (int) floorf(tex_v - box_v);
2012       int v1 = (int) ceilf(tex_v + box_v);
2013
2014       float num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
2015       buffer_next = 0;
2016       den = 0;
2017       U = u0 - tex_u;
2018       for (v = v0; v <= v1; ++v) {
2019          float V = v - tex_v;
2020          float dq = A * (2 * U + 1) + B * V;
2021          float q = (C * V + B * U) * V + A * U * U;
2022
2023          int u;
2024          for (u = u0; u <= u1; ++u) {
2025             /* Note that the ellipse has been pre-scaled so F =
2026              * WEIGHT_LUT_SIZE - 1
2027              */
2028             if (q < WEIGHT_LUT_SIZE) {
2029                /* as a LUT is used, q must never be negative;
2030                 * should not happen, though
2031                 */
2032                const int qClamped = q >= 0.0F ? q : 0;
2033                float weight = weightLut[qClamped];
2034
2035                weight_buffer[buffer_next] = weight;
2036                s_buffer[buffer_next] = u / ((float) width);
2037                t_buffer[buffer_next] = v / ((float) height);
2038             
2039                buffer_next++;
2040                if (buffer_next == TGSI_QUAD_SIZE) {
2041                   /* 4 texel coords are in the buffer -> read it now */
2042                   unsigned jj;
2043                   /* it is assumed that samp->min_img_filter is set to
2044                    * img_filter_2d_nearest or one of the
2045                    * accelerated img_filter_2d_nearest_XXX functions.
2046                    */
2047                   for (jj = 0; jj < buffer_next; jj++) {
2048                      min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
2049                                 level, sp_sview->faces[j], &rgba_temp[0][jj]);
2050                      num[0] += weight_buffer[jj] * rgba_temp[0][jj];
2051                      num[1] += weight_buffer[jj] * rgba_temp[1][jj];
2052                      num[2] += weight_buffer[jj] * rgba_temp[2][jj];
2053                      num[3] += weight_buffer[jj] * rgba_temp[3][jj];
2054                   }
2055
2056                   buffer_next = 0;
2057                }
2058
2059                den += weight;
2060             }
2061             q += dq;
2062             dq += ddq;
2063          }
2064       }
2065
2066       /* if the tex coord buffer contains unread values, we will read
2067        * them now.
2068        */
2069       if (buffer_next > 0) {
2070          unsigned jj;
2071          /* it is assumed that samp->min_img_filter is set to
2072           * img_filter_2d_nearest or one of the
2073           * accelerated img_filter_2d_nearest_XXX functions.
2074           */
2075          for (jj = 0; jj < buffer_next; jj++) {
2076             min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
2077                        level, sp_sview->faces[j], &rgba_temp[0][jj]);
2078             num[0] += weight_buffer[jj] * rgba_temp[0][jj];
2079             num[1] += weight_buffer[jj] * rgba_temp[1][jj];
2080             num[2] += weight_buffer[jj] * rgba_temp[2][jj];
2081             num[3] += weight_buffer[jj] * rgba_temp[3][jj];
2082          }
2083       }
2084
2085       if (den <= 0.0F) {
2086          /* Reaching this place would mean that no pixels intersected
2087           * the ellipse.  This should never happen because the filter
2088           * we use always intersects at least one pixel.
2089           */
2090
2091          /*rgba[0]=0;
2092          rgba[1]=0;
2093          rgba[2]=0;
2094          rgba[3]=0;*/
2095          /* not enough pixels in resampling, resort to direct interpolation */
2096          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level,
2097                     sp_sview->faces[j], &rgba_temp[0][j]);
2098          den = 1;
2099          num[0] = rgba_temp[0][j];
2100          num[1] = rgba_temp[1][j];
2101          num[2] = rgba_temp[2][j];
2102          num[3] = rgba_temp[3][j];
2103       }
2104
2105       rgba[0][j] = num[0] / den;
2106       rgba[1][j] = num[1] / den;
2107       rgba[2][j] = num[2] / den;
2108       rgba[3][j] = num[3] / den;
2109    }
2110 }
2111
2112
2113 /**
2114  * Sample 2D texture using an anisotropic filter.
2115  */
2116 static void
2117 mip_filter_linear_aniso(struct sp_sampler_view *sp_sview,
2118                         struct sp_sampler *sp_samp,
2119                         img_filter_func min_filter,
2120                         img_filter_func mag_filter,
2121                         const float s[TGSI_QUAD_SIZE],
2122                         const float t[TGSI_QUAD_SIZE],
2123                         const float p[TGSI_QUAD_SIZE],
2124                         const float c0[TGSI_QUAD_SIZE],
2125                         const float lod_in[TGSI_QUAD_SIZE],
2126                         enum tgsi_sampler_control control,
2127                         float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2128 {
2129    const struct pipe_resource *texture = sp_sview->base.texture;
2130    int level0;
2131    float lambda;
2132    float lod[TGSI_QUAD_SIZE];
2133
2134    float s_to_u = u_minify(texture->width0, sp_sview->base.u.tex.first_level);
2135    float t_to_v = u_minify(texture->height0, sp_sview->base.u.tex.first_level);
2136    float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
2137    float dudy = (s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]) * s_to_u;
2138    float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
2139    float dvdy = (t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]) * t_to_v;
2140    
2141    if (control == tgsi_sampler_lod_bias ||
2142        control == tgsi_sampler_lod_none ||
2143        /* XXX FIXME */
2144        control == tgsi_sampler_derivs_explicit) {
2145       /* note: instead of working with Px and Py, we will use the 
2146        * squared length instead, to avoid sqrt.
2147        */
2148       float Px2 = dudx * dudx + dvdx * dvdx;
2149       float Py2 = dudy * dudy + dvdy * dvdy;
2150
2151       float Pmax2;
2152       float Pmin2;
2153       float e;
2154       const float maxEccentricity = sp_samp->base.max_anisotropy * sp_samp->base.max_anisotropy;
2155       
2156       if (Px2 < Py2) {
2157          Pmax2 = Py2;
2158          Pmin2 = Px2;
2159       }
2160       else {
2161          Pmax2 = Px2;
2162          Pmin2 = Py2;
2163       }
2164       
2165       /* if the eccentricity of the ellipse is too big, scale up the shorter
2166        * of the two vectors to limit the maximum amount of work per pixel
2167        */
2168       e = Pmax2 / Pmin2;
2169       if (e > maxEccentricity) {
2170          /* float s=e / maxEccentricity;
2171             minor[0] *= s;
2172             minor[1] *= s;
2173             Pmin2 *= s; */
2174          Pmin2 = Pmax2 / maxEccentricity;
2175       }
2176       
2177       /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
2178        * this since 0.5*log(x) = log(sqrt(x))
2179        */
2180       lambda = 0.5F * util_fast_log2(Pmin2) + sp_samp->base.lod_bias;
2181       compute_lod(&sp_samp->base, control, lambda, lod_in, lod);
2182    }
2183    else {
2184       assert(control == tgsi_sampler_lod_explicit ||
2185              control == tgsi_sampler_lod_zero);
2186       compute_lod(&sp_samp->base, control, sp_samp->base.lod_bias, lod_in, lod);
2187    }
2188    
2189    /* XXX: Take into account all lod values.
2190     */
2191    lambda = lod[0];
2192    level0 = sp_sview->base.u.tex.first_level + (int)lambda;
2193
2194    /* If the ellipse covers the whole image, we can
2195     * simply return the average of the whole image.
2196     */
2197    if (level0 >= (int) texture->last_level) {
2198       int j;
2199       for (j = 0; j < TGSI_QUAD_SIZE; j++)
2200          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
2201                     sp_sview->faces[j], &rgba[0][j]);
2202    }
2203    else {
2204       /* don't bother interpolating between multiple LODs; it doesn't
2205        * seem to be worth the extra running time.
2206        */
2207       img_filter_2d_ewa(sp_sview, sp_samp, min_filter, mag_filter,
2208                         s, t, p, level0,
2209                         dudx, dvdx, dudy, dvdy, rgba);
2210    }
2211
2212    if (DEBUG_TEX) {
2213       print_sample_4(__FUNCTION__, rgba);
2214    }
2215 }
2216
2217
2218 /**
2219  * Specialized version of mip_filter_linear with hard-wired calls to
2220  * 2d lambda calculation and 2d_linear_repeat_POT img filters.
2221  */
2222 static void
2223 mip_filter_linear_2d_linear_repeat_POT(
2224    struct sp_sampler_view *sp_sview,
2225    struct sp_sampler *sp_samp,
2226    img_filter_func min_filter,
2227    img_filter_func mag_filter,
2228    const float s[TGSI_QUAD_SIZE],
2229    const float t[TGSI_QUAD_SIZE],
2230    const float p[TGSI_QUAD_SIZE],
2231    const float c0[TGSI_QUAD_SIZE],
2232    const float lod_in[TGSI_QUAD_SIZE],
2233    enum tgsi_sampler_control control,
2234    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2235 {
2236    const struct pipe_resource *texture = sp_sview->base.texture;
2237    int j;
2238    float lod[TGSI_QUAD_SIZE];
2239
2240    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
2241
2242    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2243       int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
2244
2245       /* Catches both negative and large values of level0:
2246        */
2247       if ((unsigned)level0 >= texture->last_level) { 
2248          if (level0 < 0)
2249             img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
2250                                             sp_sview->base.u.tex.first_level,
2251                                             sp_sview->faces[j], &rgba[0][j]);
2252          else
2253             img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
2254                                             sp_sview->base.texture->last_level,
2255                                             sp_sview->faces[j], &rgba[0][j]);
2256
2257       }
2258       else {
2259          float levelBlend = frac(lod[j]);
2260          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2261          int c;
2262
2263          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0,
2264                                          sp_sview->faces[j], &rgbax[0][0]);
2265          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
2266                                          sp_sview->faces[j], &rgbax[0][1]);
2267
2268          for (c = 0; c < TGSI_NUM_CHANNELS; c++)
2269             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
2270       }
2271    }
2272
2273    if (DEBUG_TEX) {
2274       print_sample_4(__FUNCTION__, rgba);
2275    }
2276 }
2277
2278
2279 /**
2280  * Do shadow/depth comparisons.
2281  */
2282 static void
2283 sample_compare(struct sp_sampler_view *sp_sview,
2284                struct sp_sampler *sp_samp,
2285                const float s[TGSI_QUAD_SIZE],
2286                const float t[TGSI_QUAD_SIZE],
2287                const float p[TGSI_QUAD_SIZE],
2288                const float c0[TGSI_QUAD_SIZE],
2289                const float c1[TGSI_QUAD_SIZE],
2290                enum tgsi_sampler_control control,
2291                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2292 {
2293    const struct pipe_sampler_state *sampler = &sp_samp->base;
2294    int j, k0, k1, k2, k3;
2295    float val;
2296    float pc0, pc1, pc2, pc3;
2297
2298    /**
2299     * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
2300     * for 2D Array texture we need to use the 'c0' (aka Q).
2301     * When we sampled the depth texture, the depth value was put into all
2302     * RGBA channels.  We look at the red channel here.
2303     */
2304
2305    if (sp_sview->base.texture->target == PIPE_TEXTURE_2D_ARRAY ||
2306        sp_sview->base.texture->target == PIPE_TEXTURE_CUBE) {
2307       pc0 = CLAMP(c0[0], 0.0F, 1.0F);
2308       pc1 = CLAMP(c0[1], 0.0F, 1.0F);
2309       pc2 = CLAMP(c0[2], 0.0F, 1.0F);
2310       pc3 = CLAMP(c0[3], 0.0F, 1.0F);
2311    } else if (sp_sview->base.texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
2312       pc0 = CLAMP(c1[0], 0.0F, 1.0F);
2313       pc1 = CLAMP(c1[1], 0.0F, 1.0F);
2314       pc2 = CLAMP(c1[2], 0.0F, 1.0F);
2315       pc3 = CLAMP(c1[3], 0.0F, 1.0F);
2316    } else {
2317       pc0 = CLAMP(p[0], 0.0F, 1.0F);
2318       pc1 = CLAMP(p[1], 0.0F, 1.0F);
2319       pc2 = CLAMP(p[2], 0.0F, 1.0F);
2320       pc3 = CLAMP(p[3], 0.0F, 1.0F);
2321    }
2322    /* compare four texcoords vs. four texture samples */
2323    switch (sampler->compare_func) {
2324    case PIPE_FUNC_LESS:
2325       k0 = pc0 < rgba[0][0];
2326       k1 = pc1 < rgba[0][1];
2327       k2 = pc2 < rgba[0][2];
2328       k3 = pc3 < rgba[0][3];
2329       break;
2330    case PIPE_FUNC_LEQUAL:
2331       k0 = pc0 <= rgba[0][0];
2332       k1 = pc1 <= rgba[0][1];
2333       k2 = pc2 <= rgba[0][2];
2334       k3 = pc3 <= rgba[0][3];
2335       break;
2336    case PIPE_FUNC_GREATER:
2337       k0 = pc0 > rgba[0][0];
2338       k1 = pc1 > rgba[0][1];
2339       k2 = pc2 > rgba[0][2];
2340       k3 = pc3 > rgba[0][3];
2341       break;
2342    case PIPE_FUNC_GEQUAL:
2343       k0 = pc0 >= rgba[0][0];
2344       k1 = pc1 >= rgba[0][1];
2345       k2 = pc2 >= rgba[0][2];
2346       k3 = pc3 >= rgba[0][3];
2347       break;
2348    case PIPE_FUNC_EQUAL:
2349       k0 = pc0 == rgba[0][0];
2350       k1 = pc1 == rgba[0][1];
2351       k2 = pc2 == rgba[0][2];
2352       k3 = pc3 == rgba[0][3];
2353       break;
2354    case PIPE_FUNC_NOTEQUAL:
2355       k0 = pc0 != rgba[0][0];
2356       k1 = pc1 != rgba[0][1];
2357       k2 = pc2 != rgba[0][2];
2358       k3 = pc3 != rgba[0][3];
2359       break;
2360    case PIPE_FUNC_ALWAYS:
2361       k0 = k1 = k2 = k3 = 1;
2362       break;
2363    case PIPE_FUNC_NEVER:
2364       k0 = k1 = k2 = k3 = 0;
2365       break;
2366    default:
2367       k0 = k1 = k2 = k3 = 0;
2368       assert(0);
2369       break;
2370    }
2371
2372    if (sampler->mag_img_filter == PIPE_TEX_FILTER_LINEAR) {
2373       /* convert four pass/fail values to an intensity in [0,1] */
2374       /*
2375        * XXX this doesn't actually make much sense.
2376        * We just average the result of four _pixels_ and output the same
2377        * value for all of the four pixels of the quad.
2378        * This really needs to work on the _samples_ i.e. inside the img filter.
2379        */
2380       val = 0.25F * (k0 + k1 + k2 + k3);
2381
2382       /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
2383       for (j = 0; j < 4; j++) {
2384          rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
2385          rgba[3][j] = 1.0F;
2386       }
2387    } else {
2388       for (j = 0; j < 4; j++) {
2389          rgba[0][j] = k0;
2390          rgba[1][j] = k1;
2391          rgba[2][j] = k2;
2392          rgba[3][j] = 1.0F;
2393       }
2394    }
2395 }
2396
2397
2398 static void
2399 do_swizzling(const struct pipe_sampler_view *sview,
2400              float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
2401              float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2402 {
2403    int j;
2404    const unsigned swizzle_r = sview->swizzle_r;
2405    const unsigned swizzle_g = sview->swizzle_g;
2406    const unsigned swizzle_b = sview->swizzle_b;
2407    const unsigned swizzle_a = sview->swizzle_a;
2408
2409    switch (swizzle_r) {
2410    case PIPE_SWIZZLE_ZERO:
2411       for (j = 0; j < 4; j++)
2412          out[0][j] = 0.0f;
2413       break;
2414    case PIPE_SWIZZLE_ONE:
2415       for (j = 0; j < 4; j++)
2416          out[0][j] = 1.0f;
2417       break;
2418    default:
2419       assert(swizzle_r < 4);
2420       for (j = 0; j < 4; j++)
2421          out[0][j] = in[swizzle_r][j];
2422    }
2423
2424    switch (swizzle_g) {
2425    case PIPE_SWIZZLE_ZERO:
2426       for (j = 0; j < 4; j++)
2427          out[1][j] = 0.0f;
2428       break;
2429    case PIPE_SWIZZLE_ONE:
2430       for (j = 0; j < 4; j++)
2431          out[1][j] = 1.0f;
2432       break;
2433    default:
2434       assert(swizzle_g < 4);
2435       for (j = 0; j < 4; j++)
2436          out[1][j] = in[swizzle_g][j];
2437    }
2438
2439    switch (swizzle_b) {
2440    case PIPE_SWIZZLE_ZERO:
2441       for (j = 0; j < 4; j++)
2442          out[2][j] = 0.0f;
2443       break;
2444    case PIPE_SWIZZLE_ONE:
2445       for (j = 0; j < 4; j++)
2446          out[2][j] = 1.0f;
2447       break;
2448    default:
2449       assert(swizzle_b < 4);
2450       for (j = 0; j < 4; j++)
2451          out[2][j] = in[swizzle_b][j];
2452    }
2453
2454    switch (swizzle_a) {
2455    case PIPE_SWIZZLE_ZERO:
2456       for (j = 0; j < 4; j++)
2457          out[3][j] = 0.0f;
2458       break;
2459    case PIPE_SWIZZLE_ONE:
2460       for (j = 0; j < 4; j++)
2461          out[3][j] = 1.0f;
2462       break;
2463    default:
2464       assert(swizzle_a < 4);
2465       for (j = 0; j < 4; j++)
2466          out[3][j] = in[swizzle_a][j];
2467    }
2468 }
2469
2470
2471 static wrap_nearest_func
2472 get_nearest_unorm_wrap(unsigned mode)
2473 {
2474    switch (mode) {
2475    case PIPE_TEX_WRAP_CLAMP:
2476       return wrap_nearest_unorm_clamp;
2477    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2478       return wrap_nearest_unorm_clamp_to_edge;
2479    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2480       return wrap_nearest_unorm_clamp_to_border;
2481    default:
2482       assert(0);
2483       return wrap_nearest_unorm_clamp;
2484    }
2485 }
2486
2487
2488 static wrap_nearest_func
2489 get_nearest_wrap(unsigned mode)
2490 {
2491    switch (mode) {
2492    case PIPE_TEX_WRAP_REPEAT:
2493       return wrap_nearest_repeat;
2494    case PIPE_TEX_WRAP_CLAMP:
2495       return wrap_nearest_clamp;
2496    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2497       return wrap_nearest_clamp_to_edge;
2498    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2499       return wrap_nearest_clamp_to_border;
2500    case PIPE_TEX_WRAP_MIRROR_REPEAT:
2501       return wrap_nearest_mirror_repeat;
2502    case PIPE_TEX_WRAP_MIRROR_CLAMP:
2503       return wrap_nearest_mirror_clamp;
2504    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
2505       return wrap_nearest_mirror_clamp_to_edge;
2506    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
2507       return wrap_nearest_mirror_clamp_to_border;
2508    default:
2509       assert(0);
2510       return wrap_nearest_repeat;
2511    }
2512 }
2513
2514
2515 static wrap_linear_func
2516 get_linear_unorm_wrap(unsigned mode)
2517 {
2518    switch (mode) {
2519    case PIPE_TEX_WRAP_CLAMP:
2520       return wrap_linear_unorm_clamp;
2521    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2522       return wrap_linear_unorm_clamp_to_edge;
2523    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2524       return wrap_linear_unorm_clamp_to_border;
2525    default:
2526       assert(0);
2527       return wrap_linear_unorm_clamp;
2528    }
2529 }
2530
2531
2532 static wrap_linear_func
2533 get_linear_wrap(unsigned mode)
2534 {
2535    switch (mode) {
2536    case PIPE_TEX_WRAP_REPEAT:
2537       return wrap_linear_repeat;
2538    case PIPE_TEX_WRAP_CLAMP:
2539       return wrap_linear_clamp;
2540    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
2541       return wrap_linear_clamp_to_edge;
2542    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
2543       return wrap_linear_clamp_to_border;
2544    case PIPE_TEX_WRAP_MIRROR_REPEAT:
2545       return wrap_linear_mirror_repeat;
2546    case PIPE_TEX_WRAP_MIRROR_CLAMP:
2547       return wrap_linear_mirror_clamp;
2548    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
2549       return wrap_linear_mirror_clamp_to_edge;
2550    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
2551       return wrap_linear_mirror_clamp_to_border;
2552    default:
2553       assert(0);
2554       return wrap_linear_repeat;
2555    }
2556 }
2557
2558
2559 /**
2560  * Is swizzling needed for the given state key?
2561  */
2562 static INLINE bool
2563 any_swizzle(const struct pipe_sampler_view *view)
2564 {
2565    return (view->swizzle_r != PIPE_SWIZZLE_RED ||
2566            view->swizzle_g != PIPE_SWIZZLE_GREEN ||
2567            view->swizzle_b != PIPE_SWIZZLE_BLUE ||
2568            view->swizzle_a != PIPE_SWIZZLE_ALPHA);
2569 }
2570
2571
2572 static img_filter_func
2573 get_img_filter(const struct sp_sampler_view *sp_sview,
2574                const struct pipe_sampler_state *sampler,
2575                unsigned filter)
2576 {
2577    switch (sp_sview->base.texture->target) {
2578    case PIPE_BUFFER:
2579    case PIPE_TEXTURE_1D:
2580       if (filter == PIPE_TEX_FILTER_NEAREST) 
2581          return img_filter_1d_nearest;
2582       else
2583          return img_filter_1d_linear;
2584       break;
2585    case PIPE_TEXTURE_1D_ARRAY:
2586       if (filter == PIPE_TEX_FILTER_NEAREST) 
2587          return img_filter_1d_array_nearest;
2588       else
2589          return img_filter_1d_array_linear;
2590       break;
2591    case PIPE_TEXTURE_2D:
2592    case PIPE_TEXTURE_RECT:
2593       /* Try for fast path:
2594        */
2595       if (sp_sview->pot2d &&
2596           sampler->wrap_s == sampler->wrap_t &&
2597           sampler->normalized_coords) 
2598       {
2599          switch (sampler->wrap_s) {
2600          case PIPE_TEX_WRAP_REPEAT:
2601             switch (filter) {
2602             case PIPE_TEX_FILTER_NEAREST:
2603                return img_filter_2d_nearest_repeat_POT;
2604             case PIPE_TEX_FILTER_LINEAR:
2605                return img_filter_2d_linear_repeat_POT;
2606             default:
2607                break;
2608             }
2609             break;
2610          case PIPE_TEX_WRAP_CLAMP:
2611             switch (filter) {
2612             case PIPE_TEX_FILTER_NEAREST:
2613                return img_filter_2d_nearest_clamp_POT;
2614             default:
2615                break;
2616             }
2617          }
2618       }
2619       /* Otherwise use default versions:
2620        */
2621       if (filter == PIPE_TEX_FILTER_NEAREST) 
2622          return img_filter_2d_nearest;
2623       else
2624          return img_filter_2d_linear;
2625       break;
2626    case PIPE_TEXTURE_2D_ARRAY:
2627       if (filter == PIPE_TEX_FILTER_NEAREST) 
2628          return img_filter_2d_array_nearest;
2629       else
2630          return img_filter_2d_array_linear;
2631       break;
2632    case PIPE_TEXTURE_CUBE:
2633       if (filter == PIPE_TEX_FILTER_NEAREST) 
2634          return img_filter_cube_nearest;
2635       else
2636          return img_filter_cube_linear;
2637       break;
2638    case PIPE_TEXTURE_CUBE_ARRAY:
2639       if (filter == PIPE_TEX_FILTER_NEAREST) 
2640          return img_filter_cube_array_nearest;
2641       else
2642          return img_filter_cube_array_linear;
2643       break;
2644    case PIPE_TEXTURE_3D:
2645       if (filter == PIPE_TEX_FILTER_NEAREST) 
2646          return img_filter_3d_nearest;
2647       else
2648          return img_filter_3d_linear;
2649       break;
2650    default:
2651       assert(0);
2652       return img_filter_1d_nearest;
2653    }
2654 }
2655
2656
2657 static void
2658 sample_mip(struct sp_sampler_view *sp_sview,
2659            struct sp_sampler *sp_samp,
2660            const float s[TGSI_QUAD_SIZE],
2661            const float t[TGSI_QUAD_SIZE],
2662            const float p[TGSI_QUAD_SIZE],
2663            const float c0[TGSI_QUAD_SIZE],
2664            const float lod[TGSI_QUAD_SIZE],
2665            enum tgsi_sampler_control control,
2666            float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2667 {
2668    mip_filter_func mip_filter;
2669    img_filter_func min_img_filter = NULL;
2670    img_filter_func mag_img_filter = NULL;
2671
2672    if (sp_sview->pot2d & sp_samp->min_mag_equal_repeat_linear) {
2673       mip_filter = mip_filter_linear_2d_linear_repeat_POT;
2674    }
2675    else {
2676       mip_filter = sp_samp->mip_filter;
2677       min_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->min_img_filter);
2678       if (sp_samp->min_mag_equal) {
2679          mag_img_filter = min_img_filter;
2680       }
2681       else {
2682          mag_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->base.mag_img_filter);
2683       }
2684    }
2685
2686    mip_filter(sp_sview, sp_samp, min_img_filter, mag_img_filter,
2687               s, t, p, c0, lod, control, rgba);
2688
2689    if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) {
2690       sample_compare(sp_sview, sp_samp, s, t, p, c0, lod, control, rgba);
2691    }
2692
2693    if (sp_sview->need_swizzle) {
2694       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2695       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
2696       do_swizzling(&sp_sview->base, rgba_temp, rgba);
2697    }
2698
2699 }
2700
2701
2702 /**
2703  * Use 3D texcoords to choose a cube face, then sample the 2D cube faces.
2704  * Put face info into the sampler faces[] array.
2705  */
2706 static void
2707 sample_cube(struct sp_sampler_view *sp_sview,
2708             struct sp_sampler *sp_samp,
2709             const float s[TGSI_QUAD_SIZE],
2710             const float t[TGSI_QUAD_SIZE],
2711             const float p[TGSI_QUAD_SIZE],
2712             const float c0[TGSI_QUAD_SIZE],
2713             const float c1[TGSI_QUAD_SIZE],
2714             enum tgsi_sampler_control control,
2715             float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2716 {
2717    unsigned j;
2718    float ssss[4], tttt[4];
2719
2720    /* Not actually used, but the intermediate steps that do the
2721     * dereferencing don't know it.
2722     */
2723    static float pppp[4] = { 0, 0, 0, 0 };
2724
2725    pppp[0] = c0[0];
2726    pppp[1] = c0[1];
2727    pppp[2] = c0[2];
2728    pppp[3] = c0[3];
2729    /*
2730      major axis
2731      direction    target                             sc     tc    ma
2732      ----------   -------------------------------    ---    ---   ---
2733      +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
2734      -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
2735      +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
2736      -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
2737      +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
2738      -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
2739    */
2740
2741    /* Choose the cube face and compute new s/t coords for the 2D face.
2742     *
2743     * Use the same cube face for all four pixels in the quad.
2744     *
2745     * This isn't ideal, but if we want to use a different cube face
2746     * per pixel in the quad, we'd have to also compute the per-face
2747     * LOD here too.  That's because the four post-face-selection
2748     * texcoords are no longer related to each other (they're
2749     * per-face!)  so we can't use subtraction to compute the partial
2750     * deriviates to compute the LOD.  Doing so (near cube edges
2751     * anyway) gives us pretty much random values.
2752     */
2753    {
2754       /* use the average of the four pixel's texcoords to choose the face */
2755       const float rx = 0.25F * (s[0] + s[1] + s[2] + s[3]);
2756       const float ry = 0.25F * (t[0] + t[1] + t[2] + t[3]);
2757       const float rz = 0.25F * (p[0] + p[1] + p[2] + p[3]);
2758       const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
2759
2760       if (arx >= ary && arx >= arz) {
2761          float sign = (rx >= 0.0F) ? 1.0F : -1.0F;
2762          uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X;
2763          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2764             const float ima = -0.5F / fabsf(s[j]);
2765             ssss[j] = sign *  p[j] * ima + 0.5F;
2766             tttt[j] =         t[j] * ima + 0.5F;
2767             sp_sview->faces[j] = face;
2768          }
2769       }
2770       else if (ary >= arx && ary >= arz) {
2771          float sign = (ry >= 0.0F) ? 1.0F : -1.0F;
2772          uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y;
2773          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2774             const float ima = -0.5F / fabsf(t[j]);
2775             ssss[j] =        -s[j] * ima + 0.5F;
2776             tttt[j] = sign * -p[j] * ima + 0.5F;
2777             sp_sview->faces[j] = face;
2778          }
2779       }
2780       else {
2781          float sign = (rz >= 0.0F) ? 1.0F : -1.0F;
2782          uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z;
2783          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2784             const float ima = -0.5F / fabsf(p[j]);
2785             ssss[j] = sign * -s[j] * ima + 0.5F;
2786             tttt[j] =         t[j] * ima + 0.5F;
2787             sp_sview->faces[j] = face;
2788          }
2789       }
2790    }
2791
2792    sample_mip(sp_sview, sp_samp, ssss, tttt, pppp, c0, c1, control, rgba);
2793 }
2794
2795
2796 static void
2797 sp_get_dims(struct sp_sampler_view *sp_sview, int level,
2798             int dims[4])
2799 {
2800    const struct pipe_sampler_view *view = &sp_sview->base;
2801    const struct pipe_resource *texture = view->texture;
2802
2803    /* undefined according to EXT_gpu_program */
2804    level += view->u.tex.first_level;
2805    if (level > view->u.tex.last_level)
2806       return;
2807
2808    dims[0] = u_minify(texture->width0, level);
2809
2810    switch(texture->target) {
2811    case PIPE_TEXTURE_1D_ARRAY:
2812       dims[1] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
2813       /* fallthrough */
2814    case PIPE_TEXTURE_1D:
2815       return;
2816    case PIPE_TEXTURE_2D_ARRAY:
2817       dims[2] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
2818       /* fallthrough */
2819    case PIPE_TEXTURE_2D:
2820    case PIPE_TEXTURE_CUBE:
2821    case PIPE_TEXTURE_RECT:
2822       dims[1] = u_minify(texture->height0, level);
2823       return;
2824    case PIPE_TEXTURE_3D:
2825       dims[1] = u_minify(texture->height0, level);
2826       dims[2] = u_minify(texture->depth0, level);
2827       return;
2828    case PIPE_TEXTURE_CUBE_ARRAY:
2829       dims[1] = u_minify(texture->height0, level);
2830       dims[2] = (view->u.tex.last_layer - view->u.tex.first_layer + 1) / 6;
2831       break;
2832    case PIPE_BUFFER:
2833       dims[0] /= util_format_get_blocksize(view->format);
2834       return;
2835    default:
2836       assert(!"unexpected texture target in sp_get_dims()");
2837       return;
2838    }
2839 }
2840
2841 /**
2842  * This function is only used for getting unfiltered texels via the
2843  * TXF opcode.  The GL spec says that out-of-bounds texel fetches
2844  * produce undefined results.  Instead of crashing, lets just clamp
2845  * coords to the texture image size.
2846  */
2847 static void
2848 sp_get_texels(struct sp_sampler_view *sp_sview,
2849               const int v_i[TGSI_QUAD_SIZE],
2850               const int v_j[TGSI_QUAD_SIZE],
2851               const int v_k[TGSI_QUAD_SIZE],
2852               const int lod[TGSI_QUAD_SIZE],
2853               const int8_t offset[3],
2854               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
2855 {
2856    union tex_tile_address addr;
2857    const struct pipe_resource *texture = sp_sview->base.texture;
2858    int j, c;
2859    const float *tx;
2860    int width, height, depth;
2861
2862    addr.value = 0;
2863    /* TODO write a better test for LOD */
2864    addr.bits.level = lod[0];
2865
2866    width = u_minify(texture->width0, addr.bits.level);
2867    height = u_minify(texture->height0, addr.bits.level);
2868    depth = u_minify(texture->depth0, addr.bits.level);
2869
2870    switch(texture->target) {
2871    case PIPE_BUFFER:
2872    case PIPE_TEXTURE_1D:
2873       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2874          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2875          tx = get_texel_2d_no_border(sp_sview, addr, x, 0);
2876          for (c = 0; c < 4; c++) {
2877             rgba[c][j] = tx[c];
2878          }
2879       }
2880       break;
2881    case PIPE_TEXTURE_1D_ARRAY:
2882       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2883          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2884          int y = CLAMP(v_j[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
2885          tx = get_texel_2d_no_border(sp_sview, addr, x, y);
2886          for (c = 0; c < 4; c++) {
2887             rgba[c][j] = tx[c];
2888          }
2889       }
2890       break;
2891    case PIPE_TEXTURE_2D:
2892    case PIPE_TEXTURE_RECT:
2893       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2894          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2895          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
2896          tx = get_texel_2d_no_border(sp_sview, addr, x, y);
2897          for (c = 0; c < 4; c++) {
2898             rgba[c][j] = tx[c];
2899          }
2900       }
2901       break;
2902    case PIPE_TEXTURE_2D_ARRAY:
2903       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2904          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2905          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
2906          int layer = CLAMP(v_k[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
2907          tx = get_texel_3d_no_border(sp_sview, addr, x, y, layer);
2908          for (c = 0; c < 4; c++) {
2909             rgba[c][j] = tx[c];
2910          }
2911       }
2912       break;
2913    case PIPE_TEXTURE_3D:
2914       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
2915          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
2916          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
2917          int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
2918          tx = get_texel_3d_no_border(sp_sview, addr, x, y, z);
2919          for (c = 0; c < 4; c++) {
2920             rgba[c][j] = tx[c];
2921          }
2922       }
2923       break;
2924    case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */
2925    default:
2926       assert(!"Unknown or CUBE texture type in TXF processing\n");
2927       break;
2928    }
2929
2930    if (sp_sview->need_swizzle) {
2931       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
2932       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
2933       do_swizzling(&sp_sview->base, rgba_temp, rgba);
2934    }
2935 }
2936
2937
2938 void *
2939 softpipe_create_sampler_state(struct pipe_context *pipe,
2940                               const struct pipe_sampler_state *sampler)
2941 {
2942    struct sp_sampler *samp = CALLOC_STRUCT(sp_sampler);
2943
2944    samp->base = *sampler;
2945
2946    /* Note that (for instance) linear_texcoord_s and
2947     * nearest_texcoord_s may be active at the same time, if the
2948     * sampler min_img_filter differs from its mag_img_filter.
2949     */
2950    if (sampler->normalized_coords) {
2951       samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
2952       samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
2953       samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
2954
2955       samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
2956       samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
2957       samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
2958    }
2959    else {
2960       samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
2961       samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
2962       samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
2963
2964       samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
2965       samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
2966       samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
2967    }
2968
2969    samp->min_img_filter = sampler->min_img_filter;
2970
2971    switch (sampler->min_mip_filter) {
2972    case PIPE_TEX_MIPFILTER_NONE:
2973       if (sampler->min_img_filter == sampler->mag_img_filter)
2974          samp->mip_filter = mip_filter_none_no_filter_select;
2975       else
2976          samp->mip_filter = mip_filter_none;
2977       break;
2978
2979    case PIPE_TEX_MIPFILTER_NEAREST:
2980       samp->mip_filter = mip_filter_nearest;
2981       break;
2982
2983    case PIPE_TEX_MIPFILTER_LINEAR:
2984       if (sampler->min_img_filter == sampler->mag_img_filter &&
2985           sampler->normalized_coords &&
2986           sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
2987           sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
2988           sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
2989           sampler->max_anisotropy <= 1) {
2990          samp->min_mag_equal_repeat_linear = TRUE;
2991       }
2992       samp->mip_filter = mip_filter_linear;
2993
2994       /* Anisotropic filtering extension. */
2995       if (sampler->max_anisotropy > 1) {
2996          samp->mip_filter = mip_filter_linear_aniso;
2997
2998          /* Override min_img_filter:
2999           * min_img_filter needs to be set to NEAREST since we need to access
3000           * each texture pixel as it is and weight it later; using linear
3001           * filters will have incorrect results.
3002           * By setting the filter to NEAREST here, we can avoid calling the
3003           * generic img_filter_2d_nearest in the anisotropic filter function,
3004           * making it possible to use one of the accelerated implementations
3005           */
3006          samp->min_img_filter = PIPE_TEX_FILTER_NEAREST;
3007
3008          /* on first access create the lookup table containing the filter weights. */
3009         if (!weightLut) {
3010            create_filter_table();
3011         }
3012       }
3013       break;
3014    }
3015    if (samp->min_img_filter == sampler->mag_img_filter) {
3016       samp->min_mag_equal = TRUE;
3017    }
3018
3019    return (void *)samp;
3020 }
3021
3022
3023 compute_lambda_func
3024 softpipe_get_lambda_func(const struct pipe_sampler_view *view, unsigned shader)
3025 {
3026    if (shader != PIPE_SHADER_FRAGMENT)
3027       return compute_lambda_vert;
3028
3029    switch (view->texture->target) {
3030    case PIPE_BUFFER:
3031    case PIPE_TEXTURE_1D:
3032    case PIPE_TEXTURE_1D_ARRAY:
3033       return compute_lambda_1d;
3034    case PIPE_TEXTURE_2D:
3035    case PIPE_TEXTURE_2D_ARRAY:
3036    case PIPE_TEXTURE_RECT:
3037    case PIPE_TEXTURE_CUBE:
3038    case PIPE_TEXTURE_CUBE_ARRAY:
3039       return compute_lambda_2d;
3040    case PIPE_TEXTURE_3D:
3041       return compute_lambda_3d;
3042    default:
3043       assert(0);
3044       return compute_lambda_1d;
3045    }
3046 }
3047
3048
3049 struct pipe_sampler_view *
3050 softpipe_create_sampler_view(struct pipe_context *pipe,
3051                              struct pipe_resource *resource,
3052                              const struct pipe_sampler_view *templ)
3053 {
3054    struct sp_sampler_view *sview = CALLOC_STRUCT(sp_sampler_view);
3055    struct softpipe_resource *spr = (struct softpipe_resource *)resource;
3056
3057    if (sview) {
3058       struct pipe_sampler_view *view = &sview->base;
3059       *view = *templ;
3060       view->reference.count = 1;
3061       view->texture = NULL;
3062       pipe_resource_reference(&view->texture, resource);
3063       view->context = pipe;
3064
3065       if (any_swizzle(view)) {
3066          sview->need_swizzle = TRUE;
3067       }
3068
3069       if (resource->target == PIPE_TEXTURE_CUBE ||
3070           resource->target == PIPE_TEXTURE_CUBE_ARRAY)
3071          sview->get_samples = sample_cube;
3072       else {
3073          sview->get_samples = sample_mip;
3074       }
3075       sview->pot2d = spr->pot &&
3076                      (resource->target == PIPE_TEXTURE_2D ||
3077                       resource->target == PIPE_TEXTURE_RECT);
3078
3079       sview->xpot = util_logbase2( resource->width0 );
3080       sview->ypot = util_logbase2( resource->height0 );
3081    }
3082
3083    return (struct pipe_sampler_view *) sview;
3084 }
3085
3086
3087 static void
3088 sp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler,
3089                  const unsigned sview_index,
3090                  int level, int dims[4])
3091 {
3092    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
3093
3094    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
3095    /* TODO should have defined behavior if no texture is bound. */
3096    sp_get_dims(&sp_samp->sp_sview[sview_index], level, dims);
3097 }
3098
3099
3100 static void
3101 sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
3102                     const unsigned sview_index,
3103                     const unsigned sampler_index,
3104                     const float s[TGSI_QUAD_SIZE],
3105                     const float t[TGSI_QUAD_SIZE],
3106                     const float p[TGSI_QUAD_SIZE],
3107                     const float c0[TGSI_QUAD_SIZE],
3108                     const float lod[TGSI_QUAD_SIZE],
3109                     float derivs[3][2][TGSI_QUAD_SIZE],
3110                     const int8_t offset[3],
3111                     enum tgsi_sampler_control control,
3112                     float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3113 {
3114    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
3115
3116    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
3117    assert(sampler_index < PIPE_MAX_SAMPLERS);
3118    assert(sp_samp->sp_sampler[sampler_index]);
3119    /* FIXME should have defined behavior if no texture is bound. */
3120    assert(sp_samp->sp_sview[sview_index].get_samples);
3121    sp_samp->sp_sview[sview_index].get_samples(&sp_samp->sp_sview[sview_index],
3122                                               sp_samp->sp_sampler[sampler_index],
3123                                               s, t, p, c0, lod, control, rgba);
3124 }
3125
3126
3127 static void
3128 sp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler,
3129                   const unsigned sview_index,
3130                   const int i[TGSI_QUAD_SIZE],
3131                   const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
3132                   const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
3133                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
3134 {
3135    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
3136
3137    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
3138    /* FIXME should have defined behavior if no texture is bound. */
3139    assert(sp_samp->sp_sview[sview_index].base.texture);
3140    sp_get_texels(&sp_samp->sp_sview[sview_index], i, j, k, lod, offset, rgba);
3141 }
3142
3143
3144 struct sp_tgsi_sampler *
3145 sp_create_tgsi_sampler(void)
3146 {
3147    struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler);
3148    if (!samp)
3149       return NULL;
3150
3151    samp->base.get_dims = sp_tgsi_get_dims;
3152    samp->base.get_samples = sp_tgsi_get_samples;
3153    samp->base.get_texel = sp_tgsi_get_texel;
3154
3155    return samp;
3156 }
3157