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