2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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 * Constants for integer linear interpolation.
42 #define ILERP_SCALE 65536.0F
43 #define ILERP_SHIFT 16
47 * Linear interpolation macros
49 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
50 #define ILERP(IT, A, B) ( (A) + (((IT) * ((B) - (A))) >> ILERP_SHIFT) )
54 * Do 2D/biliner interpolation of float values.
55 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
56 * a and b are the horizontal and vertical interpolants.
57 * It's important that this function is inlined when compiled with
58 * optimization! If we find that's not true on some systems, convert
62 lerp_2d(GLfloat a
, GLfloat b
,
63 GLfloat v00
, GLfloat v10
, GLfloat v01
, GLfloat v11
)
65 const GLfloat temp0
= LERP(a
, v00
, v10
);
66 const GLfloat temp1
= LERP(a
, v01
, v11
);
67 return LERP(b
, temp0
, temp1
);
72 * Do 2D/biliner interpolation of integer values.
76 ilerp_2d(GLint ia
, GLint ib
,
77 GLint v00
, GLint v10
, GLint v01
, GLint v11
)
79 /* fixed point interpolants in [0, ILERP_SCALE] */
80 const GLint temp0
= ILERP(ia
, v00
, v10
);
81 const GLint temp1
= ILERP(ia
, v01
, v11
);
82 return ILERP(ib
, temp0
, temp1
);
87 * Do 3D/trilinear interpolation of float values.
91 lerp_3d(GLfloat a
, GLfloat b
, GLfloat c
,
92 GLfloat v000
, GLfloat v100
, GLfloat v010
, GLfloat v110
,
93 GLfloat v001
, GLfloat v101
, GLfloat v011
, GLfloat v111
)
95 const GLfloat temp00
= LERP(a
, v000
, v100
);
96 const GLfloat temp10
= LERP(a
, v010
, v110
);
97 const GLfloat temp01
= LERP(a
, v001
, v101
);
98 const GLfloat temp11
= LERP(a
, v011
, v111
);
99 const GLfloat temp0
= LERP(b
, temp00
, temp10
);
100 const GLfloat temp1
= LERP(b
, temp01
, temp11
);
101 return LERP(c
, temp0
, temp1
);
106 * Do 3D/trilinear interpolation of integer values.
110 ilerp_3d(GLint ia
, GLint ib
, GLint ic
,
111 GLint v000
, GLint v100
, GLint v010
, GLint v110
,
112 GLint v001
, GLint v101
, GLint v011
, GLint v111
)
114 /* fixed point interpolants in [0, ILERP_SCALE] */
115 const GLint temp00
= ILERP(ia
, v000
, v100
);
116 const GLint temp10
= ILERP(ia
, v010
, v110
);
117 const GLint temp01
= ILERP(ia
, v001
, v101
);
118 const GLint temp11
= ILERP(ia
, v011
, v111
);
119 const GLint temp0
= ILERP(ib
, temp00
, temp10
);
120 const GLint temp1
= ILERP(ib
, temp01
, temp11
);
121 return ILERP(ic
, temp0
, temp1
);
127 * Compute the remainder of a divided by b, but be careful with
128 * negative values so that GL_REPEAT mode works right.
131 repeat_remainder(GLint a
, GLint b
)
136 return (a
+ 1) % b
+ b
- 1;
141 * Used to compute texel locations for linear sampling.
143 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
144 * S = texcoord in [0,1]
145 * SIZE = width (or height or depth) of texture
147 * U = texcoord in [0, width]
148 * I0, I1 = two nearest texel indexes
150 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
152 if (wrapMode == GL_REPEAT) { \
153 U = S * SIZE - 0.5F; \
154 if (tObj->_IsPowerOfTwo) { \
155 I0 = IFLOOR(U) & (SIZE - 1); \
156 I1 = (I0 + 1) & (SIZE - 1); \
159 I0 = repeat_remainder(IFLOOR(U), SIZE); \
160 I1 = repeat_remainder(I0 + 1, SIZE); \
163 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
166 else if (S >= 1.0F) \
167 U = (GLfloat) SIZE; \
175 if (I1 >= (GLint) SIZE) \
178 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
179 const GLfloat min = -1.0F / (2.0F * SIZE); \
180 const GLfloat max = 1.0F - min; \
191 else if (wrapMode == GL_MIRRORED_REPEAT) { \
192 const GLint flr = IFLOOR(S); \
194 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
196 U = S - (GLfloat) flr; /* flr is even */ \
197 U = (U * SIZE) - 0.5F; \
202 if (I1 >= (GLint) SIZE) \
205 else if (wrapMode == GL_MIRROR_CLAMP_EXT) { \
206 U = (GLfloat) fabs(S); \
208 U = (GLfloat) SIZE; \
215 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) { \
216 U = (GLfloat) fabs(S); \
218 U = (GLfloat) SIZE; \
226 if (I1 >= (GLint) SIZE) \
229 else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) { \
230 const GLfloat min = -1.0F / (2.0F * SIZE); \
231 const GLfloat max = 1.0F - min; \
232 U = (GLfloat) fabs(S); \
244 ASSERT(wrapMode == GL_CLAMP); \
247 else if (S >= 1.0F) \
248 U = (GLfloat) SIZE; \
259 * Used to compute texel location for nearest sampling.
261 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
263 if (wrapMode == GL_REPEAT) { \
264 /* s limited to [0,1) */ \
265 /* i limited to [0,size-1] */ \
266 I = IFLOOR(S * SIZE); \
267 if (tObj->_IsPowerOfTwo) \
270 I = repeat_remainder(I, SIZE); \
272 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
273 /* s limited to [min,max] */ \
274 /* i limited to [0, size-1] */ \
275 const GLfloat min = 1.0F / (2.0F * SIZE); \
276 const GLfloat max = 1.0F - min; \
282 I = IFLOOR(S * SIZE); \
284 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
285 /* s limited to [min,max] */ \
286 /* i limited to [-1, size] */ \
287 const GLfloat min = -1.0F / (2.0F * SIZE); \
288 const GLfloat max = 1.0F - min; \
294 I = IFLOOR(S * SIZE); \
296 else if (wrapMode == GL_MIRRORED_REPEAT) { \
297 const GLfloat min = 1.0F / (2.0F * SIZE); \
298 const GLfloat max = 1.0F - min; \
299 const GLint flr = IFLOOR(S); \
302 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
304 u = S - (GLfloat) flr; /* flr is even */ \
310 I = IFLOOR(u * SIZE); \
312 else if (wrapMode == GL_MIRROR_CLAMP_EXT) { \
313 /* s limited to [0,1] */ \
314 /* i limited to [0,size-1] */ \
315 const GLfloat u = (GLfloat) fabs(S); \
318 else if (u >= 1.0F) \
321 I = IFLOOR(u * SIZE); \
323 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) { \
324 /* s limited to [min,max] */ \
325 /* i limited to [0, size-1] */ \
326 const GLfloat min = 1.0F / (2.0F * SIZE); \
327 const GLfloat max = 1.0F - min; \
328 const GLfloat u = (GLfloat) fabs(S); \
334 I = IFLOOR(u * SIZE); \
336 else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) { \
337 /* s limited to [min,max] */ \
338 /* i limited to [0, size-1] */ \
339 const GLfloat min = -1.0F / (2.0F * SIZE); \
340 const GLfloat max = 1.0F - min; \
341 const GLfloat u = (GLfloat) fabs(S); \
347 I = IFLOOR(u * SIZE); \
350 ASSERT(wrapMode == GL_CLAMP); \
351 /* s limited to [0,1] */ \
352 /* i limited to [0,size-1] */ \
355 else if (S >= 1.0F) \
358 I = IFLOOR(S * SIZE); \
363 /* Power of two image sizes only */
364 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
366 U = S * SIZE - 0.5F; \
367 I0 = IFLOOR(U) & (SIZE - 1); \
368 I1 = (I0 + 1) & (SIZE - 1); \
373 * Compute linear mipmap levels for given lambda.
375 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
378 level = tObj->BaseLevel; \
379 else if (lambda > tObj->_MaxLambda) \
380 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
382 level = (GLint) (tObj->BaseLevel + lambda); \
387 * Compute nearest mipmap level for given lambda.
389 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
392 if (lambda <= 0.5F) \
394 else if (lambda > tObj->_MaxLambda + 0.4999F) \
395 l = tObj->_MaxLambda + 0.4999F; \
398 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
399 if (level > tObj->_MaxLevel) \
400 level = tObj->_MaxLevel; \
406 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
407 * see 1-pixel bands of improperly weighted linear-sampled texels. The
408 * tests/texwrap.c demo is a good test.
409 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
410 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
412 #define FRAC(f) ((f) - IFLOOR(f))
417 * Bitflags for texture border color sampling.
429 * The lambda[] array values are always monotonic. Either the whole span
430 * will be minified, magnified, or split between the two. This function
431 * determines the subranges in [0, n-1] that are to be minified or magnified.
434 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
435 GLuint
*minStart
, GLuint
*minEnd
,
436 GLuint
*magStart
, GLuint
*magEnd
)
438 ASSERT(lambda
!= NULL
);
440 /* Verify that lambda[] is monotonous.
441 * We can't really use this because the inaccuracy in the LOG2 function
442 * causes this test to fail, yet the resulting texturing is correct.
446 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
447 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
448 for (i
= 0; i
< n
- 1; i
++) {
449 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
452 else { /* increasing */
453 for (i
= 0; i
< n
- 1; i
++) {
454 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
460 /* since lambda is monotonous-array use this check first */
461 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
462 /* magnification for whole span */
465 *minStart
= *minEnd
= 0;
467 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
468 /* minification for whole span */
471 *magStart
= *magEnd
= 0;
474 /* a mix of minification and magnification */
476 if (lambda
[0] > minMagThresh
) {
477 /* start with minification */
478 for (i
= 1; i
< n
; i
++) {
479 if (lambda
[i
] <= minMagThresh
)
488 /* start with magnification */
489 for (i
= 1; i
< n
; i
++) {
490 if (lambda
[i
] > minMagThresh
)
501 /* Verify the min/mag Start/End values
502 * We don't use this either (see above)
506 for (i
= 0; i
< n
; i
++) {
507 if (lambda
[i
] > minMagThresh
) {
509 ASSERT(i
>= *minStart
);
514 ASSERT(i
>= *magStart
);
523 /**********************************************************************/
524 /* 1-D Texture Sampling Functions */
525 /**********************************************************************/
528 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
531 sample_1d_nearest(GLcontext
*ctx
,
532 const struct gl_texture_object
*tObj
,
533 const struct gl_texture_image
*img
,
534 const GLfloat texcoord
[4], GLchan rgba
[4])
536 const GLint width
= img
->Width2
; /* without border, power of two */
540 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
542 /* skip over the border, if any */
545 if (i
< 0 || i
>= (GLint
) img
->Width
) {
546 /* Need this test for GL_CLAMP_TO_BORDER mode */
547 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
550 img
->FetchTexelc(img
, i
, 0, 0, rgba
);
557 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
560 sample_1d_linear(GLcontext
*ctx
,
561 const struct gl_texture_object
*tObj
,
562 const struct gl_texture_image
*img
,
563 const GLfloat texcoord
[4], GLchan rgba
[4])
565 const GLint width
= img
->Width2
;
568 GLuint useBorderColor
;
571 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
579 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
580 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
584 const GLfloat a
= FRAC(u
);
585 GLchan t0
[4], t1
[4]; /* texels */
587 /* fetch texel colors */
588 if (useBorderColor
& I0BIT
) {
589 COPY_CHAN4(t0
, tObj
->_BorderChan
);
592 img
->FetchTexelc(img
, i0
, 0, 0, t0
);
594 if (useBorderColor
& I1BIT
) {
595 COPY_CHAN4(t1
, tObj
->_BorderChan
);
598 img
->FetchTexelc(img
, i1
, 0, 0, t1
);
601 /* do linear interpolation of texel colors */
602 #if CHAN_TYPE == GL_FLOAT
603 rgba
[0] = LERP(a
, t0
[0], t1
[0]);
604 rgba
[1] = LERP(a
, t0
[1], t1
[1]);
605 rgba
[2] = LERP(a
, t0
[2], t1
[2]);
606 rgba
[3] = LERP(a
, t0
[3], t1
[3]);
607 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
608 rgba
[0] = (GLchan
) (LERP(a
, t0
[0], t1
[0]) + 0.5);
609 rgba
[1] = (GLchan
) (LERP(a
, t0
[1], t1
[1]) + 0.5);
610 rgba
[2] = (GLchan
) (LERP(a
, t0
[2], t1
[2]) + 0.5);
611 rgba
[3] = (GLchan
) (LERP(a
, t0
[3], t1
[3]) + 0.5);
613 ASSERT(CHAN_TYPE
== GL_UNSIGNED_BYTE
);
615 /* fixed point interpolants in [0, ILERP_SCALE] */
616 const GLint ia
= IROUND_POS(a
* ILERP_SCALE
);
617 rgba
[0] = ILERP(ia
, t0
[0], t1
[0]);
618 rgba
[1] = ILERP(ia
, t0
[1], t1
[1]);
619 rgba
[2] = ILERP(ia
, t0
[2], t1
[2]);
620 rgba
[3] = ILERP(ia
, t0
[3], t1
[3]);
628 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
629 const struct gl_texture_object
*tObj
,
630 GLuint n
, const GLfloat texcoord
[][4],
631 const GLfloat lambda
[], GLchan rgba
[][4])
634 ASSERT(lambda
!= NULL
);
635 for (i
= 0; i
< n
; i
++) {
637 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
638 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
644 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
645 const struct gl_texture_object
*tObj
,
646 GLuint n
, const GLfloat texcoord
[][4],
647 const GLfloat lambda
[], GLchan rgba
[][4])
650 ASSERT(lambda
!= NULL
);
651 for (i
= 0; i
< n
; i
++) {
653 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
654 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
661 * This is really just needed in order to prevent warnings with some compilers.
663 #if CHAN_TYPE == GL_FLOAT
666 #define CHAN_CAST (GLchan) (GLint)
671 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
672 const struct gl_texture_object
*tObj
,
673 GLuint n
, const GLfloat texcoord
[][4],
674 const GLfloat lambda
[], GLchan rgba
[][4])
677 ASSERT(lambda
!= NULL
);
678 for (i
= 0; i
< n
; i
++) {
680 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
681 if (level
>= tObj
->_MaxLevel
) {
682 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
683 texcoord
[i
], rgba
[i
]);
687 const GLfloat f
= FRAC(lambda
[i
]);
688 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
689 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
690 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
691 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
692 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
693 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
701 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
702 const struct gl_texture_object
*tObj
,
703 GLuint n
, const GLfloat texcoord
[][4],
704 const GLfloat lambda
[], GLchan rgba
[][4])
707 ASSERT(lambda
!= NULL
);
708 for (i
= 0; i
< n
; i
++) {
710 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
711 if (level
>= tObj
->_MaxLevel
) {
712 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
713 texcoord
[i
], rgba
[i
]);
717 const GLfloat f
= FRAC(lambda
[i
]);
718 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
719 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
720 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
721 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
722 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
723 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
731 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
732 const struct gl_texture_object
*tObj
, GLuint n
,
733 const GLfloat texcoords
[][4], const GLfloat lambda
[],
737 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
741 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
748 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
749 const struct gl_texture_object
*tObj
, GLuint n
,
750 const GLfloat texcoords
[][4], const GLfloat lambda
[],
754 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
758 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
764 * Given an (s) texture coordinate and lambda (level of detail) value,
765 * return a texture sample.
769 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
770 const struct gl_texture_object
*tObj
, GLuint n
,
771 const GLfloat texcoords
[][4],
772 const GLfloat lambda
[], GLchan rgba
[][4] )
774 GLuint minStart
, minEnd
; /* texels with minification */
775 GLuint magStart
, magEnd
; /* texels with magnification */
778 ASSERT(lambda
!= NULL
);
779 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
780 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
782 if (minStart
< minEnd
) {
783 /* do the minified texels */
784 const GLuint m
= minEnd
- minStart
;
785 switch (tObj
->MinFilter
) {
787 for (i
= minStart
; i
< minEnd
; i
++)
788 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
789 texcoords
[i
], rgba
[i
]);
792 for (i
= minStart
; i
< minEnd
; i
++)
793 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
794 texcoords
[i
], rgba
[i
]);
796 case GL_NEAREST_MIPMAP_NEAREST
:
797 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
798 lambda
+ minStart
, rgba
+ minStart
);
800 case GL_LINEAR_MIPMAP_NEAREST
:
801 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
802 lambda
+ minStart
, rgba
+ minStart
);
804 case GL_NEAREST_MIPMAP_LINEAR
:
805 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
806 lambda
+ minStart
, rgba
+ minStart
);
808 case GL_LINEAR_MIPMAP_LINEAR
:
809 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
810 lambda
+ minStart
, rgba
+ minStart
);
813 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
818 if (magStart
< magEnd
) {
819 /* do the magnified texels */
820 switch (tObj
->MagFilter
) {
822 for (i
= magStart
; i
< magEnd
; i
++)
823 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
824 texcoords
[i
], rgba
[i
]);
827 for (i
= magStart
; i
< magEnd
; i
++)
828 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
829 texcoords
[i
], rgba
[i
]);
832 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
839 /**********************************************************************/
840 /* 2-D Texture Sampling Functions */
841 /**********************************************************************/
845 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
848 sample_2d_nearest(GLcontext
*ctx
,
849 const struct gl_texture_object
*tObj
,
850 const struct gl_texture_image
*img
,
851 const GLfloat texcoord
[4],
854 const GLint width
= img
->Width2
; /* without border, power of two */
855 const GLint height
= img
->Height2
; /* without border, power of two */
859 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
860 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
862 /* skip over the border, if any */
866 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
867 /* Need this test for GL_CLAMP_TO_BORDER mode */
868 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
871 img
->FetchTexelc(img
, i
, j
, 0, rgba
);
878 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
879 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
882 sample_2d_linear(GLcontext
*ctx
,
883 const struct gl_texture_object
*tObj
,
884 const struct gl_texture_image
*img
,
885 const GLfloat texcoord
[4],
888 const GLint width
= img
->Width2
;
889 const GLint height
= img
->Height2
;
890 GLint i0
, j0
, i1
, j1
;
891 GLuint useBorderColor
;
895 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
896 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
906 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
907 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
908 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
909 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
913 const GLfloat a
= FRAC(u
);
914 const GLfloat b
= FRAC(v
);
915 #if CHAN_TYPE == GL_UNSIGNED_BYTE
916 const GLint ia
= IROUND_POS(a
* ILERP_SCALE
);
917 const GLint ib
= IROUND_POS(b
* ILERP_SCALE
);
919 GLchan t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
921 /* fetch four texel colors */
922 if (useBorderColor
& (I0BIT
| J0BIT
)) {
923 COPY_CHAN4(t00
, tObj
->_BorderChan
);
926 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
928 if (useBorderColor
& (I1BIT
| J0BIT
)) {
929 COPY_CHAN4(t10
, tObj
->_BorderChan
);
932 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
934 if (useBorderColor
& (I0BIT
| J1BIT
)) {
935 COPY_CHAN4(t01
, tObj
->_BorderChan
);
938 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
940 if (useBorderColor
& (I1BIT
| J1BIT
)) {
941 COPY_CHAN4(t11
, tObj
->_BorderChan
);
944 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
947 /* do bilinear interpolation of texel colors */
948 #if CHAN_TYPE == GL_FLOAT
949 rgba
[0] = lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]);
950 rgba
[1] = lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]);
951 rgba
[2] = lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]);
952 rgba
[3] = lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]);
953 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
954 rgba
[0] = (GLchan
) (lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]) + 0.5);
955 rgba
[1] = (GLchan
) (lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]) + 0.5);
956 rgba
[2] = (GLchan
) (lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]) + 0.5);
957 rgba
[3] = (GLchan
) (lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]) + 0.5);
959 ASSERT(CHAN_TYPE
== GL_UNSIGNED_BYTE
);
960 rgba
[0] = ilerp_2d(ia
, ib
, t00
[0], t10
[0], t01
[0], t11
[0]);
961 rgba
[1] = ilerp_2d(ia
, ib
, t00
[1], t10
[1], t01
[1], t11
[1]);
962 rgba
[2] = ilerp_2d(ia
, ib
, t00
[2], t10
[2], t01
[2], t11
[2]);
963 rgba
[3] = ilerp_2d(ia
, ib
, t00
[3], t10
[3], t01
[3], t11
[3]);
970 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
973 sample_2d_linear_repeat(GLcontext
*ctx
,
974 const struct gl_texture_object
*tObj
,
975 const struct gl_texture_image
*img
,
976 const GLfloat texcoord
[4],
979 const GLint width
= img
->Width2
;
980 const GLint height
= img
->Height2
;
981 GLint i0
, j0
, i1
, j1
;
986 ASSERT(tObj
->WrapS
== GL_REPEAT
);
987 ASSERT(tObj
->WrapT
== GL_REPEAT
);
988 ASSERT(img
->Border
== 0);
989 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
990 ASSERT(img
->_IsPowerOfTwo
);
992 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
993 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
996 const GLfloat a
= FRAC(u
);
997 const GLfloat b
= FRAC(v
);
998 #if CHAN_TYPE == GL_UNSIGNED_BYTE
999 const GLint ia
= IROUND_POS(a
* ILERP_SCALE
);
1000 const GLint ib
= IROUND_POS(b
* ILERP_SCALE
);
1002 GLchan t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
1004 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
1005 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
1006 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
1007 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
1009 /* do bilinear interpolation of texel colors */
1010 #if CHAN_TYPE == GL_FLOAT
1011 rgba
[0] = lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]);
1012 rgba
[1] = lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]);
1013 rgba
[2] = lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]);
1014 rgba
[3] = lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]);
1015 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1016 rgba
[0] = (GLchan
) (lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]) + 0.5);
1017 rgba
[1] = (GLchan
) (lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]) + 0.5);
1018 rgba
[2] = (GLchan
) (lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]) + 0.5);
1019 rgba
[3] = (GLchan
) (lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]) + 0.5);
1021 ASSERT(CHAN_TYPE
== GL_UNSIGNED_BYTE
);
1022 rgba
[0] = ilerp_2d(ia
, ib
, t00
[0], t10
[0], t01
[0], t11
[0]);
1023 rgba
[1] = ilerp_2d(ia
, ib
, t00
[1], t10
[1], t01
[1], t11
[1]);
1024 rgba
[2] = ilerp_2d(ia
, ib
, t00
[2], t10
[2], t01
[2], t11
[2]);
1025 rgba
[3] = ilerp_2d(ia
, ib
, t00
[3], t10
[3], t01
[3], t11
[3]);
1033 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1034 const struct gl_texture_object
*tObj
,
1035 GLuint n
, const GLfloat texcoord
[][4],
1036 const GLfloat lambda
[], GLchan rgba
[][4])
1039 for (i
= 0; i
< n
; i
++) {
1041 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1042 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1049 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1050 const struct gl_texture_object
*tObj
,
1051 GLuint n
, const GLfloat texcoord
[][4],
1052 const GLfloat lambda
[], GLchan rgba
[][4])
1055 ASSERT(lambda
!= NULL
);
1056 for (i
= 0; i
< n
; i
++) {
1058 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1059 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1066 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1067 const struct gl_texture_object
*tObj
,
1068 GLuint n
, const GLfloat texcoord
[][4],
1069 const GLfloat lambda
[], GLchan rgba
[][4])
1072 ASSERT(lambda
!= NULL
);
1073 for (i
= 0; i
< n
; i
++) {
1075 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1076 if (level
>= tObj
->_MaxLevel
) {
1077 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1078 texcoord
[i
], rgba
[i
]);
1081 GLchan t0
[4], t1
[4]; /* texels */
1082 const GLfloat f
= FRAC(lambda
[i
]);
1083 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1084 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1085 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1086 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1087 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1088 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1095 /* Trilinear filtering */
1097 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1098 const struct gl_texture_object
*tObj
,
1099 GLuint n
, const GLfloat texcoord
[][4],
1100 const GLfloat lambda
[], GLchan rgba
[][4] )
1103 ASSERT(lambda
!= NULL
);
1104 for (i
= 0; i
< n
; i
++) {
1106 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1107 if (level
>= tObj
->_MaxLevel
) {
1108 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1109 texcoord
[i
], rgba
[i
]);
1112 GLchan t0
[4], t1
[4]; /* texels */
1113 const GLfloat f
= FRAC(lambda
[i
]);
1114 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1115 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1116 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1117 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1118 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1119 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1126 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1127 const struct gl_texture_object
*tObj
,
1128 GLuint n
, const GLfloat texcoord
[][4],
1129 const GLfloat lambda
[], GLchan rgba
[][4] )
1132 ASSERT(lambda
!= NULL
);
1133 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1134 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1135 ASSERT(tObj
->_IsPowerOfTwo
);
1136 for (i
= 0; i
< n
; i
++) {
1138 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1139 if (level
>= tObj
->_MaxLevel
) {
1140 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1141 texcoord
[i
], rgba
[i
]);
1144 GLchan t0
[4], t1
[4]; /* texels */
1145 const GLfloat f
= FRAC(lambda
[i
]);
1146 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1147 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1148 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1149 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1150 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1151 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1158 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1159 const struct gl_texture_object
*tObj
, GLuint n
,
1160 const GLfloat texcoords
[][4],
1161 const GLfloat lambda
[], GLchan rgba
[][4] )
1164 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1168 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1175 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1176 const struct gl_texture_object
*tObj
, GLuint n
,
1177 const GLfloat texcoords
[][4],
1178 const GLfloat lambda
[], GLchan rgba
[][4] )
1181 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1184 if (tObj
->WrapS
== GL_REPEAT
&& tObj
->WrapT
== GL_REPEAT
) {
1186 sample_2d_linear_repeat(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1191 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1198 * Optimized 2-D texture sampling:
1199 * S and T wrap mode == GL_REPEAT
1200 * GL_NEAREST min/mag filter
1202 * RowStride == Width,
1206 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1207 const struct gl_texture_object
*tObj
,
1208 GLuint n
, const GLfloat texcoords
[][4],
1209 const GLfloat lambda
[], GLchan rgba
[][4] )
1211 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1212 const GLfloat width
= (GLfloat
) img
->Width
;
1213 const GLfloat height
= (GLfloat
) img
->Height
;
1214 const GLint colMask
= img
->Width
- 1;
1215 const GLint rowMask
= img
->Height
- 1;
1216 const GLint shift
= img
->WidthLog2
;
1221 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1222 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1223 ASSERT(img
->Border
==0);
1224 ASSERT(img
->Format
==GL_RGB
);
1225 ASSERT(img
->_IsPowerOfTwo
);
1227 for (k
=0; k
<n
; k
++) {
1228 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1229 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1230 GLint pos
= (j
<< shift
) | i
;
1231 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1232 rgba
[k
][RCOMP
] = texel
[0];
1233 rgba
[k
][GCOMP
] = texel
[1];
1234 rgba
[k
][BCOMP
] = texel
[2];
1240 * Optimized 2-D texture sampling:
1241 * S and T wrap mode == GL_REPEAT
1242 * GL_NEAREST min/mag filter
1244 * RowStride == Width,
1248 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1249 const struct gl_texture_object
*tObj
,
1250 GLuint n
, const GLfloat texcoords
[][4],
1251 const GLfloat lambda
[], GLchan rgba
[][4] )
1253 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1254 const GLfloat width
= (GLfloat
) img
->Width
;
1255 const GLfloat height
= (GLfloat
) img
->Height
;
1256 const GLint colMask
= img
->Width
- 1;
1257 const GLint rowMask
= img
->Height
- 1;
1258 const GLint shift
= img
->WidthLog2
;
1263 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1264 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1265 ASSERT(img
->Border
==0);
1266 ASSERT(img
->Format
==GL_RGBA
);
1267 ASSERT(img
->_IsPowerOfTwo
);
1269 for (i
= 0; i
< n
; i
++) {
1270 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1271 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1272 const GLint pos
= (row
<< shift
) | col
;
1273 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1274 COPY_CHAN4(rgba
[i
], texel
);
1280 * Given an array of texture coordinate and lambda (level of detail)
1281 * values, return an array of texture sample.
1284 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1285 const struct gl_texture_object
*tObj
,
1286 GLuint n
, const GLfloat texcoords
[][4],
1287 const GLfloat lambda
[], GLchan rgba
[][4] )
1289 const struct gl_texture_image
*tImg
= tObj
->Image
[0][tObj
->BaseLevel
];
1290 GLuint minStart
, minEnd
; /* texels with minification */
1291 GLuint magStart
, magEnd
; /* texels with magnification */
1293 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1294 && (tObj
->WrapT
== GL_REPEAT
)
1295 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1296 && (tImg
->Format
!= GL_COLOR_INDEX
)
1297 && tImg
->_IsPowerOfTwo
;
1299 ASSERT(lambda
!= NULL
);
1300 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1301 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1303 if (minStart
< minEnd
) {
1304 /* do the minified texels */
1305 const GLuint m
= minEnd
- minStart
;
1306 switch (tObj
->MinFilter
) {
1308 if (repeatNoBorderPOT
) {
1309 switch (tImg
->TexFormat
->MesaFormat
) {
1310 case MESA_FORMAT_RGB
:
1311 case MESA_FORMAT_RGB888
:
1312 /*case MESA_FORMAT_BGR888:*/
1313 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1314 NULL
, rgba
+ minStart
);
1316 case MESA_FORMAT_RGBA
:
1317 case MESA_FORMAT_RGBA8888
:
1318 case MESA_FORMAT_ARGB8888
:
1319 /*case MESA_FORMAT_ABGR8888:*/
1320 /*case MESA_FORMAT_BGRA8888:*/
1321 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1322 NULL
, rgba
+ minStart
);
1325 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1326 NULL
, rgba
+ minStart
);
1330 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1331 NULL
, rgba
+ minStart
);
1335 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1336 NULL
, rgba
+ minStart
);
1338 case GL_NEAREST_MIPMAP_NEAREST
:
1339 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1340 texcoords
+ minStart
,
1341 lambda
+ minStart
, rgba
+ minStart
);
1343 case GL_LINEAR_MIPMAP_NEAREST
:
1344 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1345 lambda
+ minStart
, rgba
+ minStart
);
1347 case GL_NEAREST_MIPMAP_LINEAR
:
1348 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1349 lambda
+ minStart
, rgba
+ minStart
);
1351 case GL_LINEAR_MIPMAP_LINEAR
:
1352 if (repeatNoBorderPOT
)
1353 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1354 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1356 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1357 lambda
+ minStart
, rgba
+ minStart
);
1360 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1365 if (magStart
< magEnd
) {
1366 /* do the magnified texels */
1367 const GLuint m
= magEnd
- magStart
;
1369 switch (tObj
->MagFilter
) {
1371 if (repeatNoBorderPOT
) {
1372 switch (tImg
->TexFormat
->MesaFormat
) {
1373 case MESA_FORMAT_RGB
:
1374 case MESA_FORMAT_RGB888
:
1375 /*case MESA_FORMAT_BGR888:*/
1376 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1377 NULL
, rgba
+ magStart
);
1379 case MESA_FORMAT_RGBA
:
1380 case MESA_FORMAT_RGBA8888
:
1381 case MESA_FORMAT_ARGB8888
:
1382 /*case MESA_FORMAT_ABGR8888:*/
1383 /*case MESA_FORMAT_BGRA8888:*/
1384 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1385 NULL
, rgba
+ magStart
);
1388 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1389 NULL
, rgba
+ magStart
);
1393 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1394 NULL
, rgba
+ magStart
);
1398 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1399 NULL
, rgba
+ magStart
);
1402 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1409 /**********************************************************************/
1410 /* 3-D Texture Sampling Functions */
1411 /**********************************************************************/
1414 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1417 sample_3d_nearest(GLcontext
*ctx
,
1418 const struct gl_texture_object
*tObj
,
1419 const struct gl_texture_image
*img
,
1420 const GLfloat texcoord
[4],
1423 const GLint width
= img
->Width2
; /* without border, power of two */
1424 const GLint height
= img
->Height2
; /* without border, power of two */
1425 const GLint depth
= img
->Depth2
; /* without border, power of two */
1429 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1430 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1431 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1433 if (i
< 0 || i
>= (GLint
) img
->Width
||
1434 j
< 0 || j
>= (GLint
) img
->Height
||
1435 k
< 0 || k
>= (GLint
) img
->Depth
) {
1436 /* Need this test for GL_CLAMP_TO_BORDER mode */
1437 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1440 img
->FetchTexelc(img
, i
, j
, k
, rgba
);
1447 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1450 sample_3d_linear(GLcontext
*ctx
,
1451 const struct gl_texture_object
*tObj
,
1452 const struct gl_texture_image
*img
,
1453 const GLfloat texcoord
[4],
1456 const GLint width
= img
->Width2
;
1457 const GLint height
= img
->Height2
;
1458 const GLint depth
= img
->Depth2
;
1459 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1460 GLuint useBorderColor
;
1464 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1465 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1466 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1478 /* check if sampling texture border color */
1479 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1480 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1481 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1482 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1483 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1484 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1488 const GLfloat a
= FRAC(u
);
1489 const GLfloat b
= FRAC(v
);
1490 const GLfloat c
= FRAC(w
);
1491 #if CHAN_TYPE == GL_UNSIGNED_BYTE
1492 const GLint ia
= IROUND_POS(a
* ILERP_SCALE
);
1493 const GLint ib
= IROUND_POS(b
* ILERP_SCALE
);
1494 const GLint ic
= IROUND_POS(c
* ILERP_SCALE
);
1496 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1497 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1500 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1501 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1504 img
->FetchTexelc(img
, i0
, j0
, k0
, t000
);
1506 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1507 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1510 img
->FetchTexelc(img
, i1
, j0
, k0
, t100
);
1512 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1513 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1516 img
->FetchTexelc(img
, i0
, j1
, k0
, t010
);
1518 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1519 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1522 img
->FetchTexelc(img
, i1
, j1
, k0
, t110
);
1525 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1526 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1529 img
->FetchTexelc(img
, i0
, j0
, k1
, t001
);
1531 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1532 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1535 img
->FetchTexelc(img
, i1
, j0
, k1
, t101
);
1537 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1538 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1541 img
->FetchTexelc(img
, i0
, j1
, k1
, t011
);
1543 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1544 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1547 img
->FetchTexelc(img
, i1
, j1
, k1
, t111
);
1550 /* trilinear interpolation of samples */
1551 #if CHAN_TYPE == GL_FLOAT
1552 rgba
[0] = lerp_3d(a
, b
, c
,
1553 t000
[0], t100
[0], t010
[0], t110
[0],
1554 t001
[0], t101
[0], t011
[0], t111
[0]);
1555 rgba
[1] = lerp_3d(a
, b
, c
,
1556 t000
[1], t100
[1], t010
[1], t110
[1],
1557 t001
[1], t101
[1], t011
[1], t111
[1]);
1558 rgba
[2] = lerp_3d(a
, b
, c
,
1559 t000
[2], t100
[2], t010
[2], t110
[2],
1560 t001
[2], t101
[2], t011
[2], t111
[2]);
1561 rgba
[3] = lerp_3d(a
, b
, c
,
1562 t000
[3], t100
[3], t010
[3], t110
[3],
1563 t001
[3], t101
[3], t011
[3], t111
[3]);
1564 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1565 rgba
[0] = (GLchan
) (lerp_3d(a
, b
, c
,
1566 t000
[0], t100
[0], t010
[0], t110
[0],
1567 t001
[0], t101
[0], t011
[0], t111
[0]) + 0.5F
);
1568 rgba
[1] = (GLchan
) (lerp_3d(a
, b
, c
,
1569 t000
[1], t100
[1], t010
[1], t110
[1],
1570 t001
[1], t101
[1], t011
[1], t111
[1]) + 0.5F
);
1571 rgba
[2] = (GLchan
) (lerp_3d(a
, b
, c
,
1572 t000
[2], t100
[2], t010
[2], t110
[2],
1573 t001
[2], t101
[2], t011
[2], t111
[2]) + 0.5F
);
1574 rgba
[3] = (GLchan
) (lerp_3d(a
, b
, c
,
1575 t000
[3], t100
[3], t010
[3], t110
[3],
1576 t001
[3], t101
[3], t011
[3], t111
[3]) + 0.5F
);
1578 ASSERT(CHAN_TYPE
== GL_UNSIGNED_BYTE
);
1579 rgba
[0] = ilerp_3d(ia
, ib
, ic
,
1580 t000
[0], t100
[0], t010
[0], t110
[0],
1581 t001
[0], t101
[0], t011
[0], t111
[0]);
1582 rgba
[1] = ilerp_3d(ia
, ib
, ic
,
1583 t000
[1], t100
[1], t010
[1], t110
[1],
1584 t001
[1], t101
[1], t011
[1], t111
[1]);
1585 rgba
[2] = ilerp_3d(ia
, ib
, ic
,
1586 t000
[2], t100
[2], t010
[2], t110
[2],
1587 t001
[2], t101
[2], t011
[2], t111
[2]);
1588 rgba
[3] = ilerp_3d(ia
, ib
, ic
,
1589 t000
[3], t100
[3], t010
[3], t110
[3],
1590 t001
[3], t101
[3], t011
[3], t111
[3]);
1598 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1599 const struct gl_texture_object
*tObj
,
1600 GLuint n
, const GLfloat texcoord
[][4],
1601 const GLfloat lambda
[], GLchan rgba
[][4] )
1604 for (i
= 0; i
< n
; i
++) {
1606 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1607 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1613 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1614 const struct gl_texture_object
*tObj
,
1615 GLuint n
, const GLfloat texcoord
[][4],
1616 const GLfloat lambda
[], GLchan rgba
[][4])
1619 ASSERT(lambda
!= NULL
);
1620 for (i
= 0; i
< n
; i
++) {
1622 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1623 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1629 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1630 const struct gl_texture_object
*tObj
,
1631 GLuint n
, const GLfloat texcoord
[][4],
1632 const GLfloat lambda
[], GLchan rgba
[][4])
1635 ASSERT(lambda
!= NULL
);
1636 for (i
= 0; i
< n
; i
++) {
1638 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1639 if (level
>= tObj
->_MaxLevel
) {
1640 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1641 texcoord
[i
], rgba
[i
]);
1644 GLchan t0
[4], t1
[4]; /* texels */
1645 const GLfloat f
= FRAC(lambda
[i
]);
1646 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1647 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1648 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1649 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1650 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1651 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1658 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1659 const struct gl_texture_object
*tObj
,
1660 GLuint n
, const GLfloat texcoord
[][4],
1661 const GLfloat lambda
[], GLchan rgba
[][4])
1664 ASSERT(lambda
!= NULL
);
1665 for (i
= 0; i
< n
; i
++) {
1667 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1668 if (level
>= tObj
->_MaxLevel
) {
1669 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1670 texcoord
[i
], rgba
[i
]);
1673 GLchan t0
[4], t1
[4]; /* texels */
1674 const GLfloat f
= FRAC(lambda
[i
]);
1675 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1676 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1677 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1678 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1679 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1680 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1687 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1688 const struct gl_texture_object
*tObj
, GLuint n
,
1689 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1693 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1697 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1704 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1705 const struct gl_texture_object
*tObj
, GLuint n
,
1706 const GLfloat texcoords
[][4],
1707 const GLfloat lambda
[], GLchan rgba
[][4] )
1710 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1714 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1720 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1721 * return a texture sample.
1724 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1725 const struct gl_texture_object
*tObj
, GLuint n
,
1726 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1729 GLuint minStart
, minEnd
; /* texels with minification */
1730 GLuint magStart
, magEnd
; /* texels with magnification */
1733 ASSERT(lambda
!= NULL
);
1734 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1735 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1737 if (minStart
< minEnd
) {
1738 /* do the minified texels */
1739 GLuint m
= minEnd
- minStart
;
1740 switch (tObj
->MinFilter
) {
1742 for (i
= minStart
; i
< minEnd
; i
++)
1743 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1744 texcoords
[i
], rgba
[i
]);
1747 for (i
= minStart
; i
< minEnd
; i
++)
1748 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1749 texcoords
[i
], rgba
[i
]);
1751 case GL_NEAREST_MIPMAP_NEAREST
:
1752 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1753 lambda
+ minStart
, rgba
+ minStart
);
1755 case GL_LINEAR_MIPMAP_NEAREST
:
1756 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1757 lambda
+ minStart
, rgba
+ minStart
);
1759 case GL_NEAREST_MIPMAP_LINEAR
:
1760 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1761 lambda
+ minStart
, rgba
+ minStart
);
1763 case GL_LINEAR_MIPMAP_LINEAR
:
1764 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1765 lambda
+ minStart
, rgba
+ minStart
);
1768 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1773 if (magStart
< magEnd
) {
1774 /* do the magnified texels */
1775 switch (tObj
->MagFilter
) {
1777 for (i
= magStart
; i
< magEnd
; i
++)
1778 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1779 texcoords
[i
], rgba
[i
]);
1782 for (i
= magStart
; i
< magEnd
; i
++)
1783 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1784 texcoords
[i
], rgba
[i
]);
1787 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1794 /**********************************************************************/
1795 /* Texture Cube Map Sampling Functions */
1796 /**********************************************************************/
1799 * Choose one of six sides of a texture cube map given the texture
1800 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1803 static const struct gl_texture_image
**
1804 choose_cube_face(const struct gl_texture_object
*texObj
,
1805 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1809 direction target sc tc ma
1810 ---------- ------------------------------- --- --- ---
1811 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1812 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1813 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1814 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1815 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1816 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1818 const GLfloat rx
= texcoord
[0];
1819 const GLfloat ry
= texcoord
[1];
1820 const GLfloat rz
= texcoord
[2];
1821 const struct gl_texture_image
**imgArray
;
1822 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
1825 if (arx
> ary
&& arx
> arz
) {
1827 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_X
];
1833 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_X
];
1839 else if (ary
> arx
&& ary
> arz
) {
1841 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Y
];
1847 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Y
];
1855 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Z
];
1861 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Z
];
1868 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1869 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1875 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1876 const struct gl_texture_object
*tObj
, GLuint n
,
1877 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1883 for (i
= 0; i
< n
; i
++) {
1884 const struct gl_texture_image
**images
;
1885 GLfloat newCoord
[4];
1886 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1887 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1894 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1895 const struct gl_texture_object
*tObj
, GLuint n
,
1896 const GLfloat texcoords
[][4],
1897 const GLfloat lambda
[], GLchan rgba
[][4])
1902 for (i
= 0; i
< n
; i
++) {
1903 const struct gl_texture_image
**images
;
1904 GLfloat newCoord
[4];
1905 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1906 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1913 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
1914 const struct gl_texture_object
*tObj
,
1915 GLuint n
, const GLfloat texcoord
[][4],
1916 const GLfloat lambda
[], GLchan rgba
[][4])
1920 ASSERT(lambda
!= NULL
);
1921 for (i
= 0; i
< n
; i
++) {
1922 const struct gl_texture_image
**images
;
1923 GLfloat newCoord
[4];
1925 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1926 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1927 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1933 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
1934 const struct gl_texture_object
*tObj
,
1935 GLuint n
, const GLfloat texcoord
[][4],
1936 const GLfloat lambda
[], GLchan rgba
[][4])
1940 ASSERT(lambda
!= NULL
);
1941 for (i
= 0; i
< n
; i
++) {
1942 const struct gl_texture_image
**images
;
1943 GLfloat newCoord
[4];
1945 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1946 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1947 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1953 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
1954 const struct gl_texture_object
*tObj
,
1955 GLuint n
, const GLfloat texcoord
[][4],
1956 const GLfloat lambda
[], GLchan rgba
[][4])
1960 ASSERT(lambda
!= NULL
);
1961 for (i
= 0; i
< n
; i
++) {
1962 const struct gl_texture_image
**images
;
1963 GLfloat newCoord
[4];
1965 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1966 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1967 if (level
>= tObj
->_MaxLevel
) {
1968 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1972 GLchan t0
[4], t1
[4]; /* texels */
1973 const GLfloat f
= FRAC(lambda
[i
]);
1974 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1975 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1976 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1977 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1978 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1979 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1986 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
1987 const struct gl_texture_object
*tObj
,
1988 GLuint n
, const GLfloat texcoord
[][4],
1989 const GLfloat lambda
[], GLchan rgba
[][4])
1993 ASSERT(lambda
!= NULL
);
1994 for (i
= 0; i
< n
; i
++) {
1995 const struct gl_texture_image
**images
;
1996 GLfloat newCoord
[4];
1998 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1999 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2000 if (level
>= tObj
->_MaxLevel
) {
2001 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2005 GLchan t0
[4], t1
[4];
2006 const GLfloat f
= FRAC(lambda
[i
]);
2007 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2008 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2009 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2010 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2011 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2012 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2019 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2020 const struct gl_texture_object
*tObj
, GLuint n
,
2021 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2024 GLuint minStart
, minEnd
; /* texels with minification */
2025 GLuint magStart
, magEnd
; /* texels with magnification */
2027 ASSERT(lambda
!= NULL
);
2028 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2029 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2031 if (minStart
< minEnd
) {
2032 /* do the minified texels */
2033 const GLuint m
= minEnd
- minStart
;
2034 switch (tObj
->MinFilter
) {
2036 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2037 lambda
+ minStart
, rgba
+ minStart
);
2040 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2041 lambda
+ minStart
, rgba
+ minStart
);
2043 case GL_NEAREST_MIPMAP_NEAREST
:
2044 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2045 texcoords
+ minStart
,
2046 lambda
+ minStart
, rgba
+ minStart
);
2048 case GL_LINEAR_MIPMAP_NEAREST
:
2049 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2050 texcoords
+ minStart
,
2051 lambda
+ minStart
, rgba
+ minStart
);
2053 case GL_NEAREST_MIPMAP_LINEAR
:
2054 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2055 texcoords
+ minStart
,
2056 lambda
+ minStart
, rgba
+ minStart
);
2058 case GL_LINEAR_MIPMAP_LINEAR
:
2059 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2060 texcoords
+ minStart
,
2061 lambda
+ minStart
, rgba
+ minStart
);
2064 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2068 if (magStart
< magEnd
) {
2069 /* do the magnified texels */
2070 const GLuint m
= magEnd
- magStart
;
2071 switch (tObj
->MagFilter
) {
2073 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2074 lambda
+ magStart
, rgba
+ magStart
);
2077 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2078 lambda
+ magStart
, rgba
+ magStart
);
2081 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2087 /**********************************************************************/
2088 /* Texture Rectangle Sampling Functions */
2089 /**********************************************************************/
2092 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2093 const struct gl_texture_object
*tObj
, GLuint n
,
2094 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2097 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2098 const GLfloat width
= (GLfloat
) img
->Width
;
2099 const GLfloat height
= (GLfloat
) img
->Height
;
2100 const GLint width_minus_1
= img
->Width
- 1;
2101 const GLint height_minus_1
= img
->Height
- 1;
2108 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2109 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2110 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2111 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2112 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2113 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2114 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2116 /* XXX move Wrap mode tests outside of loops for common cases */
2117 for (i
= 0; i
< n
; i
++) {
2119 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2120 if (tObj
->WrapS
== GL_CLAMP
) {
2121 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
- 1) );
2123 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2124 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2127 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2129 if (tObj
->WrapT
== GL_CLAMP
) {
2130 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
- 1) );
2132 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2133 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2136 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2139 if (col
< 0 || col
> width_minus_1
|| row
< 0 || row
> height_minus_1
)
2140 COPY_CHAN4(rgba
[i
], tObj
->_BorderChan
);
2142 img
->FetchTexelc(img
, col
, row
, 0, rgba
[i
]);
2148 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2149 const struct gl_texture_object
*tObj
, GLuint n
,
2150 const GLfloat texcoords
[][4],
2151 const GLfloat lambda
[], GLchan rgba
[][4])
2153 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2154 const GLfloat width
= (GLfloat
) img
->Width
;
2155 const GLfloat height
= (GLfloat
) img
->Height
;
2156 const GLint width_minus_1
= img
->Width
- 1;
2157 const GLint height_minus_1
= img
->Height
- 1;
2164 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2165 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2166 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2167 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2168 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2169 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2170 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2172 /* XXX lots of opportunity for optimization in this loop */
2173 for (i
= 0; i
< n
; i
++) {
2175 GLint i0
, j0
, i1
, j1
;
2176 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2178 GLuint useBorderColor
= 0;
2179 #if CHAN_TYPE == GL_UNSIGNED_BYTE
2183 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2184 if (tObj
->WrapS
== GL_CLAMP
) {
2185 /* Not exactly what the spec says, but it matches NVIDIA output */
2186 fcol
= CLAMP(texcoords
[i
][0] - 0.5F
, 0.0, width_minus_1
);
2190 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2191 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2195 if (i1
> width_minus_1
)
2199 ASSERT(tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2200 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2206 if (tObj
->WrapT
== GL_CLAMP
) {
2207 /* Not exactly what the spec says, but it matches NVIDIA output */
2208 frow
= CLAMP(texcoords
[i
][1] - 0.5F
, 0.0, width_minus_1
);
2212 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2213 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2217 if (j1
> height_minus_1
)
2218 j1
= height_minus_1
;
2221 ASSERT(tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2222 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2228 /* compute integer rows/columns */
2229 if (i0
< 0 || i0
> width_minus_1
) useBorderColor
|= I0BIT
;
2230 if (i1
< 0 || i1
> width_minus_1
) useBorderColor
|= I1BIT
;
2231 if (j0
< 0 || j0
> height_minus_1
) useBorderColor
|= J0BIT
;
2232 if (j1
< 0 || j1
> height_minus_1
) useBorderColor
|= J1BIT
;
2234 /* get four texel samples */
2235 if (useBorderColor
& (I0BIT
| J0BIT
))
2236 COPY_CHAN4(t00
, tObj
->_BorderChan
);
2238 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
2240 if (useBorderColor
& (I1BIT
| J0BIT
))
2241 COPY_CHAN4(t10
, tObj
->_BorderChan
);
2243 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
2245 if (useBorderColor
& (I0BIT
| J1BIT
))
2246 COPY_CHAN4(t01
, tObj
->_BorderChan
);
2248 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
2250 if (useBorderColor
& (I1BIT
| J1BIT
))
2251 COPY_CHAN4(t11
, tObj
->_BorderChan
);
2253 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
2255 /* compute interpolants */
2258 #if CHAN_TYPE == GL_UNSIGNED_BYTE
2259 ia
= IROUND_POS(a
* ILERP_SCALE
);
2260 ib
= IROUND_POS(b
* ILERP_SCALE
);
2263 /* do bilinear interpolation of texel colors */
2264 #if CHAN_TYPE == GL_FLOAT
2265 rgba
[i
][0] = lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]);
2266 rgba
[i
][1] = lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]);
2267 rgba
[i
][2] = lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]);
2268 rgba
[i
][3] = lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]);
2269 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
2270 rgba
[i
][0] = (GLchan
) (lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]) + 0.5);
2271 rgba
[i
][1] = (GLchan
) (lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]) + 0.5);
2272 rgba
[i
][2] = (GLchan
) (lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]) + 0.5);
2273 rgba
[i
][3] = (GLchan
) (lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]) + 0.5);
2275 ASSERT(CHAN_TYPE
== GL_UNSIGNED_BYTE
);
2276 rgba
[i
][0] = ilerp_2d(ia
, ib
, t00
[0], t10
[0], t01
[0], t11
[0]);
2277 rgba
[i
][1] = ilerp_2d(ia
, ib
, t00
[1], t10
[1], t01
[1], t11
[1]);
2278 rgba
[i
][2] = ilerp_2d(ia
, ib
, t00
[2], t10
[2], t01
[2], t11
[2]);
2279 rgba
[i
][3] = ilerp_2d(ia
, ib
, t00
[3], t10
[3], t01
[3], t11
[3]);
2286 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2287 const struct gl_texture_object
*tObj
, GLuint n
,
2288 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2291 GLuint minStart
, minEnd
, magStart
, magEnd
;
2293 /* We only need lambda to decide between minification and magnification.
2294 * There is no mipmapping with rectangular textures.
2296 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2297 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2299 if (minStart
< minEnd
) {
2300 if (tObj
->MinFilter
== GL_NEAREST
) {
2301 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2302 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2305 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2306 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2309 if (magStart
< magEnd
) {
2310 if (tObj
->MagFilter
== GL_NEAREST
) {
2311 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2312 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2315 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2316 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2324 * Sample a shadow/depth texture.
2327 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2328 const struct gl_texture_object
*tObj
, GLuint n
,
2329 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2332 const GLint baseLevel
= tObj
->BaseLevel
;
2333 const struct gl_texture_image
*texImage
= tObj
->Image
[0][baseLevel
];
2334 const GLuint width
= texImage
->Width
;
2335 const GLuint height
= texImage
->Height
;
2343 ASSERT(tObj
->Image
[0][tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2344 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2345 tObj
->Target
== GL_TEXTURE_2D
||
2346 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2348 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2350 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2352 /* XXX this could be precomputed and saved in the texture object */
2353 if (tObj
->CompareFlag
) {
2354 /* GL_SGIX_shadow */
2355 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2356 function
= GL_LEQUAL
;
2359 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2360 function
= GL_GEQUAL
;
2363 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2365 function
= tObj
->CompareFunc
;
2368 function
= GL_NONE
; /* pass depth through as grayscale */
2371 if (tObj
->MagFilter
== GL_NEAREST
) {
2373 for (i
= 0; i
< n
; i
++) {
2374 GLfloat depthSample
;
2376 /* XXX fix for texture rectangle! */
2377 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2378 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2379 texImage
->FetchTexelf(texImage
, col
, row
, 0, &depthSample
);
2383 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2386 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2389 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2392 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2395 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2398 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2407 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2410 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2414 switch (tObj
->DepthMode
) {
2416 texel
[i
][RCOMP
] = result
;
2417 texel
[i
][GCOMP
] = result
;
2418 texel
[i
][BCOMP
] = result
;
2419 texel
[i
][ACOMP
] = CHAN_MAX
;
2422 texel
[i
][RCOMP
] = result
;
2423 texel
[i
][GCOMP
] = result
;
2424 texel
[i
][BCOMP
] = result
;
2425 texel
[i
][ACOMP
] = result
;
2428 texel
[i
][RCOMP
] = 0;
2429 texel
[i
][GCOMP
] = 0;
2430 texel
[i
][BCOMP
] = 0;
2431 texel
[i
][ACOMP
] = result
;
2434 _mesa_problem(ctx
, "Bad depth texture mode");
2440 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2441 for (i
= 0; i
< n
; i
++) {
2442 GLfloat depth00
, depth01
, depth10
, depth11
;
2443 GLint i0
, i1
, j0
, j1
;
2445 GLuint useBorderTexel
;
2447 /* XXX fix for texture rectangle! */
2448 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2449 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2452 if (texImage
->Border
) {
2453 i0
+= texImage
->Border
;
2454 i1
+= texImage
->Border
;
2455 j0
+= texImage
->Border
;
2456 j1
+= texImage
->Border
;
2459 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2460 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2461 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2462 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2465 /* get four depth samples from the texture */
2466 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2470 texImage
->FetchTexelf(texImage
, i0
, j0
, 0, &depth00
);
2472 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2476 texImage
->FetchTexelf(texImage
, i1
, j0
, 0, &depth10
);
2478 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2482 texImage
->FetchTexelf(texImage
, i0
, j1
, 0, &depth01
);
2484 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2488 texImage
->FetchTexelf(texImage
, i1
, j1
, 0, &depth11
);
2492 /* compute a single weighted depth sample and do one comparison */
2493 const GLfloat a
= FRAC(u
+ 1.0F
);
2494 const GLfloat b
= FRAC(v
+ 1.0F
);
2495 const GLfloat depthSample
2496 = lerp_2d(a
, b
, depth00
, depth10
, depth01
, depth11
);
2497 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2498 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2506 /* Do four depth/R comparisons and compute a weighted result.
2507 * If this touches on somebody's I.P., I'll remove this code
2510 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2511 GLfloat luminance
= CHAN_MAXF
;
2515 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2516 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2517 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2518 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2519 result
= (GLchan
) luminance
;
2522 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2523 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2524 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2525 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2526 result
= (GLchan
) luminance
;
2529 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2530 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2531 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2532 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2533 result
= (GLchan
) luminance
;
2536 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2537 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2538 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2539 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2540 result
= (GLchan
) luminance
;
2543 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2544 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2545 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2546 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2547 result
= (GLchan
) luminance
;
2550 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2551 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2552 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2553 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2554 result
= (GLchan
) luminance
;
2563 /* ordinary bilinear filtering */
2565 const GLfloat a
= FRAC(u
+ 1.0F
);
2566 const GLfloat b
= FRAC(v
+ 1.0F
);
2567 const GLfloat depthSample
2568 = lerp_2d(a
, b
, depth00
, depth10
, depth01
, depth11
);
2569 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2573 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2578 switch (tObj
->DepthMode
) {
2580 texel
[i
][RCOMP
] = result
;
2581 texel
[i
][GCOMP
] = result
;
2582 texel
[i
][BCOMP
] = result
;
2583 texel
[i
][ACOMP
] = CHAN_MAX
;
2586 texel
[i
][RCOMP
] = result
;
2587 texel
[i
][GCOMP
] = result
;
2588 texel
[i
][BCOMP
] = result
;
2589 texel
[i
][ACOMP
] = result
;
2592 texel
[i
][RCOMP
] = 0;
2593 texel
[i
][GCOMP
] = 0;
2594 texel
[i
][BCOMP
] = 0;
2595 texel
[i
][ACOMP
] = result
;
2598 _mesa_problem(ctx
, "Bad depth texture mode");
2607 * Experimental depth texture sampling function.
2610 sample_depth_texture2(const GLcontext
*ctx
,
2611 const struct gl_texture_unit
*texUnit
,
2612 GLuint n
, const GLfloat texcoords
[][4],
2615 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2616 const GLint baseLevel
= texObj
->BaseLevel
;
2617 const struct gl_texture_image
*texImage
= texObj
->Image
[0][baseLevel
];
2618 const GLuint width
= texImage
->Width
;
2619 const GLuint height
= texImage
->Height
;
2621 GLboolean lequal
, gequal
;
2623 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2624 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2628 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2629 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2633 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2634 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2635 * isn't a depth texture.
2637 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2638 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2642 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2644 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2655 for (i
= 0; i
< n
; i
++) {
2657 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2660 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2662 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2670 if (imin
< 0) imin
= 0;
2671 if (imax
>= width
) imax
= width
- 1;
2672 if (jmin
< 0) jmin
= 0;
2673 if (jmax
>= height
) jmax
= height
- 1;
2675 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2677 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2678 for (ii
= imin
; ii
<= imax
; ii
++) {
2679 GLfloat depthSample
;
2680 texImage
->FetchTexelf(texImage
, ii
, jj
, 0, &depthSample
);
2681 if ((depthSample
<= r
[i
] && lequal
) ||
2682 (depthSample
>= r
[i
] && gequal
)) {
2688 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2689 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2692 texel
[i
][RCOMP
] = lum
;
2693 texel
[i
][GCOMP
] = lum
;
2694 texel
[i
][BCOMP
] = lum
;
2695 texel
[i
][ACOMP
] = CHAN_MAX
;
2703 * We use this function when a texture object is in an "incomplete" state.
2704 * When a fragment program attempts to sample an incomplete texture we
2705 * return black (see issue 23 in GL_ARB_fragment_program spec).
2706 * Note: fragment programss don't observe the texture enable/disable flags.
2709 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2710 const struct gl_texture_object
*tObj
, GLuint n
,
2711 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2720 for (i
= 0; i
< n
; i
++) {
2724 rgba
[i
][ACOMP
] = CHAN_MAX
;
2730 * Setup the texture sampling function for this texture object.
2733 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
2734 const struct gl_texture_object
*t
)
2736 if (!t
|| !t
->Complete
) {
2737 return &null_sample_func
;
2740 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2741 const GLenum format
= t
->Image
[0][t
->BaseLevel
]->Format
;
2743 switch (t
->Target
) {
2745 if (format
== GL_DEPTH_COMPONENT
) {
2746 return &sample_depth_texture
;
2748 else if (needLambda
) {
2749 return &sample_lambda_1d
;
2751 else if (t
->MinFilter
== GL_LINEAR
) {
2752 return &sample_linear_1d
;
2755 ASSERT(t
->MinFilter
== GL_NEAREST
);
2756 return &sample_nearest_1d
;
2759 if (format
== GL_DEPTH_COMPONENT
) {
2760 return &sample_depth_texture
;
2762 else if (needLambda
) {
2763 return &sample_lambda_2d
;
2765 else if (t
->MinFilter
== GL_LINEAR
) {
2766 return &sample_linear_2d
;
2769 GLint baseLevel
= t
->BaseLevel
;
2770 ASSERT(t
->MinFilter
== GL_NEAREST
);
2771 if (t
->WrapS
== GL_REPEAT
&&
2772 t
->WrapT
== GL_REPEAT
&&
2774 t
->Image
[0][baseLevel
]->Border
== 0 &&
2775 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2776 return &opt_sample_rgb_2d
;
2778 else if (t
->WrapS
== GL_REPEAT
&&
2779 t
->WrapT
== GL_REPEAT
&&
2781 t
->Image
[0][baseLevel
]->Border
== 0 &&
2782 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2783 return &opt_sample_rgba_2d
;
2786 return &sample_nearest_2d
;
2791 return &sample_lambda_3d
;
2793 else if (t
->MinFilter
== GL_LINEAR
) {
2794 return &sample_linear_3d
;
2797 ASSERT(t
->MinFilter
== GL_NEAREST
);
2798 return &sample_nearest_3d
;
2800 case GL_TEXTURE_CUBE_MAP
:
2802 return &sample_lambda_cube
;
2804 else if (t
->MinFilter
== GL_LINEAR
) {
2805 return &sample_linear_cube
;
2808 ASSERT(t
->MinFilter
== GL_NEAREST
);
2809 return &sample_nearest_cube
;
2811 case GL_TEXTURE_RECTANGLE_NV
:
2813 return &sample_lambda_rect
;
2815 else if (t
->MinFilter
== GL_LINEAR
) {
2816 return &sample_linear_rect
;
2819 ASSERT(t
->MinFilter
== GL_NEAREST
);
2820 return &sample_nearest_rect
;
2824 "invalid target in _swrast_choose_texture_sample_func");
2825 return &null_sample_func
;
2831 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2832 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2836 * Do texture application for GL_ARB/EXT_texture_env_combine.
2837 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
2838 * GL_ATI_texture_env_combine3. Since "classic" texture environments are
2839 * implemented using GL_ARB_texture_env_combine-like state, this same function
2840 * is used for classic texture environment application as well.
2842 * \param ctx rendering context
2843 * \param textureUnit the texture unit to apply
2844 * \param n number of fragments to process (span width)
2845 * \param primary_rgba incoming fragment color array
2846 * \param texelBuffer pointer to texel colors for all texture units
2848 * \param rgba incoming colors, which get modified here
2851 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
2852 CONST
GLchan (*primary_rgba
)[4],
2853 CONST GLchan
*texelBuffer
,
2856 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
2857 const GLchan (*argRGB
[3])[4];
2858 const GLchan (*argA
[3])[4];
2859 const GLuint RGBshift
= textureUnit
->_CurrentCombine
->ScaleShiftRGB
;
2860 const GLuint Ashift
= textureUnit
->_CurrentCombine
->ScaleShiftA
;
2861 #if CHAN_TYPE == GL_FLOAT
2862 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2863 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2864 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
2865 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
2867 const GLint half
= (CHAN_MAX
+ 1) / 2;
2868 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
2869 static const GLchan zero
[4] = { 0, 0, 0, 0 };
2872 GLuint numColorArgs
;
2873 GLuint numAlphaArgs
;
2875 /* GLchan ccolor[3][4]; */
2876 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2877 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2879 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2880 ctx
->Extensions
.ARB_texture_env_combine
);
2881 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
2885 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
2886 textureUnit->_CurrentCombine->ModeRGB,
2887 textureUnit->_CurrentCombine->ModeA,
2888 textureUnit->_CurrentCombine->SourceRGB[0],
2889 textureUnit->_CurrentCombine->SourceA[0],
2890 textureUnit->_CurrentCombine->SourceRGB[1],
2891 textureUnit->_CurrentCombine->SourceA[1]);
2895 * Do operand setup for up to 3 operands. Loop over the terms.
2897 numColorArgs
= textureUnit
->_CurrentCombine
->_NumArgsRGB
;
2898 numAlphaArgs
= textureUnit
->_CurrentCombine
->_NumArgsA
;
2900 for (j
= 0; j
< numColorArgs
; j
++) {
2901 const GLenum srcRGB
= textureUnit
->_CurrentCombine
->SourceRGB
[j
];
2906 argRGB
[j
] = (const GLchan (*)[4])
2907 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2909 case GL_PRIMARY_COLOR
:
2910 argRGB
[j
] = primary_rgba
;
2913 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2917 GLchan (*c
)[4] = ccolor
[j
];
2918 GLchan red
, green
, blue
, alpha
;
2919 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2920 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2921 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2922 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2923 for (i
= 0; i
< n
; i
++) {
2925 c
[i
][GCOMP
] = green
;
2927 c
[i
][ACOMP
] = alpha
;
2929 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2932 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
2941 /* ARB_texture_env_crossbar source */
2943 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
2944 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2945 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2947 argRGB
[j
] = (const GLchan (*)[4])
2948 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2952 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] != GL_SRC_COLOR
) {
2953 const GLchan (*src
)[4] = argRGB
[j
];
2954 GLchan (*dst
)[4] = ccolor
[j
];
2956 /* point to new arg[j] storage */
2957 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2959 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2960 for (i
= 0; i
< n
; i
++) {
2961 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2962 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2963 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2966 else if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_SRC_ALPHA
) {
2967 for (i
= 0; i
< n
; i
++) {
2968 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2969 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2970 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2974 ASSERT(textureUnit
->_CurrentCombine
->OperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2975 for (i
= 0; i
< n
; i
++) {
2976 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2977 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2978 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2985 for (j
= 0; j
< numAlphaArgs
; j
++) {
2986 const GLenum srcA
= textureUnit
->_CurrentCombine
->SourceA
[j
];
2990 argA
[j
] = (const GLchan (*)[4])
2991 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2993 case GL_PRIMARY_COLOR
:
2994 argA
[j
] = primary_rgba
;
2997 argA
[j
] = (const GLchan (*)[4]) rgba
;
3001 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3002 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3003 for (i
= 0; i
< n
; i
++)
3004 c
[i
][ACOMP
] = alpha
;
3005 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3008 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3017 /* ARB_texture_env_crossbar source */
3019 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3020 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3021 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3023 argA
[j
] = (const GLchan (*)[4])
3024 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3028 if (textureUnit
->_CurrentCombine
->OperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3029 const GLchan (*src
)[4] = argA
[j
];
3030 GLchan (*dst
)[4] = ccolor
[j
];
3031 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3032 for (i
= 0; i
< n
; i
++) {
3033 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3039 * Do the texture combine.
3041 switch (textureUnit
->_CurrentCombine
->ModeRGB
) {
3044 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3046 for (i
= 0; i
< n
; i
++) {
3047 #if CHAN_TYPE == GL_FLOAT
3048 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3049 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3050 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3052 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3053 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3054 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3055 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3056 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3057 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3062 for (i
= 0; i
< n
; i
++) {
3063 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3064 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3065 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3072 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3073 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3074 #if CHAN_TYPE != GL_FLOAT
3075 const GLint shift
= CHAN_BITS
- RGBshift
;
3077 for (i
= 0; i
< n
; i
++) {
3078 #if CHAN_TYPE == GL_FLOAT
3079 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3080 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3081 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3083 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3084 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3085 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3086 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3087 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3088 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3095 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3096 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3097 for (i
= 0; i
< n
; i
++) {
3098 #if CHAN_TYPE == GL_FLOAT
3099 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3100 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3101 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3103 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3104 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3105 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3106 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3107 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3108 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3115 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3116 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3117 for (i
= 0; i
< n
; i
++) {
3118 #if CHAN_TYPE == GL_FLOAT
3119 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3120 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3121 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3123 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3124 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3125 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3126 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3127 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3128 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3129 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3130 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3131 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3136 case GL_INTERPOLATE
:
3138 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3139 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3140 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3141 #if CHAN_TYPE != GL_FLOAT
3142 const GLint shift
= CHAN_BITS
- RGBshift
;
3144 for (i
= 0; i
< n
; i
++) {
3145 #if CHAN_TYPE == GL_FLOAT
3146 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3147 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3148 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3149 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3150 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3151 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3153 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3154 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3156 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3157 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3159 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3160 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3162 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3163 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3164 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3171 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3172 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3173 for (i
= 0; i
< n
; i
++) {
3174 #if CHAN_TYPE == GL_FLOAT
3175 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3176 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3177 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3179 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3180 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3181 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3182 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3183 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3184 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3189 case GL_DOT3_RGB_EXT
:
3190 case GL_DOT3_RGBA_EXT
:
3192 /* Do not scale the result by 1 2 or 4 */
3193 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3194 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3195 for (i
= 0; i
< n
; i
++) {
3196 #if CHAN_TYPE == GL_FLOAT
3197 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3198 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3199 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3201 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3203 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3204 (GLint
)arg1
[i
][RCOMP
] - half
) +
3205 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3206 (GLint
)arg1
[i
][GCOMP
] - half
) +
3207 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3208 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3209 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3211 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3218 /* DO scale the result by 1 2 or 4 */
3219 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3220 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3221 for (i
= 0; i
< n
; i
++) {
3222 #if CHAN_TYPE == GL_FLOAT
3223 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3224 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3225 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3227 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3229 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3230 (GLint
)arg1
[i
][RCOMP
] - half
) +
3231 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3232 (GLint
)arg1
[i
][GCOMP
] - half
) +
3233 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3234 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3236 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3238 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3242 case GL_MODULATE_ADD_ATI
:
3244 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3245 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3246 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3247 #if CHAN_TYPE != GL_FLOAT
3248 const GLint shift
= CHAN_BITS
- RGBshift
;
3250 for (i
= 0; i
< n
; i
++) {
3251 #if CHAN_TYPE == GL_FLOAT
3252 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3253 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3254 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3256 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3257 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3258 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3259 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3260 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3261 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3262 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3263 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3264 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3269 case GL_MODULATE_SIGNED_ADD_ATI
:
3271 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3272 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3273 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3274 #if CHAN_TYPE != GL_FLOAT
3275 const GLint shift
= CHAN_BITS
- RGBshift
;
3277 for (i
= 0; i
< n
; i
++) {
3278 #if CHAN_TYPE == GL_FLOAT
3279 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3280 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3281 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3283 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3284 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3286 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3287 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3289 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3290 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3292 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3293 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3294 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3299 case GL_MODULATE_SUBTRACT_ATI
:
3301 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3302 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3303 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3304 #if CHAN_TYPE != GL_FLOAT
3305 const GLint shift
= CHAN_BITS
- RGBshift
;
3307 for (i
= 0; i
< n
; i
++) {
3308 #if CHAN_TYPE == GL_FLOAT
3309 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3310 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3311 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3313 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3314 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3316 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3317 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3319 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3320 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3322 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3323 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3324 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3330 _mesa_problem(ctx
, "invalid combine mode");
3333 switch (textureUnit
->_CurrentCombine
->ModeA
) {
3336 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3338 for (i
= 0; i
< n
; i
++) {
3339 #if CHAN_TYPE == GL_FLOAT
3340 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3342 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3344 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3348 for (i
= 0; i
< n
; i
++) {
3349 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3356 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3357 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3358 #if CHAN_TYPE != GL_FLOAT
3359 const GLint shift
= CHAN_BITS
- Ashift
;
3361 for (i
= 0; i
< n
; i
++) {
3362 #if CHAN_TYPE == GL_FLOAT
3363 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3365 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3366 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3373 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3374 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3375 for (i
= 0; i
< n
; i
++) {
3376 #if CHAN_TYPE == GL_FLOAT
3377 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3379 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3380 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3387 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3388 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3389 for (i
= 0; i
< n
; i
++) {
3390 #if CHAN_TYPE == GL_FLOAT
3391 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3393 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3394 a
= (a
< 0) ? 0 : a
<< Ashift
;
3395 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3400 case GL_INTERPOLATE
:
3402 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3403 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3404 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3405 #if CHAN_TYPE != GL_FLOAT
3406 const GLint shift
= CHAN_BITS
- Ashift
;
3408 for (i
=0; i
<n
; i
++) {
3409 #if CHAN_TYPE == GL_FLOAT
3410 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3411 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3414 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3415 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3417 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3424 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3425 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3426 for (i
= 0; i
< n
; i
++) {
3427 #if CHAN_TYPE == GL_FLOAT
3428 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3430 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3431 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3436 case GL_MODULATE_ADD_ATI
:
3438 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3439 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3440 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3441 #if CHAN_TYPE != GL_FLOAT
3442 const GLint shift
= CHAN_BITS
- Ashift
;
3444 for (i
= 0; i
< n
; i
++) {
3445 #if CHAN_TYPE == GL_FLOAT
3446 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3448 GLint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3449 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3451 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3456 case GL_MODULATE_SIGNED_ADD_ATI
:
3458 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3459 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3460 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3461 #if CHAN_TYPE != GL_FLOAT
3462 const GLint shift
= CHAN_BITS
- Ashift
;
3464 for (i
= 0; i
< n
; i
++) {
3465 #if CHAN_TYPE == GL_FLOAT
3466 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3468 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3469 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3471 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3476 case GL_MODULATE_SUBTRACT_ATI
:
3478 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3479 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3480 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3481 #if CHAN_TYPE != GL_FLOAT
3482 const GLint shift
= CHAN_BITS
- Ashift
;
3484 for (i
= 0; i
< n
; i
++) {
3485 #if CHAN_TYPE == GL_FLOAT
3486 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3488 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3489 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3491 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3497 _mesa_problem(ctx
, "invalid combine mode");
3500 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3501 * This is kind of a kludge. It would have been better if the spec
3502 * were written such that the GL_COMBINE_ALPHA value could be set to
3505 if (textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
3506 textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) {
3507 for (i
= 0; i
< n
; i
++) {
3508 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3511 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3517 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3518 * MODULATE, or DECAL) to an array of fragments.
3519 * Input: textureUnit - pointer to texture unit to apply
3520 * format - base internal texture format
3521 * n - number of fragments
3522 * primary_rgba - primary colors (may alias rgba for single texture)
3523 * texels - array of texel colors
3524 * InOut: rgba - incoming fragment colors modified by texel colors
3525 * according to the texture environment mode.
3528 texture_apply( const GLcontext
*ctx
,
3529 const struct gl_texture_unit
*texUnit
,
3531 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3536 GLint Rc
, Gc
, Bc
, Ac
;
3538 (void) primary_rgba
;
3541 ASSERT(texUnit
->_Current
);
3543 baseLevel
= texUnit
->_Current
->BaseLevel
;
3544 ASSERT(texUnit
->_Current
->Image
[0][baseLevel
]);
3546 format
= texUnit
->_Current
->Image
[0][baseLevel
]->Format
;
3548 if (format
== GL_COLOR_INDEX
|| format
== GL_YCBCR_MESA
) {
3549 format
= GL_RGBA
; /* a bit of a hack */
3551 else if (format
== GL_DEPTH_COMPONENT
) {
3552 format
= texUnit
->_Current
->DepthMode
;
3555 switch (texUnit
->EnvMode
) {
3562 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3568 GLchan Lt
= texel
[i
][RCOMP
];
3569 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3573 case GL_LUMINANCE_ALPHA
:
3575 GLchan Lt
= texel
[i
][RCOMP
];
3577 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3579 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3585 GLchan It
= texel
[i
][RCOMP
];
3586 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3588 rgba
[i
][ACOMP
] = It
;
3594 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3595 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3596 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3603 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3604 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3605 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3607 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3611 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3622 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3628 GLchan Lt
= texel
[i
][RCOMP
];
3629 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3630 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3631 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3635 case GL_LUMINANCE_ALPHA
:
3638 GLchan Lt
= texel
[i
][RCOMP
];
3639 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3640 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3641 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3643 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3649 GLchan It
= texel
[i
][RCOMP
];
3650 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3651 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3652 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3654 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3660 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3661 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3662 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3669 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3670 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3671 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3673 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3677 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3686 case GL_LUMINANCE_ALPHA
:
3693 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3694 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3695 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3701 /* Cv = Cf(1-At) + CtAt */
3702 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3703 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3704 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3705 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3710 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3716 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3717 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3718 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3719 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3725 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3730 /* Cv = Cf(1-Lt) + CcLt */
3731 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3732 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3733 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3734 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3738 case GL_LUMINANCE_ALPHA
:
3740 /* Cv = Cf(1-Lt) + CcLt */
3741 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3742 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3743 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3744 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3746 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3751 /* Cv = Cf(1-It) + CcIt */
3752 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3753 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3754 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3755 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3756 /* Av = Af(1-It) + Ac*It */
3757 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
3762 /* Cv = Cf(1-Ct) + CcCt */
3763 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3764 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3765 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3771 /* Cv = Cf(1-Ct) + CcCt */
3772 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3773 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3774 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3776 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3780 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
3785 /* XXX don't clamp results if GLchan is float??? */
3787 case GL_ADD
: /* GL_EXT_texture_add_env */
3794 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3799 GLuint Lt
= texel
[i
][RCOMP
];
3800 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3801 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3802 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3803 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3804 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3805 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3809 case GL_LUMINANCE_ALPHA
:
3811 GLuint Lt
= texel
[i
][RCOMP
];
3812 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3813 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3814 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3815 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3816 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3817 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3818 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3823 GLchan It
= texel
[i
][RCOMP
];
3824 GLuint r
= rgba
[i
][RCOMP
] + It
;
3825 GLuint g
= rgba
[i
][GCOMP
] + It
;
3826 GLuint b
= rgba
[i
][BCOMP
] + It
;
3827 GLuint a
= rgba
[i
][ACOMP
] + It
;
3828 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3829 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3830 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3831 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
3836 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3837 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3838 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3839 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3840 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3841 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3847 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3848 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3849 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3850 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3851 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3852 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3853 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3857 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
3863 _mesa_problem(ctx
, "Bad env mode in texture_apply");
3871 * Apply texture mapping to a span of fragments.
3874 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
3876 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
3877 GLchan primary_rgba
[MAX_WIDTH
][4];
3880 ASSERT(span
->end
< MAX_WIDTH
);
3881 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3884 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
3886 if (swrast
->_AnyTextureCombine
)
3887 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
3890 * Must do all texture sampling before combining in order to
3891 * accomodate GL_ARB_texture_env_crossbar.
3893 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3894 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3895 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3896 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
3897 GLfloat
*lambda
= span
->array
->lambda
[unit
];
3898 GLchan (*texels
)[4] = (GLchan (*)[4])
3899 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
3901 /* adjust texture lod (lambda) */
3902 if (span
->arrayMask
& SPAN_LAMBDA
) {
3903 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
3904 /* apply LOD bias, but don't clamp yet */
3905 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
3906 -ctx
->Const
.MaxTextureLodBias
,
3907 ctx
->Const
.MaxTextureLodBias
);
3909 for (i
= 0; i
< span
->end
; i
++) {
3914 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
3915 /* apply LOD clamping to lambda */
3916 const GLfloat min
= curObj
->MinLod
;
3917 const GLfloat max
= curObj
->MaxLod
;
3919 for (i
= 0; i
< span
->end
; i
++) {
3920 GLfloat l
= lambda
[i
];
3921 lambda
[i
] = CLAMP(l
, min
, max
);
3926 /* Sample the texture (span->end fragments) */
3927 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
3928 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
3931 /* GL_SGI_texture_color_table */
3932 if (texUnit
->ColorTableEnabled
) {
3933 _mesa_lookup_rgba_chan(&texUnit
->ColorTable
, span
->end
, texels
);
3939 * OK, now apply the texture (aka texture combine/blend).
3940 * We modify the span->color.rgba values.
3942 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3943 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3944 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3945 if (texUnit
->_CurrentCombine
!= &texUnit
->_EnvMode
) {
3946 texture_combine( ctx
, unit
, span
->end
,
3947 (CONST
GLchan (*)[4]) primary_rgba
,
3948 swrast
->TexelBuffer
,
3949 span
->array
->rgba
);
3952 /* conventional texture blend */
3953 const GLchan (*texels
)[4] = (const GLchan (*)[4])
3954 (swrast
->TexelBuffer
+ unit
*
3955 (span
->end
* 4 * sizeof(GLchan
)));
3956 texture_apply( ctx
, texUnit
, span
->end
,
3957 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
3958 span
->array
->rgba
);