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