1 /* $Id: s_texture.c,v 1.59 2002/04/12 15:39:59 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");
2020 * Sample a shadow/depth texture.
2023 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2024 const struct gl_texture_object
*tObj
, GLuint n
,
2025 GLfloat texcoords
[][4], const GLfloat lambda
[],
2028 const GLint baseLevel
= tObj
->BaseLevel
;
2029 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2030 const GLuint width
= texImage
->Width
;
2031 const GLuint height
= texImage
->Height
;
2032 const GLchan ambient
= tObj
->ShadowAmbient
;
2038 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2039 ASSERT(tObj
->Dimensions
== 1 || tObj
->Dimensions
== 2);
2041 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2043 /* XXX this could be precomputed and saved in the texture object */
2044 if (tObj
->CompareFlag
) {
2045 /* GL_SGIX_shadow */
2046 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2047 function
= GL_LEQUAL
;
2050 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2051 function
= GL_GEQUAL
;
2054 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2056 function
= tObj
->CompareFunc
;
2059 function
= GL_NONE
; /* pass depth through as grayscale */
2062 if (tObj
->MagFilter
== GL_NEAREST
) {
2064 for (i
= 0; i
< n
; i
++) {
2065 GLfloat depthSample
;
2067 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2068 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2069 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2073 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2076 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2079 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2082 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2085 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2088 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2097 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2100 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2104 switch (tObj
->DepthMode
) {
2106 texel
[i
][RCOMP
] = result
;
2107 texel
[i
][GCOMP
] = result
;
2108 texel
[i
][BCOMP
] = result
;
2109 texel
[i
][ACOMP
] = CHAN_MAX
;
2112 texel
[i
][RCOMP
] = result
;
2113 texel
[i
][GCOMP
] = result
;
2114 texel
[i
][BCOMP
] = result
;
2115 texel
[i
][ACOMP
] = result
;
2118 texel
[i
][RCOMP
] = 0;
2119 texel
[i
][GCOMP
] = 0;
2120 texel
[i
][BCOMP
] = 0;
2121 texel
[i
][ACOMP
] = result
;
2124 _mesa_problem(ctx
, "Bad depth texture mode");
2130 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2131 for (i
= 0; i
< n
; i
++) {
2132 GLfloat depth00
, depth01
, depth10
, depth11
;
2133 GLint i0
, i1
, j0
, j1
;
2135 GLuint useBorderTexel
;
2137 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2138 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2141 if (texImage
->Border
) {
2142 i0
+= texImage
->Border
;
2143 i1
+= texImage
->Border
;
2144 j0
+= texImage
->Border
;
2145 j1
+= texImage
->Border
;
2148 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2149 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2150 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2151 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2154 /* get four depth samples from the texture */
2155 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2159 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2161 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2165 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2167 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2171 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2173 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2177 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2181 /* compute a single weighted depth sample and do one comparison */
2182 const GLfloat a
= FRAC(u
+ 1.0F
);
2183 const GLfloat b
= FRAC(v
+ 1.0F
);
2184 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2185 const GLfloat w10
= ( a
) * (1.0F
- b
);
2186 const GLfloat w01
= (1.0F
- a
) * ( b
);
2187 const GLfloat w11
= ( a
) * ( b
);
2188 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2189 + w01
* depth01
+ w11
* depth11
;
2190 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2191 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2199 /* Do four depth/R comparisons and compute a weighted result.
2200 * If this touches on somebody's I.P., I'll remove this code
2203 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2204 GLfloat luminance
= CHAN_MAXF
;
2208 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2209 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2210 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2211 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2212 result
= (GLchan
) luminance
;
2215 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2216 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2217 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2218 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2219 result
= (GLchan
) luminance
;
2222 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2223 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2224 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2225 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2226 result
= (GLchan
) luminance
;
2229 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2230 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2231 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2232 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2233 result
= (GLchan
) luminance
;
2236 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2237 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2238 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2239 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2240 result
= (GLchan
) luminance
;
2243 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2244 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2245 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2246 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2247 result
= (GLchan
) luminance
;
2256 /* ordinary bilinear filtering */
2258 const GLfloat a
= FRAC(u
+ 1.0F
);
2259 const GLfloat b
= FRAC(v
+ 1.0F
);
2260 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2261 const GLfloat w10
= ( a
) * (1.0F
- b
);
2262 const GLfloat w01
= (1.0F
- a
) * ( b
);
2263 const GLfloat w11
= ( a
) * ( b
);
2264 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2265 + w01
* depth01
+ w11
* depth11
;
2266 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2270 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2275 switch (tObj
->DepthMode
) {
2277 texel
[i
][RCOMP
] = result
;
2278 texel
[i
][GCOMP
] = result
;
2279 texel
[i
][BCOMP
] = result
;
2280 texel
[i
][ACOMP
] = CHAN_MAX
;
2283 texel
[i
][RCOMP
] = result
;
2284 texel
[i
][GCOMP
] = result
;
2285 texel
[i
][BCOMP
] = result
;
2286 texel
[i
][ACOMP
] = result
;
2289 texel
[i
][RCOMP
] = 0;
2290 texel
[i
][GCOMP
] = 0;
2291 texel
[i
][BCOMP
] = 0;
2292 texel
[i
][ACOMP
] = result
;
2295 _mesa_problem(ctx
, "Bad depth texture mode");
2304 * Experimental depth texture sampling function.
2307 sample_depth_texture2(const GLcontext
*ctx
,
2308 const struct gl_texture_unit
*texUnit
,
2309 GLuint n
, GLfloat texcoords
[][4],
2312 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2313 const GLint baseLevel
= texObj
->BaseLevel
;
2314 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2315 const GLuint width
= texImage
->Width
;
2316 const GLuint height
= texImage
->Height
;
2317 const GLchan ambient
= texObj
->ShadowAmbient
;
2318 GLboolean lequal
, gequal
;
2320 if (texObj
->Dimensions
!= 2) {
2321 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2325 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2326 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2330 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2331 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2332 * isn't a depth texture.
2334 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2335 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2339 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2350 for (i
= 0; i
< n
; i
++) {
2352 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2355 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2357 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2365 if (imin
< 0) imin
= 0;
2366 if (imax
>= width
) imax
= width
- 1;
2367 if (jmin
< 0) jmin
= 0;
2368 if (jmax
>= height
) jmax
= height
- 1;
2370 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2372 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2373 for (ii
= imin
; ii
<= imax
; ii
++) {
2374 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2376 if ((depthSample
<= r
[i
] && lequal
) ||
2377 (depthSample
>= r
[i
] && gequal
)) {
2383 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2384 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2387 texel
[i
][RCOMP
] = lum
;
2388 texel
[i
][GCOMP
] = lum
;
2389 texel
[i
][BCOMP
] = lum
;
2390 texel
[i
][ACOMP
] = CHAN_MAX
;
2398 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2399 const struct gl_texture_object
*tObj
, GLuint n
,
2400 GLfloat texcoords
[][4], const GLfloat lambda
[],
2407 /**********************************************************************/
2408 /* Texture Sampling Setup */
2409 /**********************************************************************/
2413 * Setup the texture sampling function for this texture object.
2416 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2417 const struct gl_texture_object
*t
)
2419 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2422 swrast
->TextureSample
[texUnit
] = null_sample_func
;
2425 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2426 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2429 /* Compute min/mag filter threshold */
2430 if (t
->MagFilter
== GL_LINEAR
2431 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
2432 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
2433 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
2436 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
2440 switch (t
->Dimensions
) {
2442 if (format
== GL_DEPTH_COMPONENT
) {
2443 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2445 else if (needLambda
) {
2446 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
2448 else if (t
->MinFilter
== GL_LINEAR
) {
2449 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
2452 ASSERT(t
->MinFilter
== GL_NEAREST
);
2453 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
2457 if (format
== GL_DEPTH_COMPONENT
) {
2458 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2460 else if (needLambda
) {
2461 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
2463 else if (t
->MinFilter
== GL_LINEAR
) {
2464 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
2467 GLint baseLevel
= t
->BaseLevel
;
2468 ASSERT(t
->MinFilter
== GL_NEAREST
);
2469 if (t
->WrapS
== GL_REPEAT
&&
2470 t
->WrapT
== GL_REPEAT
&&
2471 t
->Image
[baseLevel
]->Border
== 0 &&
2472 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2473 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
2475 else if (t
->WrapS
== GL_REPEAT
&&
2476 t
->WrapT
== GL_REPEAT
&&
2477 t
->Image
[baseLevel
]->Border
== 0 &&
2478 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2479 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
2482 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
2487 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
2489 else if (t
->MinFilter
== GL_LINEAR
) {
2490 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
2493 ASSERT(t
->MinFilter
== GL_NEAREST
);
2494 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
2497 case 6: /* cube map */
2499 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
2501 else if (t
->MinFilter
== GL_LINEAR
) {
2502 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
2505 ASSERT(t
->MinFilter
== GL_NEAREST
);
2506 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
2510 _mesa_problem(ctx
, "invalid dimensions in _swrast_choose_texture_sample_func");
2516 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2517 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2520 texture_combine(const GLcontext
*ctx
,
2521 const struct gl_texture_unit
*textureUnit
,
2523 CONST
GLchan (*primary_rgba
)[4],
2524 CONST
GLchan (*texel
)[4],
2527 const GLchan (*argRGB
[3])[4];
2528 const GLchan (*argA
[3])[4];
2530 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
2531 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
2532 #if CHAN_TYPE == GL_FLOAT
2533 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2534 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2536 const GLint half
= (CHAN_MAX
+ 1) / 2;
2539 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2540 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2542 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2543 ctx
->Extensions
.ARB_texture_env_combine
);
2546 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
2547 textureUnit->CombineModeRGB,
2548 textureUnit->CombineModeA,
2549 textureUnit->CombineSourceRGB[0],
2550 textureUnit->CombineSourceA[0],
2551 textureUnit->CombineSourceRGB[1],
2552 textureUnit->CombineSourceA[1]);
2556 * Do operand setup for up to 3 operands. Loop over the terms.
2558 for (j
= 0; j
< 3; j
++) {
2559 switch (textureUnit
->CombineSourceA
[j
]) {
2563 case GL_PRIMARY_COLOR_EXT
:
2564 argA
[j
] = primary_rgba
;
2566 case GL_PREVIOUS_EXT
:
2567 argA
[j
] = (const GLchan (*)[4]) rgba
;
2569 case GL_CONSTANT_EXT
:
2571 GLchan alpha
, (*c
)[4] = ccolor
[j
];
2572 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2573 for (i
= 0; i
< n
; i
++)
2574 c
[i
][ACOMP
] = alpha
;
2575 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2579 _mesa_problem(ctx
, "invalid combine source");
2582 switch (textureUnit
->CombineSourceRGB
[j
]) {
2586 case GL_PRIMARY_COLOR_EXT
:
2587 argRGB
[j
] = primary_rgba
;
2589 case GL_PREVIOUS_EXT
:
2590 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2592 case GL_CONSTANT_EXT
:
2594 GLchan (*c
)[4] = ccolor
[j
];
2595 GLchan red
, green
, blue
, alpha
;
2596 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2597 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2598 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2599 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2600 for (i
= 0; i
< n
; i
++) {
2602 c
[i
][GCOMP
] = green
;
2604 c
[i
][ACOMP
] = alpha
;
2606 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2610 _mesa_problem(ctx
, "invalid combine source");
2613 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
2614 const GLchan (*src
)[4] = argRGB
[j
];
2615 GLchan (*dst
)[4] = ccolor
[j
];
2617 /* point to new arg[j] storage */
2618 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2620 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2621 for (i
= 0; i
< n
; i
++) {
2622 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2623 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2624 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2627 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
2628 for (i
= 0; i
< n
; i
++) {
2629 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2630 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2631 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2635 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2636 for (i
= 0; i
< n
; i
++) {
2637 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2638 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2639 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2644 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
2645 const GLchan (*src
)[4] = argA
[j
];
2646 GLchan (*dst
)[4] = ccolor
[j
];
2647 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2648 for (i
= 0; i
< n
; i
++) {
2649 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2653 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
2654 textureUnit
->CombineModeA
== GL_REPLACE
) {
2655 break; /* done, we need only arg0 */
2659 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
2660 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
2661 break; /* arg0 and arg1 are done. we don't need arg2. */
2666 * Do the texture combine.
2668 switch (textureUnit
->CombineModeRGB
) {
2671 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2673 for (i
= 0; i
< n
; i
++) {
2674 #if CHAN_TYPE == GL_FLOAT
2675 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
2676 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
2677 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
2679 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
2680 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
2681 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
2682 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2683 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2684 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2689 for (i
= 0; i
< n
; i
++) {
2690 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
2691 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
2692 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
2699 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2700 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2701 #if CHAN_TYPE != GL_FLOAT
2702 const GLint shift
= CHAN_BITS
- RGBshift
;
2704 for (i
= 0; i
< n
; i
++) {
2705 #if CHAN_TYPE == GL_FLOAT
2706 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
2707 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
2708 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
2710 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
2711 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
2712 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
2713 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2714 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2715 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2722 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2723 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2724 for (i
= 0; i
< n
; i
++) {
2725 #if CHAN_TYPE == GL_FLOAT
2726 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
2727 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
2728 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
2730 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2731 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2732 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2733 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2734 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2735 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2740 case GL_ADD_SIGNED_EXT
:
2742 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2743 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2744 for (i
= 0; i
< n
; i
++) {
2745 #if CHAN_TYPE == GL_FLOAT
2746 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
2747 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
2748 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
2750 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
2751 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
2752 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
2753 r
= (r
< 0) ? 0 : r
<< RGBshift
;
2754 g
= (g
< 0) ? 0 : g
<< RGBshift
;
2755 b
= (b
< 0) ? 0 : b
<< RGBshift
;
2756 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2757 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2758 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2763 case GL_INTERPOLATE_EXT
:
2765 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2766 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2767 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
2768 #if CHAN_TYPE != GL_FLOAT
2769 const GLint shift
= CHAN_BITS
- RGBshift
;
2771 for (i
= 0; i
< n
; i
++) {
2772 #if CHAN_TYPE == GL_FLOAT
2773 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
2774 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
2775 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
2776 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
2777 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
2778 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
2780 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
2781 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
2783 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
2784 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
2786 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
2787 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
2789 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2790 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2791 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2796 case GL_SUBTRACT_ARB
:
2798 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2799 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2800 for (i
= 0; i
< n
; i
++) {
2801 #if CHAN_TYPE == GL_FLOAT
2802 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
2803 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
2804 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
2806 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2807 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2808 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2809 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
2810 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
2811 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
2816 case GL_DOT3_RGB_ARB
:
2817 case GL_DOT3_RGBA_ARB
:
2819 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2820 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2821 /* ATI's EXT extension has a constant scale by 4. The ARB
2822 * one will likely remove this restriction, and we should
2823 * drop the EXT extension in favour of the ARB one.
2825 for (i
= 0; i
< n
; i
++) {
2826 #if CHAN_TYPE == GL_FLOAT
2827 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
2828 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
2829 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
2832 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
2833 (GLint
)arg1
[i
][RCOMP
] - half
) +
2834 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
2835 (GLint
)arg1
[i
][GCOMP
] - half
) +
2836 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
2837 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
2839 dot
= CLAMP(dot
, 0, CHAN_MAX
);
2840 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
2845 _mesa_problem(ctx
, "invalid combine mode");
2848 switch (textureUnit
->CombineModeA
) {
2851 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2853 for (i
= 0; i
< n
; i
++) {
2854 #if CHAN_TYPE == GL_FLOAT
2855 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
2857 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
2859 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2863 for (i
= 0; i
< n
; i
++) {
2864 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
2871 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2872 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2873 #if CHAN_TYPE != GL_FLOAT
2874 const GLint shift
= CHAN_BITS
- Ashift
;
2876 for (i
= 0; i
< n
; i
++) {
2877 #if CHAN_TYPE == GL_FLOAT
2878 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
2880 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
2881 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2888 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2889 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2890 for (i
= 0; i
< n
; i
++) {
2891 #if CHAN_TYPE == GL_FLOAT
2892 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
2894 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
2895 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2900 case GL_ADD_SIGNED_EXT
:
2902 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2903 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2904 for (i
= 0; i
< n
; i
++) {
2905 #if CHAN_TYPE == GL_FLOAT
2906 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
2908 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
2909 a
= (a
< 0) ? 0 : a
<< Ashift
;
2910 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2915 case GL_INTERPOLATE_EXT
:
2917 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2918 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2919 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
2920 #if CHAN_TYPE != GL_FLOAT
2921 const GLint shift
= CHAN_BITS
- Ashift
;
2923 for (i
=0; i
<n
; i
++) {
2924 #if CHAN_TYPE == GL_FLOAT
2925 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
2926 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
2929 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
2930 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
2932 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2937 case GL_SUBTRACT_ARB
:
2939 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2940 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2941 for (i
= 0; i
< n
; i
++) {
2942 #if CHAN_TYPE == GL_FLOAT
2943 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
2945 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
2946 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
2953 _mesa_problem(ctx
, "invalid combine mode");
2956 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2958 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
2959 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
2960 for (i
= 0; i
< n
; i
++) {
2961 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
2964 UNDEFARRAY(ccolor
); /* mac 32k limitation */
2970 /**********************************************************************/
2971 /* Texture Application */
2972 /**********************************************************************/
2976 * Combine incoming fragment color with texel color to produce output color.
2977 * Input: textureUnit - pointer to texture unit to apply
2978 * format - base internal texture format
2979 * n - number of fragments
2980 * primary_rgba - primary colors (may alias rgba for single texture)
2981 * texels - array of texel colors
2982 * InOut: rgba - incoming fragment colors modified by texel colors
2983 * according to the texture environment mode.
2986 apply_texture( const GLcontext
*ctx
,
2987 const struct gl_texture_unit
*texUnit
,
2989 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
2994 GLint Rc
, Gc
, Bc
, Ac
;
2998 ASSERT(texUnit
->_Current
);
3000 baseLevel
= texUnit
->_Current
->BaseLevel
;
3001 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3003 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3005 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
) {
3006 format
= GL_RGBA
; /* a bit of a hack */
3009 switch (texUnit
->EnvMode
) {
3016 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3022 GLchan Lt
= texel
[i
][RCOMP
];
3023 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3027 case GL_LUMINANCE_ALPHA
:
3029 GLchan Lt
= texel
[i
][RCOMP
];
3031 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3033 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3039 GLchan It
= texel
[i
][RCOMP
];
3040 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3042 rgba
[i
][ACOMP
] = It
;
3048 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3049 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3050 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3057 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3058 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3059 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3061 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3065 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in apply_texture");
3076 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3082 GLchan Lt
= texel
[i
][RCOMP
];
3083 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3084 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3085 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3089 case GL_LUMINANCE_ALPHA
:
3092 GLchan Lt
= texel
[i
][RCOMP
];
3093 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3094 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3095 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3097 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3103 GLchan It
= texel
[i
][RCOMP
];
3104 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3105 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3106 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3108 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3114 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3115 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3116 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3123 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3124 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3125 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3127 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3131 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in apply_texture");
3140 case GL_LUMINANCE_ALPHA
:
3147 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3148 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3149 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3155 /* Cv = Cf(1-At) + CtAt */
3156 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3157 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3158 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3159 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3164 _mesa_problem(ctx
, "Bad format (GL_DECAL) in apply_texture");
3170 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3171 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3172 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3173 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3179 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3184 /* Cv = Cf(1-Lt) + CcLt */
3185 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3186 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3187 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3188 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3192 case GL_LUMINANCE_ALPHA
:
3194 /* Cv = Cf(1-Lt) + CcLt */
3195 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3196 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3197 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3198 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3200 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3205 /* Cv = Cf(1-It) + CcLt */
3206 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3207 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3208 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3209 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3210 /* Av = Af(1-It) + Ac*It */
3211 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
3216 /* Cv = Cf(1-Ct) + CcCt */
3217 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3218 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3219 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3225 /* Cv = Cf(1-Ct) + CcCt */
3226 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3227 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3228 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3230 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3234 _mesa_problem(ctx
, "Bad format (GL_BLEND) in apply_texture");
3239 /* XXX don't clamp results if GLchan is float??? */
3241 case GL_ADD
: /* GL_EXT_texture_add_env */
3248 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3253 GLuint Lt
= texel
[i
][RCOMP
];
3254 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3255 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3256 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3257 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3258 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3259 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3263 case GL_LUMINANCE_ALPHA
:
3265 GLuint Lt
= texel
[i
][RCOMP
];
3266 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3267 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3268 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3269 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3270 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3271 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3272 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3277 GLchan It
= texel
[i
][RCOMP
];
3278 GLuint r
= rgba
[i
][RCOMP
] + It
;
3279 GLuint g
= rgba
[i
][GCOMP
] + It
;
3280 GLuint b
= rgba
[i
][BCOMP
] + It
;
3281 GLuint a
= rgba
[i
][ACOMP
] + It
;
3282 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3283 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3284 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3285 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
3290 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3291 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3292 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3293 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3294 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3295 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3301 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3302 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3303 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3304 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3305 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3306 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3307 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3311 _mesa_problem(ctx
, "Bad format (GL_ADD) in apply_texture");
3316 case GL_COMBINE_EXT
:
3317 texture_combine(ctx
, texUnit
, n
, primary_rgba
, texel
, rgba
);
3321 _mesa_problem(ctx
, "Bad env mode in apply_texture");
3329 * Apply a unit of texture mapping to the incoming fragments.
3332 _swrast_texture_fragments( GLcontext
*ctx
, GLuint texUnit
,
3333 struct sw_span
*span
,
3334 CONST GLchan primary_rgba
[][4])
3336 const GLuint mask
= TEXTURE0_ANY
<< (texUnit
* 4);
3337 GLfloat (*texcoords
)[4] = span
->texcoords
[texUnit
];
3338 GLfloat
*lambda
= span
->lambda
[texUnit
];
3341 if (ctx
->Texture
._ReallyEnabled
& mask
) {
3342 const struct gl_texture_unit
*textureUnit
= &ctx
->Texture
.Unit
[texUnit
];
3344 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3346 if (textureUnit
->_Current
) { /* XXX need this? */
3347 const struct gl_texture_object
*curObj
= textureUnit
->_Current
;
3348 GLchan texel
[MAX_WIDTH
][4];
3350 if (span
->arrayMask
| SPAN_LAMBDA
) {
3354 min
= max
= lambda
[0];
3355 for (i
= 1; i
< span
->end
; i
++) {
3356 if (lambda
[i
] > max
)
3358 if (lambda
[i
] < min
)
3361 printf("min/max %g / %g\n", min
, max
);
3363 if (textureUnit
->LodBias
!= 0.0F
) {
3364 /* apply LOD bias, but don't clamp yet */
3366 for (i
=0;i
<span
->end
;i
++) {
3367 lambda
[i
] += textureUnit
->LodBias
;
3371 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
3372 /* apply LOD clamping to lambda */
3373 const GLfloat min
= curObj
->MinLod
;
3374 const GLfloat max
= curObj
->MaxLod
;
3376 for (i
=0;i
<span
->end
;i
++) {
3377 GLfloat l
= lambda
[i
];
3378 lambda
[i
] = CLAMP(l
, min
, max
);
3383 /* Sample the texture for n fragments */
3384 SWRAST_CONTEXT(ctx
)->TextureSample
[texUnit
]( ctx
, texUnit
,
3385 textureUnit
->_Current
,
3386 span
->end
, texcoords
,
3389 apply_texture( ctx
, textureUnit
, span
->end
, primary_rgba
,
3390 (const GLchan (*)[4]) texel
, span
->color
.rgba
);
3397 * Apply multiple texture stages (or just unit 0) to the span.
3398 * At some point in the future we'll probably modify this so that
3399 * texels from any texture unit are available in any combiner unit.
3400 * That'll require doing all the texture sampling first, and then
3401 * all the application (blending) afterward.
3404 _swrast_multitexture_fragments( GLcontext
*ctx
, struct sw_span
*span
)
3406 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
3408 GLchan primary_rgba
[MAX_WIDTH
][4];
3411 ASSERT(span
->end
< MAX_WIDTH
);
3412 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3414 /* save copy of the span colors (the GL_PRIMARY_COLOR) */
3415 MEMCPY(primary_rgba
, span
->color
.rgba
, 4 * span
->end
* sizeof(GLchan
));
3417 /* loop over texture units, modifying the span->color.rgba values */
3418 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3419 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3420 _swrast_texture_fragments( ctx
, unit
, span
,
3421 (CONST
GLchan (*)[4]) primary_rgba
);
3426 /* Just unit 0 enabled */
3427 ASSERT(ctx
->Texture
._ReallyEnabled
& TEXTURE0_ANY
);
3429 _swrast_texture_fragments( ctx
, 0, span
,
3430 (CONST
GLchan (*)[4]) span
->color
.rgba
);