2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include "texformat.h"
35 #include "s_context.h"
36 #include "s_texture.h"
40 * These values are used in the fixed-point arithmetic used
41 * for linear filtering.
43 #define WEIGHT_SCALE 65536.0F
44 #define WEIGHT_SHIFT 16
48 * Compute the remainder of a divided by b, but be careful with
49 * negative values so that GL_REPEAT mode works right.
52 repeat_remainder(GLint a
, GLint b
)
57 return (a
+ 1) % b
+ b
- 1;
62 * Used to compute texel locations for linear sampling.
64 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
65 * S = texcoord in [0,1]
66 * SIZE = width (or height or depth) of texture
68 * U = texcoord in [0, width]
69 * I0, I1 = two nearest texel indexes
71 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
73 if (wrapMode == GL_REPEAT) { \
74 U = S * SIZE - 0.5F; \
75 if (tObj->_IsPowerOfTwo) { \
76 I0 = IFLOOR(U) & (SIZE - 1); \
77 I1 = (I0 + 1) & (SIZE - 1); \
80 I0 = repeat_remainder(IFLOOR(U), SIZE); \
81 I1 = repeat_remainder(I0 + 1, SIZE); \
84 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
96 if (I1 >= (GLint) SIZE) \
99 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
100 const GLfloat min = -1.0F / (2.0F * SIZE); \
101 const GLfloat max = 1.0F - min; \
112 else if (wrapMode == GL_MIRRORED_REPEAT) { \
113 const GLint flr = IFLOOR(S); \
115 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
117 U = S - (GLfloat) flr; /* flr is even */ \
118 U = (U * SIZE) - 0.5F; \
123 if (I1 >= (GLint) SIZE) \
126 else if (wrapMode == GL_MIRROR_CLAMP_EXT) { \
127 U = (GLfloat) fabs(S); \
129 U = (GLfloat) SIZE; \
136 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) { \
137 U = (GLfloat) fabs(S); \
139 U = (GLfloat) SIZE; \
147 if (I1 >= (GLint) SIZE) \
150 else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) { \
151 const GLfloat min = -1.0F / (2.0F * SIZE); \
152 const GLfloat max = 1.0F - min; \
153 U = (GLfloat) fabs(S); \
165 ASSERT(wrapMode == GL_CLAMP); \
168 else if (S >= 1.0F) \
169 U = (GLfloat) SIZE; \
180 * Used to compute texel location for nearest sampling.
182 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
184 if (wrapMode == GL_REPEAT) { \
185 /* s limited to [0,1) */ \
186 /* i limited to [0,size-1] */ \
187 I = IFLOOR(S * SIZE); \
188 if (tObj->_IsPowerOfTwo) \
191 I = repeat_remainder(I, SIZE); \
193 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
194 /* s limited to [min,max] */ \
195 /* i limited to [0, size-1] */ \
196 const GLfloat min = 1.0F / (2.0F * SIZE); \
197 const GLfloat max = 1.0F - min; \
203 I = IFLOOR(S * SIZE); \
205 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
206 /* s limited to [min,max] */ \
207 /* i limited to [-1, size] */ \
208 const GLfloat min = -1.0F / (2.0F * SIZE); \
209 const GLfloat max = 1.0F - min; \
215 I = IFLOOR(S * SIZE); \
217 else if (wrapMode == GL_MIRRORED_REPEAT) { \
218 const GLfloat min = 1.0F / (2.0F * SIZE); \
219 const GLfloat max = 1.0F - min; \
220 const GLint flr = IFLOOR(S); \
223 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
225 u = S - (GLfloat) flr; /* flr is even */ \
231 I = IFLOOR(u * SIZE); \
233 else if (wrapMode == GL_MIRROR_CLAMP_EXT) { \
234 /* s limited to [0,1] */ \
235 /* i limited to [0,size-1] */ \
236 const GLfloat u = (GLfloat) fabs(S); \
239 else if (u >= 1.0F) \
242 I = IFLOOR(u * SIZE); \
244 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) { \
245 /* s limited to [min,max] */ \
246 /* i limited to [0, size-1] */ \
247 const GLfloat min = 1.0F / (2.0F * SIZE); \
248 const GLfloat max = 1.0F - min; \
249 const GLfloat u = (GLfloat) fabs(S); \
255 I = IFLOOR(u * SIZE); \
257 else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) { \
258 /* s limited to [min,max] */ \
259 /* i limited to [0, size-1] */ \
260 const GLfloat min = -1.0F / (2.0F * SIZE); \
261 const GLfloat max = 1.0F - min; \
262 const GLfloat u = (GLfloat) fabs(S); \
268 I = IFLOOR(u * SIZE); \
271 ASSERT(wrapMode == GL_CLAMP); \
272 /* s limited to [0,1] */ \
273 /* i limited to [0,size-1] */ \
276 else if (S >= 1.0F) \
279 I = IFLOOR(S * SIZE); \
284 /* Power of two image sizes only */
285 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
287 U = S * SIZE - 0.5F; \
288 I0 = IFLOOR(U) & (SIZE - 1); \
289 I1 = (I0 + 1) & (SIZE - 1); \
294 * Compute linear mipmap levels for given lambda.
296 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
299 level = tObj->BaseLevel; \
300 else if (lambda > tObj->_MaxLambda) \
301 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
303 level = (GLint) (tObj->BaseLevel + lambda); \
308 * Compute nearest mipmap level for given lambda.
310 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
313 if (lambda <= 0.5F) \
315 else if (lambda > tObj->_MaxLambda + 0.4999F) \
316 l = tObj->_MaxLambda + 0.4999F; \
319 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
320 if (level > tObj->_MaxLevel) \
321 level = tObj->_MaxLevel; \
327 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
328 * see 1-pixel bands of improperly weighted linear-sampled texels. The
329 * tests/texwrap.c demo is a good test.
330 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
331 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
333 #define FRAC(f) ((f) - IFLOOR(f))
338 * Bitflags for texture border color sampling.
350 * The lambda[] array values are always monotonic. Either the whole span
351 * will be minified, magnified, or split between the two. This function
352 * determines the subranges in [0, n-1] that are to be minified or magnified.
355 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
356 GLuint
*minStart
, GLuint
*minEnd
,
357 GLuint
*magStart
, GLuint
*magEnd
)
359 ASSERT(lambda
!= NULL
);
361 /* Verify that lambda[] is monotonous.
362 * We can't really use this because the inaccuracy in the LOG2 function
363 * causes this test to fail, yet the resulting texturing is correct.
367 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
368 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
369 for (i
= 0; i
< n
- 1; i
++) {
370 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
373 else { /* increasing */
374 for (i
= 0; i
< n
- 1; i
++) {
375 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
381 /* since lambda is monotonous-array use this check first */
382 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
383 /* magnification for whole span */
386 *minStart
= *minEnd
= 0;
388 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
389 /* minification for whole span */
392 *magStart
= *magEnd
= 0;
395 /* a mix of minification and magnification */
397 if (lambda
[0] > minMagThresh
) {
398 /* start with minification */
399 for (i
= 1; i
< n
; i
++) {
400 if (lambda
[i
] <= minMagThresh
)
409 /* start with magnification */
410 for (i
= 1; i
< n
; i
++) {
411 if (lambda
[i
] > minMagThresh
)
422 /* Verify the min/mag Start/End values
423 * We don't use this either (see above)
427 for (i
= 0; i
< n
; i
++) {
428 if (lambda
[i
] > minMagThresh
) {
430 ASSERT(i
>= *minStart
);
435 ASSERT(i
>= *magStart
);
444 /**********************************************************************/
445 /* 1-D Texture Sampling Functions */
446 /**********************************************************************/
449 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
452 sample_1d_nearest(GLcontext
*ctx
,
453 const struct gl_texture_object
*tObj
,
454 const struct gl_texture_image
*img
,
455 const GLfloat texcoord
[4], GLchan rgba
[4])
457 const GLint width
= img
->Width2
; /* without border, power of two */
461 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
463 /* skip over the border, if any */
466 if (i
< 0 || i
>= (GLint
) img
->Width
) {
467 /* Need this test for GL_CLAMP_TO_BORDER mode */
468 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
471 img
->FetchTexelc(img
, i
, 0, 0, rgba
);
478 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
481 sample_1d_linear(GLcontext
*ctx
,
482 const struct gl_texture_object
*tObj
,
483 const struct gl_texture_image
*img
,
484 const GLfloat texcoord
[4], GLchan rgba
[4])
486 const GLint width
= img
->Width2
;
489 GLuint useBorderColor
;
492 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
500 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
501 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
505 const GLfloat a
= FRAC(u
);
507 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
508 const GLfloat w0
= (1.0F
-a
);
509 const GLfloat w1
= a
;
510 #else /* CHAN_BITS == 8 */
511 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
512 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
513 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
515 GLchan t0
[4], t1
[4]; /* texels */
517 if (useBorderColor
& I0BIT
) {
518 COPY_CHAN4(t0
, tObj
->_BorderChan
);
521 img
->FetchTexelc(img
, i0
, 0, 0, t0
);
523 if (useBorderColor
& I1BIT
) {
524 COPY_CHAN4(t1
, tObj
->_BorderChan
);
527 img
->FetchTexelc(img
, i1
, 0, 0, t1
);
530 #if CHAN_TYPE == GL_FLOAT
531 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
532 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
533 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
534 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
535 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
536 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
537 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
538 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
539 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
540 #else /* CHAN_BITS == 8 */
541 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
542 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
543 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
544 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
552 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
553 const struct gl_texture_object
*tObj
,
554 GLuint n
, const GLfloat texcoord
[][4],
555 const GLfloat lambda
[], GLchan rgba
[][4])
558 ASSERT(lambda
!= NULL
);
559 for (i
= 0; i
< n
; i
++) {
561 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
562 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
568 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
569 const struct gl_texture_object
*tObj
,
570 GLuint n
, const GLfloat texcoord
[][4],
571 const GLfloat lambda
[], GLchan rgba
[][4])
574 ASSERT(lambda
!= NULL
);
575 for (i
= 0; i
< n
; i
++) {
577 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
578 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
585 * This is really just needed in order to prevent warnings with some compilers.
587 #if CHAN_TYPE == GL_FLOAT
590 #define CHAN_CAST (GLchan) (GLint)
595 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
596 const struct gl_texture_object
*tObj
,
597 GLuint n
, const GLfloat texcoord
[][4],
598 const GLfloat lambda
[], GLchan rgba
[][4])
601 ASSERT(lambda
!= NULL
);
602 for (i
= 0; i
< n
; i
++) {
604 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
605 if (level
>= tObj
->_MaxLevel
) {
606 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
607 texcoord
[i
], rgba
[i
]);
611 const GLfloat f
= FRAC(lambda
[i
]);
612 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
613 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
614 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
615 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
616 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
617 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
625 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
626 const struct gl_texture_object
*tObj
,
627 GLuint n
, const GLfloat texcoord
[][4],
628 const GLfloat lambda
[], GLchan rgba
[][4])
631 ASSERT(lambda
!= NULL
);
632 for (i
= 0; i
< n
; i
++) {
634 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
635 if (level
>= tObj
->_MaxLevel
) {
636 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
637 texcoord
[i
], rgba
[i
]);
641 const GLfloat f
= FRAC(lambda
[i
]);
642 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
643 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
644 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
645 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
646 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
647 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
655 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
656 const struct gl_texture_object
*tObj
, GLuint n
,
657 const GLfloat texcoords
[][4], const GLfloat lambda
[],
661 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
665 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
672 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
673 const struct gl_texture_object
*tObj
, GLuint n
,
674 const GLfloat texcoords
[][4], const GLfloat lambda
[],
678 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
682 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
688 * Given an (s) texture coordinate and lambda (level of detail) value,
689 * return a texture sample.
693 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
694 const struct gl_texture_object
*tObj
, GLuint n
,
695 const GLfloat texcoords
[][4],
696 const GLfloat lambda
[], GLchan rgba
[][4] )
698 GLuint minStart
, minEnd
; /* texels with minification */
699 GLuint magStart
, magEnd
; /* texels with magnification */
702 ASSERT(lambda
!= NULL
);
703 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
704 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
706 if (minStart
< minEnd
) {
707 /* do the minified texels */
708 const GLuint m
= minEnd
- minStart
;
709 switch (tObj
->MinFilter
) {
711 for (i
= minStart
; i
< minEnd
; i
++)
712 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
713 texcoords
[i
], rgba
[i
]);
716 for (i
= minStart
; i
< minEnd
; i
++)
717 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
718 texcoords
[i
], rgba
[i
]);
720 case GL_NEAREST_MIPMAP_NEAREST
:
721 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
722 lambda
+ minStart
, rgba
+ minStart
);
724 case GL_LINEAR_MIPMAP_NEAREST
:
725 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
726 lambda
+ minStart
, rgba
+ minStart
);
728 case GL_NEAREST_MIPMAP_LINEAR
:
729 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
730 lambda
+ minStart
, rgba
+ minStart
);
732 case GL_LINEAR_MIPMAP_LINEAR
:
733 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
734 lambda
+ minStart
, rgba
+ minStart
);
737 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
742 if (magStart
< magEnd
) {
743 /* do the magnified texels */
744 switch (tObj
->MagFilter
) {
746 for (i
= magStart
; i
< magEnd
; i
++)
747 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
748 texcoords
[i
], rgba
[i
]);
751 for (i
= magStart
; i
< magEnd
; i
++)
752 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
753 texcoords
[i
], rgba
[i
]);
756 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
763 /**********************************************************************/
764 /* 2-D Texture Sampling Functions */
765 /**********************************************************************/
769 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
772 sample_2d_nearest(GLcontext
*ctx
,
773 const struct gl_texture_object
*tObj
,
774 const struct gl_texture_image
*img
,
775 const GLfloat texcoord
[4],
778 const GLint width
= img
->Width2
; /* without border, power of two */
779 const GLint height
= img
->Height2
; /* without border, power of two */
783 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
784 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
786 /* skip over the border, if any */
790 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
791 /* Need this test for GL_CLAMP_TO_BORDER mode */
792 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
795 img
->FetchTexelc(img
, i
, j
, 0, rgba
);
802 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
803 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
806 sample_2d_linear(GLcontext
*ctx
,
807 const struct gl_texture_object
*tObj
,
808 const struct gl_texture_image
*img
,
809 const GLfloat texcoord
[4],
812 const GLint width
= img
->Width2
;
813 const GLint height
= img
->Height2
;
814 GLint i0
, j0
, i1
, j1
;
815 GLuint useBorderColor
;
819 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
820 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
830 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
831 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
832 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
833 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
837 const GLfloat a
= FRAC(u
);
838 const GLfloat b
= FRAC(v
);
840 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
841 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
842 const GLfloat w10
= a
* (1.0F
-b
);
843 const GLfloat w01
= (1.0F
-a
) * b
;
844 const GLfloat w11
= a
* b
;
845 #else /* CHAN_BITS == 8 */
846 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
847 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
848 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
849 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
850 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
857 if (useBorderColor
& (I0BIT
| J0BIT
)) {
858 COPY_CHAN4(t00
, tObj
->_BorderChan
);
861 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
863 if (useBorderColor
& (I1BIT
| J0BIT
)) {
864 COPY_CHAN4(t10
, tObj
->_BorderChan
);
867 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
869 if (useBorderColor
& (I0BIT
| J1BIT
)) {
870 COPY_CHAN4(t01
, tObj
->_BorderChan
);
873 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
875 if (useBorderColor
& (I1BIT
| J1BIT
)) {
876 COPY_CHAN4(t11
, tObj
->_BorderChan
);
879 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
881 #if CHAN_TYPE == GL_FLOAT
882 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
883 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
884 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
885 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
886 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
887 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
888 w01
* t01
[0] + w11
* t11
[0] + 0.5);
889 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
890 w01
* t01
[1] + w11
* t11
[1] + 0.5);
891 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
892 w01
* t01
[2] + w11
* t11
[2] + 0.5);
893 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
894 w01
* t01
[3] + w11
* t11
[3] + 0.5);
895 #else /* CHAN_BITS == 8 */
896 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
897 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
898 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
899 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
900 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
901 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
902 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
903 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
912 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
913 * and we're not using a paletted texture.
916 sample_2d_linear_repeat(GLcontext
*ctx
,
917 const struct gl_texture_object
*tObj
,
918 const struct gl_texture_image
*img
,
919 const GLfloat texcoord
[4],
922 const GLint width
= img
->Width2
;
923 const GLint height
= img
->Height2
;
924 GLint i0
, j0
, i1
, j1
;
929 ASSERT(tObj
->WrapS
== GL_REPEAT
);
930 ASSERT(tObj
->WrapT
== GL_REPEAT
);
931 ASSERT(img
->Border
== 0);
932 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
933 ASSERT(img
->_IsPowerOfTwo
);
935 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
936 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
939 const GLfloat a
= FRAC(u
);
940 const GLfloat b
= FRAC(v
);
942 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
943 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
944 const GLfloat w10
= a
* (1.0F
-b
);
945 const GLfloat w01
= (1.0F
-a
) * b
;
946 const GLfloat w11
= a
* b
;
947 #else /* CHAN_BITS == 8 */
948 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
949 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
950 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
951 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
952 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
959 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
960 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
961 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
962 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
964 #if CHAN_TYPE == GL_FLOAT
965 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
966 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
967 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
968 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
969 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
970 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
971 w01
* t01
[0] + w11
* t11
[0] + 0.5);
972 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
973 w01
* t01
[1] + w11
* t11
[1] + 0.5);
974 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
975 w01
* t01
[2] + w11
* t11
[2] + 0.5);
976 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
977 w01
* t01
[3] + w11
* t11
[3] + 0.5);
978 #else /* CHAN_BITS == 8 */
979 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
980 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
981 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
982 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
983 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
984 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
985 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
986 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
996 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
997 const struct gl_texture_object
*tObj
,
998 GLuint n
, const GLfloat texcoord
[][4],
999 const GLfloat lambda
[], GLchan rgba
[][4])
1002 for (i
= 0; i
< n
; i
++) {
1004 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1005 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1012 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1013 const struct gl_texture_object
*tObj
,
1014 GLuint n
, const GLfloat texcoord
[][4],
1015 const GLfloat lambda
[], GLchan rgba
[][4])
1018 ASSERT(lambda
!= NULL
);
1019 for (i
= 0; i
< n
; i
++) {
1021 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1022 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1029 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1030 const struct gl_texture_object
*tObj
,
1031 GLuint n
, const GLfloat texcoord
[][4],
1032 const GLfloat lambda
[], GLchan rgba
[][4])
1035 ASSERT(lambda
!= NULL
);
1036 for (i
= 0; i
< n
; i
++) {
1038 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1039 if (level
>= tObj
->_MaxLevel
) {
1040 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1041 texcoord
[i
], rgba
[i
]);
1044 GLchan t0
[4], t1
[4]; /* texels */
1045 const GLfloat f
= FRAC(lambda
[i
]);
1046 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1047 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1048 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1049 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1050 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1051 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1058 /* Trilinear filtering */
1060 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1061 const struct gl_texture_object
*tObj
,
1062 GLuint n
, const GLfloat texcoord
[][4],
1063 const GLfloat lambda
[], GLchan rgba
[][4] )
1066 ASSERT(lambda
!= NULL
);
1067 for (i
= 0; i
< n
; i
++) {
1069 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1070 if (level
>= tObj
->_MaxLevel
) {
1071 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1072 texcoord
[i
], rgba
[i
]);
1075 GLchan t0
[4], t1
[4]; /* texels */
1076 const GLfloat f
= FRAC(lambda
[i
]);
1077 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1078 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1079 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1080 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1081 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1082 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1089 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1090 const struct gl_texture_object
*tObj
,
1091 GLuint n
, const GLfloat texcoord
[][4],
1092 const GLfloat lambda
[], GLchan rgba
[][4] )
1095 ASSERT(lambda
!= NULL
);
1096 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1097 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1098 ASSERT(tObj
->_IsPowerOfTwo
);
1099 for (i
= 0; i
< n
; i
++) {
1101 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1102 if (level
>= tObj
->_MaxLevel
) {
1103 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1104 texcoord
[i
], rgba
[i
]);
1107 GLchan t0
[4], t1
[4]; /* texels */
1108 const GLfloat f
= FRAC(lambda
[i
]);
1109 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1110 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1111 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1112 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1113 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1114 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1121 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1122 const struct gl_texture_object
*tObj
, GLuint n
,
1123 const GLfloat texcoords
[][4],
1124 const GLfloat lambda
[], GLchan rgba
[][4] )
1127 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1131 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1138 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1139 const struct gl_texture_object
*tObj
, GLuint n
,
1140 const GLfloat texcoords
[][4],
1141 const GLfloat lambda
[], GLchan rgba
[][4] )
1144 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1148 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1154 * Optimized 2-D texture sampling:
1155 * S and T wrap mode == GL_REPEAT
1156 * GL_NEAREST min/mag filter
1158 * RowStride == Width,
1162 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1163 const struct gl_texture_object
*tObj
,
1164 GLuint n
, const GLfloat texcoords
[][4],
1165 const GLfloat lambda
[], GLchan rgba
[][4] )
1167 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1168 const GLfloat width
= (GLfloat
) img
->Width
;
1169 const GLfloat height
= (GLfloat
) img
->Height
;
1170 const GLint colMask
= img
->Width
- 1;
1171 const GLint rowMask
= img
->Height
- 1;
1172 const GLint shift
= img
->WidthLog2
;
1177 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1178 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1179 ASSERT(img
->Border
==0);
1180 ASSERT(img
->Format
==GL_RGB
);
1181 ASSERT(img
->_IsPowerOfTwo
);
1183 for (k
=0; k
<n
; k
++) {
1184 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1185 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1186 GLint pos
= (j
<< shift
) | i
;
1187 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1188 rgba
[k
][RCOMP
] = texel
[0];
1189 rgba
[k
][GCOMP
] = texel
[1];
1190 rgba
[k
][BCOMP
] = texel
[2];
1196 * Optimized 2-D texture sampling:
1197 * S and T wrap mode == GL_REPEAT
1198 * GL_NEAREST min/mag filter
1200 * RowStride == Width,
1204 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1205 const struct gl_texture_object
*tObj
,
1206 GLuint n
, const GLfloat texcoords
[][4],
1207 const GLfloat lambda
[], GLchan rgba
[][4] )
1209 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1210 const GLfloat width
= (GLfloat
) img
->Width
;
1211 const GLfloat height
= (GLfloat
) img
->Height
;
1212 const GLint colMask
= img
->Width
- 1;
1213 const GLint rowMask
= img
->Height
- 1;
1214 const GLint shift
= img
->WidthLog2
;
1219 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1220 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1221 ASSERT(img
->Border
==0);
1222 ASSERT(img
->Format
==GL_RGBA
);
1223 ASSERT(img
->_IsPowerOfTwo
);
1225 for (i
= 0; i
< n
; i
++) {
1226 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1227 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1228 const GLint pos
= (row
<< shift
) | col
;
1229 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1230 COPY_CHAN4(rgba
[i
], texel
);
1236 * Given an array of texture coordinate and lambda (level of detail)
1237 * values, return an array of texture sample.
1240 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1241 const struct gl_texture_object
*tObj
,
1242 GLuint n
, const GLfloat texcoords
[][4],
1243 const GLfloat lambda
[], GLchan rgba
[][4] )
1245 const struct gl_texture_image
*tImg
= tObj
->Image
[0][tObj
->BaseLevel
];
1246 GLuint minStart
, minEnd
; /* texels with minification */
1247 GLuint magStart
, magEnd
; /* texels with magnification */
1249 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1250 && (tObj
->WrapT
== GL_REPEAT
)
1251 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1252 && (tImg
->Format
!= GL_COLOR_INDEX
)
1253 && tImg
->_IsPowerOfTwo
;
1255 ASSERT(lambda
!= NULL
);
1256 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1257 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1259 if (minStart
< minEnd
) {
1260 /* do the minified texels */
1261 const GLuint m
= minEnd
- minStart
;
1262 switch (tObj
->MinFilter
) {
1264 if (repeatNoBorderPOT
) {
1265 switch (tImg
->TexFormat
->MesaFormat
) {
1266 case MESA_FORMAT_RGB
:
1267 case MESA_FORMAT_RGB888
:
1268 /*case MESA_FORMAT_BGR888:*/
1269 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1270 NULL
, rgba
+ minStart
);
1272 case MESA_FORMAT_RGBA
:
1273 case MESA_FORMAT_RGBA8888
:
1274 case MESA_FORMAT_ARGB8888
:
1275 /*case MESA_FORMAT_ABGR8888:*/
1276 /*case MESA_FORMAT_BGRA8888:*/
1277 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1278 NULL
, rgba
+ minStart
);
1281 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1282 NULL
, rgba
+ minStart
);
1286 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1287 NULL
, rgba
+ minStart
);
1291 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1292 NULL
, rgba
+ minStart
);
1294 case GL_NEAREST_MIPMAP_NEAREST
:
1295 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1296 texcoords
+ minStart
,
1297 lambda
+ minStart
, rgba
+ minStart
);
1299 case GL_LINEAR_MIPMAP_NEAREST
:
1300 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1301 lambda
+ minStart
, rgba
+ minStart
);
1303 case GL_NEAREST_MIPMAP_LINEAR
:
1304 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1305 lambda
+ minStart
, rgba
+ minStart
);
1307 case GL_LINEAR_MIPMAP_LINEAR
:
1308 if (repeatNoBorderPOT
)
1309 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1310 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1312 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1313 lambda
+ minStart
, rgba
+ minStart
);
1316 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1321 if (magStart
< magEnd
) {
1322 /* do the magnified texels */
1323 const GLuint m
= magEnd
- magStart
;
1325 switch (tObj
->MagFilter
) {
1327 if (repeatNoBorderPOT
) {
1328 switch (tImg
->TexFormat
->MesaFormat
) {
1329 case MESA_FORMAT_RGB
:
1330 case MESA_FORMAT_RGB888
:
1331 /*case MESA_FORMAT_BGR888:*/
1332 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1333 NULL
, rgba
+ magStart
);
1335 case MESA_FORMAT_RGBA
:
1336 case MESA_FORMAT_RGBA8888
:
1337 case MESA_FORMAT_ARGB8888
:
1338 /*case MESA_FORMAT_ABGR8888:*/
1339 /*case MESA_FORMAT_BGRA8888:*/
1340 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1341 NULL
, rgba
+ magStart
);
1344 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1345 NULL
, rgba
+ magStart
);
1349 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1350 NULL
, rgba
+ magStart
);
1354 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1355 NULL
, rgba
+ magStart
);
1358 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1365 /**********************************************************************/
1366 /* 3-D Texture Sampling Functions */
1367 /**********************************************************************/
1370 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1373 sample_3d_nearest(GLcontext
*ctx
,
1374 const struct gl_texture_object
*tObj
,
1375 const struct gl_texture_image
*img
,
1376 const GLfloat texcoord
[4],
1379 const GLint width
= img
->Width2
; /* without border, power of two */
1380 const GLint height
= img
->Height2
; /* without border, power of two */
1381 const GLint depth
= img
->Depth2
; /* without border, power of two */
1385 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1386 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1387 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1389 if (i
< 0 || i
>= (GLint
) img
->Width
||
1390 j
< 0 || j
>= (GLint
) img
->Height
||
1391 k
< 0 || k
>= (GLint
) img
->Depth
) {
1392 /* Need this test for GL_CLAMP_TO_BORDER mode */
1393 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1396 img
->FetchTexelc(img
, i
, j
, k
, rgba
);
1403 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1406 sample_3d_linear(GLcontext
*ctx
,
1407 const struct gl_texture_object
*tObj
,
1408 const struct gl_texture_image
*img
,
1409 const GLfloat texcoord
[4],
1412 const GLint width
= img
->Width2
;
1413 const GLint height
= img
->Height2
;
1414 const GLint depth
= img
->Depth2
;
1415 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1416 GLuint useBorderColor
;
1420 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1421 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1422 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1434 /* check if sampling texture border color */
1435 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1436 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1437 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1438 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1439 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1440 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1444 const GLfloat a
= FRAC(u
);
1445 const GLfloat b
= FRAC(v
);
1446 const GLfloat c
= FRAC(w
);
1448 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1449 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1450 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1451 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1452 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1453 GLfloat w110
= a
* b
* (1.0F
-c
);
1454 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1455 GLfloat w101
= a
* (1.0F
-b
) * c
;
1456 GLfloat w011
= (1.0F
-a
) * b
* c
;
1457 GLfloat w111
= a
* b
* c
;
1458 #else /* CHAN_BITS == 8 */
1459 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1460 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1461 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1462 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1463 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1464 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1465 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1466 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1467 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1470 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1471 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1473 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1474 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1477 img
->FetchTexelc(img
, i0
, j0
, k0
, t000
);
1479 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1480 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1483 img
->FetchTexelc(img
, i1
, j0
, k0
, t100
);
1485 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1486 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1489 img
->FetchTexelc(img
, i0
, j1
, k0
, t010
);
1491 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1492 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1495 img
->FetchTexelc(img
, i1
, j1
, k0
, t110
);
1498 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1499 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1502 img
->FetchTexelc(img
, i0
, j0
, k1
, t001
);
1504 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1505 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1508 img
->FetchTexelc(img
, i1
, j0
, k1
, t101
);
1510 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1511 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1514 img
->FetchTexelc(img
, i0
, j1
, k1
, t011
);
1516 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1517 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1520 img
->FetchTexelc(img
, i1
, j1
, k1
, t111
);
1523 #if CHAN_TYPE == GL_FLOAT
1524 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1525 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1526 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1527 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1528 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1529 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1530 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1531 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1532 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1533 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1534 w001
*t001
[0] + w011
*t011
[0] +
1535 w100
*t100
[0] + w110
*t110
[0] +
1536 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1537 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1538 w001
*t001
[1] + w011
*t011
[1] +
1539 w100
*t100
[1] + w110
*t110
[1] +
1540 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1541 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1542 w001
*t001
[2] + w011
*t011
[2] +
1543 w100
*t100
[2] + w110
*t110
[2] +
1544 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1545 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1546 w001
*t001
[3] + w011
*t011
[3] +
1547 w100
*t100
[3] + w110
*t110
[3] +
1548 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1549 #else /* CHAN_BITS == 8 */
1550 rgba
[0] = (GLchan
) (
1551 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1552 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1554 rgba
[1] = (GLchan
) (
1555 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1556 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1558 rgba
[2] = (GLchan
) (
1559 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1560 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1562 rgba
[3] = (GLchan
) (
1563 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1564 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1574 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1575 const struct gl_texture_object
*tObj
,
1576 GLuint n
, const GLfloat texcoord
[][4],
1577 const GLfloat lambda
[], GLchan rgba
[][4] )
1580 for (i
= 0; i
< n
; i
++) {
1582 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1583 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1589 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1590 const struct gl_texture_object
*tObj
,
1591 GLuint n
, const GLfloat texcoord
[][4],
1592 const GLfloat lambda
[], GLchan rgba
[][4])
1595 ASSERT(lambda
!= NULL
);
1596 for (i
= 0; i
< n
; i
++) {
1598 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1599 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1605 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1606 const struct gl_texture_object
*tObj
,
1607 GLuint n
, const GLfloat texcoord
[][4],
1608 const GLfloat lambda
[], GLchan rgba
[][4])
1611 ASSERT(lambda
!= NULL
);
1612 for (i
= 0; i
< n
; i
++) {
1614 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1615 if (level
>= tObj
->_MaxLevel
) {
1616 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1617 texcoord
[i
], rgba
[i
]);
1620 GLchan t0
[4], t1
[4]; /* texels */
1621 const GLfloat f
= FRAC(lambda
[i
]);
1622 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1623 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1624 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1625 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1626 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1627 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1634 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1635 const struct gl_texture_object
*tObj
,
1636 GLuint n
, const GLfloat texcoord
[][4],
1637 const GLfloat lambda
[], GLchan rgba
[][4])
1640 ASSERT(lambda
!= NULL
);
1641 for (i
= 0; i
< n
; i
++) {
1643 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1644 if (level
>= tObj
->_MaxLevel
) {
1645 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1646 texcoord
[i
], rgba
[i
]);
1649 GLchan t0
[4], t1
[4]; /* texels */
1650 const GLfloat f
= FRAC(lambda
[i
]);
1651 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1652 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1653 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1654 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1655 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1656 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1663 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1664 const struct gl_texture_object
*tObj
, GLuint n
,
1665 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1669 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1673 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1680 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1681 const struct gl_texture_object
*tObj
, GLuint n
,
1682 const GLfloat texcoords
[][4],
1683 const GLfloat lambda
[], GLchan rgba
[][4] )
1686 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1690 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1696 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1697 * return a texture sample.
1700 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1701 const struct gl_texture_object
*tObj
, GLuint n
,
1702 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1705 GLuint minStart
, minEnd
; /* texels with minification */
1706 GLuint magStart
, magEnd
; /* texels with magnification */
1709 ASSERT(lambda
!= NULL
);
1710 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1711 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1713 if (minStart
< minEnd
) {
1714 /* do the minified texels */
1715 GLuint m
= minEnd
- minStart
;
1716 switch (tObj
->MinFilter
) {
1718 for (i
= minStart
; i
< minEnd
; i
++)
1719 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1720 texcoords
[i
], rgba
[i
]);
1723 for (i
= minStart
; i
< minEnd
; i
++)
1724 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1725 texcoords
[i
], rgba
[i
]);
1727 case GL_NEAREST_MIPMAP_NEAREST
:
1728 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1729 lambda
+ minStart
, rgba
+ minStart
);
1731 case GL_LINEAR_MIPMAP_NEAREST
:
1732 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1733 lambda
+ minStart
, rgba
+ minStart
);
1735 case GL_NEAREST_MIPMAP_LINEAR
:
1736 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1737 lambda
+ minStart
, rgba
+ minStart
);
1739 case GL_LINEAR_MIPMAP_LINEAR
:
1740 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1741 lambda
+ minStart
, rgba
+ minStart
);
1744 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1749 if (magStart
< magEnd
) {
1750 /* do the magnified texels */
1751 switch (tObj
->MagFilter
) {
1753 for (i
= magStart
; i
< magEnd
; i
++)
1754 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1755 texcoords
[i
], rgba
[i
]);
1758 for (i
= magStart
; i
< magEnd
; i
++)
1759 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1760 texcoords
[i
], rgba
[i
]);
1763 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1770 /**********************************************************************/
1771 /* Texture Cube Map Sampling Functions */
1772 /**********************************************************************/
1775 * Choose one of six sides of a texture cube map given the texture
1776 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1779 static const struct gl_texture_image
**
1780 choose_cube_face(const struct gl_texture_object
*texObj
,
1781 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1785 direction target sc tc ma
1786 ---------- ------------------------------- --- --- ---
1787 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1788 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1789 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1790 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1791 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1792 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1794 const GLfloat rx
= texcoord
[0];
1795 const GLfloat ry
= texcoord
[1];
1796 const GLfloat rz
= texcoord
[2];
1797 const struct gl_texture_image
**imgArray
;
1798 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
1801 if (arx
> ary
&& arx
> arz
) {
1803 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_X
];
1809 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_X
];
1815 else if (ary
> arx
&& ary
> arz
) {
1817 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Y
];
1823 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Y
];
1831 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Z
];
1837 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Z
];
1844 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1845 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1851 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1852 const struct gl_texture_object
*tObj
, GLuint n
,
1853 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1859 for (i
= 0; i
< n
; i
++) {
1860 const struct gl_texture_image
**images
;
1861 GLfloat newCoord
[4];
1862 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1863 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1870 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1871 const struct gl_texture_object
*tObj
, GLuint n
,
1872 const GLfloat texcoords
[][4],
1873 const GLfloat lambda
[], GLchan rgba
[][4])
1878 for (i
= 0; i
< n
; i
++) {
1879 const struct gl_texture_image
**images
;
1880 GLfloat newCoord
[4];
1881 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1882 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1889 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
1890 const struct gl_texture_object
*tObj
,
1891 GLuint n
, const GLfloat texcoord
[][4],
1892 const GLfloat lambda
[], GLchan rgba
[][4])
1896 ASSERT(lambda
!= NULL
);
1897 for (i
= 0; i
< n
; i
++) {
1898 const struct gl_texture_image
**images
;
1899 GLfloat newCoord
[4];
1901 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1902 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1903 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1909 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
1910 const struct gl_texture_object
*tObj
,
1911 GLuint n
, const GLfloat texcoord
[][4],
1912 const GLfloat lambda
[], GLchan rgba
[][4])
1916 ASSERT(lambda
!= NULL
);
1917 for (i
= 0; i
< n
; i
++) {
1918 const struct gl_texture_image
**images
;
1919 GLfloat newCoord
[4];
1921 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1922 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1923 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1929 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
1930 const struct gl_texture_object
*tObj
,
1931 GLuint n
, const GLfloat texcoord
[][4],
1932 const GLfloat lambda
[], GLchan rgba
[][4])
1936 ASSERT(lambda
!= NULL
);
1937 for (i
= 0; i
< n
; i
++) {
1938 const struct gl_texture_image
**images
;
1939 GLfloat newCoord
[4];
1941 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1942 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1943 if (level
>= tObj
->_MaxLevel
) {
1944 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1948 GLchan t0
[4], t1
[4]; /* texels */
1949 const GLfloat f
= FRAC(lambda
[i
]);
1950 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1951 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1952 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1953 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1954 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1955 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1962 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
1963 const struct gl_texture_object
*tObj
,
1964 GLuint n
, const GLfloat texcoord
[][4],
1965 const GLfloat lambda
[], GLchan rgba
[][4])
1969 ASSERT(lambda
!= NULL
);
1970 for (i
= 0; i
< n
; i
++) {
1971 const struct gl_texture_image
**images
;
1972 GLfloat newCoord
[4];
1974 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1975 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1976 if (level
>= tObj
->_MaxLevel
) {
1977 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1981 GLchan t0
[4], t1
[4];
1982 const GLfloat f
= FRAC(lambda
[i
]);
1983 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
1984 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1985 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1986 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1987 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1988 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1995 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1996 const struct gl_texture_object
*tObj
, GLuint n
,
1997 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2000 GLuint minStart
, minEnd
; /* texels with minification */
2001 GLuint magStart
, magEnd
; /* texels with magnification */
2003 ASSERT(lambda
!= NULL
);
2004 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2005 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2007 if (minStart
< minEnd
) {
2008 /* do the minified texels */
2009 const GLuint m
= minEnd
- minStart
;
2010 switch (tObj
->MinFilter
) {
2012 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2013 lambda
+ minStart
, rgba
+ minStart
);
2016 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2017 lambda
+ minStart
, rgba
+ minStart
);
2019 case GL_NEAREST_MIPMAP_NEAREST
:
2020 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2021 texcoords
+ minStart
,
2022 lambda
+ minStart
, rgba
+ minStart
);
2024 case GL_LINEAR_MIPMAP_NEAREST
:
2025 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2026 texcoords
+ minStart
,
2027 lambda
+ minStart
, rgba
+ minStart
);
2029 case GL_NEAREST_MIPMAP_LINEAR
:
2030 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2031 texcoords
+ minStart
,
2032 lambda
+ minStart
, rgba
+ minStart
);
2034 case GL_LINEAR_MIPMAP_LINEAR
:
2035 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2036 texcoords
+ minStart
,
2037 lambda
+ minStart
, rgba
+ minStart
);
2040 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2044 if (magStart
< magEnd
) {
2045 /* do the magnified texels */
2046 const GLuint m
= magEnd
- magStart
;
2047 switch (tObj
->MagFilter
) {
2049 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2050 lambda
+ magStart
, rgba
+ magStart
);
2053 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2054 lambda
+ magStart
, rgba
+ magStart
);
2057 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2063 /**********************************************************************/
2064 /* Texture Rectangle Sampling Functions */
2065 /**********************************************************************/
2068 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2069 const struct gl_texture_object
*tObj
, GLuint n
,
2070 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2073 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2074 const GLfloat width
= (GLfloat
) img
->Width
;
2075 const GLfloat height
= (GLfloat
) img
->Height
;
2076 const GLint width_minus_1
= img
->Width
- 1;
2077 const GLint height_minus_1
= img
->Height
- 1;
2084 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2085 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2086 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2087 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2088 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2089 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2090 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2092 /* XXX move Wrap mode tests outside of loops for common cases */
2093 for (i
= 0; i
< n
; i
++) {
2095 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2096 if (tObj
->WrapS
== GL_CLAMP
) {
2097 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
- 1) );
2099 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2100 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2103 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2105 if (tObj
->WrapT
== GL_CLAMP
) {
2106 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
- 1) );
2108 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2109 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2112 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2115 if (col
< 0 || col
> width_minus_1
|| row
< 0 || row
> height_minus_1
)
2116 COPY_CHAN4(rgba
[i
], tObj
->_BorderChan
);
2118 img
->FetchTexelc(img
, col
, row
, 0, rgba
[i
]);
2124 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2125 const struct gl_texture_object
*tObj
, GLuint n
,
2126 const GLfloat texcoords
[][4],
2127 const GLfloat lambda
[], GLchan rgba
[][4])
2129 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2130 const GLfloat width
= (GLfloat
) img
->Width
;
2131 const GLfloat height
= (GLfloat
) img
->Height
;
2132 const GLint width_minus_1
= img
->Width
- 1;
2133 const GLint height_minus_1
= img
->Height
- 1;
2140 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2141 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2142 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2143 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2144 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2145 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2146 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2148 /* XXX lots of opportunity for optimization in this loop */
2149 for (i
= 0; i
< n
; i
++) {
2151 GLint i0
, j0
, i1
, j1
;
2152 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2153 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2154 GLuint useBorderColor
= 0;
2156 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2157 if (tObj
->WrapS
== GL_CLAMP
) {
2158 /* Not exactly what the spec says, but it matches NVIDIA output */
2159 fcol
= CLAMP(texcoords
[i
][0] - 0.5F
, 0.0, width_minus_1
);
2163 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2164 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2168 if (i1
> width_minus_1
)
2172 ASSERT(tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2173 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2179 if (tObj
->WrapT
== GL_CLAMP
) {
2180 /* Not exactly what the spec says, but it matches NVIDIA output */
2181 frow
= CLAMP(texcoords
[i
][1] - 0.5F
, 0.0, width_minus_1
);
2185 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2186 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2190 if (j1
> height_minus_1
)
2191 j1
= height_minus_1
;
2194 ASSERT(tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2195 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2201 /* compute integer rows/columns */
2202 if (i0
< 0 || i0
> width_minus_1
) useBorderColor
|= I0BIT
;
2203 if (i1
< 0 || i1
> width_minus_1
) useBorderColor
|= I1BIT
;
2204 if (j0
< 0 || j0
> height_minus_1
) useBorderColor
|= J0BIT
;
2205 if (j1
< 0 || j1
> height_minus_1
) useBorderColor
|= J1BIT
;
2207 /* get four texel samples */
2208 if (useBorderColor
& (I0BIT
| J0BIT
))
2209 COPY_CHAN4(t00
, tObj
->_BorderChan
);
2211 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
2213 if (useBorderColor
& (I1BIT
| J0BIT
))
2214 COPY_CHAN4(t10
, tObj
->_BorderChan
);
2216 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
2218 if (useBorderColor
& (I0BIT
| J1BIT
))
2219 COPY_CHAN4(t01
, tObj
->_BorderChan
);
2221 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
2223 if (useBorderColor
& (I1BIT
| J1BIT
))
2224 COPY_CHAN4(t11
, tObj
->_BorderChan
);
2226 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
2228 /* compute sample weights */
2231 w00
= (1.0F
-a
) * (1.0F
-b
);
2233 w01
= (1.0F
-a
) * b
;
2236 /* compute weighted average of samples */
2238 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2240 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2242 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2244 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2250 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2251 const struct gl_texture_object
*tObj
, GLuint n
,
2252 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2255 GLuint minStart
, minEnd
, magStart
, magEnd
;
2257 /* We only need lambda to decide between minification and magnification.
2258 * There is no mipmapping with rectangular textures.
2260 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2261 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2263 if (minStart
< minEnd
) {
2264 if (tObj
->MinFilter
== GL_NEAREST
) {
2265 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2266 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2269 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2270 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2273 if (magStart
< magEnd
) {
2274 if (tObj
->MagFilter
== GL_NEAREST
) {
2275 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2276 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2279 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2280 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2288 * Sample a shadow/depth texture.
2291 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2292 const struct gl_texture_object
*tObj
, GLuint n
,
2293 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2296 const GLint baseLevel
= tObj
->BaseLevel
;
2297 const struct gl_texture_image
*texImage
= tObj
->Image
[0][baseLevel
];
2298 const GLuint width
= texImage
->Width
;
2299 const GLuint height
= texImage
->Height
;
2307 ASSERT(tObj
->Image
[0][tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2308 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2309 tObj
->Target
== GL_TEXTURE_2D
||
2310 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2312 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2314 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2316 /* XXX this could be precomputed and saved in the texture object */
2317 if (tObj
->CompareFlag
) {
2318 /* GL_SGIX_shadow */
2319 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2320 function
= GL_LEQUAL
;
2323 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2324 function
= GL_GEQUAL
;
2327 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2329 function
= tObj
->CompareFunc
;
2332 function
= GL_NONE
; /* pass depth through as grayscale */
2335 if (tObj
->MagFilter
== GL_NEAREST
) {
2337 for (i
= 0; i
< n
; i
++) {
2338 GLfloat depthSample
;
2340 /* XXX fix for texture rectangle! */
2341 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2342 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2343 texImage
->FetchTexelf(texImage
, col
, row
, 0, &depthSample
);
2347 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2350 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2353 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2356 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2359 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2362 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2371 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2374 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2378 switch (tObj
->DepthMode
) {
2380 texel
[i
][RCOMP
] = result
;
2381 texel
[i
][GCOMP
] = result
;
2382 texel
[i
][BCOMP
] = result
;
2383 texel
[i
][ACOMP
] = CHAN_MAX
;
2386 texel
[i
][RCOMP
] = result
;
2387 texel
[i
][GCOMP
] = result
;
2388 texel
[i
][BCOMP
] = result
;
2389 texel
[i
][ACOMP
] = result
;
2392 texel
[i
][RCOMP
] = 0;
2393 texel
[i
][GCOMP
] = 0;
2394 texel
[i
][BCOMP
] = 0;
2395 texel
[i
][ACOMP
] = result
;
2398 _mesa_problem(ctx
, "Bad depth texture mode");
2404 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2405 for (i
= 0; i
< n
; i
++) {
2406 GLfloat depth00
, depth01
, depth10
, depth11
;
2407 GLint i0
, i1
, j0
, j1
;
2409 GLuint useBorderTexel
;
2411 /* XXX fix for texture rectangle! */
2412 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2413 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2416 if (texImage
->Border
) {
2417 i0
+= texImage
->Border
;
2418 i1
+= texImage
->Border
;
2419 j0
+= texImage
->Border
;
2420 j1
+= texImage
->Border
;
2423 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2424 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2425 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2426 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2429 /* get four depth samples from the texture */
2430 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2434 texImage
->FetchTexelf(texImage
, i0
, j0
, 0, &depth00
);
2436 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2440 texImage
->FetchTexelf(texImage
, i1
, j0
, 0, &depth10
);
2442 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2446 texImage
->FetchTexelf(texImage
, i0
, j1
, 0, &depth01
);
2448 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2452 texImage
->FetchTexelf(texImage
, i1
, j1
, 0, &depth11
);
2456 /* compute a single weighted depth sample and do one comparison */
2457 const GLfloat a
= FRAC(u
+ 1.0F
);
2458 const GLfloat b
= FRAC(v
+ 1.0F
);
2459 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2460 const GLfloat w10
= ( a
) * (1.0F
- b
);
2461 const GLfloat w01
= (1.0F
- a
) * ( b
);
2462 const GLfloat w11
= ( a
) * ( b
);
2463 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2464 + w01
* depth01
+ w11
* depth11
;
2465 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2466 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2474 /* Do four depth/R comparisons and compute a weighted result.
2475 * If this touches on somebody's I.P., I'll remove this code
2478 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2479 GLfloat luminance
= CHAN_MAXF
;
2483 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2484 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2485 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2486 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2487 result
= (GLchan
) luminance
;
2490 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2491 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2492 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2493 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2494 result
= (GLchan
) luminance
;
2497 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2498 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2499 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2500 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2501 result
= (GLchan
) luminance
;
2504 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2505 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2506 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2507 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2508 result
= (GLchan
) luminance
;
2511 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2512 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2513 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2514 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2515 result
= (GLchan
) luminance
;
2518 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2519 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2520 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2521 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2522 result
= (GLchan
) luminance
;
2531 /* ordinary bilinear filtering */
2533 const GLfloat a
= FRAC(u
+ 1.0F
);
2534 const GLfloat b
= FRAC(v
+ 1.0F
);
2535 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2536 const GLfloat w10
= ( a
) * (1.0F
- b
);
2537 const GLfloat w01
= (1.0F
- a
) * ( b
);
2538 const GLfloat w11
= ( a
) * ( b
);
2539 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2540 + w01
* depth01
+ w11
* depth11
;
2541 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2545 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2550 switch (tObj
->DepthMode
) {
2552 texel
[i
][RCOMP
] = result
;
2553 texel
[i
][GCOMP
] = result
;
2554 texel
[i
][BCOMP
] = result
;
2555 texel
[i
][ACOMP
] = CHAN_MAX
;
2558 texel
[i
][RCOMP
] = result
;
2559 texel
[i
][GCOMP
] = result
;
2560 texel
[i
][BCOMP
] = result
;
2561 texel
[i
][ACOMP
] = result
;
2564 texel
[i
][RCOMP
] = 0;
2565 texel
[i
][GCOMP
] = 0;
2566 texel
[i
][BCOMP
] = 0;
2567 texel
[i
][ACOMP
] = result
;
2570 _mesa_problem(ctx
, "Bad depth texture mode");
2579 * Experimental depth texture sampling function.
2582 sample_depth_texture2(const GLcontext
*ctx
,
2583 const struct gl_texture_unit
*texUnit
,
2584 GLuint n
, const GLfloat texcoords
[][4],
2587 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2588 const GLint baseLevel
= texObj
->BaseLevel
;
2589 const struct gl_texture_image
*texImage
= texObj
->Image
[0][baseLevel
];
2590 const GLuint width
= texImage
->Width
;
2591 const GLuint height
= texImage
->Height
;
2593 GLboolean lequal
, gequal
;
2595 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2596 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2600 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2601 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2605 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2606 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2607 * isn't a depth texture.
2609 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2610 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2614 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2616 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2627 for (i
= 0; i
< n
; i
++) {
2629 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2632 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2634 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2642 if (imin
< 0) imin
= 0;
2643 if (imax
>= width
) imax
= width
- 1;
2644 if (jmin
< 0) jmin
= 0;
2645 if (jmax
>= height
) jmax
= height
- 1;
2647 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2649 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2650 for (ii
= imin
; ii
<= imax
; ii
++) {
2651 GLfloat depthSample
;
2652 texImage
->FetchTexelf(texImage
, ii
, jj
, 0, &depthSample
);
2653 if ((depthSample
<= r
[i
] && lequal
) ||
2654 (depthSample
>= r
[i
] && gequal
)) {
2660 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2661 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2664 texel
[i
][RCOMP
] = lum
;
2665 texel
[i
][GCOMP
] = lum
;
2666 texel
[i
][BCOMP
] = lum
;
2667 texel
[i
][ACOMP
] = CHAN_MAX
;
2675 * We use this function when a texture object is in an "incomplete" state.
2676 * When a fragment program attempts to sample an incomplete texture we
2677 * return black (see issue 23 in GL_ARB_fragment_program spec).
2678 * Note: fragment programss don't observe the texture enable/disable flags.
2681 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2682 const struct gl_texture_object
*tObj
, GLuint n
,
2683 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2692 for (i
= 0; i
< n
; i
++) {
2696 rgba
[i
][ACOMP
] = CHAN_MAX
;
2702 * Setup the texture sampling function for this texture object.
2705 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
2706 const struct gl_texture_object
*t
)
2708 if (!t
|| !t
->Complete
) {
2709 return &null_sample_func
;
2712 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2713 const GLenum format
= t
->Image
[0][t
->BaseLevel
]->Format
;
2715 switch (t
->Target
) {
2717 if (format
== GL_DEPTH_COMPONENT
) {
2718 return &sample_depth_texture
;
2720 else if (needLambda
) {
2721 return &sample_lambda_1d
;
2723 else if (t
->MinFilter
== GL_LINEAR
) {
2724 return &sample_linear_1d
;
2727 ASSERT(t
->MinFilter
== GL_NEAREST
);
2728 return &sample_nearest_1d
;
2732 if (format
== GL_DEPTH_COMPONENT
) {
2733 return &sample_depth_texture
;
2735 else if (needLambda
) {
2736 return &sample_lambda_2d
;
2738 else if (t
->MinFilter
== GL_LINEAR
) {
2739 return &sample_linear_2d
;
2742 GLint baseLevel
= t
->BaseLevel
;
2743 ASSERT(t
->MinFilter
== GL_NEAREST
);
2744 if (t
->WrapS
== GL_REPEAT
&&
2745 t
->WrapT
== GL_REPEAT
&&
2747 t
->Image
[0][baseLevel
]->Border
== 0 &&
2748 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2749 return &opt_sample_rgb_2d
;
2751 else if (t
->WrapS
== GL_REPEAT
&&
2752 t
->WrapT
== GL_REPEAT
&&
2754 t
->Image
[0][baseLevel
]->Border
== 0 &&
2755 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2756 return &opt_sample_rgba_2d
;
2759 return &sample_nearest_2d
;
2765 return &sample_lambda_3d
;
2767 else if (t
->MinFilter
== GL_LINEAR
) {
2768 return &sample_linear_3d
;
2771 ASSERT(t
->MinFilter
== GL_NEAREST
);
2772 return &sample_nearest_3d
;
2775 case GL_TEXTURE_CUBE_MAP
:
2777 return &sample_lambda_cube
;
2779 else if (t
->MinFilter
== GL_LINEAR
) {
2780 return &sample_linear_cube
;
2783 ASSERT(t
->MinFilter
== GL_NEAREST
);
2784 return &sample_nearest_cube
;
2787 case GL_TEXTURE_RECTANGLE_NV
:
2789 return &sample_lambda_rect
;
2791 else if (t
->MinFilter
== GL_LINEAR
) {
2792 return &sample_linear_rect
;
2795 ASSERT(t
->MinFilter
== GL_NEAREST
);
2796 return &sample_nearest_rect
;
2801 "invalid target in _swrast_choose_texture_sample_func");
2802 return &null_sample_func
;
2808 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2809 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2813 * Do texture application for GL_ARB/EXT_texture_env_combine.
2814 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
2815 * GL_ATI_texture_env_combine3. Since "classic" texture environments are
2816 * implemented using GL_ARB_texture_env_combine-like state, this same function
2817 * is used for classic texture environment application as well.
2819 * \param ctx rendering context
2820 * \param textureUnit the texture unit to apply
2821 * \param n number of fragments to process (span width)
2822 * \param primary_rgba incoming fragment color array
2823 * \param texelBuffer pointer to texel colors for all texture units
2825 * \param rgba incoming colors, which get modified here
2828 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
2829 CONST
GLchan (*primary_rgba
)[4],
2830 CONST GLchan
*texelBuffer
,
2833 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
2834 const GLchan (*argRGB
[3])[4];
2835 const GLchan (*argA
[3])[4];
2836 const GLuint RGBshift
= textureUnit
->_CurrentCombine
->ScaleShiftRGB
;
2837 const GLuint Ashift
= textureUnit
->_CurrentCombine
->ScaleShiftA
;
2838 #if CHAN_TYPE == GL_FLOAT
2839 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2840 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2841 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
2842 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
2844 const GLint half
= (CHAN_MAX
+ 1) / 2;
2845 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
2846 static const GLchan zero
[4] = { 0, 0, 0, 0 };
2849 GLuint numColorArgs
;
2850 GLuint numAlphaArgs
;
2852 /* GLchan ccolor[3][4]; */
2853 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2854 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2856 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2857 ctx
->Extensions
.ARB_texture_env_combine
);
2858 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
2862 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
2863 textureUnit->_CurrentCombine->ModeRGB,
2864 textureUnit->_CurrentCombine->ModeA,
2865 textureUnit->_CurrentCombine->SourceRGB[0],
2866 textureUnit->_CurrentCombine->SourceA[0],
2867 textureUnit->_CurrentCombine->SourceRGB[1],
2868 textureUnit->_CurrentCombine->SourceA[1]);
2872 * Do operand setup for up to 3 operands. Loop over the terms.
2874 numColorArgs
= textureUnit
->_CurrentCombine
->_NumArgsRGB
;
2875 numAlphaArgs
= textureUnit
->_CurrentCombine
->_NumArgsA
;
2877 for (j
= 0; j
< numColorArgs
; j
++) {
2878 const GLenum srcRGB
= textureUnit
->_CurrentCombine
->SourceRGB
[j
];
2883 argRGB
[j
] = (const GLchan (*)[4])
2884 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2886 case GL_PRIMARY_COLOR
:
2887 argRGB
[j
] = primary_rgba
;
2890 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2894 GLchan (*c
)[4] = ccolor
[j
];
2895 GLchan red
, green
, blue
, alpha
;
2896 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2897 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2898 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2899 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2900 for (i
= 0; i
< n
; i
++) {
2902 c
[i
][GCOMP
] = green
;
2904 c
[i
][ACOMP
] = alpha
;
2906 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2909 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
2918 /* ARB_texture_env_crossbar source */
2920 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
2921 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2922 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2924 argRGB
[j
] = (const GLchan (*)[4])
2925 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2929 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] != GL_SRC_COLOR
) {
2930 const GLchan (*src
)[4] = argRGB
[j
];
2931 GLchan (*dst
)[4] = ccolor
[j
];
2933 /* point to new arg[j] storage */
2934 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2936 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2937 for (i
= 0; i
< n
; i
++) {
2938 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2939 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2940 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2943 else if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_SRC_ALPHA
) {
2944 for (i
= 0; i
< n
; i
++) {
2945 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2946 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2947 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2951 ASSERT(textureUnit
->_CurrentCombine
->OperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2952 for (i
= 0; i
< n
; i
++) {
2953 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2954 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2955 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2962 for (j
= 0; j
< numAlphaArgs
; j
++) {
2963 const GLenum srcA
= textureUnit
->_CurrentCombine
->SourceA
[j
];
2967 argA
[j
] = (const GLchan (*)[4])
2968 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2970 case GL_PRIMARY_COLOR
:
2971 argA
[j
] = primary_rgba
;
2974 argA
[j
] = (const GLchan (*)[4]) rgba
;
2978 GLchan alpha
, (*c
)[4] = ccolor
[j
];
2979 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2980 for (i
= 0; i
< n
; i
++)
2981 c
[i
][ACOMP
] = alpha
;
2982 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2985 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
2994 /* ARB_texture_env_crossbar source */
2996 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
2997 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2998 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3000 argA
[j
] = (const GLchan (*)[4])
3001 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3005 if (textureUnit
->_CurrentCombine
->OperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3006 const GLchan (*src
)[4] = argA
[j
];
3007 GLchan (*dst
)[4] = ccolor
[j
];
3008 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3009 for (i
= 0; i
< n
; i
++) {
3010 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3016 * Do the texture combine.
3018 switch (textureUnit
->_CurrentCombine
->ModeRGB
) {
3021 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3023 for (i
= 0; i
< n
; i
++) {
3024 #if CHAN_TYPE == GL_FLOAT
3025 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3026 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3027 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3029 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3030 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3031 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3032 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3033 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3034 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3039 for (i
= 0; i
< n
; i
++) {
3040 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3041 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3042 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3049 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3050 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3051 #if CHAN_TYPE != GL_FLOAT
3052 const GLint shift
= CHAN_BITS
- RGBshift
;
3054 for (i
= 0; i
< n
; i
++) {
3055 #if CHAN_TYPE == GL_FLOAT
3056 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3057 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3058 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3060 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3061 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3062 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3063 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3064 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3065 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3072 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3073 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3074 for (i
= 0; i
< n
; i
++) {
3075 #if CHAN_TYPE == GL_FLOAT
3076 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3077 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3078 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3080 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3081 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3082 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3083 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3084 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3085 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3092 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3093 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3094 for (i
= 0; i
< n
; i
++) {
3095 #if CHAN_TYPE == GL_FLOAT
3096 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3097 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3098 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3100 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3101 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3102 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3103 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3104 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3105 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3106 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3107 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3108 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3113 case GL_INTERPOLATE
:
3115 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3116 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3117 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3118 #if CHAN_TYPE != GL_FLOAT
3119 const GLint shift
= CHAN_BITS
- RGBshift
;
3121 for (i
= 0; i
< n
; i
++) {
3122 #if CHAN_TYPE == GL_FLOAT
3123 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3124 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3125 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3126 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3127 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3128 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3130 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3131 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3133 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3134 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3136 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3137 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3139 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3140 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3141 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3148 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3149 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3150 for (i
= 0; i
< n
; i
++) {
3151 #if CHAN_TYPE == GL_FLOAT
3152 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3153 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3154 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3156 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3157 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3158 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3159 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3160 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3161 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3166 case GL_DOT3_RGB_EXT
:
3167 case GL_DOT3_RGBA_EXT
:
3169 /* Do not scale the result by 1 2 or 4 */
3170 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3171 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3172 for (i
= 0; i
< n
; i
++) {
3173 #if CHAN_TYPE == GL_FLOAT
3174 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3175 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3176 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3178 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3180 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3181 (GLint
)arg1
[i
][RCOMP
] - half
) +
3182 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3183 (GLint
)arg1
[i
][GCOMP
] - half
) +
3184 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3185 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3186 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3188 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3195 /* DO scale the result by 1 2 or 4 */
3196 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3197 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3198 for (i
= 0; i
< n
; i
++) {
3199 #if CHAN_TYPE == GL_FLOAT
3200 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3201 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3202 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3204 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3206 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3207 (GLint
)arg1
[i
][RCOMP
] - half
) +
3208 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3209 (GLint
)arg1
[i
][GCOMP
] - half
) +
3210 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3211 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3213 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3215 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3219 case GL_MODULATE_ADD_ATI
:
3221 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3222 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3223 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3224 #if CHAN_TYPE != GL_FLOAT
3225 const GLint shift
= CHAN_BITS
- RGBshift
;
3227 for (i
= 0; i
< n
; i
++) {
3228 #if CHAN_TYPE == GL_FLOAT
3229 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3230 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3231 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3233 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3234 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3235 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3236 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3237 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3238 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3239 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3240 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3241 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3246 case GL_MODULATE_SIGNED_ADD_ATI
:
3248 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3249 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3250 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3251 #if CHAN_TYPE != GL_FLOAT
3252 const GLint shift
= CHAN_BITS
- RGBshift
;
3254 for (i
= 0; i
< n
; i
++) {
3255 #if CHAN_TYPE == GL_FLOAT
3256 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3257 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3258 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3260 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3261 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3263 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3264 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3266 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3267 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3269 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3270 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3271 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3276 case GL_MODULATE_SUBTRACT_ATI
:
3278 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3279 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3280 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3281 #if CHAN_TYPE != GL_FLOAT
3282 const GLint shift
= CHAN_BITS
- RGBshift
;
3284 for (i
= 0; i
< n
; i
++) {
3285 #if CHAN_TYPE == GL_FLOAT
3286 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3287 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3288 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3290 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3291 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3293 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3294 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3296 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3297 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3299 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3300 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3301 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3307 _mesa_problem(ctx
, "invalid combine mode");
3310 switch (textureUnit
->_CurrentCombine
->ModeA
) {
3313 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3315 for (i
= 0; i
< n
; i
++) {
3316 #if CHAN_TYPE == GL_FLOAT
3317 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3319 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3321 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3325 for (i
= 0; i
< n
; i
++) {
3326 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3333 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3334 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3335 #if CHAN_TYPE != GL_FLOAT
3336 const GLint shift
= CHAN_BITS
- Ashift
;
3338 for (i
= 0; i
< n
; i
++) {
3339 #if CHAN_TYPE == GL_FLOAT
3340 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3342 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3343 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3350 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3351 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3352 for (i
= 0; i
< n
; i
++) {
3353 #if CHAN_TYPE == GL_FLOAT
3354 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3356 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3357 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3364 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3365 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3366 for (i
= 0; i
< n
; i
++) {
3367 #if CHAN_TYPE == GL_FLOAT
3368 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3370 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3371 a
= (a
< 0) ? 0 : a
<< Ashift
;
3372 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3377 case GL_INTERPOLATE
:
3379 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3380 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3381 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3382 #if CHAN_TYPE != GL_FLOAT
3383 const GLint shift
= CHAN_BITS
- Ashift
;
3385 for (i
=0; i
<n
; i
++) {
3386 #if CHAN_TYPE == GL_FLOAT
3387 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3388 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3391 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3392 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3394 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3401 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3402 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3403 for (i
= 0; i
< n
; i
++) {
3404 #if CHAN_TYPE == GL_FLOAT
3405 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3407 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3408 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3413 case GL_MODULATE_ADD_ATI
:
3415 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3416 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3417 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3418 #if CHAN_TYPE != GL_FLOAT
3419 const GLint shift
= CHAN_BITS
- Ashift
;
3421 for (i
= 0; i
< n
; i
++) {
3422 #if CHAN_TYPE == GL_FLOAT
3423 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3425 GLint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3426 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3428 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3433 case GL_MODULATE_SIGNED_ADD_ATI
:
3435 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3436 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3437 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3438 #if CHAN_TYPE != GL_FLOAT
3439 const GLint shift
= CHAN_BITS
- Ashift
;
3441 for (i
= 0; i
< n
; i
++) {
3442 #if CHAN_TYPE == GL_FLOAT
3443 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3445 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3446 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3448 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3453 case GL_MODULATE_SUBTRACT_ATI
:
3455 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3456 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3457 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3458 #if CHAN_TYPE != GL_FLOAT
3459 const GLint shift
= CHAN_BITS
- Ashift
;
3461 for (i
= 0; i
< n
; i
++) {
3462 #if CHAN_TYPE == GL_FLOAT
3463 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3465 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3466 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3468 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3474 _mesa_problem(ctx
, "invalid combine mode");
3477 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3478 * This is kind of a kludge. It would have been better if the spec
3479 * were written such that the GL_COMBINE_ALPHA value could be set to
3482 if (textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
3483 textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) {
3484 for (i
= 0; i
< n
; i
++) {
3485 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3488 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3494 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3495 * MODULATE, or DECAL) to an array of fragments.
3496 * Input: textureUnit - pointer to texture unit to apply
3497 * format - base internal texture format
3498 * n - number of fragments
3499 * primary_rgba - primary colors (may alias rgba for single texture)
3500 * texels - array of texel colors
3501 * InOut: rgba - incoming fragment colors modified by texel colors
3502 * according to the texture environment mode.
3505 texture_apply( const GLcontext
*ctx
,
3506 const struct gl_texture_unit
*texUnit
,
3508 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3513 GLint Rc
, Gc
, Bc
, Ac
;
3515 (void) primary_rgba
;
3518 ASSERT(texUnit
->_Current
);
3520 baseLevel
= texUnit
->_Current
->BaseLevel
;
3521 ASSERT(texUnit
->_Current
->Image
[0][baseLevel
]);
3523 format
= texUnit
->_Current
->Image
[0][baseLevel
]->Format
;
3525 if (format
== GL_COLOR_INDEX
|| format
== GL_YCBCR_MESA
) {
3526 format
= GL_RGBA
; /* a bit of a hack */
3528 else if (format
== GL_DEPTH_COMPONENT
) {
3529 format
= texUnit
->_Current
->DepthMode
;
3532 switch (texUnit
->EnvMode
) {
3539 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3545 GLchan Lt
= texel
[i
][RCOMP
];
3546 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3550 case GL_LUMINANCE_ALPHA
:
3552 GLchan Lt
= texel
[i
][RCOMP
];
3554 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3556 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3562 GLchan It
= texel
[i
][RCOMP
];
3563 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3565 rgba
[i
][ACOMP
] = It
;
3571 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3572 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3573 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3580 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3581 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3582 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3584 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3588 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3599 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3605 GLchan Lt
= texel
[i
][RCOMP
];
3606 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3607 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3608 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3612 case GL_LUMINANCE_ALPHA
:
3615 GLchan Lt
= texel
[i
][RCOMP
];
3616 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3617 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3618 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3620 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3626 GLchan It
= texel
[i
][RCOMP
];
3627 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3628 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3629 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3631 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3637 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3638 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3639 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3646 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3647 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3648 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3650 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3654 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3663 case GL_LUMINANCE_ALPHA
:
3670 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3671 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3672 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3678 /* Cv = Cf(1-At) + CtAt */
3679 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3680 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3681 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3682 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3687 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3693 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3694 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3695 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3696 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3702 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3707 /* Cv = Cf(1-Lt) + CcLt */
3708 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3709 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3710 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3711 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3715 case GL_LUMINANCE_ALPHA
:
3717 /* Cv = Cf(1-Lt) + CcLt */
3718 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3719 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3720 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3721 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3723 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3728 /* Cv = Cf(1-It) + CcIt */
3729 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3730 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3731 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3732 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3733 /* Av = Af(1-It) + Ac*It */
3734 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
3739 /* Cv = Cf(1-Ct) + CcCt */
3740 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3741 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3742 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3748 /* Cv = Cf(1-Ct) + CcCt */
3749 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3750 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3751 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3753 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3757 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
3762 /* XXX don't clamp results if GLchan is float??? */
3764 case GL_ADD
: /* GL_EXT_texture_add_env */
3771 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3776 GLuint Lt
= texel
[i
][RCOMP
];
3777 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3778 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3779 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3780 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3781 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3782 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3786 case GL_LUMINANCE_ALPHA
:
3788 GLuint Lt
= texel
[i
][RCOMP
];
3789 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3790 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3791 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3792 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3793 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3794 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3795 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3800 GLchan It
= texel
[i
][RCOMP
];
3801 GLuint r
= rgba
[i
][RCOMP
] + It
;
3802 GLuint g
= rgba
[i
][GCOMP
] + It
;
3803 GLuint b
= rgba
[i
][BCOMP
] + It
;
3804 GLuint a
= rgba
[i
][ACOMP
] + It
;
3805 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3806 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3807 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3808 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
3813 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3814 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3815 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3816 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3817 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3818 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3824 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3825 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3826 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3827 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3828 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3829 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3830 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3834 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
3840 _mesa_problem(ctx
, "Bad env mode in texture_apply");
3848 * Apply texture mapping to a span of fragments.
3851 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
3853 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
3854 GLchan primary_rgba
[MAX_WIDTH
][4];
3857 ASSERT(span
->end
< MAX_WIDTH
);
3858 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3861 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
3863 if (swrast
->_AnyTextureCombine
)
3864 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
3867 * Must do all texture sampling before combining in order to
3868 * accomodate GL_ARB_texture_env_crossbar.
3870 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3871 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3872 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3873 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
3874 GLfloat
*lambda
= span
->array
->lambda
[unit
];
3875 GLchan (*texels
)[4] = (GLchan (*)[4])
3876 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
3878 /* adjust texture lod (lambda) */
3879 if (span
->arrayMask
& SPAN_LAMBDA
) {
3880 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
3881 /* apply LOD bias, but don't clamp yet */
3882 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
3883 -ctx
->Const
.MaxTextureLodBias
,
3884 ctx
->Const
.MaxTextureLodBias
);
3886 for (i
= 0; i
< span
->end
; i
++) {
3891 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
3892 /* apply LOD clamping to lambda */
3893 const GLfloat min
= curObj
->MinLod
;
3894 const GLfloat max
= curObj
->MaxLod
;
3896 for (i
= 0; i
< span
->end
; i
++) {
3897 GLfloat l
= lambda
[i
];
3898 lambda
[i
] = CLAMP(l
, min
, max
);
3903 /* Sample the texture (span->end fragments) */
3904 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
3905 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
3908 /* GL_SGI_texture_color_table */
3909 if (texUnit
->ColorTableEnabled
) {
3910 _mesa_lookup_rgba_chan(&texUnit
->ColorTable
, span
->end
, texels
);
3916 * OK, now apply the texture (aka texture combine/blend).
3917 * We modify the span->color.rgba values.
3919 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3920 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3921 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3922 if (texUnit
->_CurrentCombine
!= &texUnit
->_EnvMode
) {
3923 texture_combine( ctx
, unit
, span
->end
,
3924 (CONST
GLchan (*)[4]) primary_rgba
,
3925 swrast
->TexelBuffer
,
3926 span
->array
->rgba
);
3929 /* conventional texture blend */
3930 const GLchan (*texels
)[4] = (const GLchan (*)[4])
3931 (swrast
->TexelBuffer
+ unit
*
3932 (span
->end
* 4 * sizeof(GLchan
)));
3933 texture_apply( ctx
, texUnit
, span
->end
,
3934 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
3935 span
->array
->rgba
);