1 /* $Id: s_texture.c,v 1.64 2002/06/26 14:56:20 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include "texformat.h"
37 #include "s_context.h"
38 #include "s_texture.h"
42 * These values are used in the fixed-point arithmetic used
43 * for linear filtering.
45 #define WEIGHT_SCALE 65536.0F
46 #define WEIGHT_SHIFT 16
50 * Used to compute texel locations for linear sampling.
52 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB
53 * S = texcoord in [0,1]
54 * SIZE = width (or height or depth) of texture
56 * U = texcoord in [0, width]
57 * I0, I1 = two nearest texel indexes
59 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
61 if (wrapMode == GL_REPEAT) { \
62 U = S * SIZE - 0.5F; \
63 I0 = IFLOOR(U) & (SIZE - 1); \
64 I1 = (I0 + 1) & (SIZE - 1); \
66 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
78 if (I1 >= (GLint) SIZE) \
81 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
82 const GLfloat min = -1.0F / (2.0F * SIZE); \
83 const GLfloat max = 1.0F - min; \
94 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
95 const GLint flr = IFLOOR(S); \
97 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
99 U = S - (GLfloat) flr; /* flr is even */ \
104 if (I1 >= (GLint) SIZE) \
108 ASSERT(wrapMode == GL_CLAMP); \
111 else if (S >= 1.0F) \
112 U = (GLfloat) SIZE; \
123 * Used to compute texel location for nearest sampling.
125 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
127 if (wrapMode == GL_REPEAT) { \
128 /* s limited to [0,1) */ \
129 /* i limited to [0,size-1] */ \
130 I = IFLOOR(S * SIZE); \
133 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
134 /* s limited to [min,max] */ \
135 /* i limited to [0, size-1] */ \
136 const GLfloat min = 1.0F / (2.0F * SIZE); \
137 const GLfloat max = 1.0F - min; \
143 I = IFLOOR(S * SIZE); \
145 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
146 /* s limited to [min,max] */ \
147 /* i limited to [-1, size] */ \
148 const GLfloat min = -1.0F / (2.0F * SIZE); \
149 const GLfloat max = 1.0F - min; \
155 I = IFLOOR(S * SIZE); \
157 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
158 const GLfloat min = 1.0F / (2.0F * SIZE); \
159 const GLfloat max = 1.0F - min; \
160 const GLint flr = IFLOOR(S); \
163 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
165 u = S - (GLfloat) flr; /* flr is even */ \
171 I = IFLOOR(u * SIZE); \
174 ASSERT(wrapMode == GL_CLAMP); \
175 /* s limited to [0,1] */ \
176 /* i limited to [0,size-1] */ \
179 else if (S >= 1.0F) \
182 I = IFLOOR(S * SIZE); \
187 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
189 U = S * SIZE - 0.5F; \
190 I0 = IFLOOR(U) & (SIZE - 1); \
191 I1 = (I0 + 1) & (SIZE - 1); \
196 * Compute linear mipmap levels for given lambda.
198 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
201 level = tObj->BaseLevel; \
202 else if (lambda > tObj->_MaxLambda) \
203 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
205 level = (GLint) (tObj->BaseLevel + lambda); \
210 * Compute nearest mipmap level for given lambda.
212 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
215 if (lambda <= 0.5F) \
217 else if (lambda > tObj->_MaxLambda + 0.4999F) \
218 l = tObj->_MaxLambda + 0.4999F; \
221 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
222 if (level > tObj->_MaxLevel) \
223 level = tObj->_MaxLevel; \
229 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
230 * see 1-pixel bands of improperly weighted linear-sampled texels. The
231 * tests/texwrap.c demo is a good test.
232 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
233 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
235 #define FRAC(f) ((f) - IFLOOR(f))
240 * Bitflags for texture border color sampling.
252 * Get texture palette entry.
255 palette_sample(const GLcontext
*ctx
,
256 const struct gl_texture_object
*tObj
,
257 GLint index
, GLchan rgba
[4] )
259 const GLchan
*palette
;
262 if (ctx
->Texture
.SharedPalette
) {
263 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
264 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
265 format
= ctx
->Texture
.Palette
.Format
;
268 ASSERT(!tObj
->Palette
.FloatTable
);
269 palette
= (const GLchan
*) tObj
->Palette
.Table
;
270 format
= tObj
->Palette
.Format
;
275 rgba
[ACOMP
] = palette
[index
];
279 rgba
[RCOMP
] = palette
[index
];
281 case GL_LUMINANCE_ALPHA
:
282 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
283 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
286 rgba
[RCOMP
] = palette
[index
* 3 + 0];
287 rgba
[GCOMP
] = palette
[index
* 3 + 1];
288 rgba
[BCOMP
] = palette
[index
* 3 + 2];
291 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
292 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
293 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
294 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
297 _mesa_problem(ctx
, "Bad palette format in palette_sample");
303 * The lambda[] array values are always monotonic. Either the whole span
304 * will be minified, magnified, or split between the two. This function
305 * determines the subranges in [0, n-1] that are to be minified or magnified.
308 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
309 GLuint
*minStart
, GLuint
*minEnd
,
310 GLuint
*magStart
, GLuint
*magEnd
)
312 ASSERT(lambda
!= NULL
);
314 /* Verify that lambda[] is monotonous.
315 * We can't really use this because the inaccuracy in the LOG2 function
316 * causes this test to fail, yet the resulting texturing is correct.
320 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
321 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
322 for (i
= 0; i
< n
- 1; i
++) {
323 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
326 else { /* increasing */
327 for (i
= 0; i
< n
- 1; i
++) {
328 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
334 /* since lambda is monotonous-array use this check first */
335 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
336 /* magnification for whole span */
339 *minStart
= *minEnd
= 0;
341 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
342 /* minification for whole span */
345 *magStart
= *magEnd
= 0;
348 /* a mix of minification and magnification */
350 if (lambda
[0] > minMagThresh
) {
351 /* start with minification */
352 for (i
= 1; i
< n
; i
++) {
353 if (lambda
[i
] <= minMagThresh
)
362 /* start with magnification */
363 for (i
= 1; i
< n
; i
++) {
364 if (lambda
[i
] > minMagThresh
)
375 /* Verify the min/mag Start/End values
376 * We don't use this either (see above)
380 for (i
= 0; i
< n
; i
++) {
381 if (lambda
[i
] > minMagThresh
) {
383 ASSERT(i
>= *minStart
);
388 ASSERT(i
>= *magStart
);
397 /**********************************************************************/
398 /* 1-D Texture Sampling Functions */
399 /**********************************************************************/
402 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
405 sample_1d_nearest(GLcontext
*ctx
,
406 const struct gl_texture_object
*tObj
,
407 const struct gl_texture_image
*img
,
408 const GLfloat texcoord
[4], GLchan rgba
[4])
410 const GLint width
= img
->Width2
; /* without border, power of two */
413 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
415 /* skip over the border, if any */
418 if (i
< 0 || i
>= (GLint
) img
->Width
) {
419 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
420 COPY_CHAN4(rgba
, tObj
->BorderColor
);
423 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
424 if (img
->Format
== GL_COLOR_INDEX
) {
425 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
433 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
436 sample_1d_linear(GLcontext
*ctx
,
437 const struct gl_texture_object
*tObj
,
438 const struct gl_texture_image
*img
,
439 const GLfloat texcoord
[4], GLchan rgba
[4])
441 const GLint width
= img
->Width2
;
444 GLuint useBorderColor
;
446 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
454 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
455 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
459 const GLfloat a
= FRAC(u
);
461 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
462 const GLfloat w0
= (1.0F
-a
);
463 const GLfloat w1
= a
;
464 #else /* CHAN_BITS == 8 */
465 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
466 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
467 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
469 GLchan t0
[4], t1
[4]; /* texels */
471 if (useBorderColor
& I0BIT
) {
472 COPY_CHAN4(t0
, tObj
->BorderColor
);
475 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
476 if (img
->Format
== GL_COLOR_INDEX
) {
477 palette_sample(ctx
, tObj
, t0
[0], t0
);
480 if (useBorderColor
& I1BIT
) {
481 COPY_CHAN4(t1
, tObj
->BorderColor
);
484 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
485 if (img
->Format
== GL_COLOR_INDEX
) {
486 palette_sample(ctx
, tObj
, t1
[0], t1
);
490 #if CHAN_TYPE == GL_FLOAT
491 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
492 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
493 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
494 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
495 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
496 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
497 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
498 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
499 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
500 #else /* CHAN_BITS == 8 */
501 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
502 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
503 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
504 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
512 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
513 const struct gl_texture_object
*tObj
,
514 GLuint n
, GLfloat texcoord
[][4],
515 const GLfloat lambda
[], GLchan rgba
[][4])
518 ASSERT(lambda
!= NULL
);
519 for (i
= 0; i
< n
; i
++) {
521 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
522 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
528 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
529 const struct gl_texture_object
*tObj
,
530 GLuint n
, GLfloat texcoord
[][4],
531 const GLfloat lambda
[], GLchan rgba
[][4])
534 ASSERT(lambda
!= NULL
);
535 for (i
= 0; i
< n
; i
++) {
537 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
538 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
545 * This is really just needed in order to prevent warnings with some compilers.
547 #if CHAN_TYPE == GL_FLOAT
550 #define CHAN_CAST (GLchan) (GLint)
555 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
556 const struct gl_texture_object
*tObj
,
557 GLuint n
, GLfloat texcoord
[][4],
558 const GLfloat lambda
[], GLchan rgba
[][4])
561 ASSERT(lambda
!= NULL
);
562 for (i
= 0; i
< n
; i
++) {
564 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
565 if (level
>= tObj
->_MaxLevel
) {
566 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
567 texcoord
[i
], rgba
[i
]);
571 const GLfloat f
= FRAC(lambda
[i
]);
572 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
573 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
574 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
575 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
576 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
577 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
585 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
586 const struct gl_texture_object
*tObj
,
587 GLuint n
, GLfloat texcoord
[][4],
588 const GLfloat lambda
[], GLchan rgba
[][4])
591 ASSERT(lambda
!= NULL
);
592 for (i
= 0; i
< n
; i
++) {
594 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
595 if (level
>= tObj
->_MaxLevel
) {
596 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
597 texcoord
[i
], rgba
[i
]);
601 const GLfloat f
= FRAC(lambda
[i
]);
602 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
603 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
604 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
605 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
606 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
607 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
615 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
616 const struct gl_texture_object
*tObj
, GLuint n
,
617 GLfloat texcoords
[][4], const GLfloat lambda
[],
621 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
624 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
631 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
632 const struct gl_texture_object
*tObj
, GLuint n
,
633 GLfloat texcoords
[][4], const GLfloat lambda
[],
637 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
640 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
646 * Given an (s) texture coordinate and lambda (level of detail) value,
647 * return a texture sample.
651 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
652 const struct gl_texture_object
*tObj
, GLuint n
,
653 GLfloat texcoords
[][4],
654 const GLfloat lambda
[], GLchan rgba
[][4] )
656 GLuint minStart
, minEnd
; /* texels with minification */
657 GLuint magStart
, magEnd
; /* texels with magnification */
660 ASSERT(lambda
!= NULL
);
661 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
662 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
664 if (minStart
< minEnd
) {
665 /* do the minified texels */
666 const GLuint m
= minEnd
- minStart
;
667 switch (tObj
->MinFilter
) {
669 for (i
= minStart
; i
< minEnd
; i
++)
670 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
671 texcoords
[i
], rgba
[i
]);
674 for (i
= minStart
; i
< minEnd
; i
++)
675 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
676 texcoords
[i
], rgba
[i
]);
678 case GL_NEAREST_MIPMAP_NEAREST
:
679 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
680 lambda
+ minStart
, rgba
+ minStart
);
682 case GL_LINEAR_MIPMAP_NEAREST
:
683 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
684 lambda
+ minStart
, rgba
+ minStart
);
686 case GL_NEAREST_MIPMAP_LINEAR
:
687 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
688 lambda
+ minStart
, rgba
+ minStart
);
690 case GL_LINEAR_MIPMAP_LINEAR
:
691 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
692 lambda
+ minStart
, rgba
+ minStart
);
695 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
700 if (magStart
< magEnd
) {
701 /* do the magnified texels */
702 switch (tObj
->MagFilter
) {
704 for (i
= magStart
; i
< magEnd
; i
++)
705 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
706 texcoords
[i
], rgba
[i
]);
709 for (i
= magStart
; i
< magEnd
; i
++)
710 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
711 texcoords
[i
], rgba
[i
]);
714 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
721 /**********************************************************************/
722 /* 2-D Texture Sampling Functions */
723 /**********************************************************************/
727 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
730 sample_2d_nearest(GLcontext
*ctx
,
731 const struct gl_texture_object
*tObj
,
732 const struct gl_texture_image
*img
,
733 const GLfloat texcoord
[4],
736 const GLint width
= img
->Width2
; /* without border, power of two */
737 const GLint height
= img
->Height2
; /* without border, power of two */
740 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
741 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
743 /* skip over the border, if any */
747 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
748 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
749 COPY_CHAN4(rgba
, tObj
->BorderColor
);
752 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
753 if (img
->Format
== GL_COLOR_INDEX
) {
754 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
762 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
763 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
766 sample_2d_linear(GLcontext
*ctx
,
767 const struct gl_texture_object
*tObj
,
768 const struct gl_texture_image
*img
,
769 const GLfloat texcoord
[4],
772 const GLint width
= img
->Width2
;
773 const GLint height
= img
->Height2
;
774 GLint i0
, j0
, i1
, j1
;
775 GLuint useBorderColor
;
778 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
779 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
789 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
790 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
791 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
792 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
796 const GLfloat a
= FRAC(u
);
797 const GLfloat b
= FRAC(v
);
799 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
800 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
801 const GLfloat w10
= a
* (1.0F
-b
);
802 const GLfloat w01
= (1.0F
-a
) * b
;
803 const GLfloat w11
= a
* b
;
804 #else /* CHAN_BITS == 8 */
805 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
806 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
807 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
808 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
809 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
816 if (useBorderColor
& (I0BIT
| J0BIT
)) {
817 COPY_CHAN4(t00
, tObj
->BorderColor
);
820 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
821 if (img
->Format
== GL_COLOR_INDEX
) {
822 palette_sample(ctx
, tObj
, t00
[0], t00
);
825 if (useBorderColor
& (I1BIT
| J0BIT
)) {
826 COPY_CHAN4(t10
, tObj
->BorderColor
);
829 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
830 if (img
->Format
== GL_COLOR_INDEX
) {
831 palette_sample(ctx
, tObj
, t10
[0], t10
);
834 if (useBorderColor
& (I0BIT
| J1BIT
)) {
835 COPY_CHAN4(t01
, tObj
->BorderColor
);
838 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
839 if (img
->Format
== GL_COLOR_INDEX
) {
840 palette_sample(ctx
, tObj
, t01
[0], t01
);
843 if (useBorderColor
& (I1BIT
| J1BIT
)) {
844 COPY_CHAN4(t11
, tObj
->BorderColor
);
847 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
848 if (img
->Format
== GL_COLOR_INDEX
) {
849 palette_sample(ctx
, tObj
, t11
[0], t11
);
852 #if CHAN_TYPE == GL_FLOAT
853 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
854 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
855 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
856 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
857 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
858 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
859 w01
* t01
[0] + w11
* t11
[0] + 0.5);
860 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
861 w01
* t01
[1] + w11
* t11
[1] + 0.5);
862 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
863 w01
* t01
[2] + w11
* t11
[2] + 0.5);
864 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
865 w01
* t01
[3] + w11
* t11
[3] + 0.5);
866 #else /* CHAN_BITS == 8 */
867 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
868 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
869 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
870 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
871 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
872 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
873 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
874 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
883 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
884 * and we're not using a paletted texture.
887 sample_2d_linear_repeat(GLcontext
*ctx
,
888 const struct gl_texture_object
*tObj
,
889 const struct gl_texture_image
*img
,
890 const GLfloat texcoord
[4],
893 const GLint width
= img
->Width2
;
894 const GLint height
= img
->Height2
;
895 GLint i0
, j0
, i1
, j1
;
898 ASSERT(tObj
->WrapS
== GL_REPEAT
);
899 ASSERT(tObj
->WrapT
== GL_REPEAT
);
900 ASSERT(img
->Border
== 0);
901 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
903 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
904 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
907 const GLfloat a
= FRAC(u
);
908 const GLfloat b
= FRAC(v
);
910 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
911 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
912 const GLfloat w10
= a
* (1.0F
-b
);
913 const GLfloat w01
= (1.0F
-a
) * b
;
914 const GLfloat w11
= a
* b
;
915 #else /* CHAN_BITS == 8 */
916 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
917 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
918 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
919 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
920 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
927 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
928 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
929 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
930 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
932 #if CHAN_TYPE == GL_FLOAT
933 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
934 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
935 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
936 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
937 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
938 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
939 w01
* t01
[0] + w11
* t11
[0] + 0.5);
940 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
941 w01
* t01
[1] + w11
* t11
[1] + 0.5);
942 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
943 w01
* t01
[2] + w11
* t11
[2] + 0.5);
944 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
945 w01
* t01
[3] + w11
* t11
[3] + 0.5);
946 #else /* CHAN_BITS == 8 */
947 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
948 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
949 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
950 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
951 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
952 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
953 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
954 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
964 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
965 const struct gl_texture_object
*tObj
,
966 GLuint n
, GLfloat texcoord
[][4],
967 const GLfloat lambda
[], GLchan rgba
[][4])
970 for (i
= 0; i
< n
; i
++) {
972 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
973 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
980 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
981 const struct gl_texture_object
*tObj
,
982 GLuint n
, GLfloat texcoord
[][4],
983 const GLfloat lambda
[], GLchan rgba
[][4])
986 ASSERT(lambda
!= NULL
);
987 for (i
= 0; i
< n
; i
++) {
989 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
990 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
997 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
998 const struct gl_texture_object
*tObj
,
999 GLuint n
, GLfloat texcoord
[][4],
1000 const GLfloat lambda
[], GLchan rgba
[][4])
1003 ASSERT(lambda
!= NULL
);
1004 for (i
= 0; i
< n
; i
++) {
1006 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1007 if (level
>= tObj
->_MaxLevel
) {
1008 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1009 texcoord
[i
], rgba
[i
]);
1012 GLchan t0
[4], t1
[4]; /* texels */
1013 const GLfloat f
= FRAC(lambda
[i
]);
1014 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1015 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1016 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1017 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1018 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1019 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1026 /* Trilinear filtering */
1028 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1029 const struct gl_texture_object
*tObj
,
1030 GLuint n
, GLfloat texcoord
[][4],
1031 const GLfloat lambda
[], GLchan rgba
[][4] )
1034 ASSERT(lambda
!= NULL
);
1035 for (i
= 0; i
< n
; i
++) {
1037 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1038 if (level
>= tObj
->_MaxLevel
) {
1039 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1040 texcoord
[i
], rgba
[i
]);
1043 GLchan t0
[4], t1
[4]; /* texels */
1044 const GLfloat f
= FRAC(lambda
[i
]);
1045 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1046 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1047 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1048 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1049 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1050 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1057 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1058 const struct gl_texture_object
*tObj
,
1059 GLuint n
, GLfloat texcoord
[][4],
1060 const GLfloat lambda
[], GLchan rgba
[][4] )
1063 ASSERT(lambda
!= NULL
);
1064 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1065 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1066 for (i
= 0; i
< n
; i
++) {
1068 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1069 if (level
>= tObj
->_MaxLevel
) {
1070 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1071 texcoord
[i
], rgba
[i
]);
1074 GLchan t0
[4], t1
[4]; /* texels */
1075 const GLfloat f
= FRAC(lambda
[i
]);
1076 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1077 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1078 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1079 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1080 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1081 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1088 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1089 const struct gl_texture_object
*tObj
, GLuint n
,
1090 GLfloat texcoords
[][4],
1091 const GLfloat lambda
[], GLchan rgba
[][4] )
1094 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1097 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1104 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1105 const struct gl_texture_object
*tObj
, GLuint n
,
1106 GLfloat texcoords
[][4],
1107 const GLfloat lambda
[], GLchan rgba
[][4] )
1110 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1113 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1119 * Optimized 2-D texture sampling:
1120 * S and T wrap mode == GL_REPEAT
1121 * GL_NEAREST min/mag filter
1126 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1127 const struct gl_texture_object
*tObj
,
1128 GLuint n
, GLfloat texcoords
[][4],
1129 const GLfloat lambda
[], GLchan rgba
[][4] )
1131 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1132 const GLfloat width
= (GLfloat
) img
->Width
;
1133 const GLfloat height
= (GLfloat
) img
->Height
;
1134 const GLint colMask
= img
->Width
- 1;
1135 const GLint rowMask
= img
->Height
- 1;
1136 const GLint shift
= img
->WidthLog2
;
1139 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1140 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1141 ASSERT(img
->Border
==0);
1142 ASSERT(img
->Format
==GL_RGB
);
1144 for (k
=0; k
<n
; k
++) {
1145 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1146 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1147 GLint pos
= (j
<< shift
) | i
;
1148 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1149 rgba
[k
][RCOMP
] = texel
[0];
1150 rgba
[k
][GCOMP
] = texel
[1];
1151 rgba
[k
][BCOMP
] = texel
[2];
1157 * Optimized 2-D texture sampling:
1158 * S and T wrap mode == GL_REPEAT
1159 * GL_NEAREST min/mag filter
1164 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1165 const struct gl_texture_object
*tObj
,
1166 GLuint n
, GLfloat texcoords
[][4],
1167 const GLfloat lambda
[], GLchan rgba
[][4] )
1169 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1170 const GLfloat width
= (GLfloat
) img
->Width
;
1171 const GLfloat height
= (GLfloat
) img
->Height
;
1172 const GLint colMask
= img
->Width
- 1;
1173 const GLint rowMask
= img
->Height
- 1;
1174 const GLint shift
= img
->WidthLog2
;
1177 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1178 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1179 ASSERT(img
->Border
==0);
1180 ASSERT(img
->Format
==GL_RGBA
);
1182 for (i
= 0; i
< n
; i
++) {
1183 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1184 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1185 const GLint pos
= (row
<< shift
) | col
;
1186 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1187 COPY_CHAN4(rgba
[i
], texel
);
1193 * Given an array of texture coordinate and lambda (level of detail)
1194 * values, return an array of texture sample.
1197 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1198 const struct gl_texture_object
*tObj
,
1199 GLuint n
, GLfloat texcoords
[][4],
1200 const GLfloat lambda
[], GLchan rgba
[][4] )
1202 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1203 GLuint minStart
, minEnd
; /* texels with minification */
1204 GLuint magStart
, magEnd
; /* texels with magnification */
1206 const GLboolean repeatNoBorder
= (tObj
->WrapS
== GL_REPEAT
)
1207 && (tObj
->WrapT
== GL_REPEAT
)
1208 && (tImg
->Border
== 0)
1209 && (tImg
->Format
!= GL_COLOR_INDEX
);
1211 ASSERT(lambda
!= NULL
);
1212 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1213 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1215 if (minStart
< minEnd
) {
1216 /* do the minified texels */
1217 const GLuint m
= minEnd
- minStart
;
1218 switch (tObj
->MinFilter
) {
1220 if (repeatNoBorder
) {
1221 switch (tImg
->Format
) {
1223 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1224 NULL
, rgba
+ minStart
);
1227 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1228 NULL
, rgba
+ minStart
);
1231 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1232 NULL
, rgba
+ minStart
);
1236 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1237 NULL
, rgba
+ minStart
);
1241 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1242 NULL
, rgba
+ minStart
);
1244 case GL_NEAREST_MIPMAP_NEAREST
:
1245 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1246 lambda
+ minStart
, rgba
+ minStart
);
1248 case GL_LINEAR_MIPMAP_NEAREST
:
1249 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1250 lambda
+ minStart
, rgba
+ minStart
);
1252 case GL_NEAREST_MIPMAP_LINEAR
:
1253 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1254 lambda
+ minStart
, rgba
+ minStart
);
1256 case GL_LINEAR_MIPMAP_LINEAR
:
1258 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1259 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1261 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1262 lambda
+ minStart
, rgba
+ minStart
);
1265 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1270 if (magStart
< magEnd
) {
1271 /* do the magnified texels */
1272 const GLuint m
= magEnd
- magStart
;
1274 switch (tObj
->MagFilter
) {
1276 if (repeatNoBorder
) {
1277 switch (tImg
->Format
) {
1279 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1280 NULL
, rgba
+ magStart
);
1283 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1284 NULL
, rgba
+ magStart
);
1287 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1288 NULL
, rgba
+ magStart
);
1292 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1293 NULL
, rgba
+ magStart
);
1297 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1298 NULL
, rgba
+ magStart
);
1301 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1308 /**********************************************************************/
1309 /* 3-D Texture Sampling Functions */
1310 /**********************************************************************/
1313 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1316 sample_3d_nearest(GLcontext
*ctx
,
1317 const struct gl_texture_object
*tObj
,
1318 const struct gl_texture_image
*img
,
1319 const GLfloat texcoord
[4],
1322 const GLint width
= img
->Width2
; /* without border, power of two */
1323 const GLint height
= img
->Height2
; /* without border, power of two */
1324 const GLint depth
= img
->Depth2
; /* without border, power of two */
1327 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1328 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1329 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1331 if (i
< 0 || i
>= (GLint
) img
->Width
||
1332 j
< 0 || j
>= (GLint
) img
->Height
||
1333 k
< 0 || k
>= (GLint
) img
->Depth
) {
1334 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1335 COPY_CHAN4(rgba
, tObj
->BorderColor
);
1338 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1339 if (img
->Format
== GL_COLOR_INDEX
) {
1340 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1348 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1351 sample_3d_linear(GLcontext
*ctx
,
1352 const struct gl_texture_object
*tObj
,
1353 const struct gl_texture_image
*img
,
1354 const GLfloat texcoord
[4],
1357 const GLint width
= img
->Width2
;
1358 const GLint height
= img
->Height2
;
1359 const GLint depth
= img
->Depth2
;
1360 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1361 GLuint useBorderColor
;
1364 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1365 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1366 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1378 /* check if sampling texture border color */
1379 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1380 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1381 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1382 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1383 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1384 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1388 const GLfloat a
= FRAC(u
);
1389 const GLfloat b
= FRAC(v
);
1390 const GLfloat c
= FRAC(w
);
1392 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1393 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1394 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1395 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1396 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1397 GLfloat w110
= a
* b
* (1.0F
-c
);
1398 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1399 GLfloat w101
= a
* (1.0F
-b
) * c
;
1400 GLfloat w011
= (1.0F
-a
) * b
* c
;
1401 GLfloat w111
= a
* b
* c
;
1402 #else /* CHAN_BITS == 8 */
1403 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1404 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1405 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1406 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1407 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1408 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1409 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1410 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1411 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1414 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1415 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1417 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1418 COPY_CHAN4(t000
, tObj
->BorderColor
);
1421 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1422 if (img
->Format
== GL_COLOR_INDEX
) {
1423 palette_sample(ctx
, tObj
, t000
[0], t000
);
1426 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1427 COPY_CHAN4(t100
, tObj
->BorderColor
);
1430 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1431 if (img
->Format
== GL_COLOR_INDEX
) {
1432 palette_sample(ctx
, tObj
, t100
[0], t100
);
1435 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1436 COPY_CHAN4(t010
, tObj
->BorderColor
);
1439 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1440 if (img
->Format
== GL_COLOR_INDEX
) {
1441 palette_sample(ctx
, tObj
, t010
[0], t010
);
1444 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1445 COPY_CHAN4(t110
, tObj
->BorderColor
);
1448 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1449 if (img
->Format
== GL_COLOR_INDEX
) {
1450 palette_sample(ctx
, tObj
, t110
[0], t110
);
1454 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1455 COPY_CHAN4(t001
, tObj
->BorderColor
);
1458 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1459 if (img
->Format
== GL_COLOR_INDEX
) {
1460 palette_sample(ctx
, tObj
, t001
[0], t001
);
1463 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1464 COPY_CHAN4(t101
, tObj
->BorderColor
);
1467 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1468 if (img
->Format
== GL_COLOR_INDEX
) {
1469 palette_sample(ctx
, tObj
, t101
[0], t101
);
1472 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1473 COPY_CHAN4(t011
, tObj
->BorderColor
);
1476 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1477 if (img
->Format
== GL_COLOR_INDEX
) {
1478 palette_sample(ctx
, tObj
, t011
[0], t011
);
1481 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1482 COPY_CHAN4(t111
, tObj
->BorderColor
);
1485 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1486 if (img
->Format
== GL_COLOR_INDEX
) {
1487 palette_sample(ctx
, tObj
, t111
[0], t111
);
1491 #if CHAN_TYPE == GL_FLOAT
1492 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1493 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1494 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1495 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1496 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1497 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1498 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1499 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1500 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1501 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1502 w001
*t001
[0] + w011
*t011
[0] +
1503 w100
*t100
[0] + w110
*t110
[0] +
1504 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1505 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1506 w001
*t001
[1] + w011
*t011
[1] +
1507 w100
*t100
[1] + w110
*t110
[1] +
1508 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1509 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1510 w001
*t001
[2] + w011
*t011
[2] +
1511 w100
*t100
[2] + w110
*t110
[2] +
1512 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1513 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1514 w001
*t001
[3] + w011
*t011
[3] +
1515 w100
*t100
[3] + w110
*t110
[3] +
1516 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1517 #else /* CHAN_BITS == 8 */
1518 rgba
[0] = (GLchan
) (
1519 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1520 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1522 rgba
[1] = (GLchan
) (
1523 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1524 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1526 rgba
[2] = (GLchan
) (
1527 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1528 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1530 rgba
[3] = (GLchan
) (
1531 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1532 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1542 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1543 const struct gl_texture_object
*tObj
,
1544 GLuint n
, GLfloat texcoord
[][4],
1545 const GLfloat lambda
[], GLchan rgba
[][4] )
1548 for (i
= 0; i
< n
; i
++) {
1550 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1551 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1557 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1558 const struct gl_texture_object
*tObj
,
1559 GLuint n
, GLfloat texcoord
[][4],
1560 const GLfloat lambda
[], GLchan rgba
[][4])
1563 ASSERT(lambda
!= NULL
);
1564 for (i
= 0; i
< n
; i
++) {
1566 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1567 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1573 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1574 const struct gl_texture_object
*tObj
,
1575 GLuint n
, GLfloat texcoord
[][4],
1576 const GLfloat lambda
[], GLchan rgba
[][4])
1579 ASSERT(lambda
!= NULL
);
1580 for (i
= 0; i
< n
; i
++) {
1582 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1583 if (level
>= tObj
->_MaxLevel
) {
1584 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1585 texcoord
[i
], rgba
[i
]);
1588 GLchan t0
[4], t1
[4]; /* texels */
1589 const GLfloat f
= FRAC(lambda
[i
]);
1590 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1591 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1592 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1593 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1594 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1595 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1602 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1603 const struct gl_texture_object
*tObj
,
1604 GLuint n
, GLfloat texcoord
[][4],
1605 const GLfloat lambda
[], GLchan rgba
[][4])
1608 ASSERT(lambda
!= NULL
);
1609 for (i
= 0; i
< n
; i
++) {
1611 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1612 if (level
>= tObj
->_MaxLevel
) {
1613 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1614 texcoord
[i
], rgba
[i
]);
1617 GLchan t0
[4], t1
[4]; /* texels */
1618 const GLfloat f
= FRAC(lambda
[i
]);
1619 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1620 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1621 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1622 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1623 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1624 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1631 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1632 const struct gl_texture_object
*tObj
, GLuint n
,
1633 GLfloat texcoords
[][4], const GLfloat lambda
[],
1637 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1640 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1647 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1648 const struct gl_texture_object
*tObj
, GLuint n
,
1649 GLfloat texcoords
[][4],
1650 const GLfloat lambda
[], GLchan rgba
[][4] )
1653 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1656 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1662 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1663 * return a texture sample.
1666 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1667 const struct gl_texture_object
*tObj
, GLuint n
,
1668 GLfloat texcoords
[][4], const GLfloat lambda
[],
1671 GLuint minStart
, minEnd
; /* texels with minification */
1672 GLuint magStart
, magEnd
; /* texels with magnification */
1675 ASSERT(lambda
!= NULL
);
1676 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1677 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1679 if (minStart
< minEnd
) {
1680 /* do the minified texels */
1681 GLuint m
= minEnd
- minStart
;
1682 switch (tObj
->MinFilter
) {
1684 for (i
= minStart
; i
< minEnd
; i
++)
1685 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1686 texcoords
[i
], rgba
[i
]);
1689 for (i
= minStart
; i
< minEnd
; i
++)
1690 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1691 texcoords
[i
], rgba
[i
]);
1693 case GL_NEAREST_MIPMAP_NEAREST
:
1694 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1695 lambda
+ minStart
, rgba
+ minStart
);
1697 case GL_LINEAR_MIPMAP_NEAREST
:
1698 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1699 lambda
+ minStart
, rgba
+ minStart
);
1701 case GL_NEAREST_MIPMAP_LINEAR
:
1702 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1703 lambda
+ minStart
, rgba
+ minStart
);
1705 case GL_LINEAR_MIPMAP_LINEAR
:
1706 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1707 lambda
+ minStart
, rgba
+ minStart
);
1710 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1715 if (magStart
< magEnd
) {
1716 /* do the magnified texels */
1717 switch (tObj
->MagFilter
) {
1719 for (i
= magStart
; i
< magEnd
; i
++)
1720 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1721 texcoords
[i
], rgba
[i
]);
1724 for (i
= magStart
; i
< magEnd
; i
++)
1725 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1726 texcoords
[i
], rgba
[i
]);
1729 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1736 /**********************************************************************/
1737 /* Texture Cube Map Sampling Functions */
1738 /**********************************************************************/
1741 * Choose one of six sides of a texture cube map given the texture
1742 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1745 static const struct gl_texture_image
**
1746 choose_cube_face(const struct gl_texture_object
*texObj
,
1747 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1751 direction target sc tc ma
1752 ---------- ------------------------------- --- --- ---
1753 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1754 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1755 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1756 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1757 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1758 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1760 const GLfloat rx
= texcoord
[0];
1761 const GLfloat ry
= texcoord
[1];
1762 const GLfloat rz
= texcoord
[2];
1763 const struct gl_texture_image
**imgArray
;
1764 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
1767 if (arx
> ary
&& arx
> arz
) {
1769 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
1775 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
1781 else if (ary
> arx
&& ary
> arz
) {
1783 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
1789 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
1797 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
1803 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
1810 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1811 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1817 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1818 const struct gl_texture_object
*tObj
, GLuint n
,
1819 GLfloat texcoords
[][4], const GLfloat lambda
[],
1824 for (i
= 0; i
< n
; i
++) {
1825 const struct gl_texture_image
**images
;
1826 GLfloat newCoord
[4];
1827 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1828 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1835 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1836 const struct gl_texture_object
*tObj
, GLuint n
,
1837 GLfloat texcoords
[][4],
1838 const GLfloat lambda
[], GLchan rgba
[][4])
1842 for (i
= 0; i
< n
; i
++) {
1843 const struct gl_texture_image
**images
;
1844 GLfloat newCoord
[4];
1845 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1846 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1853 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1854 const struct gl_texture_object
*tObj
,
1855 GLuint n
, GLfloat texcoord
[][4],
1856 const GLfloat lambda
[], GLchan rgba
[][4])
1859 ASSERT(lambda
!= NULL
);
1860 for (i
= 0; i
< n
; i
++) {
1861 const struct gl_texture_image
**images
;
1862 GLfloat newCoord
[4];
1864 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1865 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1866 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1872 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1873 const struct gl_texture_object
*tObj
,
1874 GLuint n
, GLfloat texcoord
[][4],
1875 const GLfloat lambda
[], GLchan rgba
[][4])
1878 ASSERT(lambda
!= NULL
);
1879 for (i
= 0; i
< n
; i
++) {
1880 const struct gl_texture_image
**images
;
1881 GLfloat newCoord
[4];
1883 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1884 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1885 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1891 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1892 const struct gl_texture_object
*tObj
,
1893 GLuint n
, GLfloat texcoord
[][4],
1894 const GLfloat lambda
[], GLchan rgba
[][4])
1897 ASSERT(lambda
!= NULL
);
1898 for (i
= 0; i
< n
; i
++) {
1899 const struct gl_texture_image
**images
;
1900 GLfloat newCoord
[4];
1902 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1903 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1904 if (level
>= tObj
->_MaxLevel
) {
1905 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1909 GLchan t0
[4], t1
[4]; /* texels */
1910 const GLfloat f
= FRAC(lambda
[i
]);
1911 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1912 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1913 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1914 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1915 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1916 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1923 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1924 const struct gl_texture_object
*tObj
,
1925 GLuint n
, GLfloat texcoord
[][4],
1926 const GLfloat lambda
[], GLchan rgba
[][4])
1929 ASSERT(lambda
!= NULL
);
1930 for (i
= 0; i
< n
; i
++) {
1931 const struct gl_texture_image
**images
;
1932 GLfloat newCoord
[4];
1934 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1935 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1936 if (level
>= tObj
->_MaxLevel
) {
1937 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1941 GLchan t0
[4], t1
[4];
1942 const GLfloat f
= FRAC(lambda
[i
]);
1943 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
1944 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1945 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1946 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1947 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1948 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1955 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1956 const struct gl_texture_object
*tObj
, GLuint n
,
1957 GLfloat texcoords
[][4], const GLfloat lambda
[],
1960 GLuint minStart
, minEnd
; /* texels with minification */
1961 GLuint magStart
, magEnd
; /* texels with magnification */
1963 ASSERT(lambda
!= NULL
);
1964 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1965 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1967 if (minStart
< minEnd
) {
1968 /* do the minified texels */
1969 const GLuint m
= minEnd
- minStart
;
1970 switch (tObj
->MinFilter
) {
1972 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1973 lambda
+ minStart
, rgba
+ minStart
);
1976 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1977 lambda
+ minStart
, rgba
+ minStart
);
1979 case GL_NEAREST_MIPMAP_NEAREST
:
1980 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1981 lambda
+ minStart
, rgba
+ minStart
);
1983 case GL_LINEAR_MIPMAP_NEAREST
:
1984 sample_cube_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1985 lambda
+ minStart
, rgba
+ minStart
);
1987 case GL_NEAREST_MIPMAP_LINEAR
:
1988 sample_cube_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1989 lambda
+ minStart
, rgba
+ minStart
);
1991 case GL_LINEAR_MIPMAP_LINEAR
:
1992 sample_cube_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1993 lambda
+ minStart
, rgba
+ minStart
);
1996 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2000 if (magStart
< magEnd
) {
2001 /* do the magnified texels */
2002 const GLuint m
= magEnd
- magStart
;
2003 switch (tObj
->MagFilter
) {
2005 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2006 lambda
+ magStart
, rgba
+ magStart
);
2009 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2010 lambda
+ magStart
, rgba
+ magStart
);
2013 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2019 /**********************************************************************/
2020 /* Texture Rectangle Sampling Functions */
2021 /**********************************************************************/
2024 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2025 const struct gl_texture_object
*tObj
, GLuint n
,
2026 GLfloat texcoords
[][4], const GLfloat lambda
[],
2029 const struct gl_texture_image
*img
= tObj
->Image
[0];
2030 const GLfloat width
= (GLfloat
) img
->Width
;
2031 const GLfloat height
= (GLfloat
) img
->Height
;
2032 const GLint width_minus_1
= img
->Width
- 1;
2033 const GLint height_minus_1
= img
->Height
- 1;
2039 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2040 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2041 tObj
->WrapS
== GL_CLAMP_TO_BORDER_ARB
);
2042 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2043 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2044 tObj
->WrapT
== GL_CLAMP_TO_BORDER_ARB
);
2045 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2047 /* XXX move Wrap mode tests outside of loops for common cases */
2048 for (i
= 0; i
< n
; i
++) {
2050 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2051 if (tObj
->WrapS
== GL_CLAMP
) {
2052 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2054 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2055 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2058 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2060 if (tObj
->WrapT
== GL_CLAMP
) {
2061 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2063 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2064 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2067 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2070 col
= CLAMP(col
, 0, width_minus_1
);
2071 row
= CLAMP(row
, 0, height_minus_1
);
2073 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2079 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2080 const struct gl_texture_object
*tObj
, GLuint n
,
2081 GLfloat texcoords
[][4],
2082 const GLfloat lambda
[], GLchan rgba
[][4])
2084 const struct gl_texture_image
*img
= tObj
->Image
[0];
2085 const GLfloat width
= (GLfloat
) img
->Width
;
2086 const GLfloat height
= (GLfloat
) img
->Height
;
2087 const GLint width_minus_1
= img
->Width
- 1;
2088 const GLint height_minus_1
= img
->Height
- 1;
2094 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2095 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2096 tObj
->WrapS
== GL_CLAMP_TO_BORDER_ARB
);
2097 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2098 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2099 tObj
->WrapT
== GL_CLAMP_TO_BORDER_ARB
);
2100 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2102 /* XXX lots of opportunity for optimization in this loop */
2103 for (i
= 0; i
< n
; i
++) {
2105 GLint row0
, col0
, row1
, col1
;
2106 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2107 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2109 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2110 if (tObj
->WrapS
== GL_CLAMP
) {
2111 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2113 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2114 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2117 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2119 if (tObj
->WrapT
== GL_CLAMP
) {
2120 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2122 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2123 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2126 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2129 /* compute integer rows/columns */
2130 col0
= IFLOOR(fcol
);
2132 col0
= CLAMP(col0
, 0, width_minus_1
);
2133 col1
= CLAMP(col1
, 0, width_minus_1
);
2134 row0
= IFLOOR(frow
);
2136 row0
= CLAMP(row0
, 0, height_minus_1
);
2137 row1
= CLAMP(row1
, 0, height_minus_1
);
2139 /* get four texel samples */
2140 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2141 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2142 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2143 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2145 /* compute sample weights */
2148 w00
= (1.0F
-a
) * (1.0F
-b
);
2150 w01
= (1.0F
-a
) * b
;
2153 /* compute weighted average of samples */
2154 rgba
[i
][0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
2155 rgba
[i
][1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
2156 rgba
[i
][2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
2157 rgba
[i
][3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
2163 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2164 const struct gl_texture_object
*tObj
, GLuint n
,
2165 GLfloat texcoords
[][4], const GLfloat lambda
[],
2168 GLuint minStart
, minEnd
, magStart
, magEnd
;
2170 /* We only need lambda to decide between minification and magnification.
2171 * There is no mipmapping with rectangular textures.
2173 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2174 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2176 if (minStart
< minEnd
) {
2177 if (tObj
->MinFilter
== GL_NEAREST
) {
2178 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2179 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2182 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2183 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2186 if (magStart
< magEnd
) {
2187 if (tObj
->MagFilter
== GL_NEAREST
) {
2188 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2189 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2192 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2193 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2201 * Sample a shadow/depth texture.
2204 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2205 const struct gl_texture_object
*tObj
, GLuint n
,
2206 GLfloat texcoords
[][4], const GLfloat lambda
[],
2209 const GLint baseLevel
= tObj
->BaseLevel
;
2210 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2211 const GLuint width
= texImage
->Width
;
2212 const GLuint height
= texImage
->Height
;
2213 const GLchan ambient
= tObj
->ShadowAmbient
;
2219 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2220 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2221 tObj
->Target
== GL_TEXTURE_2D
||
2222 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2224 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2226 /* XXX this could be precomputed and saved in the texture object */
2227 if (tObj
->CompareFlag
) {
2228 /* GL_SGIX_shadow */
2229 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2230 function
= GL_LEQUAL
;
2233 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2234 function
= GL_GEQUAL
;
2237 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2239 function
= tObj
->CompareFunc
;
2242 function
= GL_NONE
; /* pass depth through as grayscale */
2245 if (tObj
->MagFilter
== GL_NEAREST
) {
2247 for (i
= 0; i
< n
; i
++) {
2248 GLfloat depthSample
;
2250 /* XXX fix for texture rectangle! */
2251 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2252 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2253 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2257 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2260 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2263 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2266 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2269 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2272 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2281 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2284 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2288 switch (tObj
->DepthMode
) {
2290 texel
[i
][RCOMP
] = result
;
2291 texel
[i
][GCOMP
] = result
;
2292 texel
[i
][BCOMP
] = result
;
2293 texel
[i
][ACOMP
] = CHAN_MAX
;
2296 texel
[i
][RCOMP
] = result
;
2297 texel
[i
][GCOMP
] = result
;
2298 texel
[i
][BCOMP
] = result
;
2299 texel
[i
][ACOMP
] = result
;
2302 texel
[i
][RCOMP
] = 0;
2303 texel
[i
][GCOMP
] = 0;
2304 texel
[i
][BCOMP
] = 0;
2305 texel
[i
][ACOMP
] = result
;
2308 _mesa_problem(ctx
, "Bad depth texture mode");
2314 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2315 for (i
= 0; i
< n
; i
++) {
2316 GLfloat depth00
, depth01
, depth10
, depth11
;
2317 GLint i0
, i1
, j0
, j1
;
2319 GLuint useBorderTexel
;
2321 /* XXX fix for texture rectangle! */
2322 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2323 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2326 if (texImage
->Border
) {
2327 i0
+= texImage
->Border
;
2328 i1
+= texImage
->Border
;
2329 j0
+= texImage
->Border
;
2330 j1
+= texImage
->Border
;
2333 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2334 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2335 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2336 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2339 /* get four depth samples from the texture */
2340 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2344 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2346 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2350 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2352 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2356 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2358 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2362 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2366 /* compute a single weighted depth sample and do one comparison */
2367 const GLfloat a
= FRAC(u
+ 1.0F
);
2368 const GLfloat b
= FRAC(v
+ 1.0F
);
2369 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2370 const GLfloat w10
= ( a
) * (1.0F
- b
);
2371 const GLfloat w01
= (1.0F
- a
) * ( b
);
2372 const GLfloat w11
= ( a
) * ( b
);
2373 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2374 + w01
* depth01
+ w11
* depth11
;
2375 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2376 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2384 /* Do four depth/R comparisons and compute a weighted result.
2385 * If this touches on somebody's I.P., I'll remove this code
2388 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2389 GLfloat luminance
= CHAN_MAXF
;
2393 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2394 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2395 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2396 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2397 result
= (GLchan
) luminance
;
2400 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2401 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2402 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2403 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2404 result
= (GLchan
) luminance
;
2407 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2408 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2409 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2410 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2411 result
= (GLchan
) luminance
;
2414 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2415 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2416 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2417 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2418 result
= (GLchan
) luminance
;
2421 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2422 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2423 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2424 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2425 result
= (GLchan
) luminance
;
2428 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2429 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2430 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2431 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2432 result
= (GLchan
) luminance
;
2441 /* ordinary bilinear filtering */
2443 const GLfloat a
= FRAC(u
+ 1.0F
);
2444 const GLfloat b
= FRAC(v
+ 1.0F
);
2445 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2446 const GLfloat w10
= ( a
) * (1.0F
- b
);
2447 const GLfloat w01
= (1.0F
- a
) * ( b
);
2448 const GLfloat w11
= ( a
) * ( b
);
2449 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2450 + w01
* depth01
+ w11
* depth11
;
2451 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2455 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2460 switch (tObj
->DepthMode
) {
2462 texel
[i
][RCOMP
] = result
;
2463 texel
[i
][GCOMP
] = result
;
2464 texel
[i
][BCOMP
] = result
;
2465 texel
[i
][ACOMP
] = CHAN_MAX
;
2468 texel
[i
][RCOMP
] = result
;
2469 texel
[i
][GCOMP
] = result
;
2470 texel
[i
][BCOMP
] = result
;
2471 texel
[i
][ACOMP
] = result
;
2474 texel
[i
][RCOMP
] = 0;
2475 texel
[i
][GCOMP
] = 0;
2476 texel
[i
][BCOMP
] = 0;
2477 texel
[i
][ACOMP
] = result
;
2480 _mesa_problem(ctx
, "Bad depth texture mode");
2489 * Experimental depth texture sampling function.
2492 sample_depth_texture2(const GLcontext
*ctx
,
2493 const struct gl_texture_unit
*texUnit
,
2494 GLuint n
, GLfloat texcoords
[][4],
2497 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2498 const GLint baseLevel
= texObj
->BaseLevel
;
2499 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2500 const GLuint width
= texImage
->Width
;
2501 const GLuint height
= texImage
->Height
;
2502 const GLchan ambient
= texObj
->ShadowAmbient
;
2503 GLboolean lequal
, gequal
;
2505 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2506 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2510 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2511 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2515 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2516 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2517 * isn't a depth texture.
2519 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2520 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2524 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2535 for (i
= 0; i
< n
; i
++) {
2537 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2540 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2542 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2550 if (imin
< 0) imin
= 0;
2551 if (imax
>= width
) imax
= width
- 1;
2552 if (jmin
< 0) jmin
= 0;
2553 if (jmax
>= height
) jmax
= height
- 1;
2555 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2557 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2558 for (ii
= imin
; ii
<= imax
; ii
++) {
2559 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2561 if ((depthSample
<= r
[i
] && lequal
) ||
2562 (depthSample
>= r
[i
] && gequal
)) {
2568 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2569 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2572 texel
[i
][RCOMP
] = lum
;
2573 texel
[i
][GCOMP
] = lum
;
2574 texel
[i
][BCOMP
] = lum
;
2575 texel
[i
][ACOMP
] = CHAN_MAX
;
2583 * We use this function when a texture object is in an "incomplete" state.
2586 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2587 const struct gl_texture_object
*tObj
, GLuint n
,
2588 GLfloat texcoords
[][4], const GLfloat lambda
[],
2596 * Setup the texture sampling function for this texture object.
2599 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2600 const struct gl_texture_object
*t
)
2602 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2605 swrast
->TextureSample
[texUnit
] = null_sample_func
;
2608 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2609 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2612 /* Compute min/mag filter threshold */
2613 if (t
->MagFilter
== GL_LINEAR
2614 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
2615 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
2616 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
2619 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
2623 switch (t
->Target
) {
2625 if (format
== GL_DEPTH_COMPONENT
) {
2626 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2628 else if (needLambda
) {
2629 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
2631 else if (t
->MinFilter
== GL_LINEAR
) {
2632 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
2635 ASSERT(t
->MinFilter
== GL_NEAREST
);
2636 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
2640 if (format
== GL_DEPTH_COMPONENT
) {
2641 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2643 else if (needLambda
) {
2644 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
2646 else if (t
->MinFilter
== GL_LINEAR
) {
2647 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
2650 GLint baseLevel
= t
->BaseLevel
;
2651 ASSERT(t
->MinFilter
== GL_NEAREST
);
2652 if (t
->WrapS
== GL_REPEAT
&&
2653 t
->WrapT
== GL_REPEAT
&&
2654 t
->Image
[baseLevel
]->Border
== 0 &&
2655 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2656 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
2658 else if (t
->WrapS
== GL_REPEAT
&&
2659 t
->WrapT
== GL_REPEAT
&&
2660 t
->Image
[baseLevel
]->Border
== 0 &&
2661 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2662 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
2665 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
2670 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
2672 else if (t
->MinFilter
== GL_LINEAR
) {
2673 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
2676 ASSERT(t
->MinFilter
== GL_NEAREST
);
2677 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
2680 case GL_TEXTURE_CUBE_MAP_ARB
:
2682 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
2684 else if (t
->MinFilter
== GL_LINEAR
) {
2685 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
2688 ASSERT(t
->MinFilter
== GL_NEAREST
);
2689 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
2692 case GL_TEXTURE_RECTANGLE_NV
:
2694 swrast
->TextureSample
[texUnit
] = sample_lambda_rect
;
2696 else if (t
->MinFilter
== GL_LINEAR
) {
2697 swrast
->TextureSample
[texUnit
] = sample_linear_rect
;
2700 ASSERT(t
->MinFilter
== GL_NEAREST
);
2701 swrast
->TextureSample
[texUnit
] = sample_nearest_rect
;
2705 _mesa_problem(ctx
, "invalid target in _swrast_choose_texture_sample_func");
2711 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2712 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2716 * Do texture application for GL_ARB/EXT_texture_env_combine.
2718 * ctx - rendering context
2719 * textureUnit - the texture unit to apply
2720 * n - number of fragments to process (span width)
2721 * primary_rgba - incoming fragment color array
2722 * texelBuffer - pointer to texel colors for all texture units
2724 * rgba - incoming colors, which get modified here
2727 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
2728 CONST
GLchan (*primary_rgba
)[4],
2729 CONST GLchan
*texelBuffer
,
2732 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
2733 const GLchan (*argRGB
[3])[4];
2734 const GLchan (*argA
[3])[4];
2735 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
2736 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
2737 #if CHAN_TYPE == GL_FLOAT
2738 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2739 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2741 const GLint half
= (CHAN_MAX
+ 1) / 2;
2745 /* GLchan ccolor[3][4]; */
2746 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2747 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2749 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2750 ctx
->Extensions
.ARB_texture_env_combine
);
2751 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
2755 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
2756 textureUnit->CombineModeRGB,
2757 textureUnit->CombineModeA,
2758 textureUnit->CombineSourceRGB[0],
2759 textureUnit->CombineSourceA[0],
2760 textureUnit->CombineSourceRGB[1],
2761 textureUnit->CombineSourceA[1]);
2765 * Do operand setup for up to 3 operands. Loop over the terms.
2767 for (j
= 0; j
< 3; j
++) {
2768 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
2769 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
2773 argA
[j
] = (const GLchan (*)[4])
2774 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2776 case GL_PRIMARY_COLOR_EXT
:
2777 argA
[j
] = primary_rgba
;
2779 case GL_PREVIOUS_EXT
:
2780 argA
[j
] = (const GLchan (*)[4]) rgba
;
2782 case GL_CONSTANT_EXT
:
2784 GLchan alpha
, (*c
)[4] = ccolor
[j
];
2785 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2786 for (i
= 0; i
< n
; i
++)
2787 c
[i
][ACOMP
] = alpha
;
2788 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2792 /* ARB_texture_env_crossbar source */
2794 const GLuint srcUnit
= srcA
- GL_TEXTURE0_ARB
;
2795 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2796 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2798 argA
[j
] = (const GLchan (*)[4])
2799 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2805 argRGB
[j
] = (const GLchan (*)[4])
2806 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2808 case GL_PRIMARY_COLOR_EXT
:
2809 argRGB
[j
] = primary_rgba
;
2811 case GL_PREVIOUS_EXT
:
2812 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2814 case GL_CONSTANT_EXT
:
2816 GLchan (*c
)[4] = ccolor
[j
];
2817 GLchan red
, green
, blue
, alpha
;
2818 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2819 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2820 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2821 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2822 for (i
= 0; i
< n
; i
++) {
2824 c
[i
][GCOMP
] = green
;
2826 c
[i
][ACOMP
] = alpha
;
2828 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2832 /* ARB_texture_env_crossbar source */
2834 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0_ARB
;
2835 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2836 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2838 argRGB
[j
] = (const GLchan (*)[4])
2839 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2843 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
2844 const GLchan (*src
)[4] = argRGB
[j
];
2845 GLchan (*dst
)[4] = ccolor
[j
];
2847 /* point to new arg[j] storage */
2848 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2850 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2851 for (i
= 0; i
< n
; i
++) {
2852 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2853 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2854 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2857 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
2858 for (i
= 0; i
< n
; i
++) {
2859 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2860 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2861 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2865 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2866 for (i
= 0; i
< n
; i
++) {
2867 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2868 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2869 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2874 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
2875 const GLchan (*src
)[4] = argA
[j
];
2876 GLchan (*dst
)[4] = ccolor
[j
];
2877 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2878 for (i
= 0; i
< n
; i
++) {
2879 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2883 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
2884 textureUnit
->CombineModeA
== GL_REPLACE
) {
2885 break; /* done, we need only arg0 */
2889 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
2890 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
2891 break; /* arg0 and arg1 are done. we don't need arg2. */
2896 * Do the texture combine.
2898 switch (textureUnit
->CombineModeRGB
) {
2901 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2903 for (i
= 0; i
< n
; i
++) {
2904 #if CHAN_TYPE == GL_FLOAT
2905 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
2906 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
2907 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
2909 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
2910 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
2911 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
2912 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2913 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2914 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2919 for (i
= 0; i
< n
; i
++) {
2920 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
2921 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
2922 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
2929 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2930 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2931 #if CHAN_TYPE != GL_FLOAT
2932 const GLint shift
= CHAN_BITS
- RGBshift
;
2934 for (i
= 0; i
< n
; i
++) {
2935 #if CHAN_TYPE == GL_FLOAT
2936 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
2937 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
2938 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
2940 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
2941 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
2942 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
2943 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2944 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2945 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2952 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2953 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2954 for (i
= 0; i
< n
; i
++) {
2955 #if CHAN_TYPE == GL_FLOAT
2956 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
2957 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
2958 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
2960 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2961 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2962 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2963 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2964 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2965 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2970 case GL_ADD_SIGNED_EXT
:
2972 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2973 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2974 for (i
= 0; i
< n
; i
++) {
2975 #if CHAN_TYPE == GL_FLOAT
2976 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
2977 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
2978 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
2980 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
2981 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
2982 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
2983 r
= (r
< 0) ? 0 : r
<< RGBshift
;
2984 g
= (g
< 0) ? 0 : g
<< RGBshift
;
2985 b
= (b
< 0) ? 0 : b
<< RGBshift
;
2986 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2987 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2988 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2993 case GL_INTERPOLATE_EXT
:
2995 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2996 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2997 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
2998 #if CHAN_TYPE != GL_FLOAT
2999 const GLint shift
= CHAN_BITS
- RGBshift
;
3001 for (i
= 0; i
< n
; i
++) {
3002 #if CHAN_TYPE == GL_FLOAT
3003 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3004 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3005 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3006 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3007 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3008 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3010 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3011 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3013 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3014 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3016 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3017 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3019 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3020 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3021 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3026 case GL_SUBTRACT_ARB
:
3028 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3029 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3030 for (i
= 0; i
< n
; i
++) {
3031 #if CHAN_TYPE == GL_FLOAT
3032 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3033 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3034 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3036 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3037 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3038 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3039 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3040 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3041 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3046 case GL_DOT3_RGB_EXT
:
3047 case GL_DOT3_RGBA_EXT
:
3049 /* Do not scale the result by 1 2 or 4 */
3050 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3051 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3052 for (i
= 0; i
< n
; i
++) {
3053 #if CHAN_TYPE == GL_FLOAT
3054 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3055 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3056 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3058 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3060 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3061 (GLint
)arg1
[i
][RCOMP
] - half
) +
3062 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3063 (GLint
)arg1
[i
][GCOMP
] - half
) +
3064 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3065 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3066 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3068 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3072 case GL_DOT3_RGB_ARB
:
3073 case GL_DOT3_RGBA_ARB
:
3075 /* DO scale the result by 1 2 or 4 */
3076 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3077 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3078 for (i
= 0; i
< n
; i
++) {
3079 #if CHAN_TYPE == GL_FLOAT
3080 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3081 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3082 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3084 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
) * RGBmult
;
3086 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3087 (GLint
)arg1
[i
][RCOMP
] - half
) +
3088 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3089 (GLint
)arg1
[i
][GCOMP
] - half
) +
3090 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3091 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3092 dot
= CLAMP(dot
, 0, CHAN_MAX
) << RGBshift
;
3094 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3099 _mesa_problem(ctx
, "invalid combine mode");
3102 switch (textureUnit
->CombineModeA
) {
3105 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3107 for (i
= 0; i
< n
; i
++) {
3108 #if CHAN_TYPE == GL_FLOAT
3109 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3111 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3113 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3117 for (i
= 0; i
< n
; i
++) {
3118 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3125 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3126 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3127 #if CHAN_TYPE != GL_FLOAT
3128 const GLint shift
= CHAN_BITS
- Ashift
;
3130 for (i
= 0; i
< n
; i
++) {
3131 #if CHAN_TYPE == GL_FLOAT
3132 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3134 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3135 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3142 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3143 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3144 for (i
= 0; i
< n
; i
++) {
3145 #if CHAN_TYPE == GL_FLOAT
3146 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3148 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3149 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3154 case GL_ADD_SIGNED_EXT
:
3156 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3157 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3158 for (i
= 0; i
< n
; i
++) {
3159 #if CHAN_TYPE == GL_FLOAT
3160 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3162 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3163 a
= (a
< 0) ? 0 : a
<< Ashift
;
3164 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3169 case GL_INTERPOLATE_EXT
:
3171 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3172 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3173 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3174 #if CHAN_TYPE != GL_FLOAT
3175 const GLint shift
= CHAN_BITS
- Ashift
;
3177 for (i
=0; i
<n
; i
++) {
3178 #if CHAN_TYPE == GL_FLOAT
3179 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3180 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3183 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3184 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3186 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3191 case GL_SUBTRACT_ARB
:
3193 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3194 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3195 for (i
= 0; i
< n
; i
++) {
3196 #if CHAN_TYPE == GL_FLOAT
3197 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3199 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3200 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3207 _mesa_problem(ctx
, "invalid combine mode");
3210 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3211 * This is kind of a kludge. It would have been better if the spec
3212 * were written such that the GL_COMBINE_ALPHA value could be set to
3215 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3216 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
3217 for (i
= 0; i
< n
; i
++) {
3218 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3221 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3227 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3228 * texUnit->EnvMode == GL_COMBINE4_NV.
3231 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3232 CONST
GLchan (*primary_rgba
)[4],
3233 CONST GLchan
*texelBuffer
,
3241 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3242 * MODULATE, or DECAL) to an array of fragments.
3243 * Input: textureUnit - pointer to texture unit to apply
3244 * format - base internal texture format
3245 * n - number of fragments
3246 * primary_rgba - primary colors (may alias rgba for single texture)
3247 * texels - array of texel colors
3248 * InOut: rgba - incoming fragment colors modified by texel colors
3249 * according to the texture environment mode.
3252 texture_apply( const GLcontext
*ctx
,
3253 const struct gl_texture_unit
*texUnit
,
3255 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3260 GLint Rc
, Gc
, Bc
, Ac
;
3264 ASSERT(texUnit
->_Current
);
3266 baseLevel
= texUnit
->_Current
->BaseLevel
;
3267 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3269 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3271 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
) {
3272 format
= GL_RGBA
; /* a bit of a hack */
3275 switch (texUnit
->EnvMode
) {
3282 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3288 GLchan Lt
= texel
[i
][RCOMP
];
3289 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3293 case GL_LUMINANCE_ALPHA
:
3295 GLchan Lt
= texel
[i
][RCOMP
];
3297 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3299 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3305 GLchan It
= texel
[i
][RCOMP
];
3306 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3308 rgba
[i
][ACOMP
] = It
;
3314 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3315 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3316 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3323 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3324 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3325 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3327 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3331 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3342 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3348 GLchan Lt
= texel
[i
][RCOMP
];
3349 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3350 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3351 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3355 case GL_LUMINANCE_ALPHA
:
3358 GLchan Lt
= texel
[i
][RCOMP
];
3359 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3360 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3361 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3363 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3369 GLchan It
= texel
[i
][RCOMP
];
3370 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3371 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3372 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3374 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3380 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3381 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3382 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3389 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3390 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3391 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3393 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3397 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3406 case GL_LUMINANCE_ALPHA
:
3413 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3414 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3415 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3421 /* Cv = Cf(1-At) + CtAt */
3422 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3423 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3424 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3425 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3430 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3436 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3437 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3438 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3439 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3445 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3450 /* Cv = Cf(1-Lt) + CcLt */
3451 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3452 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3453 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3454 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3458 case GL_LUMINANCE_ALPHA
:
3460 /* Cv = Cf(1-Lt) + CcLt */
3461 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3462 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3463 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3464 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3466 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3471 /* Cv = Cf(1-It) + CcLt */
3472 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3473 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3474 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3475 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3476 /* Av = Af(1-It) + Ac*It */
3477 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
3482 /* Cv = Cf(1-Ct) + CcCt */
3483 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3484 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3485 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3491 /* Cv = Cf(1-Ct) + CcCt */
3492 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3493 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3494 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3496 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3500 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
3505 /* XXX don't clamp results if GLchan is float??? */
3507 case GL_ADD
: /* GL_EXT_texture_add_env */
3514 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3519 GLuint Lt
= texel
[i
][RCOMP
];
3520 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3521 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3522 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3523 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3524 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3525 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3529 case GL_LUMINANCE_ALPHA
:
3531 GLuint Lt
= texel
[i
][RCOMP
];
3532 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3533 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3534 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3535 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3536 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3537 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3538 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3543 GLchan It
= texel
[i
][RCOMP
];
3544 GLuint r
= rgba
[i
][RCOMP
] + It
;
3545 GLuint g
= rgba
[i
][GCOMP
] + It
;
3546 GLuint b
= rgba
[i
][BCOMP
] + It
;
3547 GLuint a
= rgba
[i
][ACOMP
] + It
;
3548 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3549 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3550 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3551 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
3556 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3557 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3558 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3559 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3560 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3561 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3567 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3568 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3569 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3570 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3571 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3572 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3573 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3577 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
3583 _mesa_problem(ctx
, "Bad env mode in texture_apply");
3591 * Apply texture mapping to a span of fragments.
3594 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
3596 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
3597 GLchan primary_rgba
[MAX_WIDTH
][4];
3600 ASSERT(span
->end
< MAX_WIDTH
);
3601 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3604 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
3606 if (swrast
->_AnyTextureCombine
)
3607 MEMCPY(primary_rgba
, span
->color
.rgba
, 4 * span
->end
* sizeof(GLchan
));
3610 * Must do all texture sampling before combining in order to
3611 * accomodate GL_ARB_texture_env_crossbar.
3613 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3614 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3615 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3616 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
3617 GLfloat
*lambda
= span
->lambda
[unit
];
3618 GLchan (*texels
)[4] = (GLchan (*)[4])
3619 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
3621 /* adjust texture lod (lambda) */
3622 if (span
->arrayMask
| SPAN_LAMBDA
) {
3623 if (texUnit
->LodBias
!= 0.0F
) {
3624 /* apply LOD bias, but don't clamp yet */
3626 for (i
= 0; i
< span
->end
; i
++) {
3627 lambda
[i
] += texUnit
->LodBias
;
3631 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
3632 /* apply LOD clamping to lambda */
3633 const GLfloat min
= curObj
->MinLod
;
3634 const GLfloat max
= curObj
->MaxLod
;
3636 for (i
= 0; i
< span
->end
; i
++) {
3637 GLfloat l
= lambda
[i
];
3638 lambda
[i
] = CLAMP(l
, min
, max
);
3643 /* Sample the texture (span->end fragments) */
3644 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
,
3645 span
->end
, span
->texcoords
[unit
],
3651 * OK, now apply the texture (aka texture combine/blend).
3652 * We modify the span->color.rgba values.
3654 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3655 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3656 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3657 if (texUnit
->EnvMode
== GL_COMBINE_EXT
) {
3658 /* GL_ARB/EXT_texture_env_combine */
3659 texture_combine( ctx
, unit
, span
->end
,
3660 (CONST
GLchan (*)[4]) primary_rgba
,
3661 swrast
->TexelBuffer
,
3664 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
3665 /* GL_NV_texture_env_combine4 */
3666 texture_combine4( ctx
, unit
, span
->end
,
3667 (CONST
GLchan (*)[4]) primary_rgba
,
3668 swrast
->TexelBuffer
,
3672 /* conventional texture blend */
3673 const GLchan (*texels
)[4] = (const GLchan (*)[4])
3674 (swrast
->TexelBuffer
+ unit
*
3675 (span
->end
* 4 * sizeof(GLchan
)));
3676 texture_apply( ctx
, texUnit
, span
->end
,
3677 (CONST
GLchan (*)[4]) primary_rgba
, texels
,