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