e1e1d0f0ceb674f2c72fc6917e183cdf4c0eb958
[mesa.git] / src / mesa / swrast / s_texture.c
1 /* $Id: s_texture.c,v 1.42 2001/11/19 01:18:28 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions 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 MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "colormac.h"
31 #include "macros.h"
32 #include "mmath.h"
33 #include "mem.h"
34 #include "texformat.h"
35 #include "teximage.h"
36
37 #include "s_context.h"
38 #include "s_pb.h"
39 #include "s_texture.h"
40
41
42 /*
43 * These values are used in the fixed-point arithmetic used
44 * for linear filtering.
45 */
46 #define WEIGHT_SCALE 65536.0F
47 #define WEIGHT_SHIFT 16
48
49
50 /*
51 * Used to compute texel locations for linear sampling.
52 * Input:
53 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB
54 * S = texcoord in [0,1]
55 * SIZE = width (or height or depth) of texture
56 * Output:
57 * U = texcoord in [0, width]
58 * I0, I1 = two nearest texel indexes
59 */
60 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
61 { \
62 if (wrapMode == GL_REPEAT) { \
63 U = S * SIZE - 0.5F; \
64 I0 = IFLOOR(U) & (SIZE - 1); \
65 I1 = (I0 + 1) & (SIZE - 1); \
66 } \
67 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
68 if (S <= 0.0F) \
69 U = 0.0F; \
70 else if (S >= 1.0F) \
71 U = (GLfloat) SIZE; \
72 else \
73 U = S * SIZE; \
74 U -= 0.5F; \
75 I0 = IFLOOR(U); \
76 I1 = I0 + 1; \
77 if (I0 < 0) \
78 I0 = 0; \
79 if (I1 >= (GLint) SIZE) \
80 I1 = SIZE - 1; \
81 } \
82 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
83 const GLfloat min = -1.0F / (2.0F * SIZE); \
84 const GLfloat max = 1.0F - min; \
85 if (S <= min) \
86 U = min * SIZE; \
87 else if (S >= max) \
88 U = max * SIZE; \
89 else \
90 U = S * SIZE; \
91 U -= 0.5F; \
92 I0 = IFLOOR(U); \
93 I1 = I0 + 1; \
94 } \
95 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
96 const GLint flr = IFLOOR(S); \
97 if (flr & 1) \
98 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
99 else \
100 U = S - (GLfloat) flr; /* flr is even */ \
101 I0 = IFLOOR(U); \
102 I1 = I0 + 1; \
103 if (I0 < 0) \
104 I0 = 0; \
105 if (I1 >= (GLint) SIZE) \
106 I1 = SIZE - 1; \
107 } \
108 else { \
109 ASSERT(wrapMode == GL_CLAMP); \
110 if (S <= 0.0F) \
111 U = 0.0F; \
112 else if (S >= 1.0F) \
113 U = (GLfloat) SIZE; \
114 else \
115 U = S * SIZE; \
116 U -= 0.5F; \
117 I0 = IFLOOR(U); \
118 I1 = I0 + 1; \
119 } \
120 }
121
122
123 /*
124 * Used to compute texel location for nearest sampling.
125 */
126 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
127 { \
128 if (wrapMode == GL_REPEAT) { \
129 /* s limited to [0,1) */ \
130 /* i limited to [0,size-1] */ \
131 I = IFLOOR(S * SIZE); \
132 I &= (SIZE - 1); \
133 } \
134 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
135 /* s limited to [min,max] */ \
136 /* i limited to [0, size-1] */ \
137 const GLfloat min = 1.0F / (2.0F * SIZE); \
138 const GLfloat max = 1.0F - min; \
139 if (S < min) \
140 I = 0; \
141 else if (S > max) \
142 I = SIZE - 1; \
143 else \
144 I = IFLOOR(S * SIZE); \
145 } \
146 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
147 /* s limited to [min,max] */ \
148 /* i limited to [-1, size] */ \
149 const GLfloat min = -1.0F / (2.0F * SIZE); \
150 const GLfloat max = 1.0F - min; \
151 if (S <= min) \
152 I = -1; \
153 else if (S >= max) \
154 I = SIZE; \
155 else \
156 I = IFLOOR(S * SIZE); \
157 } \
158 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
159 const GLfloat min = 1.0F / (2.0F * SIZE); \
160 const GLfloat max = 1.0F - min; \
161 const GLint flr = IFLOOR(S); \
162 GLfloat u; \
163 if (flr & 1) \
164 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
165 else \
166 u = S - (GLfloat) flr; /* flr is even */ \
167 if (u < min) \
168 I = 0; \
169 else if (u > max) \
170 I = SIZE - 1; \
171 else \
172 I = IFLOOR(u * SIZE); \
173 } \
174 else { \
175 ASSERT(wrapMode == GL_CLAMP); \
176 /* s limited to [0,1] */ \
177 /* i limited to [0,size-1] */ \
178 if (S <= 0.0F) \
179 I = 0; \
180 else if (S >= 1.0F) \
181 I = SIZE - 1; \
182 else \
183 I = IFLOOR(S * SIZE); \
184 } \
185 }
186
187
188 /*
189 * Compute linear mipmap levels for given lambda.
190 */
191 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
192 { \
193 if (lambda < 0.0F) \
194 lambda = 0.0F; \
195 else if (lambda > tObj->_MaxLambda) \
196 lambda = tObj->_MaxLambda; \
197 level = (GLint) (tObj->BaseLevel + lambda); \
198 }
199
200
201 /*
202 * Compute nearest mipmap level for given lambda.
203 */
204 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
205 { \
206 if (lambda <= 0.5F) \
207 lambda = 0.0F; \
208 else if (lambda > tObj->_MaxLambda + 0.4999F) \
209 lambda = tObj->_MaxLambda + 0.4999F; \
210 level = (GLint) (tObj->BaseLevel + lambda + 0.5F); \
211 if (level > tObj->_MaxLevel) \
212 level = tObj->_MaxLevel; \
213 }
214
215
216
217 /*
218 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
219 * see 1-pixel bands of improperly weighted linear-sampled texels. The
220 * tests/texwrap.c demo is a good test.
221 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
222 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
223 */
224 #define FRAC(f) ((f) - IFLOOR(f))
225
226
227
228 /*
229 * Bitflags for texture border color sampling.
230 */
231 #define I0BIT 1
232 #define I1BIT 2
233 #define J0BIT 4
234 #define J1BIT 8
235 #define K0BIT 16
236 #define K1BIT 32
237
238
239
240 /*
241 * Get texture palette entry.
242 */
243 static void
244 palette_sample(const GLcontext *ctx,
245 const struct gl_texture_object *tObj,
246 GLint index, GLchan rgba[4] )
247 {
248 const GLchan *palette;
249 GLenum format;
250
251 if (ctx->Texture.SharedPalette) {
252 ASSERT(!ctx->Texture.Palette.FloatTable);
253 palette = (const GLchan *) ctx->Texture.Palette.Table;
254 format = ctx->Texture.Palette.Format;
255 }
256 else {
257 ASSERT(!tObj->Palette.FloatTable);
258 palette = (const GLchan *) tObj->Palette.Table;
259 format = tObj->Palette.Format;
260 }
261
262 switch (format) {
263 case GL_ALPHA:
264 rgba[ACOMP] = palette[index];
265 return;
266 case GL_LUMINANCE:
267 case GL_INTENSITY:
268 rgba[RCOMP] = palette[index];
269 return;
270 case GL_LUMINANCE_ALPHA:
271 rgba[RCOMP] = palette[(index << 1) + 0];
272 rgba[ACOMP] = palette[(index << 1) + 1];
273 return;
274 case GL_RGB:
275 rgba[RCOMP] = palette[index * 3 + 0];
276 rgba[GCOMP] = palette[index * 3 + 1];
277 rgba[BCOMP] = palette[index * 3 + 2];
278 return;
279 case GL_RGBA:
280 rgba[RCOMP] = palette[(index << 2) + 0];
281 rgba[GCOMP] = palette[(index << 2) + 1];
282 rgba[BCOMP] = palette[(index << 2) + 2];
283 rgba[ACOMP] = palette[(index << 2) + 3];
284 return;
285 default:
286 _mesa_problem(ctx, "Bad palette format in palette_sample");
287 }
288 }
289
290
291
292 /**********************************************************************/
293 /* 1-D Texture Sampling Functions */
294 /**********************************************************************/
295
296 /*
297 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
298 */
299 static void
300 sample_1d_nearest(GLcontext *ctx,
301 const struct gl_texture_object *tObj,
302 const struct gl_texture_image *img,
303 GLfloat s, GLchan rgba[4])
304 {
305 const GLint width = img->Width2; /* without border, power of two */
306 GLint i;
307
308 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
309
310 /* skip over the border, if any */
311 i += img->Border;
312
313 if (i < 0 || i >= (GLint) img->Width) {
314 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
315 COPY_CHAN4(rgba, tObj->BorderColor);
316 }
317 else {
318 (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba);
319 if (img->Format == GL_COLOR_INDEX) {
320 palette_sample(ctx, tObj, rgba[0], rgba);
321 }
322 }
323 }
324
325
326
327 /*
328 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
329 */
330 static void
331 sample_1d_linear(GLcontext *ctx,
332 const struct gl_texture_object *tObj,
333 const struct gl_texture_image *img,
334 GLfloat s, GLchan rgba[4])
335 {
336 const GLint width = img->Width2;
337 GLint i0, i1;
338 GLfloat u;
339 GLuint useBorderColor;
340
341 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
342
343 useBorderColor = 0;
344 if (img->Border) {
345 i0 += img->Border;
346 i1 += img->Border;
347 }
348 else {
349 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
350 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
351 }
352
353 {
354 const GLfloat a = FRAC(u);
355
356 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
357 const GLfloat w0 = (1.0F-a);
358 const GLfloat w1 = a ;
359 #else /* CHAN_BITS == 8 */
360 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
361 const GLint w0 = IROUND_POS((1.0F - a) * WEIGHT_SCALE);
362 const GLint w1 = IROUND_POS( a * WEIGHT_SCALE);
363 #endif
364 GLchan t0[4], t1[4]; /* texels */
365
366 if (useBorderColor & I0BIT) {
367 COPY_CHAN4(t0, tObj->BorderColor);
368 }
369 else {
370 (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0);
371 if (img->Format == GL_COLOR_INDEX) {
372 palette_sample(ctx, tObj, t0[0], t0);
373 }
374 }
375 if (useBorderColor & I1BIT) {
376 COPY_CHAN4(t1, tObj->BorderColor);
377 }
378 else {
379 (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1);
380 if (img->Format == GL_COLOR_INDEX) {
381 palette_sample(ctx, tObj, t1[0], t1);
382 }
383 }
384
385 #if CHAN_TYPE == GL_FLOAT
386 rgba[0] = w0 * t0[0] + w1 * t1[0];
387 rgba[1] = w0 * t0[1] + w1 * t1[1];
388 rgba[2] = w0 * t0[2] + w1 * t1[2];
389 rgba[3] = w0 * t0[3] + w1 * t1[3];
390 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
391 rgba[0] = (GLchan) (w0 * t0[0] + w1 * t1[0] + 0.5);
392 rgba[1] = (GLchan) (w0 * t0[1] + w1 * t1[1] + 0.5);
393 rgba[2] = (GLchan) (w0 * t0[2] + w1 * t1[2] + 0.5);
394 rgba[3] = (GLchan) (w0 * t0[3] + w1 * t1[3] + 0.5);
395 #else /* CHAN_BITS == 8 */
396 rgba[0] = (GLchan) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT);
397 rgba[1] = (GLchan) ((w0 * t0[1] + w1 * t1[1]) >> WEIGHT_SHIFT);
398 rgba[2] = (GLchan) ((w0 * t0[2] + w1 * t1[2]) >> WEIGHT_SHIFT);
399 rgba[3] = (GLchan) ((w0 * t0[3] + w1 * t1[3]) >> WEIGHT_SHIFT);
400 #endif
401
402 }
403 }
404
405
406 static void
407 sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
408 const struct gl_texture_object *tObj,
409 GLfloat s, GLfloat lambda,
410 GLchan rgba[4])
411 {
412 GLint level;
413 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
414 sample_1d_nearest(ctx, tObj, tObj->Image[level], s, rgba);
415 }
416
417
418 static void
419 sample_1d_linear_mipmap_nearest(GLcontext *ctx,
420 const struct gl_texture_object *tObj,
421 GLfloat s, GLfloat lambda,
422 GLchan rgba[4])
423 {
424 GLint level;
425 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
426 sample_1d_linear(ctx, tObj, tObj->Image[level], s, rgba);
427 }
428
429
430
431 /*
432 * This is really just needed in order to prevent warnings with some compilers.
433 */
434 #if CHAN_TYPE == GL_FLOAT
435 #define INTCAST
436 #else
437 #define INTCAST (GLint)
438 #endif
439
440
441 static void
442 sample_1d_nearest_mipmap_linear(GLcontext *ctx,
443 const struct gl_texture_object *tObj,
444 GLfloat s, GLfloat lambda,
445 GLchan rgba[4])
446 {
447 GLint level;
448
449 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
450
451 if (level >= tObj->_MaxLevel) {
452 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, rgba);
453 }
454 else {
455 GLchan t0[4], t1[4];
456 const GLfloat f = FRAC(lambda);
457 sample_1d_nearest(ctx, tObj, tObj->Image[level ], s, t0);
458 sample_1d_nearest(ctx, tObj, tObj->Image[level+1], s, t1);
459 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
460 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
461 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
462 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
463 }
464 }
465
466
467
468 static void
469 sample_1d_linear_mipmap_linear(GLcontext *ctx,
470 const struct gl_texture_object *tObj,
471 GLfloat s, GLfloat lambda,
472 GLchan rgba[4])
473 {
474 GLint level;
475
476 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
477
478 if (level >= tObj->_MaxLevel) {
479 sample_1d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, rgba);
480 }
481 else {
482 GLchan t0[4], t1[4];
483 const GLfloat f = FRAC(lambda);
484 sample_1d_linear(ctx, tObj, tObj->Image[level ], s, t0);
485 sample_1d_linear(ctx, tObj, tObj->Image[level+1], s, t1);
486 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
487 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
488 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
489 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
490 }
491 }
492
493
494
495 static void
496 sample_nearest_1d( GLcontext *ctx, GLuint texUnit,
497 const struct gl_texture_object *tObj, GLuint n,
498 const GLfloat s[], const GLfloat t[],
499 const GLfloat u[], const GLfloat lambda[],
500 GLchan rgba[][4] )
501 {
502 GLuint i;
503 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
504 (void) t;
505 (void) u;
506 (void) lambda;
507 for (i=0;i<n;i++) {
508 sample_1d_nearest(ctx, tObj, image, s[i], rgba[i]);
509 }
510 }
511
512
513
514 static void
515 sample_linear_1d( GLcontext *ctx, GLuint texUnit,
516 const struct gl_texture_object *tObj, GLuint n,
517 const GLfloat s[], const GLfloat t[],
518 const GLfloat u[], const GLfloat lambda[],
519 GLchan rgba[][4] )
520 {
521 GLuint i;
522 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
523 (void) t;
524 (void) u;
525 (void) lambda;
526 for (i=0;i<n;i++) {
527 sample_1d_linear(ctx, tObj, image, s[i], rgba[i]);
528 }
529 }
530
531
532 /*
533 * Given an (s) texture coordinate and lambda (level of detail) value,
534 * return a texture sample.
535 *
536 */
537 static void
538 sample_lambda_1d( GLcontext *ctx, GLuint texUnit,
539 const struct gl_texture_object *tObj, GLuint n,
540 const GLfloat s[], const GLfloat t[],
541 const GLfloat u[], const GLfloat lambda[],
542 GLchan rgba[][4] )
543 {
544 GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
545 GLuint i;
546
547 (void) t;
548 (void) u;
549
550 for (i=0;i<n;i++) {
551 if (lambda[i] > MinMagThresh) {
552 /* minification */
553 switch (tObj->MinFilter) {
554 case GL_NEAREST:
555 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
556 s[i], rgba[i]);
557 break;
558 case GL_LINEAR:
559 sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
560 s[i], rgba[i]);
561 break;
562 case GL_NEAREST_MIPMAP_NEAREST:
563 sample_1d_nearest_mipmap_nearest(ctx, tObj, lambda[i], s[i],
564 rgba[i]);
565 break;
566 case GL_LINEAR_MIPMAP_NEAREST:
567 sample_1d_linear_mipmap_nearest(ctx, tObj, s[i], lambda[i],
568 rgba[i]);
569 break;
570 case GL_NEAREST_MIPMAP_LINEAR:
571 sample_1d_nearest_mipmap_linear(ctx, tObj, s[i], lambda[i],
572 rgba[i]);
573 break;
574 case GL_LINEAR_MIPMAP_LINEAR:
575 sample_1d_linear_mipmap_linear(ctx, tObj, s[i], lambda[i],
576 rgba[i]);
577 break;
578 default:
579 _mesa_problem(NULL, "Bad min filter in sample_1d_texture");
580 return;
581 }
582 }
583 else {
584 /* magnification */
585 switch (tObj->MagFilter) {
586 case GL_NEAREST:
587 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
588 s[i], rgba[i]);
589 break;
590 case GL_LINEAR:
591 sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
592 s[i], rgba[i]);
593 break;
594 default:
595 _mesa_problem(NULL, "Bad mag filter in sample_1d_texture");
596 return;
597 }
598 }
599 }
600 }
601
602
603
604
605 /**********************************************************************/
606 /* 2-D Texture Sampling Functions */
607 /**********************************************************************/
608
609
610 /*
611 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
612 */
613 static void
614 sample_2d_nearest(GLcontext *ctx,
615 const struct gl_texture_object *tObj,
616 const struct gl_texture_image *img,
617 GLfloat s, GLfloat t,
618 GLchan rgba[])
619 {
620 const GLint width = img->Width2; /* without border, power of two */
621 const GLint height = img->Height2; /* without border, power of two */
622 GLint i, j;
623
624 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
625 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j);
626
627 /* skip over the border, if any */
628 i += img->Border;
629 j += img->Border;
630
631 if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
632 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
633 COPY_CHAN4(rgba, tObj->BorderColor);
634 }
635 else {
636 (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba);
637 if (img->Format == GL_COLOR_INDEX) {
638 palette_sample(ctx, tObj, rgba[0], rgba);
639 }
640 }
641 }
642
643
644
645 /*
646 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
647 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
648 */
649 static void
650 sample_2d_linear(GLcontext *ctx,
651 const struct gl_texture_object *tObj,
652 const struct gl_texture_image *img,
653 GLfloat s, GLfloat t,
654 GLchan rgba[])
655 {
656 const GLint width = img->Width2;
657 const GLint height = img->Height2;
658 GLint i0, j0, i1, j1;
659 GLuint useBorderColor;
660 GLfloat u, v;
661
662 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
663 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1);
664
665 useBorderColor = 0;
666 if (img->Border) {
667 i0 += img->Border;
668 i1 += img->Border;
669 j0 += img->Border;
670 j1 += img->Border;
671 }
672 else {
673 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
674 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
675 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
676 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
677 }
678
679 {
680 const GLfloat a = FRAC(u);
681 const GLfloat b = FRAC(v);
682
683 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
684 const GLfloat w00 = (1.0F-a) * (1.0F-b);
685 const GLfloat w10 = a * (1.0F-b);
686 const GLfloat w01 = (1.0F-a) * b ;
687 const GLfloat w11 = a * b ;
688 #else /* CHAN_BITS == 8 */
689 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
690 const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
691 const GLint w10 = IROUND_POS( a * (1.0F-b) * WEIGHT_SCALE);
692 const GLint w01 = IROUND_POS((1.0F-a) * b * WEIGHT_SCALE);
693 const GLint w11 = IROUND_POS( a * b * WEIGHT_SCALE);
694 #endif
695 GLchan t00[4];
696 GLchan t10[4];
697 GLchan t01[4];
698 GLchan t11[4];
699
700 if (useBorderColor & (I0BIT | J0BIT)) {
701 COPY_CHAN4(t00, tObj->BorderColor);
702 }
703 else {
704 (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
705 if (img->Format == GL_COLOR_INDEX) {
706 palette_sample(ctx, tObj, t00[0], t00);
707 }
708 }
709 if (useBorderColor & (I1BIT | J0BIT)) {
710 COPY_CHAN4(t10, tObj->BorderColor);
711 }
712 else {
713 (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
714 if (img->Format == GL_COLOR_INDEX) {
715 palette_sample(ctx, tObj, t10[0], t10);
716 }
717 }
718 if (useBorderColor & (I0BIT | J1BIT)) {
719 COPY_CHAN4(t01, tObj->BorderColor);
720 }
721 else {
722 (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
723 if (img->Format == GL_COLOR_INDEX) {
724 palette_sample(ctx, tObj, t01[0], t01);
725 }
726 }
727 if (useBorderColor & (I1BIT | J1BIT)) {
728 COPY_CHAN4(t11, tObj->BorderColor);
729 }
730 else {
731 (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
732 if (img->Format == GL_COLOR_INDEX) {
733 palette_sample(ctx, tObj, t11[0], t11);
734 }
735 }
736 #if CHAN_TYPE == GL_FLOAT
737 rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0];
738 rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1];
739 rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2];
740 rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3];
741 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
742 rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] +
743 w01 * t01[0] + w11 * t11[0] + 0.5);
744 rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] +
745 w01 * t01[1] + w11 * t11[1] + 0.5);
746 rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] +
747 w01 * t01[2] + w11 * t11[2] + 0.5);
748 rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] +
749 w01 * t01[3] + w11 * t11[3] + 0.5);
750 #else /* CHAN_BITS == 8 */
751 rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] +
752 w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
753 rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] +
754 w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
755 rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] +
756 w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
757 rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] +
758 w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
759 #endif
760
761 }
762
763 }
764
765
766
767 static void
768 sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
769 const struct gl_texture_object *tObj,
770 GLfloat s, GLfloat t, GLfloat lambda,
771 GLchan rgba[4])
772 {
773 GLint level;
774 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
775 sample_2d_nearest(ctx, tObj, tObj->Image[level], s, t, rgba);
776 }
777
778
779
780 static void
781 sample_2d_linear_mipmap_nearest(GLcontext *ctx,
782 const struct gl_texture_object *tObj,
783 GLfloat s, GLfloat t, GLfloat lambda,
784 GLchan rgba[4])
785 {
786 GLint level;
787 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
788 sample_2d_linear(ctx, tObj, tObj->Image[level], s, t, rgba);
789 }
790
791
792
793 static void
794 sample_2d_nearest_mipmap_linear(GLcontext *ctx,
795 const struct gl_texture_object *tObj,
796 GLfloat s, GLfloat t, GLfloat lambda,
797 GLchan rgba[4])
798 {
799 GLint level;
800
801 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
802
803 if (level >= tObj->_MaxLevel) {
804 sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, rgba);
805 }
806 else {
807 GLchan t0[4], t1[4]; /* texels */
808 const GLfloat f = FRAC(lambda);
809 sample_2d_nearest(ctx, tObj, tObj->Image[level ], s, t, t0);
810 sample_2d_nearest(ctx, tObj, tObj->Image[level+1], s, t, t1);
811 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
812 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
813 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
814 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
815 }
816 }
817
818
819
820 static void
821 sample_2d_linear_mipmap_linear(GLcontext *ctx,
822 const struct gl_texture_object *tObj,
823 GLfloat s, GLfloat t, GLfloat lambda,
824 GLchan rgba[4])
825 {
826 GLint level;
827
828 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
829
830 if (level >= tObj->_MaxLevel) {
831 sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, rgba);
832 }
833 else {
834 GLchan t0[4], t1[4]; /* texels */
835 const GLfloat f = FRAC(lambda);
836 sample_2d_linear(ctx, tObj, tObj->Image[level ], s, t, t0);
837 sample_2d_linear(ctx, tObj, tObj->Image[level+1], s, t, t1);
838 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
839 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
840 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
841 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
842 }
843 }
844
845
846
847 static void
848 sample_nearest_2d( GLcontext *ctx, GLuint texUnit,
849 const struct gl_texture_object *tObj, GLuint n,
850 const GLfloat s[], const GLfloat t[],
851 const GLfloat u[], const GLfloat lambda[],
852 GLchan rgba[][4] )
853 {
854 GLuint i;
855 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
856 (void) u;
857 (void) lambda;
858 for (i=0;i<n;i++) {
859 sample_2d_nearest(ctx, tObj, image, s[i], t[i], rgba[i]);
860 }
861 }
862
863
864
865 static void
866 sample_linear_2d( GLcontext *ctx, GLuint texUnit,
867 const struct gl_texture_object *tObj, GLuint n,
868 const GLfloat s[], const GLfloat t[],
869 const GLfloat u[], const GLfloat lambda[],
870 GLchan rgba[][4] )
871 {
872 GLuint i;
873 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
874 (void) u;
875 (void) lambda;
876 for (i=0;i<n;i++) {
877 sample_2d_linear(ctx, tObj, image, s[i], t[i], rgba[i]);
878 }
879 }
880
881
882 /*
883 * Optimized 2-D texture sampling:
884 * S and T wrap mode == GL_REPEAT
885 * GL_NEAREST min/mag filter
886 * No border
887 * Format = GL_RGB
888 */
889 static void
890 opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit,
891 const struct gl_texture_object *tObj,
892 GLuint n, const GLfloat s[], const GLfloat t[],
893 const GLfloat u[], const GLfloat lambda[],
894 GLchan rgba[][4] )
895 {
896 const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
897 const GLfloat width = (GLfloat) img->Width;
898 const GLfloat height = (GLfloat) img->Height;
899 const GLint colMask = img->Width - 1;
900 const GLint rowMask = img->Height - 1;
901 const GLint shift = img->WidthLog2;
902 GLuint k;
903 (void) u;
904 (void) lambda;
905 ASSERT(tObj->WrapS==GL_REPEAT);
906 ASSERT(tObj->WrapT==GL_REPEAT);
907 ASSERT(img->Border==0);
908 ASSERT(img->Format==GL_RGB);
909
910 for (k=0; k<n; k++) {
911 GLint i = IFLOOR(s[k] * width) & colMask;
912 GLint j = IFLOOR(t[k] * height) & rowMask;
913 GLint pos = (j << shift) | i;
914 GLchan *texel = ((GLchan *) img->Data) + 3*pos;
915 rgba[k][RCOMP] = texel[0];
916 rgba[k][GCOMP] = texel[1];
917 rgba[k][BCOMP] = texel[2];
918 }
919 }
920
921
922 /*
923 * Optimized 2-D texture sampling:
924 * S and T wrap mode == GL_REPEAT
925 * GL_NEAREST min/mag filter
926 * No border
927 * Format = GL_RGBA
928 */
929 static void
930 opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit,
931 const struct gl_texture_object *tObj,
932 GLuint n, const GLfloat s[], const GLfloat t[],
933 const GLfloat u[], const GLfloat lambda[],
934 GLchan rgba[][4] )
935 {
936 const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
937 const GLfloat width = (GLfloat) img->Width;
938 const GLfloat height = (GLfloat) img->Height;
939 const GLint colMask = img->Width - 1;
940 const GLint rowMask = img->Height - 1;
941 const GLint shift = img->WidthLog2;
942 GLuint i;
943 (void) u;
944 (void) lambda;
945 ASSERT(tObj->WrapS==GL_REPEAT);
946 ASSERT(tObj->WrapT==GL_REPEAT);
947 ASSERT(img->Border==0);
948 ASSERT(img->Format==GL_RGBA);
949
950 for (i = 0; i < n; i++) {
951 const GLint col = IFLOOR(s[i] * width) & colMask;
952 const GLint row = IFLOOR(t[i] * height) & rowMask;
953 const GLint pos = (row << shift) | col;
954 const GLchan *texel = ((GLchan *) img->Data) + (pos << 2); /* pos*4 */
955 COPY_CHAN4(rgba[i], texel);
956 }
957 }
958
959 #ifdef DEBUG
960 static int
961 span_is_monotonous (GLuint n, const GLfloat lambda[])
962 {
963 GLuint i;
964
965 if (n <= 1) /* array too short */
966 return GL_TRUE;
967 else if (lambda[0] >= lambda[n-1]) { /* decreasing */
968 for (i=0; i<n-1; i++)
969 if (lambda[i] < lambda[i+1])
970 return GL_FALSE;
971 }
972 else { /* increasing */
973 for (i=0; i<n-1; i++)
974 if (lambda[i] > lambda[i+1])
975 return GL_FALSE;
976 }
977
978 return GL_TRUE;
979 }
980 #endif /* DEBUG */
981
982 /*
983 * Given an array of (s,t) texture coordinate and lambda (level of detail)
984 * values, return an array of texture sample.
985 */
986 static void
987 sample_lambda_2d( GLcontext *ctx, GLuint texUnit,
988 const struct gl_texture_object *tObj,
989 GLuint n,
990 const GLfloat s[], const GLfloat t[],
991 const GLfloat u[], const GLfloat lambda[],
992 GLchan rgba[][4] )
993 {
994 const GLfloat minMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
995 GLuint i;
996 (void) u;
997
998 #ifdef DEBUG
999 ASSERT (span_is_monotonous(n, lambda) == GL_TRUE);
1000 #endif /* DEBUG */
1001
1002 /* since lambda is monotonous-array use this check first */
1003 if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
1004 /* magnification for whole span */
1005 const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
1006 switch (tObj->MagFilter) {
1007 case GL_NEAREST:
1008 if (tObj->WrapS == GL_REPEAT && tObj->WrapT == GL_REPEAT &&
1009 img->Border == 0) {
1010 switch (img->Format) {
1011 case GL_RGB:
1012 opt_sample_rgb_2d(ctx, texUnit, tObj, n, s, t, NULL,
1013 NULL, rgba);
1014 break;
1015 case GL_RGBA:
1016 opt_sample_rgba_2d(ctx, texUnit, tObj, n, s, t, NULL,
1017 NULL, rgba);
1018 break;
1019 default:
1020 sample_nearest_2d(ctx, texUnit, tObj, n, s, t, NULL,
1021 NULL, rgba);
1022 }
1023 }
1024 else {
1025 sample_nearest_2d(ctx, texUnit, tObj, n, s, t, NULL,
1026 NULL, rgba);
1027 }
1028 break;
1029 case GL_LINEAR:
1030 sample_linear_2d(ctx, texUnit, tObj, n, s, t, NULL,
1031 NULL, rgba);
1032 break;
1033 default:
1034 _mesa_problem(NULL, "Bad mag filter in sample_lambda_2d");
1035 }
1036 }
1037 else {
1038 for (i = 0; i < n; i++) {
1039 if (lambda[i] > minMagThresh) {
1040 /* minification */
1041 switch (tObj->MinFilter) {
1042 case GL_NEAREST:
1043 sample_2d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1044 s[i], t[i], rgba[i]);
1045 break;
1046 case GL_LINEAR:
1047 sample_2d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1048 s[i], t[i], rgba[i]);
1049 break;
1050 case GL_NEAREST_MIPMAP_NEAREST:
1051 sample_2d_nearest_mipmap_nearest(ctx, tObj, s[i], t[i],
1052 lambda[i], rgba[i]);
1053 break;
1054 case GL_LINEAR_MIPMAP_NEAREST:
1055 sample_2d_linear_mipmap_nearest(ctx,tObj, s[i], t[i],
1056 lambda[i], rgba[i]);
1057 break;
1058 case GL_NEAREST_MIPMAP_LINEAR:
1059 sample_2d_nearest_mipmap_linear(ctx,tObj, s[i], t[i],
1060 lambda[i], rgba[i]);
1061 break;
1062 case GL_LINEAR_MIPMAP_LINEAR:
1063 sample_2d_linear_mipmap_linear(ctx,tObj, s[i], t[i],
1064 lambda[i], rgba[i] );
1065 break;
1066 default:
1067 _mesa_problem(NULL, "Bad min filter in sample_2d_texture");
1068 return;
1069 }
1070 }
1071 else {
1072 /* magnification */
1073 switch (tObj->MagFilter) {
1074 case GL_NEAREST:
1075 sample_2d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1076 s[i], t[i], rgba[i]);
1077 break;
1078 case GL_LINEAR:
1079 sample_2d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1080 s[i], t[i], rgba[i] );
1081 break;
1082 default:
1083 _mesa_problem(NULL, "Bad mag filter in sample_2d_texture");
1084 }
1085 }
1086 }
1087 }
1088 }
1089
1090
1091
1092 /**********************************************************************/
1093 /* 3-D Texture Sampling Functions */
1094 /**********************************************************************/
1095
1096 /*
1097 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1098 */
1099 static void
1100 sample_3d_nearest(GLcontext *ctx,
1101 const struct gl_texture_object *tObj,
1102 const struct gl_texture_image *img,
1103 GLfloat s, GLfloat t, GLfloat r,
1104 GLchan rgba[4])
1105 {
1106 const GLint width = img->Width2; /* without border, power of two */
1107 const GLint height = img->Height2; /* without border, power of two */
1108 const GLint depth = img->Depth2; /* without border, power of two */
1109 GLint i, j, k;
1110
1111 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
1112 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j);
1113 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, r, depth, k);
1114
1115 if (i < 0 || i >= (GLint) img->Width ||
1116 j < 0 || j >= (GLint) img->Height ||
1117 k < 0 || k >= (GLint) img->Depth) {
1118 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1119 COPY_CHAN4(rgba, tObj->BorderColor);
1120 }
1121 else {
1122 (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba);
1123 if (img->Format == GL_COLOR_INDEX) {
1124 palette_sample(ctx, tObj, rgba[0], rgba);
1125 }
1126 }
1127 }
1128
1129
1130
1131 /*
1132 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1133 */
1134 static void
1135 sample_3d_linear(GLcontext *ctx,
1136 const struct gl_texture_object *tObj,
1137 const struct gl_texture_image *img,
1138 GLfloat s, GLfloat t, GLfloat r,
1139 GLchan rgba[4])
1140 {
1141 const GLint width = img->Width2;
1142 const GLint height = img->Height2;
1143 const GLint depth = img->Depth2;
1144 GLint i0, j0, k0, i1, j1, k1;
1145 GLuint useBorderColor;
1146 GLfloat u, v, w;
1147
1148 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
1149 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1);
1150 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, r, w, depth, k0, k1);
1151
1152 useBorderColor = 0;
1153 if (img->Border) {
1154 i0 += img->Border;
1155 i1 += img->Border;
1156 j0 += img->Border;
1157 j1 += img->Border;
1158 k0 += img->Border;
1159 k1 += img->Border;
1160 }
1161 else {
1162 /* check if sampling texture border color */
1163 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
1164 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
1165 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
1166 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
1167 if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT;
1168 if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT;
1169 }
1170
1171 {
1172 const GLfloat a = FRAC(u);
1173 const GLfloat b = FRAC(v);
1174 const GLfloat c = FRAC(w);
1175
1176 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1177 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1178 GLfloat w000 = (1.0F-a) * (1.0F-b) * (1.0F-c);
1179 GLfloat w100 = a * (1.0F-b) * (1.0F-c);
1180 GLfloat w010 = (1.0F-a) * b * (1.0F-c);
1181 GLfloat w110 = a * b * (1.0F-c);
1182 GLfloat w001 = (1.0F-a) * (1.0F-b) * c ;
1183 GLfloat w101 = a * (1.0F-b) * c ;
1184 GLfloat w011 = (1.0F-a) * b * c ;
1185 GLfloat w111 = a * b * c ;
1186 #else /* CHAN_BITS == 8 */
1187 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1188 GLint w000 = IROUND_POS((1.0F-a) * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
1189 GLint w100 = IROUND_POS( a * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
1190 GLint w010 = IROUND_POS((1.0F-a) * b * (1.0F-c) * WEIGHT_SCALE);
1191 GLint w110 = IROUND_POS( a * b * (1.0F-c) * WEIGHT_SCALE);
1192 GLint w001 = IROUND_POS((1.0F-a) * (1.0F-b) * c * WEIGHT_SCALE);
1193 GLint w101 = IROUND_POS( a * (1.0F-b) * c * WEIGHT_SCALE);
1194 GLint w011 = IROUND_POS((1.0F-a) * b * c * WEIGHT_SCALE);
1195 GLint w111 = IROUND_POS( a * b * c * WEIGHT_SCALE);
1196 #endif
1197
1198 GLchan t000[4], t010[4], t001[4], t011[4];
1199 GLchan t100[4], t110[4], t101[4], t111[4];
1200
1201 if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
1202 COPY_CHAN4(t000, tObj->BorderColor);
1203 }
1204 else {
1205 (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000);
1206 if (img->Format == GL_COLOR_INDEX) {
1207 palette_sample(ctx, tObj, t000[0], t000);
1208 }
1209 }
1210 if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
1211 COPY_CHAN4(t100, tObj->BorderColor);
1212 }
1213 else {
1214 (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100);
1215 if (img->Format == GL_COLOR_INDEX) {
1216 palette_sample(ctx, tObj, t100[0], t100);
1217 }
1218 }
1219 if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
1220 COPY_CHAN4(t010, tObj->BorderColor);
1221 }
1222 else {
1223 (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010);
1224 if (img->Format == GL_COLOR_INDEX) {
1225 palette_sample(ctx, tObj, t010[0], t010);
1226 }
1227 }
1228 if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
1229 COPY_CHAN4(t110, tObj->BorderColor);
1230 }
1231 else {
1232 (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110);
1233 if (img->Format == GL_COLOR_INDEX) {
1234 palette_sample(ctx, tObj, t110[0], t110);
1235 }
1236 }
1237
1238 if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
1239 COPY_CHAN4(t001, tObj->BorderColor);
1240 }
1241 else {
1242 (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001);
1243 if (img->Format == GL_COLOR_INDEX) {
1244 palette_sample(ctx, tObj, t001[0], t001);
1245 }
1246 }
1247 if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
1248 COPY_CHAN4(t101, tObj->BorderColor);
1249 }
1250 else {
1251 (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101);
1252 if (img->Format == GL_COLOR_INDEX) {
1253 palette_sample(ctx, tObj, t101[0], t101);
1254 }
1255 }
1256 if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
1257 COPY_CHAN4(t011, tObj->BorderColor);
1258 }
1259 else {
1260 (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011);
1261 if (img->Format == GL_COLOR_INDEX) {
1262 palette_sample(ctx, tObj, t011[0], t011);
1263 }
1264 }
1265 if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
1266 COPY_CHAN4(t111, tObj->BorderColor);
1267 }
1268 else {
1269 (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111);
1270 if (img->Format == GL_COLOR_INDEX) {
1271 palette_sample(ctx, tObj, t111[0], t111);
1272 }
1273 }
1274
1275 #if CHAN_TYPE == GL_FLOAT
1276 rgba[0] = w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1277 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0];
1278 rgba[1] = w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1279 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1];
1280 rgba[2] = w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1281 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2];
1282 rgba[3] = w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1283 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3];
1284 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1285 rgba[0] = (GLchan) (w000*t000[0] + w010*t010[0] +
1286 w001*t001[0] + w011*t011[0] +
1287 w100*t100[0] + w110*t110[0] +
1288 w101*t101[0] + w111*t111[0] + 0.5);
1289 rgba[1] = (GLchan) (w000*t000[1] + w010*t010[1] +
1290 w001*t001[1] + w011*t011[1] +
1291 w100*t100[1] + w110*t110[1] +
1292 w101*t101[1] + w111*t111[1] + 0.5);
1293 rgba[2] = (GLchan) (w000*t000[2] + w010*t010[2] +
1294 w001*t001[2] + w011*t011[2] +
1295 w100*t100[2] + w110*t110[2] +
1296 w101*t101[2] + w111*t111[2] + 0.5);
1297 rgba[3] = (GLchan) (w000*t000[3] + w010*t010[3] +
1298 w001*t001[3] + w011*t011[3] +
1299 w100*t100[3] + w110*t110[3] +
1300 w101*t101[3] + w111*t111[3] + 0.5);
1301 #else /* CHAN_BITS == 8 */
1302 rgba[0] = (GLchan) (
1303 (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1304 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
1305 >> WEIGHT_SHIFT);
1306 rgba[1] = (GLchan) (
1307 (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1308 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
1309 >> WEIGHT_SHIFT);
1310 rgba[2] = (GLchan) (
1311 (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1312 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
1313 >> WEIGHT_SHIFT);
1314 rgba[3] = (GLchan) (
1315 (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1316 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
1317 >> WEIGHT_SHIFT);
1318 #endif
1319
1320 }
1321 }
1322
1323
1324
1325 static void
1326 sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
1327 const struct gl_texture_object *tObj,
1328 GLfloat s, GLfloat t, GLfloat r,
1329 GLfloat lambda, GLchan rgba[4] )
1330 {
1331 GLint level;
1332 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1333 sample_3d_nearest(ctx, tObj, tObj->Image[level], s, t, r, rgba);
1334 }
1335
1336
1337 static void
1338 sample_3d_linear_mipmap_nearest(GLcontext *ctx,
1339 const struct gl_texture_object *tObj,
1340 GLfloat s, GLfloat t, GLfloat r,
1341 GLfloat lambda, GLchan rgba[4])
1342 {
1343 GLint level;
1344 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1345 sample_3d_linear(ctx, tObj, tObj->Image[level], s, t, r, rgba);
1346 }
1347
1348
1349 static void
1350 sample_3d_nearest_mipmap_linear(GLcontext *ctx,
1351 const struct gl_texture_object *tObj,
1352 GLfloat s, GLfloat t, GLfloat r,
1353 GLfloat lambda, GLchan rgba[4])
1354 {
1355 GLint level;
1356
1357 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1358
1359 if (level >= tObj->_MaxLevel) {
1360 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1361 s, t, r, rgba);
1362 }
1363 else {
1364 GLchan t0[4], t1[4]; /* texels */
1365 const GLfloat f = FRAC(lambda);
1366 sample_3d_nearest(ctx, tObj, tObj->Image[level ], s, t, r, t0);
1367 sample_3d_nearest(ctx, tObj, tObj->Image[level+1], s, t, r, t1);
1368 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1369 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1370 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1371 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1372 }
1373 }
1374
1375
1376 static void
1377 sample_3d_linear_mipmap_linear(GLcontext *ctx,
1378 const struct gl_texture_object *tObj,
1379 GLfloat s, GLfloat t, GLfloat r,
1380 GLfloat lambda, GLchan rgba[4] )
1381 {
1382 GLint level;
1383
1384 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1385
1386 if (level >= tObj->_MaxLevel) {
1387 sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, r, rgba);
1388 }
1389 else {
1390 GLchan t0[4], t1[4]; /* texels */
1391 const GLfloat f = FRAC(lambda);
1392 sample_3d_linear(ctx, tObj, tObj->Image[level ], s, t, r, t0);
1393 sample_3d_linear(ctx, tObj, tObj->Image[level+1], s, t, r, t1);
1394 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1395 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1396 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1397 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1398 }
1399 }
1400
1401
1402 static void
1403 sample_nearest_3d(GLcontext *ctx, GLuint texUnit,
1404 const struct gl_texture_object *tObj, GLuint n,
1405 const GLfloat s[], const GLfloat t[],
1406 const GLfloat u[], const GLfloat lambda[],
1407 GLchan rgba[][4])
1408 {
1409 GLuint i;
1410 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1411 (void) lambda;
1412 for (i=0;i<n;i++) {
1413 sample_3d_nearest(ctx, tObj, image, s[i], t[i], u[i], rgba[i]);
1414 }
1415 }
1416
1417
1418
1419 static void
1420 sample_linear_3d( GLcontext *ctx, GLuint texUnit,
1421 const struct gl_texture_object *tObj, GLuint n,
1422 const GLfloat s[], const GLfloat t[],
1423 const GLfloat u[], const GLfloat lambda[],
1424 GLchan rgba[][4] )
1425 {
1426 GLuint i;
1427 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1428 (void) lambda;
1429 for (i=0;i<n;i++) {
1430 sample_3d_linear(ctx, tObj, image, s[i], t[i], u[i], rgba[i]);
1431 }
1432 }
1433
1434
1435 /*
1436 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1437 * return a texture sample.
1438 */
1439 static void
1440 sample_lambda_3d( GLcontext *ctx, GLuint texUnit,
1441 const struct gl_texture_object *tObj, GLuint n,
1442 const GLfloat s[], const GLfloat t[],
1443 const GLfloat u[], const GLfloat lambda[],
1444 GLchan rgba[][4] )
1445 {
1446 GLuint i;
1447 GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
1448
1449 for (i=0;i<n;i++) {
1450
1451 if (lambda[i] > MinMagThresh) {
1452 /* minification */
1453 switch (tObj->MinFilter) {
1454 case GL_NEAREST:
1455 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1456 s[i], t[i], u[i], rgba[i]);
1457 break;
1458 case GL_LINEAR:
1459 sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1460 s[i], t[i], u[i], rgba[i]);
1461 break;
1462 case GL_NEAREST_MIPMAP_NEAREST:
1463 sample_3d_nearest_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1464 lambda[i], rgba[i]);
1465 break;
1466 case GL_LINEAR_MIPMAP_NEAREST:
1467 sample_3d_linear_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1468 lambda[i], rgba[i]);
1469 break;
1470 case GL_NEAREST_MIPMAP_LINEAR:
1471 sample_3d_nearest_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1472 lambda[i], rgba[i]);
1473 break;
1474 case GL_LINEAR_MIPMAP_LINEAR:
1475 sample_3d_linear_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1476 lambda[i], rgba[i]);
1477 break;
1478 default:
1479 _mesa_problem(NULL, "Bad min filterin sample_3d_texture");
1480 }
1481 }
1482 else {
1483 /* magnification */
1484 switch (tObj->MagFilter) {
1485 case GL_NEAREST:
1486 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1487 s[i], t[i], u[i], rgba[i]);
1488 break;
1489 case GL_LINEAR:
1490 sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1491 s[i], t[i], u[i], rgba[i]);
1492 break;
1493 default:
1494 _mesa_problem(NULL, "Bad mag filter in sample_3d_texture");
1495 }
1496 }
1497 }
1498 }
1499
1500
1501 /**********************************************************************/
1502 /* Texture Cube Map Sampling Functions */
1503 /**********************************************************************/
1504
1505 /*
1506 * Choose one of six sides of a texture cube map given the texture
1507 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1508 * images.
1509 */
1510 static const struct gl_texture_image **
1511 choose_cube_face(const struct gl_texture_object *texObj,
1512 GLfloat rx, GLfloat ry, GLfloat rz,
1513 GLfloat *newS, GLfloat *newT)
1514 {
1515 /*
1516 major axis
1517 direction target sc tc ma
1518 ---------- ------------------------------- --- --- ---
1519 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1520 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1521 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1522 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1523 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1524 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1525 */
1526 const struct gl_texture_image **imgArray;
1527 const GLfloat arx = ABSF(rx), ary = ABSF(ry), arz = ABSF(rz);
1528 GLfloat sc, tc, ma;
1529
1530 if (arx > ary && arx > arz) {
1531 if (rx >= 0.0F) {
1532 imgArray = (const struct gl_texture_image **) texObj->Image;
1533 sc = -rz;
1534 tc = -ry;
1535 ma = arx;
1536 }
1537 else {
1538 imgArray = (const struct gl_texture_image **) texObj->NegX;
1539 sc = rz;
1540 tc = -ry;
1541 ma = arx;
1542 }
1543 }
1544 else if (ary > arx && ary > arz) {
1545 if (ry >= 0.0F) {
1546 imgArray = (const struct gl_texture_image **) texObj->PosY;
1547 sc = rx;
1548 tc = rz;
1549 ma = ary;
1550 }
1551 else {
1552 imgArray = (const struct gl_texture_image **) texObj->NegY;
1553 sc = rx;
1554 tc = -rz;
1555 ma = ary;
1556 }
1557 }
1558 else {
1559 if (rz > 0.0F) {
1560 imgArray = (const struct gl_texture_image **) texObj->PosZ;
1561 sc = rx;
1562 tc = -ry;
1563 ma = arz;
1564 }
1565 else {
1566 imgArray = (const struct gl_texture_image **) texObj->NegZ;
1567 sc = -rx;
1568 tc = -ry;
1569 ma = arz;
1570 }
1571 }
1572
1573 *newS = ( sc / ma + 1.0F ) * 0.5F;
1574 *newT = ( tc / ma + 1.0F ) * 0.5F;
1575 return imgArray;
1576 }
1577
1578
1579 static void
1580 sample_nearest_cube(GLcontext *ctx, GLuint texUnit,
1581 const struct gl_texture_object *tObj, GLuint n,
1582 const GLfloat s[], const GLfloat t[],
1583 const GLfloat u[], const GLfloat lambda[],
1584 GLchan rgba[][4])
1585 {
1586 GLuint i;
1587 (void) lambda;
1588 for (i = 0; i < n; i++) {
1589 const struct gl_texture_image **images;
1590 GLfloat newS, newT;
1591 images = choose_cube_face(tObj, s[i], t[i], u[i], &newS, &newT);
1592 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
1593 newS, newT, rgba[i]);
1594 }
1595 }
1596
1597
1598 static void
1599 sample_linear_cube(GLcontext *ctx, GLuint texUnit,
1600 const struct gl_texture_object *tObj, GLuint n,
1601 const GLfloat s[], const GLfloat t[],
1602 const GLfloat u[], const GLfloat lambda[],
1603 GLchan rgba[][4])
1604 {
1605 GLuint i;
1606 (void) lambda;
1607 for (i = 0; i < n; i++) {
1608 const struct gl_texture_image **images;
1609 GLfloat newS, newT;
1610 images = choose_cube_face(tObj, s[i], t[i], u[i], &newS, &newT);
1611 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
1612 newS, newT, rgba[i]);
1613 }
1614 }
1615
1616
1617 static void
1618 sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
1619 const struct gl_texture_object *tObj,
1620 GLfloat s, GLfloat t, GLfloat u,
1621 GLfloat lambda, GLchan rgba[4])
1622 {
1623 const struct gl_texture_image **images;
1624 GLfloat newS, newT;
1625 GLint level;
1626
1627 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1628
1629 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1630 sample_2d_nearest(ctx, tObj, images[level], newS, newT, rgba);
1631 }
1632
1633
1634 static void
1635 sample_cube_linear_mipmap_nearest(GLcontext *ctx,
1636 const struct gl_texture_object *tObj,
1637 GLfloat s, GLfloat t, GLfloat u,
1638 GLfloat lambda, GLchan rgba[4])
1639 {
1640 const struct gl_texture_image **images;
1641 GLfloat newS, newT;
1642 GLint level;
1643
1644 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1645
1646 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1647 sample_2d_linear(ctx, tObj, images[level], newS, newT, rgba);
1648 }
1649
1650
1651 static void
1652 sample_cube_nearest_mipmap_linear(GLcontext *ctx,
1653 const struct gl_texture_object *tObj,
1654 GLfloat s, GLfloat t, GLfloat u,
1655 GLfloat lambda, GLchan rgba[4])
1656 {
1657 const struct gl_texture_image **images;
1658 GLfloat newS, newT;
1659 GLint level;
1660
1661 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1662
1663 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1664
1665 if (level >= tObj->_MaxLevel) {
1666 sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], newS, newT, rgba);
1667 }
1668 else {
1669 GLchan t0[4], t1[4]; /* texels */
1670 const GLfloat f = FRAC(lambda);
1671 sample_2d_nearest(ctx, tObj, images[level ], newS, newT, t0);
1672 sample_2d_nearest(ctx, tObj, images[level+1], newS, newT, t1);
1673 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1674 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1675 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1676 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1677 }
1678 }
1679
1680
1681 static void
1682 sample_cube_linear_mipmap_linear(GLcontext *ctx,
1683 const struct gl_texture_object *tObj,
1684 GLfloat s, GLfloat t, GLfloat u,
1685 GLfloat lambda, GLchan rgba[4])
1686 {
1687 const struct gl_texture_image **images;
1688 GLfloat newS, newT;
1689 GLint level;
1690
1691 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1692
1693 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1694
1695 if (level >= tObj->_MaxLevel) {
1696 sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], newS, newT, rgba);
1697 }
1698 else {
1699 GLchan t0[4], t1[4];
1700 const GLfloat f = FRAC(lambda);
1701 sample_2d_linear(ctx, tObj, images[level ], newS, newT, t0);
1702 sample_2d_linear(ctx, tObj, images[level+1], newS, newT, t1);
1703 rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1704 rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1705 rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1706 rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1707 }
1708 }
1709
1710
1711 static void
1712 sample_lambda_cube( GLcontext *ctx, GLuint texUnit,
1713 const struct gl_texture_object *tObj, GLuint n,
1714 const GLfloat s[], const GLfloat t[],
1715 const GLfloat u[], const GLfloat lambda[],
1716 GLchan rgba[][4])
1717 {
1718 GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
1719 GLuint i;
1720
1721 for (i = 0; i < n; i++) {
1722 if (lambda[i] > MinMagThresh) {
1723 /* minification */
1724 switch (tObj->MinFilter) {
1725 case GL_NEAREST:
1726 {
1727 const struct gl_texture_image **images;
1728 GLfloat newS, newT;
1729 images = choose_cube_face(tObj, s[i], t[i], u[i],
1730 &newS, &newT);
1731 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
1732 newS, newT, rgba[i]);
1733 }
1734 break;
1735 case GL_LINEAR:
1736 {
1737 const struct gl_texture_image **images;
1738 GLfloat newS, newT;
1739 images = choose_cube_face(tObj, s[i], t[i], u[i],
1740 &newS, &newT);
1741 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
1742 newS, newT, rgba[i]);
1743 }
1744 break;
1745 case GL_NEAREST_MIPMAP_NEAREST:
1746 sample_cube_nearest_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1747 lambda[i], rgba[i]);
1748 break;
1749 case GL_LINEAR_MIPMAP_NEAREST:
1750 sample_cube_linear_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1751 lambda[i], rgba[i]);
1752 break;
1753 case GL_NEAREST_MIPMAP_LINEAR:
1754 sample_cube_nearest_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1755 lambda[i], rgba[i]);
1756 break;
1757 case GL_LINEAR_MIPMAP_LINEAR:
1758 sample_cube_linear_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1759 lambda[i], rgba[i]);
1760 break;
1761 default:
1762 _mesa_problem(NULL, "Bad min filter in sample_lambda_cube");
1763 }
1764 }
1765 else {
1766 /* magnification */
1767 const struct gl_texture_image **images;
1768 GLfloat newS, newT;
1769 images = choose_cube_face(tObj, s[i], t[i], u[i],
1770 &newS, &newT);
1771 switch (tObj->MagFilter) {
1772 case GL_NEAREST:
1773 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
1774 newS, newT, rgba[i]);
1775 break;
1776 case GL_LINEAR:
1777 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
1778 newS, newT, rgba[i]);
1779 break;
1780 default:
1781 _mesa_problem(NULL, "Bad mag filter in sample_lambda_cube");
1782 }
1783 }
1784 }
1785 }
1786
1787
1788 static void
1789 null_sample_func( GLcontext *ctx, GLuint texUnit,
1790 const struct gl_texture_object *tObj, GLuint n,
1791 const GLfloat s[], const GLfloat t[],
1792 const GLfloat u[], const GLfloat lambda[],
1793 GLchan rgba[][4])
1794 {
1795 }
1796
1797
1798
1799 /**********************************************************************/
1800 /* Texture Sampling Setup */
1801 /**********************************************************************/
1802
1803
1804 /*
1805 * Setup the texture sampling function for this texture object.
1806 */
1807 void
1808 _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit,
1809 const struct gl_texture_object *t )
1810 {
1811 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1812
1813 if (!t->Complete) {
1814 swrast->TextureSample[texUnit] = null_sample_func;
1815 }
1816 else {
1817 GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
1818
1819 if (needLambda) {
1820 /* Compute min/mag filter threshold */
1821 if (t->MagFilter == GL_LINEAR
1822 && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
1823 t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
1824 swrast->_MinMagThresh[texUnit] = 0.5F;
1825 }
1826 else {
1827 swrast->_MinMagThresh[texUnit] = 0.0F;
1828 }
1829 }
1830
1831 switch (t->Dimensions) {
1832 case 1:
1833 if (needLambda) {
1834 swrast->TextureSample[texUnit] = sample_lambda_1d;
1835 }
1836 else if (t->MinFilter==GL_LINEAR) {
1837 swrast->TextureSample[texUnit] = sample_linear_1d;
1838 }
1839 else {
1840 ASSERT(t->MinFilter==GL_NEAREST);
1841 swrast->TextureSample[texUnit] = sample_nearest_1d;
1842 }
1843 break;
1844 case 2:
1845 if (needLambda) {
1846 swrast->TextureSample[texUnit] = sample_lambda_2d;
1847 }
1848 else if (t->MinFilter==GL_LINEAR) {
1849 swrast->TextureSample[texUnit] = sample_linear_2d;
1850 }
1851 else {
1852 GLint baseLevel = t->BaseLevel;
1853 ASSERT(t->MinFilter==GL_NEAREST);
1854 if (t->WrapS == GL_REPEAT &&
1855 t->WrapT == GL_REPEAT &&
1856 t->Image[baseLevel]->Border == 0 &&
1857 t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) {
1858 swrast->TextureSample[texUnit] = opt_sample_rgb_2d;
1859 }
1860 else if (t->WrapS == GL_REPEAT &&
1861 t->WrapT == GL_REPEAT &&
1862 t->Image[baseLevel]->Border == 0 &&
1863 t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) {
1864 swrast->TextureSample[texUnit] = opt_sample_rgba_2d;
1865 }
1866 else
1867 swrast->TextureSample[texUnit] = sample_nearest_2d;
1868 }
1869 break;
1870 case 3:
1871 if (needLambda) {
1872 swrast->TextureSample[texUnit] = sample_lambda_3d;
1873 }
1874 else if (t->MinFilter==GL_LINEAR) {
1875 swrast->TextureSample[texUnit] = sample_linear_3d;
1876 }
1877 else {
1878 ASSERT(t->MinFilter==GL_NEAREST);
1879 swrast->TextureSample[texUnit] = sample_nearest_3d;
1880 }
1881 break;
1882 case 6: /* cube map */
1883 if (needLambda) {
1884 swrast->TextureSample[texUnit] = sample_lambda_cube;
1885 }
1886 else if (t->MinFilter==GL_LINEAR) {
1887 swrast->TextureSample[texUnit] = sample_linear_cube;
1888 }
1889 else {
1890 ASSERT(t->MinFilter==GL_NEAREST);
1891 swrast->TextureSample[texUnit] = sample_nearest_cube;
1892 }
1893 break;
1894 default:
1895 _mesa_problem(NULL, "invalid dimensions in _mesa_set_texture_sampler");
1896 }
1897 }
1898 }
1899
1900
1901 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
1902 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
1903
1904 static INLINE void
1905 texture_combine(const GLcontext *ctx,
1906 const struct gl_texture_unit *textureUnit,
1907 GLuint n,
1908 CONST GLchan (*primary_rgba)[4],
1909 CONST GLchan (*texel)[4],
1910 GLchan (*rgba)[4])
1911 {
1912 const GLchan (*argRGB [3])[4];
1913 const GLchan (*argA [3])[4];
1914 GLuint i, j;
1915 const GLuint RGBshift = textureUnit->CombineScaleShiftRGB;
1916 const GLuint Ashift = textureUnit->CombineScaleShiftA;
1917 #if CHAN_TYPE == GL_FLOAT
1918 const GLchan RGBmult = (GLfloat) (1 << RGBshift);
1919 const GLchan Amult = (GLfloat) (1 << Ashift);
1920 #else
1921 const GLint half = (CHAN_MAX + 1) / 2;
1922 #endif
1923
1924 DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4); /* mac 32k limitation */
1925 CHECKARRAY(ccolor, return); /* mac 32k limitation */
1926
1927 ASSERT(ctx->Extensions.EXT_texture_env_combine ||
1928 ctx->Extensions.ARB_texture_env_combine);
1929
1930 /*
1931 * Do operand setup for up to 3 operands. Loop over the terms.
1932 */
1933 for (j = 0; j < 3; j++) {
1934 switch (textureUnit->CombineSourceA[j]) {
1935 case GL_TEXTURE:
1936 argA[j] = texel;
1937 break;
1938 case GL_PRIMARY_COLOR_EXT:
1939 argA[j] = primary_rgba;
1940 break;
1941 case GL_PREVIOUS_EXT:
1942 argA[j] = (const GLchan (*)[4]) rgba;
1943 break;
1944 case GL_CONSTANT_EXT:
1945 {
1946 GLchan alpha, (*c)[4] = ccolor[j];
1947 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
1948 for (i = 0; i < n; i++)
1949 c[i][ACOMP] = alpha;
1950 argA[j] = (const GLchan (*)[4]) ccolor[j];
1951 }
1952 break;
1953 default:
1954 _mesa_problem(NULL, "invalid combine source");
1955 }
1956
1957 switch (textureUnit->CombineSourceRGB[j]) {
1958 case GL_TEXTURE:
1959 argRGB[j] = texel;
1960 break;
1961 case GL_PRIMARY_COLOR_EXT:
1962 argRGB[j] = primary_rgba;
1963 break;
1964 case GL_PREVIOUS_EXT:
1965 argRGB[j] = (const GLchan (*)[4]) rgba;
1966 break;
1967 case GL_CONSTANT_EXT:
1968 {
1969 GLchan (*c)[4] = ccolor[j];
1970 GLchan red, green, blue, alpha;
1971 UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]);
1972 UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
1973 UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]);
1974 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
1975 for (i = 0; i < n; i++) {
1976 c[i][RCOMP] = red;
1977 c[i][GCOMP] = green;
1978 c[i][BCOMP] = blue;
1979 c[i][ACOMP] = alpha;
1980 }
1981 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
1982 }
1983 break;
1984 default:
1985 _mesa_problem(NULL, "invalid combine source");
1986 }
1987
1988 if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) {
1989 const GLchan (*src)[4] = argRGB[j];
1990 GLchan (*dst)[4] = ccolor[j];
1991
1992 /* point to new arg[j] storage */
1993 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
1994
1995 if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
1996 for (i = 0; i < n; i++) {
1997 dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
1998 dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
1999 dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
2000 }
2001 }
2002 else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) {
2003 for (i = 0; i < n; i++) {
2004 dst[i][RCOMP] = src[i][ACOMP];
2005 dst[i][GCOMP] = src[i][ACOMP];
2006 dst[i][BCOMP] = src[i][ACOMP];
2007 }
2008 }
2009 else {
2010 ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
2011 for (i = 0; i < n; i++) {
2012 dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
2013 dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
2014 dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
2015 }
2016 }
2017 }
2018
2019 if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
2020 const GLchan (*src)[4] = argA[j];
2021 GLchan (*dst)[4] = ccolor[j];
2022 argA[j] = (const GLchan (*)[4]) ccolor[j];
2023 for (i = 0; i < n; i++) {
2024 dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
2025 }
2026 }
2027
2028 if (textureUnit->CombineModeRGB == GL_REPLACE &&
2029 textureUnit->CombineModeA == GL_REPLACE) {
2030 break; /* done, we need only arg0 */
2031 }
2032
2033 if (j == 1 &&
2034 textureUnit->CombineModeRGB != GL_INTERPOLATE_EXT &&
2035 textureUnit->CombineModeA != GL_INTERPOLATE_EXT) {
2036 break; /* arg0 and arg1 are done. we don't need arg2. */
2037 }
2038 }
2039
2040 /*
2041 * Do the texture combine.
2042 */
2043 switch (textureUnit->CombineModeRGB) {
2044 case GL_REPLACE:
2045 {
2046 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2047 if (RGBshift) {
2048 for (i = 0; i < n; i++) {
2049 #if CHAN_TYPE == GL_FLOAT
2050 rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult;
2051 rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult;
2052 rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult;
2053 #else
2054 GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
2055 GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
2056 GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
2057 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2058 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2059 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2060 #endif
2061 }
2062 }
2063 else {
2064 for (i = 0; i < n; i++) {
2065 rgba[i][RCOMP] = arg0[i][RCOMP];
2066 rgba[i][GCOMP] = arg0[i][GCOMP];
2067 rgba[i][BCOMP] = arg0[i][BCOMP];
2068 }
2069 }
2070 }
2071 break;
2072 case GL_MODULATE:
2073 {
2074 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2075 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2076 #if CHAN_TYPE != GL_FLOAT
2077 const GLint shift = 8 - RGBshift;
2078 #endif
2079 for (i = 0; i < n; i++) {
2080 #if CHAN_TYPE == GL_FLOAT
2081 rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult;
2082 rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult;
2083 rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult;
2084 #else
2085 GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift;
2086 GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift;
2087 GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift;
2088 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
2089 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
2090 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
2091 #endif
2092 }
2093 }
2094 break;
2095 case GL_ADD:
2096 {
2097 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2098 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2099 for (i = 0; i < n; i++) {
2100 #if CHAN_TYPE == GL_FLOAT
2101 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult;
2102 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult;
2103 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult;
2104 #else
2105 GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
2106 GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
2107 GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
2108 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
2109 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
2110 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
2111 #endif
2112 }
2113 }
2114 break;
2115 case GL_ADD_SIGNED_EXT:
2116 {
2117 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2118 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2119 for (i = 0; i < n; i++) {
2120 #if CHAN_TYPE == GL_FLOAT
2121 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult;
2122 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult;
2123 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult;
2124 #else
2125 GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half;
2126 GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half;
2127 GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half;
2128 r = (r < 0) ? 0 : r << RGBshift;
2129 g = (g < 0) ? 0 : g << RGBshift;
2130 b = (b < 0) ? 0 : b << RGBshift;
2131 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
2132 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
2133 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
2134 #endif
2135 }
2136 }
2137 break;
2138 case GL_INTERPOLATE_EXT:
2139 {
2140 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2141 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2142 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
2143 #if CHAN_TYPE != GL_FLOAT
2144 const GLint shift = 8 - RGBshift;
2145 #endif
2146 for (i = 0; i < n; i++) {
2147 #if CHAN_TYPE == GL_FLOAT
2148 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
2149 arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult;
2150 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
2151 arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult;
2152 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
2153 arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult;
2154 #else
2155 GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
2156 + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
2157 >> shift;
2158 GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
2159 + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
2160 >> shift;
2161 GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
2162 + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
2163 >> shift;
2164 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
2165 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
2166 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
2167 #endif
2168 }
2169 }
2170 break;
2171 case GL_SUBTRACT_ARB:
2172 {
2173 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2174 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2175 for (i = 0; i < n; i++) {
2176 #if CHAN_TYPE == GL_FLOAT
2177 rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult;
2178 rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult;
2179 rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult;
2180 #else
2181 GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
2182 GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
2183 GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
2184 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
2185 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
2186 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
2187 #endif
2188 }
2189 }
2190 break;
2191 case GL_DOT3_RGB_ARB:
2192 case GL_DOT3_RGBA_ARB:
2193 {
2194 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2195 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2196 /* ATI's EXT extension has a constant scale by 4. The ARB
2197 * one will likely remove this restriction, and we should
2198 * drop the EXT extension in favour of the ARB one.
2199 */
2200 for (i = 0; i < n; i++) {
2201 #if CHAN_TYPE == GL_FLOAT
2202 GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
2203 (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
2204 (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
2205 * 4.0F;
2206 #else
2207 GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
2208 (GLint)arg1[i][RCOMP] - half) +
2209 S_PROD((GLint)arg0[i][GCOMP] - half,
2210 (GLint)arg1[i][GCOMP] - half) +
2211 S_PROD((GLint)arg0[i][BCOMP] - half,
2212 (GLint)arg1[i][BCOMP] - half)) >> 6;
2213 #endif
2214 dot = CLAMP(dot, 0, CHAN_MAX);
2215 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
2216 }
2217 }
2218 break;
2219 default:
2220 _mesa_problem(NULL, "invalid combine mode");
2221 }
2222
2223 switch (textureUnit->CombineModeA) {
2224 case GL_REPLACE:
2225 {
2226 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2227 if (Ashift) {
2228 for (i = 0; i < n; i++) {
2229 #if CHAN_TYPE == GL_FLOAT
2230 GLchan a = arg0[i][ACOMP] * Amult;
2231 #else
2232 GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
2233 #endif
2234 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2235 }
2236 }
2237 else {
2238 for (i = 0; i < n; i++) {
2239 rgba[i][ACOMP] = arg0[i][ACOMP];
2240 }
2241 }
2242 }
2243 break;
2244 case GL_MODULATE:
2245 {
2246 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2247 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2248 #if CHAN_TYPE != GL_FLOAT
2249 const GLint shift = 8 - Ashift;
2250 #endif
2251 for (i = 0; i < n; i++) {
2252 #if CHAN_TYPE == GL_FLOAT
2253 rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult;
2254 #else
2255 GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
2256 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2257 #endif
2258 }
2259 }
2260 break;
2261 case GL_ADD:
2262 {
2263 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2264 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2265 for (i = 0; i < n; i++) {
2266 #if CHAN_TYPE == GL_FLOAT
2267 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult;
2268 #else
2269 GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
2270 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2271 #endif
2272 }
2273 }
2274 break;
2275 case GL_ADD_SIGNED_EXT:
2276 {
2277 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2278 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2279 for (i = 0; i < n; i++) {
2280 #if CHAN_TYPE == GL_FLOAT
2281 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult;
2282 #else
2283 GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half;
2284 a = (a < 0) ? 0 : a << Ashift;
2285 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2286 #endif
2287 }
2288 }
2289 break;
2290 case GL_INTERPOLATE_EXT:
2291 {
2292 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2293 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2294 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
2295 #if CHAN_TYPE != GL_FLOAT
2296 const GLint shift = 8 - Ashift;
2297 #endif
2298 for (i=0; i<n; i++) {
2299 #if CHAN_TYPE == GL_FLOAT
2300 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
2301 arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP]))
2302 * Amult;
2303 #else
2304 GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
2305 + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
2306 >> shift;
2307 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2308 #endif
2309 }
2310 }
2311 break;
2312 case GL_SUBTRACT_ARB:
2313 {
2314 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2315 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2316 for (i = 0; i < n; i++) {
2317 #if CHAN_TYPE == GL_FLOAT
2318 rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult;
2319 #else
2320 GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << RGBshift;
2321 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
2322 #endif
2323 }
2324 }
2325 break;
2326
2327 default:
2328 _mesa_problem(NULL, "invalid combine mode");
2329 }
2330
2331 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2332 */
2333 if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT ||
2334 textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) {
2335 for (i = 0; i < n; i++) {
2336 rgba[i][ACOMP] = rgba[i][RCOMP];
2337 }
2338 }
2339 UNDEFARRAY(ccolor); /* mac 32k limitation */
2340 }
2341 #undef PROD
2342
2343
2344
2345 /**********************************************************************/
2346 /* Texture Application */
2347 /**********************************************************************/
2348
2349
2350 /*
2351 * Combine incoming fragment color with texel color to produce output color.
2352 * Input: textureUnit - pointer to texture unit to apply
2353 * format - base internal texture format
2354 * n - number of fragments
2355 * primary_rgba - primary colors (may alias rgba for single texture)
2356 * texels - array of texel colors
2357 * InOut: rgba - incoming fragment colors modified by texel colors
2358 * according to the texture environment mode.
2359 */
2360 static void
2361 apply_texture( const GLcontext *ctx,
2362 const struct gl_texture_unit *texUnit,
2363 GLuint n,
2364 CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
2365 GLchan rgba[][4] )
2366 {
2367 GLint baseLevel;
2368 GLuint i;
2369 GLint Rc, Gc, Bc, Ac;
2370 GLenum format;
2371
2372 ASSERT(texUnit);
2373 ASSERT(texUnit->_Current);
2374
2375 baseLevel = texUnit->_Current->BaseLevel;
2376 ASSERT(texUnit->_Current->Image[baseLevel]);
2377
2378 format = texUnit->_Current->Image[baseLevel]->Format;
2379
2380 if (format==GL_COLOR_INDEX || format==GL_DEPTH_COMPONENT) {
2381 format = GL_RGBA; /* XXXX a hack! */
2382 }
2383
2384 switch (texUnit->EnvMode) {
2385 case GL_REPLACE:
2386 switch (format) {
2387 case GL_ALPHA:
2388 for (i=0;i<n;i++) {
2389 /* Cv = Cf */
2390 /* Av = At */
2391 rgba[i][ACOMP] = texel[i][ACOMP];
2392 }
2393 break;
2394 case GL_LUMINANCE:
2395 for (i=0;i<n;i++) {
2396 /* Cv = Lt */
2397 GLchan Lt = texel[i][RCOMP];
2398 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
2399 /* Av = Af */
2400 }
2401 break;
2402 case GL_LUMINANCE_ALPHA:
2403 for (i=0;i<n;i++) {
2404 GLchan Lt = texel[i][RCOMP];
2405 /* Cv = Lt */
2406 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
2407 /* Av = At */
2408 rgba[i][ACOMP] = texel[i][ACOMP];
2409 }
2410 break;
2411 case GL_INTENSITY:
2412 for (i=0;i<n;i++) {
2413 /* Cv = It */
2414 GLchan It = texel[i][RCOMP];
2415 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
2416 /* Av = It */
2417 rgba[i][ACOMP] = It;
2418 }
2419 break;
2420 case GL_RGB:
2421 for (i=0;i<n;i++) {
2422 /* Cv = Ct */
2423 rgba[i][RCOMP] = texel[i][RCOMP];
2424 rgba[i][GCOMP] = texel[i][GCOMP];
2425 rgba[i][BCOMP] = texel[i][BCOMP];
2426 /* Av = Af */
2427 }
2428 break;
2429 case GL_RGBA:
2430 for (i=0;i<n;i++) {
2431 /* Cv = Ct */
2432 rgba[i][RCOMP] = texel[i][RCOMP];
2433 rgba[i][GCOMP] = texel[i][GCOMP];
2434 rgba[i][BCOMP] = texel[i][BCOMP];
2435 /* Av = At */
2436 rgba[i][ACOMP] = texel[i][ACOMP];
2437 }
2438 break;
2439 default:
2440 _mesa_problem(ctx, "Bad format (GL_REPLACE) in apply_texture");
2441 return;
2442 }
2443 break;
2444
2445 case GL_MODULATE:
2446 switch (format) {
2447 case GL_ALPHA:
2448 for (i=0;i<n;i++) {
2449 /* Cv = Cf */
2450 /* Av = AfAt */
2451 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2452 }
2453 break;
2454 case GL_LUMINANCE:
2455 for (i=0;i<n;i++) {
2456 /* Cv = LtCf */
2457 GLchan Lt = texel[i][RCOMP];
2458 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
2459 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
2460 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
2461 /* Av = Af */
2462 }
2463 break;
2464 case GL_LUMINANCE_ALPHA:
2465 for (i=0;i<n;i++) {
2466 /* Cv = CfLt */
2467 GLchan Lt = texel[i][RCOMP];
2468 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
2469 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
2470 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
2471 /* Av = AfAt */
2472 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2473 }
2474 break;
2475 case GL_INTENSITY:
2476 for (i=0;i<n;i++) {
2477 /* Cv = CfIt */
2478 GLchan It = texel[i][RCOMP];
2479 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
2480 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
2481 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
2482 /* Av = AfIt */
2483 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
2484 }
2485 break;
2486 case GL_RGB:
2487 for (i=0;i<n;i++) {
2488 /* Cv = CfCt */
2489 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
2490 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
2491 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
2492 /* Av = Af */
2493 }
2494 break;
2495 case GL_RGBA:
2496 for (i=0;i<n;i++) {
2497 /* Cv = CfCt */
2498 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
2499 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
2500 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
2501 /* Av = AfAt */
2502 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2503 }
2504 break;
2505 default:
2506 _mesa_problem(ctx, "Bad format (GL_MODULATE) in apply_texture");
2507 return;
2508 }
2509 break;
2510
2511 case GL_DECAL:
2512 switch (format) {
2513 case GL_ALPHA:
2514 case GL_LUMINANCE:
2515 case GL_LUMINANCE_ALPHA:
2516 case GL_INTENSITY:
2517 /* undefined */
2518 break;
2519 case GL_RGB:
2520 for (i=0;i<n;i++) {
2521 /* Cv = Ct */
2522 rgba[i][RCOMP] = texel[i][RCOMP];
2523 rgba[i][GCOMP] = texel[i][GCOMP];
2524 rgba[i][BCOMP] = texel[i][BCOMP];
2525 /* Av = Af */
2526 }
2527 break;
2528 case GL_RGBA:
2529 for (i=0;i<n;i++) {
2530 /* Cv = Cf(1-At) + CtAt */
2531 GLint t = texel[i][ACOMP], s = CHAN_MAX - t;
2532 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
2533 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
2534 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
2535 /* Av = Af */
2536 }
2537 break;
2538 default:
2539 _mesa_problem(ctx, "Bad format (GL_DECAL) in apply_texture");
2540 return;
2541 }
2542 break;
2543
2544 case GL_BLEND:
2545 Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF);
2546 Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF);
2547 Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF);
2548 Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF);
2549 switch (format) {
2550 case GL_ALPHA:
2551 for (i=0;i<n;i++) {
2552 /* Cv = Cf */
2553 /* Av = AfAt */
2554 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2555 }
2556 break;
2557 case GL_LUMINANCE:
2558 for (i=0;i<n;i++) {
2559 /* Cv = Cf(1-Lt) + CcLt */
2560 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
2561 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
2562 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
2563 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
2564 /* Av = Af */
2565 }
2566 break;
2567 case GL_LUMINANCE_ALPHA:
2568 for (i=0;i<n;i++) {
2569 /* Cv = Cf(1-Lt) + CcLt */
2570 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
2571 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
2572 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
2573 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
2574 /* Av = AfAt */
2575 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
2576 }
2577 break;
2578 case GL_INTENSITY:
2579 for (i=0;i<n;i++) {
2580 /* Cv = Cf(1-It) + CcLt */
2581 GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
2582 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
2583 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
2584 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
2585 /* Av = Af(1-It) + Ac*It */
2586 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
2587 }
2588 break;
2589 case GL_RGB:
2590 for (i=0;i<n;i++) {
2591 /* Cv = Cf(1-Ct) + CcCt */
2592 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
2593 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
2594 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
2595 /* Av = Af */
2596 }
2597 break;
2598 case GL_RGBA:
2599 for (i=0;i<n;i++) {
2600 /* Cv = Cf(1-Ct) + CcCt */
2601 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
2602 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
2603 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
2604 /* Av = AfAt */
2605 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
2606 }
2607 break;
2608 default:
2609 _mesa_problem(ctx, "Bad format (GL_BLEND) in apply_texture");
2610 return;
2611 }
2612 break;
2613
2614 /* XXX don't clamp results if GLchan is float??? */
2615
2616 case GL_ADD: /* GL_EXT_texture_add_env */
2617 switch (format) {
2618 case GL_ALPHA:
2619 for (i=0;i<n;i++) {
2620 /* Rv = Rf */
2621 /* Gv = Gf */
2622 /* Bv = Bf */
2623 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2624 }
2625 break;
2626 case GL_LUMINANCE:
2627 for (i=0;i<n;i++) {
2628 GLuint Lt = texel[i][RCOMP];
2629 GLuint r = rgba[i][RCOMP] + Lt;
2630 GLuint g = rgba[i][GCOMP] + Lt;
2631 GLuint b = rgba[i][BCOMP] + Lt;
2632 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2633 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2634 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2635 /* Av = Af */
2636 }
2637 break;
2638 case GL_LUMINANCE_ALPHA:
2639 for (i=0;i<n;i++) {
2640 GLuint Lt = texel[i][RCOMP];
2641 GLuint r = rgba[i][RCOMP] + Lt;
2642 GLuint g = rgba[i][GCOMP] + Lt;
2643 GLuint b = rgba[i][BCOMP] + Lt;
2644 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2645 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2646 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2647 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2648 }
2649 break;
2650 case GL_INTENSITY:
2651 for (i=0;i<n;i++) {
2652 GLchan It = texel[i][RCOMP];
2653 GLuint r = rgba[i][RCOMP] + It;
2654 GLuint g = rgba[i][GCOMP] + It;
2655 GLuint b = rgba[i][BCOMP] + It;
2656 GLuint a = rgba[i][ACOMP] + It;
2657 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2658 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2659 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2660 rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
2661 }
2662 break;
2663 case GL_RGB:
2664 for (i=0;i<n;i++) {
2665 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
2666 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
2667 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
2668 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2669 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2670 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2671 /* Av = Af */
2672 }
2673 break;
2674 case GL_RGBA:
2675 for (i=0;i<n;i++) {
2676 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
2677 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
2678 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
2679 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2680 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2681 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2682 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2683 }
2684 break;
2685 default:
2686 _mesa_problem(ctx, "Bad format (GL_ADD) in apply_texture");
2687 return;
2688 }
2689 break;
2690
2691 case GL_COMBINE_EXT:
2692 texture_combine(ctx, texUnit, n, primary_rgba, texel, rgba);
2693 break;
2694
2695 default:
2696 _mesa_problem(ctx, "Bad env mode in apply_texture");
2697 return;
2698 }
2699 }
2700
2701
2702
2703 /*
2704 * Sample a shadow/depth texture.
2705 * Input: ctx - context
2706 * texUnit - the texture unit
2707 * n - number of samples
2708 * s,t,r - array [n] of texture coordinates
2709 * In/Out: rgba - array [n] of texel colors.
2710 */
2711 static void
2712 sample_depth_texture(const GLcontext *ctx,
2713 const struct gl_texture_unit *texUnit,
2714 GLuint n,
2715 const GLfloat s[], const GLfloat t[], const GLfloat r[],
2716 GLchan texel[][4])
2717 {
2718 const struct gl_texture_object *texObj = texUnit->_Current;
2719 const GLint baseLevel = texObj->BaseLevel;
2720 const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2721 const GLuint width = texImage->Width;
2722 const GLuint height = texImage->Height;
2723 const GLchan ambient = texObj->ShadowAmbient;
2724 GLboolean lequal, gequal;
2725
2726 if (texObj->Dimensions != 2) {
2727 _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2728 return;
2729 }
2730
2731 if (texObj->MinFilter != texObj->MagFilter) {
2732 _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2733 return;
2734 }
2735
2736 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2737 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2738 * isn't a depth texture.
2739 */
2740 if (texImage->Format != GL_DEPTH_COMPONENT) {
2741 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2742 return;
2743 }
2744
2745 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2746 lequal = GL_TRUE;
2747 gequal = GL_FALSE;
2748 }
2749 else {
2750 lequal = GL_FALSE;
2751 gequal = GL_TRUE;
2752 }
2753
2754 if (texObj->MagFilter == GL_NEAREST) {
2755 GLuint i;
2756 for (i = 0; i < n; i++) {
2757 GLfloat depthSample;
2758 GLint col, row;
2759 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
2760 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
2761 depthSample = *((const GLfloat *) texImage->Data + row * width + col);
2762 if ((r[i] <= depthSample && lequal) ||
2763 (r[i] >= depthSample && gequal)) {
2764 texel[i][RCOMP] = CHAN_MAX;
2765 texel[i][GCOMP] = CHAN_MAX;
2766 texel[i][BCOMP] = CHAN_MAX;
2767 texel[i][ACOMP] = CHAN_MAX;
2768 }
2769 else {
2770 texel[i][RCOMP] = ambient;
2771 texel[i][GCOMP] = ambient;
2772 texel[i][BCOMP] = ambient;
2773 texel[i][ACOMP] = CHAN_MAX;
2774 }
2775 }
2776 }
2777 else {
2778 GLuint i;
2779 ASSERT(texObj->MagFilter == GL_LINEAR);
2780 for (i = 0; i < n; i++) {
2781 GLfloat depth00, depth01, depth10, depth11;
2782 GLint i0, i1, j0, j1;
2783 GLfloat u, v;
2784 GLuint useBorderTexel;
2785
2786 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapS, s[i], u, width, i0, i1);
2787 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapT, t[i], v, height,j0, j1);
2788
2789 useBorderTexel = 0;
2790 if (texImage->Border) {
2791 i0 += texImage->Border;
2792 i1 += texImage->Border;
2793 j0 += texImage->Border;
2794 j1 += texImage->Border;
2795 }
2796 else {
2797 if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT;
2798 if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT;
2799 if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT;
2800 if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT;
2801 }
2802
2803 /* get four depth samples from the texture */
2804 if (useBorderTexel & (I0BIT | J0BIT)) {
2805 depth00 = 1.0;
2806 }
2807 else {
2808 depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0);
2809 }
2810 if (useBorderTexel & (I1BIT | J0BIT)) {
2811 depth10 = 1.0;
2812 }
2813 else {
2814 depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1);
2815 }
2816 if (useBorderTexel & (I0BIT | J1BIT)) {
2817 depth01 = 1.0;
2818 }
2819 else {
2820 depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0);
2821 }
2822 if (useBorderTexel & (I1BIT | J1BIT)) {
2823 depth11 = 1.0;
2824 }
2825 else {
2826 depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1);
2827 }
2828
2829 if (0) {
2830 /* compute a single weighted depth sample and do one comparison */
2831 const GLfloat a = FRAC(u + 1.0F);
2832 const GLfloat b = FRAC(v + 1.0F);
2833 const GLfloat w00 = (1.0F - a) * (1.0F - b);
2834 const GLfloat w10 = ( a) * (1.0F - b);
2835 const GLfloat w01 = (1.0F - a) * ( b);
2836 const GLfloat w11 = ( a) * ( b);
2837 const GLfloat depthSample = w00 * depth00 + w10 * depth10
2838 + w01 * depth01 + w11 * depth11;
2839 if ((depthSample <= r[i] && lequal) ||
2840 (depthSample >= r[i] && gequal)) {
2841 texel[i][RCOMP] = ambient;
2842 texel[i][GCOMP] = ambient;
2843 texel[i][BCOMP] = ambient;
2844 texel[i][ACOMP] = CHAN_MAX;
2845 }
2846 else {
2847 texel[i][RCOMP] = CHAN_MAX;
2848 texel[i][GCOMP] = CHAN_MAX;
2849 texel[i][BCOMP] = CHAN_MAX;
2850 texel[i][ACOMP] = CHAN_MAX;
2851 }
2852 }
2853 else {
2854 /* Do four depth/R comparisons and compute a weighted result.
2855 * If this touches on somebody's I.P., I'll remove this code
2856 * upon request.
2857 */
2858 const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
2859 GLfloat luminance = CHAN_MAXF;
2860 GLchan lum;
2861 if (lequal) {
2862 if (depth00 <= r[i]) luminance -= d;
2863 if (depth01 <= r[i]) luminance -= d;
2864 if (depth10 <= r[i]) luminance -= d;
2865 if (depth11 <= r[i]) luminance -= d;
2866 }
2867 else {
2868 if (depth00 >= r[i]) luminance -= d;
2869 if (depth01 >= r[i]) luminance -= d;
2870 if (depth10 >= r[i]) luminance -= d;
2871 if (depth11 >= r[i]) luminance -= d;
2872 }
2873 lum = (GLchan) luminance;
2874 texel[i][RCOMP] = lum;
2875 texel[i][GCOMP] = lum;
2876 texel[i][BCOMP] = lum;
2877 texel[i][ACOMP] = CHAN_MAX;
2878 }
2879 }
2880 }
2881 }
2882
2883
2884 #if 0
2885 /*
2886 * Experimental depth texture sampling function.
2887 */
2888 static void
2889 sample_depth_texture2(const GLcontext *ctx,
2890 const struct gl_texture_unit *texUnit,
2891 GLuint n,
2892 const GLfloat s[], const GLfloat t[], const GLfloat r[],
2893 GLchan texel[][4])
2894 {
2895 const struct gl_texture_object *texObj = texUnit->_Current;
2896 const GLint baseLevel = texObj->BaseLevel;
2897 const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2898 const GLuint width = texImage->Width;
2899 const GLuint height = texImage->Height;
2900 const GLchan ambient = texObj->ShadowAmbient;
2901 GLboolean lequal, gequal;
2902
2903 if (texObj->Dimensions != 2) {
2904 _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2905 return;
2906 }
2907
2908 if (texObj->MinFilter != texObj->MagFilter) {
2909 _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2910 return;
2911 }
2912
2913 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2914 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2915 * isn't a depth texture.
2916 */
2917 if (texImage->Format != GL_DEPTH_COMPONENT) {
2918 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2919 return;
2920 }
2921
2922 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2923 lequal = GL_TRUE;
2924 gequal = GL_FALSE;
2925 }
2926 else {
2927 lequal = GL_FALSE;
2928 gequal = GL_TRUE;
2929 }
2930
2931 {
2932 GLuint i;
2933 for (i = 0; i < n; i++) {
2934 const GLint K = 3;
2935 GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
2936 GLfloat w;
2937 GLchan lum;
2938 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
2939 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
2940
2941 imin = col - K;
2942 imax = col + K;
2943 jmin = row - K;
2944 jmax = row + K;
2945
2946 if (imin < 0) imin = 0;
2947 if (imax >= width) imax = width - 1;
2948 if (jmin < 0) jmin = 0;
2949 if (jmax >= height) jmax = height - 1;
2950
2951 samples = (imax - imin + 1) * (jmax - jmin + 1);
2952 count = 0;
2953 for (jj = jmin; jj <= jmax; jj++) {
2954 for (ii = imin; ii <= imax; ii++) {
2955 GLfloat depthSample = *((const GLfloat *) texImage->Data
2956 + jj * width + ii);
2957 if ((depthSample <= r[i] && lequal) ||
2958 (depthSample >= r[i] && gequal)) {
2959 count++;
2960 }
2961 }
2962 }
2963
2964 w = (GLfloat) count / (GLfloat) samples;
2965 w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
2966 lum = (GLint) w;
2967
2968 texel[i][RCOMP] = lum;
2969 texel[i][GCOMP] = lum;
2970 texel[i][BCOMP] = lum;
2971 texel[i][ACOMP] = CHAN_MAX;
2972 }
2973 }
2974 }
2975 #endif
2976
2977
2978 /*
2979 * Apply a unit of texture mapping to the incoming fragments.
2980 */
2981 void
2982 _swrast_texture_fragments( GLcontext *ctx, GLuint texUnit, GLuint n,
2983 const GLfloat s[], const GLfloat t[],
2984 const GLfloat r[], GLfloat lambda[],
2985 CONST GLchan primary_rgba[][4], GLchan rgba[][4] )
2986 {
2987 const GLuint mask = TEXTURE0_ANY << (texUnit * 4);
2988
2989 if (ctx->Texture._ReallyEnabled & mask) {
2990 const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
2991
2992 if (textureUnit->_Current) { /* XXX need this? */
2993 GLchan texel[PB_SIZE][4];
2994
2995 if (textureUnit->LodBias != 0.0F) {
2996 /* apply LOD bias, but don't clamp yet */
2997 GLuint i;
2998 for (i=0;i<n;i++) {
2999 lambda[i] += textureUnit->LodBias;
3000 }
3001 }
3002
3003 if ((textureUnit->_Current->MinLod != -1000.0
3004 || textureUnit->_Current->MaxLod != 1000.0)
3005 && lambda) {
3006 /* apply LOD clamping to lambda */
3007 const GLfloat min = textureUnit->_Current->MinLod;
3008 const GLfloat max = textureUnit->_Current->MaxLod;
3009 GLuint i;
3010 for (i=0;i<n;i++) {
3011 GLfloat l = lambda[i];
3012 lambda[i] = CLAMP(l, min, max);
3013 }
3014 }
3015
3016 /* Sample the texture. */
3017 if (textureUnit->_Current->CompareFlag) {
3018 /* depth texture */
3019 sample_depth_texture(ctx, textureUnit, n, s, t, r, texel);
3020 }
3021 else {
3022 /* color texture */
3023 SWRAST_CONTEXT(ctx)->TextureSample[texUnit]( ctx, texUnit,
3024 textureUnit->_Current,
3025 n, s, t, r,
3026 lambda, texel );
3027 }
3028 apply_texture( ctx, textureUnit, n, primary_rgba,
3029 (const GLchan (*)[4]) texel, rgba );
3030 }
3031 }
3032 }