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