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 */
460 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
462 /* skip over the border, if any */
465 if (i
< 0 || i
>= (GLint
) img
->Width
) {
466 /* Need this test for GL_CLAMP_TO_BORDER mode */
467 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
470 img
->FetchTexelc(img
, i
, 0, 0, rgba
);
477 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
480 sample_1d_linear(GLcontext
*ctx
,
481 const struct gl_texture_object
*tObj
,
482 const struct gl_texture_image
*img
,
483 const GLfloat texcoord
[4], GLchan rgba
[4])
485 const GLint width
= img
->Width2
;
488 GLuint useBorderColor
;
490 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
498 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
499 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
503 const GLfloat a
= FRAC(u
);
505 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
506 const GLfloat w0
= (1.0F
-a
);
507 const GLfloat w1
= a
;
508 #else /* CHAN_BITS == 8 */
509 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
510 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
511 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
513 GLchan t0
[4], t1
[4]; /* texels */
515 if (useBorderColor
& I0BIT
) {
516 COPY_CHAN4(t0
, tObj
->_BorderChan
);
519 img
->FetchTexelc(img
, i0
, 0, 0, t0
);
521 if (useBorderColor
& I1BIT
) {
522 COPY_CHAN4(t1
, tObj
->_BorderChan
);
525 img
->FetchTexelc(img
, i1
, 0, 0, t1
);
528 #if CHAN_TYPE == GL_FLOAT
529 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
530 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
531 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
532 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
533 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
534 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
535 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
536 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
537 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
538 #else /* CHAN_BITS == 8 */
539 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
540 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
541 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
542 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
550 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
551 const struct gl_texture_object
*tObj
,
552 GLuint n
, const GLfloat texcoord
[][4],
553 const GLfloat lambda
[], GLchan rgba
[][4])
556 ASSERT(lambda
!= NULL
);
557 for (i
= 0; i
< n
; i
++) {
559 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
560 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
566 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
567 const struct gl_texture_object
*tObj
,
568 GLuint n
, const GLfloat texcoord
[][4],
569 const GLfloat lambda
[], GLchan rgba
[][4])
572 ASSERT(lambda
!= NULL
);
573 for (i
= 0; i
< n
; i
++) {
575 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
576 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
583 * This is really just needed in order to prevent warnings with some compilers.
585 #if CHAN_TYPE == GL_FLOAT
588 #define CHAN_CAST (GLchan) (GLint)
593 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
594 const struct gl_texture_object
*tObj
,
595 GLuint n
, const GLfloat texcoord
[][4],
596 const GLfloat lambda
[], GLchan rgba
[][4])
599 ASSERT(lambda
!= NULL
);
600 for (i
= 0; i
< n
; i
++) {
602 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
603 if (level
>= tObj
->_MaxLevel
) {
604 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
605 texcoord
[i
], rgba
[i
]);
609 const GLfloat f
= FRAC(lambda
[i
]);
610 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
611 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
612 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
613 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
614 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
615 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
623 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
624 const struct gl_texture_object
*tObj
,
625 GLuint n
, const GLfloat texcoord
[][4],
626 const GLfloat lambda
[], GLchan rgba
[][4])
629 ASSERT(lambda
!= NULL
);
630 for (i
= 0; i
< n
; i
++) {
632 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
633 if (level
>= tObj
->_MaxLevel
) {
634 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
635 texcoord
[i
], rgba
[i
]);
639 const GLfloat f
= FRAC(lambda
[i
]);
640 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
641 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
642 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
643 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
644 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
645 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
653 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
654 const struct gl_texture_object
*tObj
, GLuint n
,
655 const GLfloat texcoords
[][4], const GLfloat lambda
[],
659 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
662 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
669 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
670 const struct gl_texture_object
*tObj
, GLuint n
,
671 const GLfloat texcoords
[][4], const GLfloat lambda
[],
675 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
678 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
684 * Given an (s) texture coordinate and lambda (level of detail) value,
685 * return a texture sample.
689 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
690 const struct gl_texture_object
*tObj
, GLuint n
,
691 const GLfloat texcoords
[][4],
692 const GLfloat lambda
[], GLchan rgba
[][4] )
694 GLuint minStart
, minEnd
; /* texels with minification */
695 GLuint magStart
, magEnd
; /* texels with magnification */
698 ASSERT(lambda
!= NULL
);
699 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
700 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
702 if (minStart
< minEnd
) {
703 /* do the minified texels */
704 const GLuint m
= minEnd
- minStart
;
705 switch (tObj
->MinFilter
) {
707 for (i
= minStart
; i
< minEnd
; i
++)
708 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
709 texcoords
[i
], rgba
[i
]);
712 for (i
= minStart
; i
< minEnd
; i
++)
713 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
714 texcoords
[i
], rgba
[i
]);
716 case GL_NEAREST_MIPMAP_NEAREST
:
717 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
718 lambda
+ minStart
, rgba
+ minStart
);
720 case GL_LINEAR_MIPMAP_NEAREST
:
721 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
722 lambda
+ minStart
, rgba
+ minStart
);
724 case GL_NEAREST_MIPMAP_LINEAR
:
725 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
726 lambda
+ minStart
, rgba
+ minStart
);
728 case GL_LINEAR_MIPMAP_LINEAR
:
729 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
730 lambda
+ minStart
, rgba
+ minStart
);
733 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
738 if (magStart
< magEnd
) {
739 /* do the magnified texels */
740 switch (tObj
->MagFilter
) {
742 for (i
= magStart
; i
< magEnd
; i
++)
743 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
744 texcoords
[i
], rgba
[i
]);
747 for (i
= magStart
; i
< magEnd
; i
++)
748 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
749 texcoords
[i
], rgba
[i
]);
752 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
759 /**********************************************************************/
760 /* 2-D Texture Sampling Functions */
761 /**********************************************************************/
765 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
768 sample_2d_nearest(GLcontext
*ctx
,
769 const struct gl_texture_object
*tObj
,
770 const struct gl_texture_image
*img
,
771 const GLfloat texcoord
[4],
774 const GLint width
= img
->Width2
; /* without border, power of two */
775 const GLint height
= img
->Height2
; /* without border, power of two */
778 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
779 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
781 /* skip over the border, if any */
785 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
786 /* Need this test for GL_CLAMP_TO_BORDER mode */
787 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
790 img
->FetchTexelc(img
, i
, j
, 0, rgba
);
797 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
798 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
801 sample_2d_linear(GLcontext
*ctx
,
802 const struct gl_texture_object
*tObj
,
803 const struct gl_texture_image
*img
,
804 const GLfloat texcoord
[4],
807 const GLint width
= img
->Width2
;
808 const GLint height
= img
->Height2
;
809 GLint i0
, j0
, i1
, j1
;
810 GLuint useBorderColor
;
813 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
814 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
824 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
825 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
826 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
827 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
831 const GLfloat a
= FRAC(u
);
832 const GLfloat b
= FRAC(v
);
834 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
835 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
836 const GLfloat w10
= a
* (1.0F
-b
);
837 const GLfloat w01
= (1.0F
-a
) * b
;
838 const GLfloat w11
= a
* b
;
839 #else /* CHAN_BITS == 8 */
840 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
841 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
842 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
843 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
844 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
851 if (useBorderColor
& (I0BIT
| J0BIT
)) {
852 COPY_CHAN4(t00
, tObj
->_BorderChan
);
855 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
857 if (useBorderColor
& (I1BIT
| J0BIT
)) {
858 COPY_CHAN4(t10
, tObj
->_BorderChan
);
861 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
863 if (useBorderColor
& (I0BIT
| J1BIT
)) {
864 COPY_CHAN4(t01
, tObj
->_BorderChan
);
867 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
869 if (useBorderColor
& (I1BIT
| J1BIT
)) {
870 COPY_CHAN4(t11
, tObj
->_BorderChan
);
873 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
875 #if CHAN_TYPE == GL_FLOAT
876 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
877 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
878 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
879 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
880 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
881 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
882 w01
* t01
[0] + w11
* t11
[0] + 0.5);
883 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
884 w01
* t01
[1] + w11
* t11
[1] + 0.5);
885 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
886 w01
* t01
[2] + w11
* t11
[2] + 0.5);
887 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
888 w01
* t01
[3] + w11
* t11
[3] + 0.5);
889 #else /* CHAN_BITS == 8 */
890 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
891 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
892 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
893 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
894 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
895 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
896 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
897 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
906 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
907 * and we're not using a paletted texture.
910 sample_2d_linear_repeat(GLcontext
*ctx
,
911 const struct gl_texture_object
*tObj
,
912 const struct gl_texture_image
*img
,
913 const GLfloat texcoord
[4],
916 const GLint width
= img
->Width2
;
917 const GLint height
= img
->Height2
;
918 GLint i0
, j0
, i1
, j1
;
921 ASSERT(tObj
->WrapS
== GL_REPEAT
);
922 ASSERT(tObj
->WrapT
== GL_REPEAT
);
923 ASSERT(img
->Border
== 0);
924 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
925 ASSERT(img
->_IsPowerOfTwo
);
927 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
928 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
931 const GLfloat a
= FRAC(u
);
932 const GLfloat b
= FRAC(v
);
934 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
935 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
936 const GLfloat w10
= a
* (1.0F
-b
);
937 const GLfloat w01
= (1.0F
-a
) * b
;
938 const GLfloat w11
= a
* b
;
939 #else /* CHAN_BITS == 8 */
940 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
941 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
942 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
943 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
944 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
951 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
952 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
953 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
954 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
956 #if CHAN_TYPE == GL_FLOAT
957 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
958 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
959 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
960 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
961 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
962 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
963 w01
* t01
[0] + w11
* t11
[0] + 0.5);
964 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
965 w01
* t01
[1] + w11
* t11
[1] + 0.5);
966 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
967 w01
* t01
[2] + w11
* t11
[2] + 0.5);
968 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
969 w01
* t01
[3] + w11
* t11
[3] + 0.5);
970 #else /* CHAN_BITS == 8 */
971 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
972 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
973 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
974 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
975 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
976 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
977 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
978 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
988 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
989 const struct gl_texture_object
*tObj
,
990 GLuint n
, const GLfloat texcoord
[][4],
991 const GLfloat lambda
[], GLchan rgba
[][4])
994 for (i
= 0; i
< n
; i
++) {
996 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
997 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1004 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1005 const struct gl_texture_object
*tObj
,
1006 GLuint n
, const GLfloat texcoord
[][4],
1007 const GLfloat lambda
[], GLchan rgba
[][4])
1010 ASSERT(lambda
!= NULL
);
1011 for (i
= 0; i
< n
; i
++) {
1013 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1014 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1021 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1022 const struct gl_texture_object
*tObj
,
1023 GLuint n
, const GLfloat texcoord
[][4],
1024 const GLfloat lambda
[], GLchan rgba
[][4])
1027 ASSERT(lambda
!= NULL
);
1028 for (i
= 0; i
< n
; i
++) {
1030 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1031 if (level
>= tObj
->_MaxLevel
) {
1032 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1033 texcoord
[i
], rgba
[i
]);
1036 GLchan t0
[4], t1
[4]; /* texels */
1037 const GLfloat f
= FRAC(lambda
[i
]);
1038 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1039 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1040 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1041 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1042 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1043 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1050 /* Trilinear filtering */
1052 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1053 const struct gl_texture_object
*tObj
,
1054 GLuint n
, const GLfloat texcoord
[][4],
1055 const GLfloat lambda
[], GLchan rgba
[][4] )
1058 ASSERT(lambda
!= NULL
);
1059 for (i
= 0; i
< n
; i
++) {
1061 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1062 if (level
>= tObj
->_MaxLevel
) {
1063 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1064 texcoord
[i
], rgba
[i
]);
1067 GLchan t0
[4], t1
[4]; /* texels */
1068 const GLfloat f
= FRAC(lambda
[i
]);
1069 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1070 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1071 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1072 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1073 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1074 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1081 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1082 const struct gl_texture_object
*tObj
,
1083 GLuint n
, const GLfloat texcoord
[][4],
1084 const GLfloat lambda
[], GLchan rgba
[][4] )
1087 ASSERT(lambda
!= NULL
);
1088 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1089 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1090 ASSERT(tObj
->_IsPowerOfTwo
);
1091 for (i
= 0; i
< n
; i
++) {
1093 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1094 if (level
>= tObj
->_MaxLevel
) {
1095 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1096 texcoord
[i
], rgba
[i
]);
1099 GLchan t0
[4], t1
[4]; /* texels */
1100 const GLfloat f
= FRAC(lambda
[i
]);
1101 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1102 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1103 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1104 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1105 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1106 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1113 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1114 const struct gl_texture_object
*tObj
, GLuint n
,
1115 const GLfloat texcoords
[][4],
1116 const GLfloat lambda
[], GLchan rgba
[][4] )
1119 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1122 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1129 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1130 const struct gl_texture_object
*tObj
, GLuint n
,
1131 const GLfloat texcoords
[][4],
1132 const GLfloat lambda
[], GLchan rgba
[][4] )
1135 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1138 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1144 * Optimized 2-D texture sampling:
1145 * S and T wrap mode == GL_REPEAT
1146 * GL_NEAREST min/mag filter
1148 * RowStride == Width,
1152 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1153 const struct gl_texture_object
*tObj
,
1154 GLuint n
, const GLfloat texcoords
[][4],
1155 const GLfloat lambda
[], GLchan rgba
[][4] )
1157 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1158 const GLfloat width
= (GLfloat
) img
->Width
;
1159 const GLfloat height
= (GLfloat
) img
->Height
;
1160 const GLint colMask
= img
->Width
- 1;
1161 const GLint rowMask
= img
->Height
- 1;
1162 const GLint shift
= img
->WidthLog2
;
1165 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1166 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1167 ASSERT(img
->Border
==0);
1168 ASSERT(img
->Format
==GL_RGB
);
1169 ASSERT(img
->_IsPowerOfTwo
);
1171 for (k
=0; k
<n
; k
++) {
1172 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1173 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1174 GLint pos
= (j
<< shift
) | i
;
1175 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1176 rgba
[k
][RCOMP
] = texel
[0];
1177 rgba
[k
][GCOMP
] = texel
[1];
1178 rgba
[k
][BCOMP
] = texel
[2];
1184 * Optimized 2-D texture sampling:
1185 * S and T wrap mode == GL_REPEAT
1186 * GL_NEAREST min/mag filter
1188 * RowStride == Width,
1192 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1193 const struct gl_texture_object
*tObj
,
1194 GLuint n
, const GLfloat texcoords
[][4],
1195 const GLfloat lambda
[], GLchan rgba
[][4] )
1197 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1198 const GLfloat width
= (GLfloat
) img
->Width
;
1199 const GLfloat height
= (GLfloat
) img
->Height
;
1200 const GLint colMask
= img
->Width
- 1;
1201 const GLint rowMask
= img
->Height
- 1;
1202 const GLint shift
= img
->WidthLog2
;
1205 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1206 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1207 ASSERT(img
->Border
==0);
1208 ASSERT(img
->Format
==GL_RGBA
);
1209 ASSERT(img
->_IsPowerOfTwo
);
1211 for (i
= 0; i
< n
; i
++) {
1212 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1213 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1214 const GLint pos
= (row
<< shift
) | col
;
1215 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1216 COPY_CHAN4(rgba
[i
], texel
);
1222 * Given an array of texture coordinate and lambda (level of detail)
1223 * values, return an array of texture sample.
1226 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1227 const struct gl_texture_object
*tObj
,
1228 GLuint n
, const GLfloat texcoords
[][4],
1229 const GLfloat lambda
[], GLchan rgba
[][4] )
1231 const struct gl_texture_image
*tImg
= tObj
->Image
[0][tObj
->BaseLevel
];
1232 GLuint minStart
, minEnd
; /* texels with minification */
1233 GLuint magStart
, magEnd
; /* texels with magnification */
1235 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1236 && (tObj
->WrapT
== GL_REPEAT
)
1237 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1238 && (tImg
->Format
!= GL_COLOR_INDEX
)
1239 && tImg
->_IsPowerOfTwo
;
1241 ASSERT(lambda
!= NULL
);
1242 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1243 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1245 if (minStart
< minEnd
) {
1246 /* do the minified texels */
1247 const GLuint m
= minEnd
- minStart
;
1248 switch (tObj
->MinFilter
) {
1250 if (repeatNoBorderPOT
) {
1251 switch (tImg
->TexFormat
->MesaFormat
) {
1252 case MESA_FORMAT_RGB
:
1253 case MESA_FORMAT_RGB888
:
1254 /*case MESA_FORMAT_BGR888:*/
1255 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1256 NULL
, rgba
+ minStart
);
1258 case MESA_FORMAT_RGBA
:
1259 case MESA_FORMAT_RGBA8888
:
1260 case MESA_FORMAT_ARGB8888
:
1261 /*case MESA_FORMAT_ABGR8888:*/
1262 /*case MESA_FORMAT_BGRA8888:*/
1263 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1264 NULL
, rgba
+ minStart
);
1267 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1268 NULL
, rgba
+ minStart
);
1272 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1273 NULL
, rgba
+ minStart
);
1277 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1278 NULL
, rgba
+ minStart
);
1280 case GL_NEAREST_MIPMAP_NEAREST
:
1281 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1282 texcoords
+ minStart
,
1283 lambda
+ minStart
, rgba
+ minStart
);
1285 case GL_LINEAR_MIPMAP_NEAREST
:
1286 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1287 lambda
+ minStart
, rgba
+ minStart
);
1289 case GL_NEAREST_MIPMAP_LINEAR
:
1290 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1291 lambda
+ minStart
, rgba
+ minStart
);
1293 case GL_LINEAR_MIPMAP_LINEAR
:
1294 if (repeatNoBorderPOT
)
1295 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1296 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1298 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1299 lambda
+ minStart
, rgba
+ minStart
);
1302 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1307 if (magStart
< magEnd
) {
1308 /* do the magnified texels */
1309 const GLuint m
= magEnd
- magStart
;
1311 switch (tObj
->MagFilter
) {
1313 if (repeatNoBorderPOT
) {
1314 switch (tImg
->TexFormat
->MesaFormat
) {
1315 case MESA_FORMAT_RGB
:
1316 case MESA_FORMAT_RGB888
:
1317 /*case MESA_FORMAT_BGR888:*/
1318 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1319 NULL
, rgba
+ magStart
);
1321 case MESA_FORMAT_RGBA
:
1322 case MESA_FORMAT_RGBA8888
:
1323 case MESA_FORMAT_ARGB8888
:
1324 /*case MESA_FORMAT_ABGR8888:*/
1325 /*case MESA_FORMAT_BGRA8888:*/
1326 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1327 NULL
, rgba
+ magStart
);
1330 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1331 NULL
, rgba
+ magStart
);
1335 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1336 NULL
, rgba
+ magStart
);
1340 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1341 NULL
, rgba
+ magStart
);
1344 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1351 /**********************************************************************/
1352 /* 3-D Texture Sampling Functions */
1353 /**********************************************************************/
1356 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1359 sample_3d_nearest(GLcontext
*ctx
,
1360 const struct gl_texture_object
*tObj
,
1361 const struct gl_texture_image
*img
,
1362 const GLfloat texcoord
[4],
1365 const GLint width
= img
->Width2
; /* without border, power of two */
1366 const GLint height
= img
->Height2
; /* without border, power of two */
1367 const GLint depth
= img
->Depth2
; /* without border, power of two */
1370 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1371 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1372 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1374 if (i
< 0 || i
>= (GLint
) img
->Width
||
1375 j
< 0 || j
>= (GLint
) img
->Height
||
1376 k
< 0 || k
>= (GLint
) img
->Depth
) {
1377 /* Need this test for GL_CLAMP_TO_BORDER mode */
1378 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1381 img
->FetchTexelc(img
, i
, j
, k
, rgba
);
1388 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1391 sample_3d_linear(GLcontext
*ctx
,
1392 const struct gl_texture_object
*tObj
,
1393 const struct gl_texture_image
*img
,
1394 const GLfloat texcoord
[4],
1397 const GLint width
= img
->Width2
;
1398 const GLint height
= img
->Height2
;
1399 const GLint depth
= img
->Depth2
;
1400 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1401 GLuint useBorderColor
;
1404 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1405 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1406 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1418 /* check if sampling texture border color */
1419 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1420 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1421 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1422 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1423 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1424 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1428 const GLfloat a
= FRAC(u
);
1429 const GLfloat b
= FRAC(v
);
1430 const GLfloat c
= FRAC(w
);
1432 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1433 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1434 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1435 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1436 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1437 GLfloat w110
= a
* b
* (1.0F
-c
);
1438 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1439 GLfloat w101
= a
* (1.0F
-b
) * c
;
1440 GLfloat w011
= (1.0F
-a
) * b
* c
;
1441 GLfloat w111
= a
* b
* c
;
1442 #else /* CHAN_BITS == 8 */
1443 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1444 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1445 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1446 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1447 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1448 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1449 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1450 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1451 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1454 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1455 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1457 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1458 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1461 img
->FetchTexelc(img
, i0
, j0
, k0
, t000
);
1463 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1464 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1467 img
->FetchTexelc(img
, i1
, j0
, k0
, t100
);
1469 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1470 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1473 img
->FetchTexelc(img
, i0
, j1
, k0
, t010
);
1475 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1476 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1479 img
->FetchTexelc(img
, i1
, j1
, k0
, t110
);
1482 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1483 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1486 img
->FetchTexelc(img
, i0
, j0
, k1
, t001
);
1488 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1489 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1492 img
->FetchTexelc(img
, i1
, j0
, k1
, t101
);
1494 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1495 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1498 img
->FetchTexelc(img
, i0
, j1
, k1
, t011
);
1500 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1501 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1504 img
->FetchTexelc(img
, i1
, j1
, k1
, t111
);
1507 #if CHAN_TYPE == GL_FLOAT
1508 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1509 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1510 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1511 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1512 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1513 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1514 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1515 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1516 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1517 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1518 w001
*t001
[0] + w011
*t011
[0] +
1519 w100
*t100
[0] + w110
*t110
[0] +
1520 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1521 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1522 w001
*t001
[1] + w011
*t011
[1] +
1523 w100
*t100
[1] + w110
*t110
[1] +
1524 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1525 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1526 w001
*t001
[2] + w011
*t011
[2] +
1527 w100
*t100
[2] + w110
*t110
[2] +
1528 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1529 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1530 w001
*t001
[3] + w011
*t011
[3] +
1531 w100
*t100
[3] + w110
*t110
[3] +
1532 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1533 #else /* CHAN_BITS == 8 */
1534 rgba
[0] = (GLchan
) (
1535 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1536 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1538 rgba
[1] = (GLchan
) (
1539 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1540 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1542 rgba
[2] = (GLchan
) (
1543 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1544 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1546 rgba
[3] = (GLchan
) (
1547 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1548 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1558 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1559 const struct gl_texture_object
*tObj
,
1560 GLuint n
, const GLfloat texcoord
[][4],
1561 const GLfloat lambda
[], GLchan rgba
[][4] )
1564 for (i
= 0; i
< n
; i
++) {
1566 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1567 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1573 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1574 const struct gl_texture_object
*tObj
,
1575 GLuint n
, const GLfloat texcoord
[][4],
1576 const GLfloat lambda
[], GLchan rgba
[][4])
1579 ASSERT(lambda
!= NULL
);
1580 for (i
= 0; i
< n
; i
++) {
1582 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1583 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1589 sample_3d_nearest_mipmap_linear(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_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1599 if (level
>= tObj
->_MaxLevel
) {
1600 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1601 texcoord
[i
], rgba
[i
]);
1604 GLchan t0
[4], t1
[4]; /* texels */
1605 const GLfloat f
= FRAC(lambda
[i
]);
1606 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1607 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1608 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1609 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1610 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1611 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1618 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1619 const struct gl_texture_object
*tObj
,
1620 GLuint n
, const GLfloat texcoord
[][4],
1621 const GLfloat lambda
[], GLchan rgba
[][4])
1624 ASSERT(lambda
!= NULL
);
1625 for (i
= 0; i
< n
; i
++) {
1627 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1628 if (level
>= tObj
->_MaxLevel
) {
1629 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1630 texcoord
[i
], rgba
[i
]);
1633 GLchan t0
[4], t1
[4]; /* texels */
1634 const GLfloat f
= FRAC(lambda
[i
]);
1635 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1636 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1637 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1638 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1639 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1640 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1647 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1648 const struct gl_texture_object
*tObj
, GLuint n
,
1649 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1653 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1656 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1663 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1664 const struct gl_texture_object
*tObj
, GLuint n
,
1665 const GLfloat texcoords
[][4],
1666 const GLfloat lambda
[], GLchan rgba
[][4] )
1669 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1672 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1678 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1679 * return a texture sample.
1682 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1683 const struct gl_texture_object
*tObj
, GLuint n
,
1684 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1687 GLuint minStart
, minEnd
; /* texels with minification */
1688 GLuint magStart
, magEnd
; /* texels with magnification */
1691 ASSERT(lambda
!= NULL
);
1692 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1693 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1695 if (minStart
< minEnd
) {
1696 /* do the minified texels */
1697 GLuint m
= minEnd
- minStart
;
1698 switch (tObj
->MinFilter
) {
1700 for (i
= minStart
; i
< minEnd
; i
++)
1701 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1702 texcoords
[i
], rgba
[i
]);
1705 for (i
= minStart
; i
< minEnd
; i
++)
1706 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1707 texcoords
[i
], rgba
[i
]);
1709 case GL_NEAREST_MIPMAP_NEAREST
:
1710 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1711 lambda
+ minStart
, rgba
+ minStart
);
1713 case GL_LINEAR_MIPMAP_NEAREST
:
1714 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1715 lambda
+ minStart
, rgba
+ minStart
);
1717 case GL_NEAREST_MIPMAP_LINEAR
:
1718 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1719 lambda
+ minStart
, rgba
+ minStart
);
1721 case GL_LINEAR_MIPMAP_LINEAR
:
1722 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1723 lambda
+ minStart
, rgba
+ minStart
);
1726 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1731 if (magStart
< magEnd
) {
1732 /* do the magnified texels */
1733 switch (tObj
->MagFilter
) {
1735 for (i
= magStart
; i
< magEnd
; i
++)
1736 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1737 texcoords
[i
], rgba
[i
]);
1740 for (i
= magStart
; i
< magEnd
; i
++)
1741 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1742 texcoords
[i
], rgba
[i
]);
1745 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1752 /**********************************************************************/
1753 /* Texture Cube Map Sampling Functions */
1754 /**********************************************************************/
1757 * Choose one of six sides of a texture cube map given the texture
1758 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1761 static const struct gl_texture_image
**
1762 choose_cube_face(const struct gl_texture_object
*texObj
,
1763 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1767 direction target sc tc ma
1768 ---------- ------------------------------- --- --- ---
1769 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1770 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1771 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1772 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1773 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1774 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1776 const GLfloat rx
= texcoord
[0];
1777 const GLfloat ry
= texcoord
[1];
1778 const GLfloat rz
= texcoord
[2];
1779 const struct gl_texture_image
**imgArray
;
1780 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
1783 if (arx
> ary
&& arx
> arz
) {
1785 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_X
];
1791 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_X
];
1797 else if (ary
> arx
&& ary
> arz
) {
1799 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Y
];
1805 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Y
];
1813 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Z
];
1819 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Z
];
1826 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1827 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1833 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1834 const struct gl_texture_object
*tObj
, GLuint n
,
1835 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1840 for (i
= 0; i
< n
; i
++) {
1841 const struct gl_texture_image
**images
;
1842 GLfloat newCoord
[4];
1843 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1844 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1851 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1852 const struct gl_texture_object
*tObj
, GLuint n
,
1853 const GLfloat texcoords
[][4],
1854 const GLfloat lambda
[], GLchan rgba
[][4])
1858 for (i
= 0; i
< n
; i
++) {
1859 const struct gl_texture_image
**images
;
1860 GLfloat newCoord
[4];
1861 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1862 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1869 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
1870 const struct gl_texture_object
*tObj
,
1871 GLuint n
, const GLfloat texcoord
[][4],
1872 const GLfloat lambda
[], GLchan rgba
[][4])
1875 ASSERT(lambda
!= NULL
);
1876 for (i
= 0; i
< n
; i
++) {
1877 const struct gl_texture_image
**images
;
1878 GLfloat newCoord
[4];
1880 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1881 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1882 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1888 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
1889 const struct gl_texture_object
*tObj
,
1890 GLuint n
, const GLfloat texcoord
[][4],
1891 const GLfloat lambda
[], GLchan rgba
[][4])
1894 ASSERT(lambda
!= NULL
);
1895 for (i
= 0; i
< n
; i
++) {
1896 const struct gl_texture_image
**images
;
1897 GLfloat newCoord
[4];
1899 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1900 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1901 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1907 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
1908 const struct gl_texture_object
*tObj
,
1909 GLuint n
, const GLfloat texcoord
[][4],
1910 const GLfloat lambda
[], GLchan rgba
[][4])
1913 ASSERT(lambda
!= NULL
);
1914 for (i
= 0; i
< n
; i
++) {
1915 const struct gl_texture_image
**images
;
1916 GLfloat newCoord
[4];
1918 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1919 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1920 if (level
>= tObj
->_MaxLevel
) {
1921 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1925 GLchan t0
[4], t1
[4]; /* texels */
1926 const GLfloat f
= FRAC(lambda
[i
]);
1927 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1928 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1929 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1930 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1931 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1932 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1939 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
1940 const struct gl_texture_object
*tObj
,
1941 GLuint n
, const GLfloat texcoord
[][4],
1942 const GLfloat lambda
[], GLchan rgba
[][4])
1945 ASSERT(lambda
!= NULL
);
1946 for (i
= 0; i
< n
; i
++) {
1947 const struct gl_texture_image
**images
;
1948 GLfloat newCoord
[4];
1950 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1951 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1952 if (level
>= tObj
->_MaxLevel
) {
1953 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1957 GLchan t0
[4], t1
[4];
1958 const GLfloat f
= FRAC(lambda
[i
]);
1959 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
1960 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1961 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1962 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1963 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1964 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1971 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1972 const struct gl_texture_object
*tObj
, GLuint n
,
1973 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1976 GLuint minStart
, minEnd
; /* texels with minification */
1977 GLuint magStart
, magEnd
; /* texels with magnification */
1979 ASSERT(lambda
!= NULL
);
1980 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1981 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1983 if (minStart
< minEnd
) {
1984 /* do the minified texels */
1985 const GLuint m
= minEnd
- minStart
;
1986 switch (tObj
->MinFilter
) {
1988 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1989 lambda
+ minStart
, rgba
+ minStart
);
1992 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1993 lambda
+ minStart
, rgba
+ minStart
);
1995 case GL_NEAREST_MIPMAP_NEAREST
:
1996 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
1997 texcoords
+ minStart
,
1998 lambda
+ minStart
, rgba
+ minStart
);
2000 case GL_LINEAR_MIPMAP_NEAREST
:
2001 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2002 texcoords
+ minStart
,
2003 lambda
+ minStart
, rgba
+ minStart
);
2005 case GL_NEAREST_MIPMAP_LINEAR
:
2006 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2007 texcoords
+ minStart
,
2008 lambda
+ minStart
, rgba
+ minStart
);
2010 case GL_LINEAR_MIPMAP_LINEAR
:
2011 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2012 texcoords
+ minStart
,
2013 lambda
+ minStart
, rgba
+ minStart
);
2016 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2020 if (magStart
< magEnd
) {
2021 /* do the magnified texels */
2022 const GLuint m
= magEnd
- magStart
;
2023 switch (tObj
->MagFilter
) {
2025 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2026 lambda
+ magStart
, rgba
+ magStart
);
2029 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2030 lambda
+ magStart
, rgba
+ magStart
);
2033 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2039 /**********************************************************************/
2040 /* Texture Rectangle Sampling Functions */
2041 /**********************************************************************/
2044 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2045 const struct gl_texture_object
*tObj
, GLuint n
,
2046 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2049 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2050 const GLfloat width
= (GLfloat
) img
->Width
;
2051 const GLfloat height
= (GLfloat
) img
->Height
;
2052 const GLint width_minus_1
= img
->Width
- 1;
2053 const GLint height_minus_1
= img
->Height
- 1;
2059 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2060 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2061 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2062 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2063 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2064 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2065 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2067 /* XXX move Wrap mode tests outside of loops for common cases */
2068 for (i
= 0; i
< n
; i
++) {
2070 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2071 if (tObj
->WrapS
== GL_CLAMP
) {
2072 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
- 1) );
2074 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2075 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2078 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2080 if (tObj
->WrapT
== GL_CLAMP
) {
2081 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
- 1) );
2083 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2084 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2087 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2090 if (col
< 0 || col
> width_minus_1
|| row
< 0 || row
> height_minus_1
)
2091 COPY_CHAN4(rgba
[i
], tObj
->_BorderChan
);
2093 img
->FetchTexelc(img
, col
, row
, 0, rgba
[i
]);
2099 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2100 const struct gl_texture_object
*tObj
, GLuint n
,
2101 const GLfloat texcoords
[][4],
2102 const GLfloat lambda
[], GLchan rgba
[][4])
2104 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2105 const GLfloat width
= (GLfloat
) img
->Width
;
2106 const GLfloat height
= (GLfloat
) img
->Height
;
2107 const GLint width_minus_1
= img
->Width
- 1;
2108 const GLint height_minus_1
= img
->Height
- 1;
2114 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2115 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2116 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2117 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2118 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2119 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2120 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2122 /* XXX lots of opportunity for optimization in this loop */
2123 for (i
= 0; i
< n
; i
++) {
2125 GLint i0
, j0
, i1
, j1
;
2126 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2127 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2128 GLuint useBorderColor
= 0;
2130 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2131 if (tObj
->WrapS
== GL_CLAMP
) {
2132 /* clamping to width-1 looks wrong, but it's really correct */
2133 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width_minus_1
);
2137 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2138 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2141 if (i1
> width_minus_1
)
2144 else { /* GL_CLAMP_TO_BORDER */
2146 /* literal reading of GL_NV_texture_rectangle spec */
2147 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2151 /* Note: this produces results that matches NVIDIA, but it's not
2152 * exactly what the GL_NV_texture_rectangle specifies!
2154 fcol
= texcoords
[i
][0];
2160 if (tObj
->WrapT
== GL_CLAMP
) {
2161 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height_minus_1
);
2165 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2166 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2169 if (j1
> height_minus_1
)
2170 j1
= height_minus_1
;
2172 else { /* GL_CLAMP_TO_BORDER */
2174 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2178 frow
= texcoords
[i
][1];
2184 /* compute integer rows/columns */
2185 if (i0
< 0 || i0
> width_minus_1
) useBorderColor
|= I0BIT
;
2186 if (i1
< 0 || i1
> width_minus_1
) useBorderColor
|= I1BIT
;
2187 if (j0
< 0 || j0
> height_minus_1
) useBorderColor
|= J0BIT
;
2188 if (j1
< 0 || j1
> height_minus_1
) useBorderColor
|= J1BIT
;
2190 /* get four texel samples */
2191 if (useBorderColor
& (I0BIT
| J0BIT
))
2192 COPY_CHAN4(t00
, tObj
->_BorderChan
);
2194 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
2196 if (useBorderColor
& (I1BIT
| J0BIT
))
2197 COPY_CHAN4(t10
, tObj
->_BorderChan
);
2199 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
2201 if (useBorderColor
& (I0BIT
| J1BIT
))
2202 COPY_CHAN4(t01
, tObj
->_BorderChan
);
2204 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
2206 if (useBorderColor
& (I1BIT
| J1BIT
))
2207 COPY_CHAN4(t11
, tObj
->_BorderChan
);
2209 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
2211 /* compute sample weights */
2214 w00
= (1.0F
-a
) * (1.0F
-b
);
2216 w01
= (1.0F
-a
) * b
;
2219 /* compute weighted average of samples */
2221 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2223 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2225 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2227 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2233 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2234 const struct gl_texture_object
*tObj
, GLuint n
,
2235 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2238 GLuint minStart
, minEnd
, magStart
, magEnd
;
2240 /* We only need lambda to decide between minification and magnification.
2241 * There is no mipmapping with rectangular textures.
2243 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2244 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2246 if (minStart
< minEnd
) {
2247 if (tObj
->MinFilter
== GL_NEAREST
) {
2248 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2249 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2252 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2253 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2256 if (magStart
< magEnd
) {
2257 if (tObj
->MagFilter
== GL_NEAREST
) {
2258 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2259 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2262 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2263 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2271 * Sample a shadow/depth texture.
2274 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2275 const struct gl_texture_object
*tObj
, GLuint n
,
2276 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2279 const GLint baseLevel
= tObj
->BaseLevel
;
2280 const struct gl_texture_image
*texImage
= tObj
->Image
[0][baseLevel
];
2281 const GLuint width
= texImage
->Width
;
2282 const GLuint height
= texImage
->Height
;
2289 ASSERT(tObj
->Image
[0][tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2290 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2291 tObj
->Target
== GL_TEXTURE_2D
||
2292 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2294 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2296 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2298 /* XXX this could be precomputed and saved in the texture object */
2299 if (tObj
->CompareFlag
) {
2300 /* GL_SGIX_shadow */
2301 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2302 function
= GL_LEQUAL
;
2305 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2306 function
= GL_GEQUAL
;
2309 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2311 function
= tObj
->CompareFunc
;
2314 function
= GL_NONE
; /* pass depth through as grayscale */
2317 if (tObj
->MagFilter
== GL_NEAREST
) {
2319 for (i
= 0; i
< n
; i
++) {
2320 GLfloat depthSample
;
2322 /* XXX fix for texture rectangle! */
2323 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2324 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2325 texImage
->FetchTexelf(texImage
, col
, row
, 0, &depthSample
);
2329 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2332 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2335 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2338 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2341 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2344 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2353 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2356 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2360 switch (tObj
->DepthMode
) {
2362 texel
[i
][RCOMP
] = result
;
2363 texel
[i
][GCOMP
] = result
;
2364 texel
[i
][BCOMP
] = result
;
2365 texel
[i
][ACOMP
] = CHAN_MAX
;
2368 texel
[i
][RCOMP
] = result
;
2369 texel
[i
][GCOMP
] = result
;
2370 texel
[i
][BCOMP
] = result
;
2371 texel
[i
][ACOMP
] = result
;
2374 texel
[i
][RCOMP
] = 0;
2375 texel
[i
][GCOMP
] = 0;
2376 texel
[i
][BCOMP
] = 0;
2377 texel
[i
][ACOMP
] = result
;
2380 _mesa_problem(ctx
, "Bad depth texture mode");
2386 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2387 for (i
= 0; i
< n
; i
++) {
2388 GLfloat depth00
, depth01
, depth10
, depth11
;
2389 GLint i0
, i1
, j0
, j1
;
2391 GLuint useBorderTexel
;
2393 /* XXX fix for texture rectangle! */
2394 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2395 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2398 if (texImage
->Border
) {
2399 i0
+= texImage
->Border
;
2400 i1
+= texImage
->Border
;
2401 j0
+= texImage
->Border
;
2402 j1
+= texImage
->Border
;
2405 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2406 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2407 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2408 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2411 /* get four depth samples from the texture */
2412 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2416 texImage
->FetchTexelf(texImage
, i0
, j0
, 0, &depth00
);
2418 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2422 texImage
->FetchTexelf(texImage
, i1
, j0
, 0, &depth10
);
2424 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2428 texImage
->FetchTexelf(texImage
, i0
, j1
, 0, &depth01
);
2430 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2434 texImage
->FetchTexelf(texImage
, i1
, j1
, 0, &depth11
);
2438 /* compute a single weighted depth sample and do one comparison */
2439 const GLfloat a
= FRAC(u
+ 1.0F
);
2440 const GLfloat b
= FRAC(v
+ 1.0F
);
2441 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2442 const GLfloat w10
= ( a
) * (1.0F
- b
);
2443 const GLfloat w01
= (1.0F
- a
) * ( b
);
2444 const GLfloat w11
= ( a
) * ( b
);
2445 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2446 + w01
* depth01
+ w11
* depth11
;
2447 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2448 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2456 /* Do four depth/R comparisons and compute a weighted result.
2457 * If this touches on somebody's I.P., I'll remove this code
2460 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2461 GLfloat luminance
= CHAN_MAXF
;
2465 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2466 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2467 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2468 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2469 result
= (GLchan
) luminance
;
2472 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2473 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2474 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2475 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2476 result
= (GLchan
) luminance
;
2479 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2480 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2481 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2482 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2483 result
= (GLchan
) luminance
;
2486 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2487 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2488 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2489 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2490 result
= (GLchan
) luminance
;
2493 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2494 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2495 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2496 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2497 result
= (GLchan
) luminance
;
2500 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2501 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2502 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2503 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2504 result
= (GLchan
) luminance
;
2513 /* ordinary bilinear filtering */
2515 const GLfloat a
= FRAC(u
+ 1.0F
);
2516 const GLfloat b
= FRAC(v
+ 1.0F
);
2517 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2518 const GLfloat w10
= ( a
) * (1.0F
- b
);
2519 const GLfloat w01
= (1.0F
- a
) * ( b
);
2520 const GLfloat w11
= ( a
) * ( b
);
2521 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2522 + w01
* depth01
+ w11
* depth11
;
2523 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2527 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2532 switch (tObj
->DepthMode
) {
2534 texel
[i
][RCOMP
] = result
;
2535 texel
[i
][GCOMP
] = result
;
2536 texel
[i
][BCOMP
] = result
;
2537 texel
[i
][ACOMP
] = CHAN_MAX
;
2540 texel
[i
][RCOMP
] = result
;
2541 texel
[i
][GCOMP
] = result
;
2542 texel
[i
][BCOMP
] = result
;
2543 texel
[i
][ACOMP
] = result
;
2546 texel
[i
][RCOMP
] = 0;
2547 texel
[i
][GCOMP
] = 0;
2548 texel
[i
][BCOMP
] = 0;
2549 texel
[i
][ACOMP
] = result
;
2552 _mesa_problem(ctx
, "Bad depth texture mode");
2561 * Experimental depth texture sampling function.
2564 sample_depth_texture2(const GLcontext
*ctx
,
2565 const struct gl_texture_unit
*texUnit
,
2566 GLuint n
, const GLfloat texcoords
[][4],
2569 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2570 const GLint baseLevel
= texObj
->BaseLevel
;
2571 const struct gl_texture_image
*texImage
= texObj
->Image
[0][baseLevel
];
2572 const GLuint width
= texImage
->Width
;
2573 const GLuint height
= texImage
->Height
;
2575 GLboolean lequal
, gequal
;
2577 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2578 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2582 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2583 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2587 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2588 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2589 * isn't a depth texture.
2591 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2592 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2596 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2598 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2609 for (i
= 0; i
< n
; i
++) {
2611 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2614 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2616 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2624 if (imin
< 0) imin
= 0;
2625 if (imax
>= width
) imax
= width
- 1;
2626 if (jmin
< 0) jmin
= 0;
2627 if (jmax
>= height
) jmax
= height
- 1;
2629 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2631 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2632 for (ii
= imin
; ii
<= imax
; ii
++) {
2633 GLfloat depthSample
;
2634 texImage
->FetchTexelf(texImage
, ii
, jj
, 0, &depthSample
);
2635 if ((depthSample
<= r
[i
] && lequal
) ||
2636 (depthSample
>= r
[i
] && gequal
)) {
2642 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2643 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2646 texel
[i
][RCOMP
] = lum
;
2647 texel
[i
][GCOMP
] = lum
;
2648 texel
[i
][BCOMP
] = lum
;
2649 texel
[i
][ACOMP
] = CHAN_MAX
;
2657 * We use this function when a texture object is in an "incomplete" state.
2658 * When a fragment program attempts to sample an incomplete texture we
2659 * return black (see issue 23 in GL_ARB_fragment_program spec).
2660 * Note: fragment programss don't observe the texture enable/disable flags.
2663 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2664 const struct gl_texture_object
*tObj
, GLuint n
,
2665 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2674 for (i
= 0; i
< n
; i
++) {
2678 rgba
[i
][ACOMP
] = CHAN_MAX
;
2684 * Setup the texture sampling function for this texture object.
2687 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
2688 const struct gl_texture_object
*t
)
2690 if (!t
|| !t
->Complete
) {
2691 return &null_sample_func
;
2694 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2695 const GLenum format
= t
->Image
[0][t
->BaseLevel
]->Format
;
2697 switch (t
->Target
) {
2699 if (format
== GL_DEPTH_COMPONENT
) {
2700 return &sample_depth_texture
;
2702 else if (needLambda
) {
2703 return &sample_lambda_1d
;
2705 else if (t
->MinFilter
== GL_LINEAR
) {
2706 return &sample_linear_1d
;
2709 ASSERT(t
->MinFilter
== GL_NEAREST
);
2710 return &sample_nearest_1d
;
2714 if (format
== GL_DEPTH_COMPONENT
) {
2715 return &sample_depth_texture
;
2717 else if (needLambda
) {
2718 return &sample_lambda_2d
;
2720 else if (t
->MinFilter
== GL_LINEAR
) {
2721 return &sample_linear_2d
;
2724 GLint baseLevel
= t
->BaseLevel
;
2725 ASSERT(t
->MinFilter
== GL_NEAREST
);
2726 if (t
->WrapS
== GL_REPEAT
&&
2727 t
->WrapT
== GL_REPEAT
&&
2729 t
->Image
[0][baseLevel
]->Border
== 0 &&
2730 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2731 return &opt_sample_rgb_2d
;
2733 else if (t
->WrapS
== GL_REPEAT
&&
2734 t
->WrapT
== GL_REPEAT
&&
2736 t
->Image
[0][baseLevel
]->Border
== 0 &&
2737 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2738 return &opt_sample_rgba_2d
;
2741 return &sample_nearest_2d
;
2747 return &sample_lambda_3d
;
2749 else if (t
->MinFilter
== GL_LINEAR
) {
2750 return &sample_linear_3d
;
2753 ASSERT(t
->MinFilter
== GL_NEAREST
);
2754 return &sample_nearest_3d
;
2757 case GL_TEXTURE_CUBE_MAP
:
2759 return &sample_lambda_cube
;
2761 else if (t
->MinFilter
== GL_LINEAR
) {
2762 return &sample_linear_cube
;
2765 ASSERT(t
->MinFilter
== GL_NEAREST
);
2766 return &sample_nearest_cube
;
2769 case GL_TEXTURE_RECTANGLE_NV
:
2771 return &sample_lambda_rect
;
2773 else if (t
->MinFilter
== GL_LINEAR
) {
2774 return &sample_linear_rect
;
2777 ASSERT(t
->MinFilter
== GL_NEAREST
);
2778 return &sample_nearest_rect
;
2783 "invalid target in _swrast_choose_texture_sample_func");
2784 return &null_sample_func
;
2790 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2791 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2795 * Do texture application for GL_ARB/EXT_texture_env_combine.
2796 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
2797 * GL_ATI_texture_env_combine3. Since "classic" texture environments are
2798 * implemented using GL_ARB_texture_env_combine-like state, this same function
2799 * is used for classic texture environment application as well.
2801 * \param ctx rendering context
2802 * \param textureUnit the texture unit to apply
2803 * \param n number of fragments to process (span width)
2804 * \param primary_rgba incoming fragment color array
2805 * \param texelBuffer pointer to texel colors for all texture units
2807 * \param rgba incoming colors, which get modified here
2810 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
2811 CONST
GLchan (*primary_rgba
)[4],
2812 CONST GLchan
*texelBuffer
,
2815 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
2816 const GLchan (*argRGB
[3])[4];
2817 const GLchan (*argA
[3])[4];
2818 const GLuint RGBshift
= textureUnit
->_CurrentCombine
->ScaleShiftRGB
;
2819 const GLuint Ashift
= textureUnit
->_CurrentCombine
->ScaleShiftA
;
2820 #if CHAN_TYPE == GL_FLOAT
2821 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2822 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2823 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
2824 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
2826 const GLint half
= (CHAN_MAX
+ 1) / 2;
2827 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
2828 static const GLchan zero
[4] = { 0, 0, 0, 0 };
2831 GLuint numColorArgs
;
2832 GLuint numAlphaArgs
;
2834 /* GLchan ccolor[3][4]; */
2835 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2836 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2838 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2839 ctx
->Extensions
.ARB_texture_env_combine
);
2840 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
2844 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
2845 textureUnit->_CurrentCombine->ModeRGB,
2846 textureUnit->_CurrentCombine->ModeA,
2847 textureUnit->_CurrentCombine->SourceRGB[0],
2848 textureUnit->_CurrentCombine->SourceA[0],
2849 textureUnit->_CurrentCombine->SourceRGB[1],
2850 textureUnit->_CurrentCombine->SourceA[1]);
2854 * Do operand setup for up to 3 operands. Loop over the terms.
2856 numColorArgs
= textureUnit
->_CurrentCombine
->_NumArgsRGB
;
2857 numAlphaArgs
= textureUnit
->_CurrentCombine
->_NumArgsA
;
2859 for (j
= 0; j
< numColorArgs
; j
++) {
2860 const GLenum srcRGB
= textureUnit
->_CurrentCombine
->SourceRGB
[j
];
2865 argRGB
[j
] = (const GLchan (*)[4])
2866 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2868 case GL_PRIMARY_COLOR
:
2869 argRGB
[j
] = primary_rgba
;
2872 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2876 GLchan (*c
)[4] = ccolor
[j
];
2877 GLchan red
, green
, blue
, alpha
;
2878 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2879 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2880 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2881 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2882 for (i
= 0; i
< n
; i
++) {
2884 c
[i
][GCOMP
] = green
;
2886 c
[i
][ACOMP
] = alpha
;
2888 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2891 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
2900 /* ARB_texture_env_crossbar source */
2902 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
2903 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2904 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2906 argRGB
[j
] = (const GLchan (*)[4])
2907 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2911 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] != GL_SRC_COLOR
) {
2912 const GLchan (*src
)[4] = argRGB
[j
];
2913 GLchan (*dst
)[4] = ccolor
[j
];
2915 /* point to new arg[j] storage */
2916 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2918 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2919 for (i
= 0; i
< n
; i
++) {
2920 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2921 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2922 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2925 else if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_SRC_ALPHA
) {
2926 for (i
= 0; i
< n
; i
++) {
2927 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2928 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2929 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2933 ASSERT(textureUnit
->_CurrentCombine
->OperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2934 for (i
= 0; i
< n
; i
++) {
2935 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2936 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2937 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2944 for (j
= 0; j
< numAlphaArgs
; j
++) {
2945 const GLenum srcA
= textureUnit
->_CurrentCombine
->SourceA
[j
];
2949 argA
[j
] = (const GLchan (*)[4])
2950 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2952 case GL_PRIMARY_COLOR
:
2953 argA
[j
] = primary_rgba
;
2956 argA
[j
] = (const GLchan (*)[4]) rgba
;
2960 GLchan alpha
, (*c
)[4] = ccolor
[j
];
2961 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2962 for (i
= 0; i
< n
; i
++)
2963 c
[i
][ACOMP
] = alpha
;
2964 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2967 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
2976 /* ARB_texture_env_crossbar source */
2978 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
2979 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2980 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2982 argA
[j
] = (const GLchan (*)[4])
2983 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2987 if (textureUnit
->_CurrentCombine
->OperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
2988 const GLchan (*src
)[4] = argA
[j
];
2989 GLchan (*dst
)[4] = ccolor
[j
];
2990 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2991 for (i
= 0; i
< n
; i
++) {
2992 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2998 * Do the texture combine.
3000 switch (textureUnit
->_CurrentCombine
->ModeRGB
) {
3003 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3005 for (i
= 0; i
< n
; i
++) {
3006 #if CHAN_TYPE == GL_FLOAT
3007 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3008 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3009 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3011 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3012 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3013 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3014 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3015 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3016 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3021 for (i
= 0; i
< n
; i
++) {
3022 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3023 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3024 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3031 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3032 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3033 #if CHAN_TYPE != GL_FLOAT
3034 const GLint shift
= CHAN_BITS
- RGBshift
;
3036 for (i
= 0; i
< n
; i
++) {
3037 #if CHAN_TYPE == GL_FLOAT
3038 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3039 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3040 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3042 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3043 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3044 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3045 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3046 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3047 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3054 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3055 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3056 for (i
= 0; i
< n
; i
++) {
3057 #if CHAN_TYPE == GL_FLOAT
3058 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3059 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3060 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3062 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3063 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3064 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3065 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3066 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3067 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3074 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3075 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3076 for (i
= 0; i
< n
; i
++) {
3077 #if CHAN_TYPE == GL_FLOAT
3078 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3079 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3080 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3082 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3083 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3084 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3085 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3086 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3087 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3088 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3089 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3090 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3095 case GL_INTERPOLATE
:
3097 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3098 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3099 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3100 #if CHAN_TYPE != GL_FLOAT
3101 const GLint shift
= CHAN_BITS
- RGBshift
;
3103 for (i
= 0; i
< n
; i
++) {
3104 #if CHAN_TYPE == GL_FLOAT
3105 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3106 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3107 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3108 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3109 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3110 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3112 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3113 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3115 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3116 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3118 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3119 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3121 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3122 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3123 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3130 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3131 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3132 for (i
= 0; i
< n
; i
++) {
3133 #if CHAN_TYPE == GL_FLOAT
3134 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3135 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3136 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3138 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3139 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3140 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3141 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3142 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3143 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3148 case GL_DOT3_RGB_EXT
:
3149 case GL_DOT3_RGBA_EXT
:
3151 /* Do not scale the result by 1 2 or 4 */
3152 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3153 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3154 for (i
= 0; i
< n
; i
++) {
3155 #if CHAN_TYPE == GL_FLOAT
3156 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3157 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3158 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3160 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3162 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3163 (GLint
)arg1
[i
][RCOMP
] - half
) +
3164 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3165 (GLint
)arg1
[i
][GCOMP
] - half
) +
3166 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3167 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3168 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3170 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3177 /* DO scale the result by 1 2 or 4 */
3178 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3179 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3180 for (i
= 0; i
< n
; i
++) {
3181 #if CHAN_TYPE == GL_FLOAT
3182 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3183 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3184 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3186 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3188 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3189 (GLint
)arg1
[i
][RCOMP
] - half
) +
3190 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3191 (GLint
)arg1
[i
][GCOMP
] - half
) +
3192 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3193 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3195 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3197 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3201 case GL_MODULATE_ADD_ATI
:
3203 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3204 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3205 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3206 #if CHAN_TYPE != GL_FLOAT
3207 const GLint shift
= CHAN_BITS
- RGBshift
;
3209 for (i
= 0; i
< n
; i
++) {
3210 #if CHAN_TYPE == GL_FLOAT
3211 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3212 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3213 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3215 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3216 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3217 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3218 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3219 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3220 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3221 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3222 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3223 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3228 case GL_MODULATE_SIGNED_ADD_ATI
:
3230 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3231 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3232 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3233 #if CHAN_TYPE != GL_FLOAT
3234 const GLint shift
= CHAN_BITS
- RGBshift
;
3236 for (i
= 0; i
< n
; i
++) {
3237 #if CHAN_TYPE == GL_FLOAT
3238 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3239 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3240 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3242 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3243 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3245 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3246 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3248 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3249 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3251 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3252 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3253 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3258 case GL_MODULATE_SUBTRACT_ATI
:
3260 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3261 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3262 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3263 #if CHAN_TYPE != GL_FLOAT
3264 const GLint shift
= CHAN_BITS
- RGBshift
;
3266 for (i
= 0; i
< n
; i
++) {
3267 #if CHAN_TYPE == GL_FLOAT
3268 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3269 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3270 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3272 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3273 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3275 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3276 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3278 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3279 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3281 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3282 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3283 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3289 _mesa_problem(ctx
, "invalid combine mode");
3292 switch (textureUnit
->_CurrentCombine
->ModeA
) {
3295 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3297 for (i
= 0; i
< n
; i
++) {
3298 #if CHAN_TYPE == GL_FLOAT
3299 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3301 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3303 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3307 for (i
= 0; i
< n
; i
++) {
3308 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3315 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3316 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3317 #if CHAN_TYPE != GL_FLOAT
3318 const GLint shift
= CHAN_BITS
- Ashift
;
3320 for (i
= 0; i
< n
; i
++) {
3321 #if CHAN_TYPE == GL_FLOAT
3322 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3324 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3325 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3332 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3333 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3334 for (i
= 0; i
< n
; i
++) {
3335 #if CHAN_TYPE == GL_FLOAT
3336 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3338 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3339 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3346 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3347 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3348 for (i
= 0; i
< n
; i
++) {
3349 #if CHAN_TYPE == GL_FLOAT
3350 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3352 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3353 a
= (a
< 0) ? 0 : a
<< Ashift
;
3354 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3359 case GL_INTERPOLATE
:
3361 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3362 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3363 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3364 #if CHAN_TYPE != GL_FLOAT
3365 const GLint shift
= CHAN_BITS
- Ashift
;
3367 for (i
=0; i
<n
; i
++) {
3368 #if CHAN_TYPE == GL_FLOAT
3369 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3370 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3373 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3374 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3376 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3383 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3384 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3385 for (i
= 0; i
< n
; i
++) {
3386 #if CHAN_TYPE == GL_FLOAT
3387 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3389 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3390 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3395 case GL_MODULATE_ADD_ATI
:
3397 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3398 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3399 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3400 #if CHAN_TYPE != GL_FLOAT
3401 const GLint shift
= CHAN_BITS
- Ashift
;
3403 for (i
= 0; i
< n
; i
++) {
3404 #if CHAN_TYPE == GL_FLOAT
3405 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3407 GLint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3408 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3410 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3415 case GL_MODULATE_SIGNED_ADD_ATI
:
3417 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3418 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3419 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3420 #if CHAN_TYPE != GL_FLOAT
3421 const GLint shift
= CHAN_BITS
- Ashift
;
3423 for (i
= 0; i
< n
; i
++) {
3424 #if CHAN_TYPE == GL_FLOAT
3425 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3427 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3428 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3430 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3435 case GL_MODULATE_SUBTRACT_ATI
:
3437 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3438 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3439 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3440 #if CHAN_TYPE != GL_FLOAT
3441 const GLint shift
= CHAN_BITS
- Ashift
;
3443 for (i
= 0; i
< n
; i
++) {
3444 #if CHAN_TYPE == GL_FLOAT
3445 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3447 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3448 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3450 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3456 _mesa_problem(ctx
, "invalid combine mode");
3459 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3460 * This is kind of a kludge. It would have been better if the spec
3461 * were written such that the GL_COMBINE_ALPHA value could be set to
3464 if (textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
3465 textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) {
3466 for (i
= 0; i
< n
; i
++) {
3467 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3470 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3476 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3477 * MODULATE, or DECAL) to an array of fragments.
3478 * Input: textureUnit - pointer to texture unit to apply
3479 * format - base internal texture format
3480 * n - number of fragments
3481 * primary_rgba - primary colors (may alias rgba for single texture)
3482 * texels - array of texel colors
3483 * InOut: rgba - incoming fragment colors modified by texel colors
3484 * according to the texture environment mode.
3487 texture_apply( const GLcontext
*ctx
,
3488 const struct gl_texture_unit
*texUnit
,
3490 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3495 GLint Rc
, Gc
, Bc
, Ac
;
3499 ASSERT(texUnit
->_Current
);
3501 baseLevel
= texUnit
->_Current
->BaseLevel
;
3502 ASSERT(texUnit
->_Current
->Image
[0][baseLevel
]);
3504 format
= texUnit
->_Current
->Image
[0][baseLevel
]->Format
;
3506 if (format
== GL_COLOR_INDEX
|| format
== GL_YCBCR_MESA
) {
3507 format
= GL_RGBA
; /* a bit of a hack */
3509 else if (format
== GL_DEPTH_COMPONENT
) {
3510 format
= texUnit
->_Current
->DepthMode
;
3513 switch (texUnit
->EnvMode
) {
3520 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3526 GLchan Lt
= texel
[i
][RCOMP
];
3527 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3531 case GL_LUMINANCE_ALPHA
:
3533 GLchan Lt
= texel
[i
][RCOMP
];
3535 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3537 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3543 GLchan It
= texel
[i
][RCOMP
];
3544 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3546 rgba
[i
][ACOMP
] = It
;
3552 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3553 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3554 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3561 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3562 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3563 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3565 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3569 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3580 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3586 GLchan Lt
= texel
[i
][RCOMP
];
3587 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3588 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3589 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3593 case GL_LUMINANCE_ALPHA
:
3596 GLchan Lt
= texel
[i
][RCOMP
];
3597 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3598 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3599 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3601 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3607 GLchan It
= texel
[i
][RCOMP
];
3608 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3609 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3610 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3612 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3618 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3619 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3620 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3627 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3628 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3629 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3631 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3635 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3644 case GL_LUMINANCE_ALPHA
:
3651 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3652 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3653 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3659 /* Cv = Cf(1-At) + CtAt */
3660 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3661 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3662 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3663 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3668 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3674 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3675 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3676 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3677 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3683 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3688 /* Cv = Cf(1-Lt) + CcLt */
3689 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3690 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3691 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3692 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3696 case GL_LUMINANCE_ALPHA
:
3698 /* Cv = Cf(1-Lt) + CcLt */
3699 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3700 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3701 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3702 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3704 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3709 /* Cv = Cf(1-It) + CcLt */
3710 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3711 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3712 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3713 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3714 /* Av = Af(1-It) + Ac*It */
3715 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
3720 /* Cv = Cf(1-Ct) + CcCt */
3721 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3722 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3723 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3729 /* Cv = Cf(1-Ct) + CcCt */
3730 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3731 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3732 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3734 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3738 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
3743 /* XXX don't clamp results if GLchan is float??? */
3745 case GL_ADD
: /* GL_EXT_texture_add_env */
3752 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3757 GLuint Lt
= texel
[i
][RCOMP
];
3758 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3759 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3760 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3761 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3762 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3763 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3767 case GL_LUMINANCE_ALPHA
:
3769 GLuint Lt
= texel
[i
][RCOMP
];
3770 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3771 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3772 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3773 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3774 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3775 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3776 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3781 GLchan It
= texel
[i
][RCOMP
];
3782 GLuint r
= rgba
[i
][RCOMP
] + It
;
3783 GLuint g
= rgba
[i
][GCOMP
] + It
;
3784 GLuint b
= rgba
[i
][BCOMP
] + It
;
3785 GLuint a
= rgba
[i
][ACOMP
] + It
;
3786 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3787 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3788 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3789 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
3794 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3795 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3796 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3797 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3798 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3799 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3805 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3806 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3807 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3808 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3809 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3810 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3811 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3815 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
3821 _mesa_problem(ctx
, "Bad env mode in texture_apply");
3829 * Apply texture mapping to a span of fragments.
3832 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
3834 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
3835 GLchan primary_rgba
[MAX_WIDTH
][4];
3838 ASSERT(span
->end
< MAX_WIDTH
);
3839 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3842 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
3844 if (swrast
->_AnyTextureCombine
)
3845 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
3848 * Must do all texture sampling before combining in order to
3849 * accomodate GL_ARB_texture_env_crossbar.
3851 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3852 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3853 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3854 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
3855 GLfloat
*lambda
= span
->array
->lambda
[unit
];
3856 GLchan (*texels
)[4] = (GLchan (*)[4])
3857 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
3859 /* adjust texture lod (lambda) */
3860 if (span
->arrayMask
& SPAN_LAMBDA
) {
3861 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
3862 /* apply LOD bias, but don't clamp yet */
3863 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
3864 -ctx
->Const
.MaxTextureLodBias
,
3865 ctx
->Const
.MaxTextureLodBias
);
3867 for (i
= 0; i
< span
->end
; i
++) {
3872 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
3873 /* apply LOD clamping to lambda */
3874 const GLfloat min
= curObj
->MinLod
;
3875 const GLfloat max
= curObj
->MaxLod
;
3877 for (i
= 0; i
< span
->end
; i
++) {
3878 GLfloat l
= lambda
[i
];
3879 lambda
[i
] = CLAMP(l
, min
, max
);
3884 /* Sample the texture (span->end fragments) */
3885 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
3886 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
3889 /* GL_SGI_texture_color_table */
3890 if (texUnit
->ColorTableEnabled
) {
3891 _mesa_lookup_rgba_chan(&texUnit
->ColorTable
, span
->end
, texels
);
3897 * OK, now apply the texture (aka texture combine/blend).
3898 * We modify the span->color.rgba values.
3900 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3901 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3902 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3903 if (texUnit
->_CurrentCombine
!= &texUnit
->_EnvMode
) {
3904 texture_combine( ctx
, unit
, span
->end
,
3905 (CONST
GLchan (*)[4]) primary_rgba
,
3906 swrast
->TexelBuffer
,
3907 span
->array
->rgba
);
3910 /* conventional texture blend */
3911 const GLchan (*texels
)[4] = (const GLchan (*)[4])
3912 (swrast
->TexelBuffer
+ unit
*
3913 (span
->end
* 4 * sizeof(GLchan
)));
3914 texture_apply( ctx
, texUnit
, span
->end
,
3915 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
3916 span
->array
->rgba
);