added missing \'s
[mesa.git] / src / mesa / swrast / s_texture.c
1 /* $Id: s_texture.c,v 1.32 2001/06/01 13:23:27 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 DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4); /* mac 32k limitation */
1807 CHECKARRAY(ccolor, return); /* mac 32k limitation */
1808
1809 ASSERT(ctx->Extensions.EXT_texture_env_combine ||
1810 ctx->Extensions.ARB_texture_env_combine);
1811
1812 /*
1813 * Do operand setup for up to 3 operands. Loop over the terms.
1814 */
1815 for (j = 0; j < 3; j++) {
1816 switch (textureUnit->CombineSourceA[j]) {
1817 case GL_TEXTURE:
1818 argA[j] = texel;
1819 break;
1820 case GL_PRIMARY_COLOR_EXT:
1821 argA[j] = primary_rgba;
1822 break;
1823 case GL_PREVIOUS_EXT:
1824 argA[j] = (const GLchan (*)[4]) rgba;
1825 break;
1826 case GL_CONSTANT_EXT:
1827 {
1828 GLchan alpha, (*c)[4] = ccolor[j];
1829 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
1830 for (i = 0; i < n; i++)
1831 c[i][ACOMP] = alpha;
1832 argA[j] = (const GLchan (*)[4]) ccolor[j];
1833 }
1834 break;
1835 default:
1836 _mesa_problem(NULL, "invalid combine source");
1837 }
1838
1839 switch (textureUnit->CombineSourceRGB[j]) {
1840 case GL_TEXTURE:
1841 argRGB[j] = texel;
1842 break;
1843 case GL_PRIMARY_COLOR_EXT:
1844 argRGB[j] = primary_rgba;
1845 break;
1846 case GL_PREVIOUS_EXT:
1847 argRGB[j] = (const GLchan (*)[4]) rgba;
1848 break;
1849 case GL_CONSTANT_EXT:
1850 {
1851 GLchan (*c)[4] = ccolor[j];
1852 GLchan red, green, blue, alpha;
1853 UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]);
1854 UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
1855 UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]);
1856 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
1857 for (i = 0; i < n; i++) {
1858 c[i][RCOMP] = red;
1859 c[i][GCOMP] = green;
1860 c[i][BCOMP] = blue;
1861 c[i][ACOMP] = alpha;
1862 }
1863 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
1864 }
1865 break;
1866 default:
1867 _mesa_problem(NULL, "invalid combine source");
1868 }
1869
1870 if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) {
1871 const GLchan (*src)[4] = argRGB[j];
1872 GLchan (*dst)[4] = ccolor[j];
1873
1874 /* point to new arg[j] storage */
1875 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
1876
1877 if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
1878 for (i = 0; i < n; i++) {
1879 dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
1880 dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
1881 dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
1882 }
1883 }
1884 else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) {
1885 for (i = 0; i < n; i++) {
1886 dst[i][RCOMP] = src[i][ACOMP];
1887 dst[i][GCOMP] = src[i][ACOMP];
1888 dst[i][BCOMP] = src[i][ACOMP];
1889 }
1890 }
1891 else {
1892 ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
1893 for (i = 0; i < n; i++) {
1894 dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
1895 dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
1896 dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
1897 }
1898 }
1899 }
1900
1901 if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
1902 const GLchan (*src)[4] = argA[j];
1903 GLchan (*dst)[4] = ccolor[j];
1904 argA[j] = (const GLchan (*)[4]) ccolor[j];
1905 for (i = 0; i < n; i++) {
1906 dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
1907 }
1908 }
1909
1910 if (textureUnit->CombineModeRGB == GL_REPLACE &&
1911 textureUnit->CombineModeA == GL_REPLACE) {
1912 break; /* done, we need only arg0 */
1913 }
1914
1915 if (j == 1 &&
1916 textureUnit->CombineModeRGB != GL_INTERPOLATE_EXT &&
1917 textureUnit->CombineModeA != GL_INTERPOLATE_EXT) {
1918 break; /* arg0 and arg1 are done. we don't need arg2. */
1919 }
1920 }
1921
1922 /*
1923 * Do the texture combine.
1924 */
1925 switch (textureUnit->CombineModeRGB) {
1926 case GL_REPLACE:
1927 {
1928 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1929 if (RGBshift) {
1930 for (i = 0; i < n; i++) {
1931 GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
1932 GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
1933 GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
1934 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1935 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1936 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1937 }
1938 }
1939 else {
1940 for (i = 0; i < n; i++) {
1941 rgba[i][RCOMP] = arg0[i][RCOMP];
1942 rgba[i][GCOMP] = arg0[i][GCOMP];
1943 rgba[i][BCOMP] = arg0[i][BCOMP];
1944 }
1945 }
1946 }
1947 break;
1948 case GL_MODULATE:
1949 {
1950 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1951 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1952 const GLint shift = 8 - RGBshift;
1953 for (i = 0; i < n; i++) {
1954 GLuint r = PROD(arg0[i][0], arg1[i][RCOMP]) >> shift;
1955 GLuint g = PROD(arg0[i][1], arg1[i][GCOMP]) >> shift;
1956 GLuint b = PROD(arg0[i][2], arg1[i][BCOMP]) >> shift;
1957 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1958 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1959 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1960 }
1961 }
1962 break;
1963 case GL_ADD:
1964 {
1965 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1966 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1967 for (i = 0; i < n; i++) {
1968 GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
1969 GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
1970 GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
1971 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1972 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1973 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1974 }
1975 }
1976 break;
1977 case GL_ADD_SIGNED_EXT:
1978 {
1979 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1980 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1981 for (i = 0; i < n; i++) {
1982 GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] - 128;
1983 GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] - 128;
1984 GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] - 128;
1985 r = (r < 0) ? 0 : r << RGBshift;
1986 g = (g < 0) ? 0 : g << RGBshift;
1987 b = (b < 0) ? 0 : b << RGBshift;
1988 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1989 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1990 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1991 }
1992 }
1993 break;
1994 case GL_INTERPOLATE_EXT:
1995 {
1996 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1997 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1998 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
1999 const GLint shift = 8 - RGBshift;
2000 for (i = 0; i < n; i++) {
2001 GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
2002 + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
2003 >> shift;
2004 GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
2005 + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
2006 >> shift;
2007 GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
2008 + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
2009 >> shift;
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 }
2014 }
2015 break;
2016 case GL_SUBTRACT_ARB:
2017 {
2018 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2019 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2020 for (i = 0; i < n; i++) {
2021 GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
2022 GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
2023 GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
2024 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
2025 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
2026 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
2027 }
2028 }
2029 break;
2030 case GL_DOT3_RGB_EXT:
2031 case GL_DOT3_RGBA_EXT:
2032 case GL_DOT3_RGB_ARB:
2033 case GL_DOT3_RGBA_ARB:
2034 {
2035 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2036 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2037 /* ATI's EXT extension has a constant scale by 4. The ARB
2038 * one will likely remove this restriction, and we should
2039 * drop the EXT extension in favour of the ARB one.
2040 */
2041 for (i = 0; i < n; i++) {
2042 GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - 128,
2043 (GLint)arg1[i][RCOMP] - 128) +
2044 S_PROD((GLint)arg0[i][GCOMP] - 128,
2045 (GLint)arg1[i][GCOMP] - 128) +
2046 S_PROD((GLint)arg0[i][BCOMP] - 128,
2047 (GLint)arg1[i][BCOMP] - 128)) >> 6;
2048 dot = CLAMP(dot, 0, 255);
2049 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
2050 }
2051 }
2052 break;
2053 default:
2054 _mesa_problem(NULL, "invalid combine mode");
2055 }
2056
2057 switch (textureUnit->CombineModeA) {
2058 case GL_REPLACE:
2059 {
2060 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2061 if (Ashift) {
2062 for (i = 0; i < n; i++) {
2063 GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
2064 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2065 }
2066 }
2067 else {
2068 for (i = 0; i < n; i++) {
2069 rgba[i][ACOMP] = arg0[i][ACOMP];
2070 }
2071 }
2072 }
2073 break;
2074 case GL_MODULATE:
2075 {
2076 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2077 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2078 const GLint shift = 8 - Ashift;
2079 for (i = 0; i < n; i++) {
2080 GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
2081 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2082 }
2083 }
2084 break;
2085 case GL_ADD:
2086 {
2087 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2088 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2089 for (i = 0; i < n; i++) {
2090 GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
2091 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2092 }
2093 }
2094 break;
2095 case GL_ADD_SIGNED_EXT:
2096 {
2097 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2098 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2099 for (i = 0; i < n; i++) {
2100 GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] - 128;
2101 a = (a < 0) ? 0 : a << Ashift;
2102 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2103 }
2104 }
2105 break;
2106 case GL_INTERPOLATE_EXT:
2107 {
2108 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
2109 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
2110 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
2111 const GLint shift = 8 - Ashift;
2112 for (i=0; i<n; i++) {
2113 GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
2114 + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
2115 >> shift;
2116 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
2117 }
2118 }
2119 break;
2120 case GL_SUBTRACT_ARB:
2121 {
2122 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2123 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2124 for (i = 0; i < n; i++) {
2125 GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << RGBshift;
2126 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
2127 }
2128 }
2129 break;
2130
2131 default:
2132 _mesa_problem(NULL, "invalid combine mode");
2133 }
2134
2135 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2136 */
2137 if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT ||
2138 textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) {
2139 for (i = 0; i < n; i++) {
2140 rgba[i][ACOMP] = rgba[i][RCOMP];
2141 }
2142 }
2143 UNDEFARRAY(ccolor); /* mac 32k limitation */
2144 }
2145 #undef PROD
2146
2147
2148
2149 /**********************************************************************/
2150 /* Texture Application */
2151 /**********************************************************************/
2152
2153
2154 /*
2155 * Combine incoming fragment color with texel color to produce output color.
2156 * Input: textureUnit - pointer to texture unit to apply
2157 * format - base internal texture format
2158 * n - number of fragments
2159 * primary_rgba - primary colors (may alias rgba for single texture)
2160 * texels - array of texel colors
2161 * InOut: rgba - incoming fragment colors modified by texel colors
2162 * according to the texture environment mode.
2163 */
2164 static void
2165 apply_texture( const GLcontext *ctx,
2166 const struct gl_texture_unit *texUnit,
2167 GLuint n,
2168 CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
2169 GLchan rgba[][4] )
2170 {
2171 GLint baseLevel;
2172 GLuint i;
2173 GLint Rc, Gc, Bc, Ac;
2174 GLenum format;
2175
2176 ASSERT(texUnit);
2177 ASSERT(texUnit->_Current);
2178
2179 baseLevel = texUnit->_Current->BaseLevel;
2180 ASSERT(texUnit->_Current->Image[baseLevel]);
2181
2182 format = texUnit->_Current->Image[baseLevel]->Format;
2183
2184 if (format==GL_COLOR_INDEX || format==GL_DEPTH_COMPONENT) {
2185 format = GL_RGBA; /* XXXX a hack! */
2186 }
2187
2188 switch (texUnit->EnvMode) {
2189 case GL_REPLACE:
2190 switch (format) {
2191 case GL_ALPHA:
2192 for (i=0;i<n;i++) {
2193 /* Cv = Cf */
2194 /* Av = At */
2195 rgba[i][ACOMP] = texel[i][ACOMP];
2196 }
2197 break;
2198 case GL_LUMINANCE:
2199 for (i=0;i<n;i++) {
2200 /* Cv = Lt */
2201 GLchan Lt = texel[i][RCOMP];
2202 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
2203 /* Av = Af */
2204 }
2205 break;
2206 case GL_LUMINANCE_ALPHA:
2207 for (i=0;i<n;i++) {
2208 GLchan Lt = texel[i][RCOMP];
2209 /* Cv = Lt */
2210 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
2211 /* Av = At */
2212 rgba[i][ACOMP] = texel[i][ACOMP];
2213 }
2214 break;
2215 case GL_INTENSITY:
2216 for (i=0;i<n;i++) {
2217 /* Cv = It */
2218 GLchan It = texel[i][RCOMP];
2219 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
2220 /* Av = It */
2221 rgba[i][ACOMP] = It;
2222 }
2223 break;
2224 case GL_RGB:
2225 for (i=0;i<n;i++) {
2226 /* Cv = Ct */
2227 rgba[i][RCOMP] = texel[i][RCOMP];
2228 rgba[i][GCOMP] = texel[i][GCOMP];
2229 rgba[i][BCOMP] = texel[i][BCOMP];
2230 /* Av = Af */
2231 }
2232 break;
2233 case GL_RGBA:
2234 for (i=0;i<n;i++) {
2235 /* Cv = Ct */
2236 rgba[i][RCOMP] = texel[i][RCOMP];
2237 rgba[i][GCOMP] = texel[i][GCOMP];
2238 rgba[i][BCOMP] = texel[i][BCOMP];
2239 /* Av = At */
2240 rgba[i][ACOMP] = texel[i][ACOMP];
2241 }
2242 break;
2243 default:
2244 _mesa_problem(ctx, "Bad format (GL_REPLACE) in apply_texture");
2245 return;
2246 }
2247 break;
2248
2249 case GL_MODULATE:
2250 switch (format) {
2251 case GL_ALPHA:
2252 for (i=0;i<n;i++) {
2253 /* Cv = Cf */
2254 /* Av = AfAt */
2255 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2256 }
2257 break;
2258 case GL_LUMINANCE:
2259 for (i=0;i<n;i++) {
2260 /* Cv = LtCf */
2261 GLchan Lt = texel[i][RCOMP];
2262 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
2263 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
2264 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
2265 /* Av = Af */
2266 }
2267 break;
2268 case GL_LUMINANCE_ALPHA:
2269 for (i=0;i<n;i++) {
2270 /* Cv = CfLt */
2271 GLchan Lt = texel[i][RCOMP];
2272 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
2273 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
2274 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
2275 /* Av = AfAt */
2276 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2277 }
2278 break;
2279 case GL_INTENSITY:
2280 for (i=0;i<n;i++) {
2281 /* Cv = CfIt */
2282 GLchan It = texel[i][RCOMP];
2283 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
2284 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
2285 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
2286 /* Av = AfIt */
2287 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
2288 }
2289 break;
2290 case GL_RGB:
2291 for (i=0;i<n;i++) {
2292 /* Cv = CfCt */
2293 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
2294 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
2295 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
2296 /* Av = Af */
2297 }
2298 break;
2299 case GL_RGBA:
2300 for (i=0;i<n;i++) {
2301 /* Cv = CfCt */
2302 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
2303 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
2304 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
2305 /* Av = AfAt */
2306 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2307 }
2308 break;
2309 default:
2310 _mesa_problem(ctx, "Bad format (GL_MODULATE) in apply_texture");
2311 return;
2312 }
2313 break;
2314
2315 case GL_DECAL:
2316 switch (format) {
2317 case GL_ALPHA:
2318 case GL_LUMINANCE:
2319 case GL_LUMINANCE_ALPHA:
2320 case GL_INTENSITY:
2321 /* undefined */
2322 break;
2323 case GL_RGB:
2324 for (i=0;i<n;i++) {
2325 /* Cv = Ct */
2326 rgba[i][RCOMP] = texel[i][RCOMP];
2327 rgba[i][GCOMP] = texel[i][GCOMP];
2328 rgba[i][BCOMP] = texel[i][BCOMP];
2329 /* Av = Af */
2330 }
2331 break;
2332 case GL_RGBA:
2333 for (i=0;i<n;i++) {
2334 /* Cv = Cf(1-At) + CtAt */
2335 GLint t = texel[i][ACOMP], s = CHAN_MAX - t;
2336 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
2337 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
2338 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
2339 /* Av = Af */
2340 }
2341 break;
2342 default:
2343 _mesa_problem(ctx, "Bad format (GL_DECAL) in apply_texture");
2344 return;
2345 }
2346 break;
2347
2348 case GL_BLEND:
2349 Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF);
2350 Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF);
2351 Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF);
2352 Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF);
2353 switch (format) {
2354 case GL_ALPHA:
2355 for (i=0;i<n;i++) {
2356 /* Cv = Cf */
2357 /* Av = AfAt */
2358 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2359 }
2360 break;
2361 case GL_LUMINANCE:
2362 for (i=0;i<n;i++) {
2363 /* Cv = Cf(1-Lt) + CcLt */
2364 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
2365 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
2366 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
2367 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
2368 /* Av = Af */
2369 }
2370 break;
2371 case GL_LUMINANCE_ALPHA:
2372 for (i=0;i<n;i++) {
2373 /* Cv = Cf(1-Lt) + CcLt */
2374 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
2375 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
2376 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
2377 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
2378 /* Av = AfAt */
2379 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
2380 }
2381 break;
2382 case GL_INTENSITY:
2383 for (i=0;i<n;i++) {
2384 /* Cv = Cf(1-It) + CcLt */
2385 GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
2386 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
2387 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
2388 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
2389 /* Av = Af(1-It) + Ac*It */
2390 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
2391 }
2392 break;
2393 case GL_RGB:
2394 for (i=0;i<n;i++) {
2395 /* Cv = Cf(1-Ct) + CcCt */
2396 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
2397 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
2398 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
2399 /* Av = Af */
2400 }
2401 break;
2402 case GL_RGBA:
2403 for (i=0;i<n;i++) {
2404 /* Cv = Cf(1-Ct) + CcCt */
2405 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
2406 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
2407 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
2408 /* Av = AfAt */
2409 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
2410 }
2411 break;
2412 default:
2413 _mesa_problem(ctx, "Bad format (GL_BLEND) in apply_texture");
2414 return;
2415 }
2416 break;
2417
2418 case GL_ADD: /* GL_EXT_texture_add_env */
2419 switch (format) {
2420 case GL_ALPHA:
2421 for (i=0;i<n;i++) {
2422 /* Rv = Rf */
2423 /* Gv = Gf */
2424 /* Bv = Bf */
2425 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2426 }
2427 break;
2428 case GL_LUMINANCE:
2429 for (i=0;i<n;i++) {
2430 GLuint Lt = texel[i][RCOMP];
2431 GLuint r = rgba[i][RCOMP] + Lt;
2432 GLuint g = rgba[i][GCOMP] + Lt;
2433 GLuint b = rgba[i][BCOMP] + Lt;
2434 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2435 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2436 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2437 /* Av = Af */
2438 }
2439 break;
2440 case GL_LUMINANCE_ALPHA:
2441 for (i=0;i<n;i++) {
2442 GLuint Lt = texel[i][RCOMP];
2443 GLuint r = rgba[i][RCOMP] + Lt;
2444 GLuint g = rgba[i][GCOMP] + Lt;
2445 GLuint b = rgba[i][BCOMP] + Lt;
2446 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2447 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2448 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2449 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2450 }
2451 break;
2452 case GL_INTENSITY:
2453 for (i=0;i<n;i++) {
2454 GLchan It = texel[i][RCOMP];
2455 GLuint r = rgba[i][RCOMP] + It;
2456 GLuint g = rgba[i][GCOMP] + It;
2457 GLuint b = rgba[i][BCOMP] + It;
2458 GLuint a = rgba[i][ACOMP] + It;
2459 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2460 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2461 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2462 rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
2463 }
2464 break;
2465 case GL_RGB:
2466 for (i=0;i<n;i++) {
2467 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
2468 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
2469 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
2470 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2471 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2472 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2473 /* Av = Af */
2474 }
2475 break;
2476 case GL_RGBA:
2477 for (i=0;i<n;i++) {
2478 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
2479 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
2480 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
2481 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2482 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2483 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2484 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2485 }
2486 break;
2487 default:
2488 _mesa_problem(ctx, "Bad format (GL_ADD) in apply_texture");
2489 return;
2490 }
2491 break;
2492
2493 case GL_COMBINE_EXT:
2494 texture_combine(ctx, texUnit, n, primary_rgba, texel, rgba);
2495 break;
2496
2497 default:
2498 _mesa_problem(ctx, "Bad env mode in apply_texture");
2499 return;
2500 }
2501 }
2502
2503
2504
2505 /*
2506 * Sample a shadow/depth texture.
2507 * Input: ctx - context
2508 * texUnit - the texture unit
2509 * n - number of samples
2510 * s,t,r - array [n] of texture coordinates
2511 * In/Out: rgba - array [n] of texel colors.
2512 */
2513 static void
2514 sample_depth_texture(const GLcontext *ctx,
2515 const struct gl_texture_unit *texUnit,
2516 GLuint n,
2517 const GLfloat s[], const GLfloat t[], const GLfloat r[],
2518 GLchan texel[][4])
2519 {
2520 const struct gl_texture_object *texObj = texUnit->_Current;
2521 const GLint baseLevel = texObj->BaseLevel;
2522 const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2523 const GLuint width = texImage->Width;
2524 const GLuint height = texImage->Height;
2525 const GLchan ambient = texObj->ShadowAmbient;
2526 GLboolean lequal, gequal;
2527
2528 if (texObj->Dimensions != 2) {
2529 _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2530 return;
2531 }
2532
2533 if (texObj->MinFilter != texObj->MagFilter) {
2534 _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2535 return;
2536 }
2537
2538 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2539 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2540 * isn't a depth texture.
2541 */
2542 if (texImage->Format != GL_DEPTH_COMPONENT) {
2543 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2544 return;
2545 }
2546
2547 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2548 lequal = GL_TRUE;
2549 gequal = GL_FALSE;
2550 }
2551 else {
2552 lequal = GL_FALSE;
2553 gequal = GL_TRUE;
2554 }
2555
2556 if (texObj->MagFilter == GL_NEAREST) {
2557 GLuint i;
2558 for (i = 0; i < n; i++) {
2559 GLfloat depthSample;
2560 GLint col, row;
2561 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
2562 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
2563 depthSample = *((const GLfloat *) texImage->Data + row * width + col);
2564 if ((r[i] <= depthSample && lequal) ||
2565 (r[i] >= depthSample && gequal)) {
2566 texel[i][RCOMP] = CHAN_MAX;
2567 texel[i][GCOMP] = CHAN_MAX;
2568 texel[i][BCOMP] = CHAN_MAX;
2569 texel[i][ACOMP] = CHAN_MAX;
2570 }
2571 else {
2572 texel[i][RCOMP] = ambient;
2573 texel[i][GCOMP] = ambient;
2574 texel[i][BCOMP] = ambient;
2575 texel[i][ACOMP] = CHAN_MAX;
2576 }
2577 }
2578 }
2579 else {
2580 GLuint i;
2581 ASSERT(texObj->MagFilter == GL_LINEAR);
2582 for (i = 0; i < n; i++) {
2583 GLfloat depth00, depth01, depth10, depth11;
2584 GLint i0, i1, j0, j1;
2585 GLfloat u, v;
2586 GLuint useBorderTexel;
2587
2588 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapS, s[i], u, width, i0, i1);
2589 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapT, t[i], v, height,j0, j1);
2590
2591 useBorderTexel = 0;
2592 if (texImage->Border) {
2593 i0 += texImage->Border;
2594 i1 += texImage->Border;
2595 j0 += texImage->Border;
2596 j1 += texImage->Border;
2597 }
2598 else {
2599 if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT;
2600 if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT;
2601 if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT;
2602 if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT;
2603 }
2604
2605 /* get four depth samples from the texture */
2606 if (useBorderTexel & (I0BIT | J0BIT)) {
2607 depth00 = 1.0;
2608 }
2609 else {
2610 depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0);
2611 }
2612 if (useBorderTexel & (I1BIT | J0BIT)) {
2613 depth10 = 1.0;
2614 }
2615 else {
2616 depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1);
2617 }
2618 if (useBorderTexel & (I0BIT | J1BIT)) {
2619 depth01 = 1.0;
2620 }
2621 else {
2622 depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0);
2623 }
2624 if (useBorderTexel & (I1BIT | J1BIT)) {
2625 depth11 = 1.0;
2626 }
2627 else {
2628 depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1);
2629 }
2630
2631 if (0) {
2632 /* compute a single weighted depth sample and do one comparison */
2633 const GLfloat a = FRAC(u + 1.0F);
2634 const GLfloat b = FRAC(v + 1.0F);
2635 const GLfloat w00 = (1.0F - a) * (1.0F - b);
2636 const GLfloat w10 = ( a) * (1.0F - b);
2637 const GLfloat w01 = (1.0F - a) * ( b);
2638 const GLfloat w11 = ( a) * ( b);
2639 const GLfloat depthSample = w00 * depth00 + w10 * depth10
2640 + w01 * depth01 + w11 * depth11;
2641 if ((depthSample <= r[i] && lequal) ||
2642 (depthSample >= r[i] && gequal)) {
2643 texel[i][RCOMP] = ambient;
2644 texel[i][GCOMP] = ambient;
2645 texel[i][BCOMP] = ambient;
2646 texel[i][ACOMP] = CHAN_MAX;
2647 }
2648 else {
2649 texel[i][RCOMP] = CHAN_MAX;
2650 texel[i][GCOMP] = CHAN_MAX;
2651 texel[i][BCOMP] = CHAN_MAX;
2652 texel[i][ACOMP] = CHAN_MAX;
2653 }
2654 }
2655 else {
2656 /* Do four depth/R comparisons and compute a weighted result.
2657 * If this touches on somebody's I.P., I'll remove this code
2658 * upon request.
2659 */
2660 const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
2661 GLfloat luminance = CHAN_MAXF;
2662 GLchan lum;
2663 if (lequal) {
2664 if (depth00 <= r[i]) luminance -= d;
2665 if (depth01 <= r[i]) luminance -= d;
2666 if (depth10 <= r[i]) luminance -= d;
2667 if (depth11 <= r[i]) luminance -= d;
2668 }
2669 else {
2670 if (depth00 >= r[i]) luminance -= d;
2671 if (depth01 >= r[i]) luminance -= d;
2672 if (depth10 >= r[i]) luminance -= d;
2673 if (depth11 >= r[i]) luminance -= d;
2674 }
2675 lum = (GLchan) luminance;
2676 texel[i][RCOMP] = lum;
2677 texel[i][GCOMP] = lum;
2678 texel[i][BCOMP] = lum;
2679 texel[i][ACOMP] = CHAN_MAX;
2680 }
2681 }
2682 }
2683 }
2684
2685
2686 #if 0
2687 /*
2688 * Experimental depth texture sampling function.
2689 */
2690 static void
2691 sample_depth_texture2(const GLcontext *ctx,
2692 const struct gl_texture_unit *texUnit,
2693 GLuint n,
2694 const GLfloat s[], const GLfloat t[], const GLfloat r[],
2695 GLchan texel[][4])
2696 {
2697 const struct gl_texture_object *texObj = texUnit->_Current;
2698 const GLint baseLevel = texObj->BaseLevel;
2699 const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2700 const GLuint width = texImage->Width;
2701 const GLuint height = texImage->Height;
2702 const GLchan ambient = texObj->ShadowAmbient;
2703 GLboolean lequal, gequal;
2704
2705 if (texObj->Dimensions != 2) {
2706 _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2707 return;
2708 }
2709
2710 if (texObj->MinFilter != texObj->MagFilter) {
2711 _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2712 return;
2713 }
2714
2715 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2716 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2717 * isn't a depth texture.
2718 */
2719 if (texImage->Format != GL_DEPTH_COMPONENT) {
2720 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2721 return;
2722 }
2723
2724 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2725 lequal = GL_TRUE;
2726 gequal = GL_FALSE;
2727 }
2728 else {
2729 lequal = GL_FALSE;
2730 gequal = GL_TRUE;
2731 }
2732
2733 {
2734 GLuint i;
2735 for (i = 0; i < n; i++) {
2736 const GLint K = 3;
2737 GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
2738 GLfloat w;
2739 GLchan lum;
2740 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
2741 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
2742
2743 imin = col - K;
2744 imax = col + K;
2745 jmin = row - K;
2746 jmax = row + K;
2747
2748 if (imin < 0) imin = 0;
2749 if (imax >= width) imax = width - 1;
2750 if (jmin < 0) jmin = 0;
2751 if (jmax >= height) jmax = height - 1;
2752
2753 samples = (imax - imin + 1) * (jmax - jmin + 1);
2754 count = 0;
2755 for (jj = jmin; jj <= jmax; jj++) {
2756 for (ii = imin; ii <= imax; ii++) {
2757 GLfloat depthSample = *((const GLfloat *) texImage->Data
2758 + jj * width + ii);
2759 if ((depthSample <= r[i] && lequal) ||
2760 (depthSample >= r[i] && gequal)) {
2761 count++;
2762 }
2763 }
2764 }
2765
2766 w = (GLfloat) count / (GLfloat) samples;
2767 w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
2768 lum = (GLint) w;
2769
2770 texel[i][RCOMP] = lum;
2771 texel[i][GCOMP] = lum;
2772 texel[i][BCOMP] = lum;
2773 texel[i][ACOMP] = CHAN_MAX;
2774 }
2775 }
2776 }
2777 #endif
2778
2779
2780 /*
2781 * Apply a unit of texture mapping to the incoming fragments.
2782 */
2783 void
2784 _swrast_texture_fragments( GLcontext *ctx, GLuint texUnit, GLuint n,
2785 const GLfloat s[], const GLfloat t[],
2786 const GLfloat r[], GLfloat lambda[],
2787 CONST GLchan primary_rgba[][4], GLchan rgba[][4] )
2788 {
2789 const GLuint mask = TEXTURE0_ANY << (texUnit * 4);
2790
2791 if (ctx->Texture._ReallyEnabled & mask) {
2792 const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
2793
2794 if (textureUnit->_Current) { /* XXX need this? */
2795 GLchan texel[PB_SIZE][4];
2796
2797 if (textureUnit->LodBias != 0.0F) {
2798 /* apply LOD bias, but don't clamp yet */
2799 GLuint i;
2800 for (i=0;i<n;i++) {
2801 lambda[i] += textureUnit->LodBias;
2802 }
2803 }
2804
2805 if ((textureUnit->_Current->MinLod != -1000.0
2806 || textureUnit->_Current->MaxLod != 1000.0)
2807 && lambda) {
2808 /* apply LOD clamping to lambda */
2809 const GLfloat min = textureUnit->_Current->MinLod;
2810 const GLfloat max = textureUnit->_Current->MaxLod;
2811 GLuint i;
2812 for (i=0;i<n;i++) {
2813 GLfloat l = lambda[i];
2814 lambda[i] = CLAMP(l, min, max);
2815 }
2816 }
2817
2818 /* Sample the texture. */
2819 if (textureUnit->_Current->CompareFlag) {
2820 /* depth texture */
2821 sample_depth_texture(ctx, textureUnit, n, s, t, r, texel);
2822 }
2823 else {
2824 /* color texture */
2825 SWRAST_CONTEXT(ctx)->TextureSample[texUnit]( ctx, texUnit,
2826 textureUnit->_Current,
2827 n, s, t, r,
2828 lambda, texel );
2829 }
2830 apply_texture( ctx, textureUnit, n, primary_rgba,
2831 (const GLchan (*)[4]) texel, rgba );
2832 }
2833 }
2834 }