1 /* $Id: s_texture.c,v 1.73 2002/10/24 23:57:24 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 */ \
100 U = (U * SIZE) - 0.5; \
105 if (I1 >= (GLint) SIZE) \
108 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
111 U = (GLfloat) SIZE; \
118 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
121 U = (GLfloat) SIZE; \
129 if (I1 >= (GLint) SIZE) \
133 ASSERT(wrapMode == GL_CLAMP); \
136 else if (S >= 1.0F) \
137 U = (GLfloat) SIZE; \
148 * Used to compute texel location for nearest sampling.
150 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
152 if (wrapMode == GL_REPEAT) { \
153 /* s limited to [0,1) */ \
154 /* i limited to [0,size-1] */ \
155 I = IFLOOR(S * SIZE); \
158 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
159 /* s limited to [min,max] */ \
160 /* i limited to [0, size-1] */ \
161 const GLfloat min = 1.0F / (2.0F * SIZE); \
162 const GLfloat max = 1.0F - min; \
168 I = IFLOOR(S * SIZE); \
170 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
171 /* s limited to [min,max] */ \
172 /* i limited to [-1, size] */ \
173 const GLfloat min = -1.0F / (2.0F * SIZE); \
174 const GLfloat max = 1.0F - min; \
180 I = IFLOOR(S * SIZE); \
182 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
183 const GLfloat min = 1.0F / (2.0F * SIZE); \
184 const GLfloat max = 1.0F - min; \
185 const GLint flr = IFLOOR(S); \
188 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
190 u = S - (GLfloat) flr; /* flr is even */ \
196 I = IFLOOR(u * SIZE); \
198 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
199 /* s limited to [0,1] */ \
200 /* i limited to [0,size-1] */ \
201 const GLfloat u = fabs(S); \
204 else if (u >= 1.0F) \
207 I = IFLOOR(u * SIZE); \
209 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
210 /* s limited to [min,max] */ \
211 /* i limited to [0, size-1] */ \
212 const GLfloat min = 1.0F / (2.0F * SIZE); \
213 const GLfloat max = 1.0F - min; \
214 const GLfloat u = fabs(S); \
220 I = IFLOOR(u * SIZE); \
223 ASSERT(wrapMode == GL_CLAMP); \
224 /* s limited to [0,1] */ \
225 /* i limited to [0,size-1] */ \
228 else if (S >= 1.0F) \
231 I = IFLOOR(S * SIZE); \
236 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
238 U = S * SIZE - 0.5F; \
239 I0 = IFLOOR(U) & (SIZE - 1); \
240 I1 = (I0 + 1) & (SIZE - 1); \
245 * Compute linear mipmap levels for given lambda.
247 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
250 level = tObj->BaseLevel; \
251 else if (lambda > tObj->_MaxLambda) \
252 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
254 level = (GLint) (tObj->BaseLevel + lambda); \
259 * Compute nearest mipmap level for given lambda.
261 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
264 if (lambda <= 0.5F) \
266 else if (lambda > tObj->_MaxLambda + 0.4999F) \
267 l = tObj->_MaxLambda + 0.4999F; \
270 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
271 if (level > tObj->_MaxLevel) \
272 level = tObj->_MaxLevel; \
278 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
279 * see 1-pixel bands of improperly weighted linear-sampled texels. The
280 * tests/texwrap.c demo is a good test.
281 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
282 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
284 #define FRAC(f) ((f) - IFLOOR(f))
289 * Bitflags for texture border color sampling.
301 * Get texture palette entry.
304 palette_sample(const GLcontext
*ctx
,
305 const struct gl_texture_object
*tObj
,
306 GLint index
, GLchan rgba
[4] )
308 const GLchan
*palette
;
311 if (ctx
->Texture
.SharedPalette
) {
312 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
313 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
314 format
= ctx
->Texture
.Palette
.Format
;
317 ASSERT(!tObj
->Palette
.FloatTable
);
318 palette
= (const GLchan
*) tObj
->Palette
.Table
;
319 format
= tObj
->Palette
.Format
;
324 rgba
[ACOMP
] = palette
[index
];
328 rgba
[RCOMP
] = palette
[index
];
330 case GL_LUMINANCE_ALPHA
:
331 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
332 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
335 rgba
[RCOMP
] = palette
[index
* 3 + 0];
336 rgba
[GCOMP
] = palette
[index
* 3 + 1];
337 rgba
[BCOMP
] = palette
[index
* 3 + 2];
340 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
341 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
342 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
343 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
346 _mesa_problem(ctx
, "Bad palette format in palette_sample");
352 * The lambda[] array values are always monotonic. Either the whole span
353 * will be minified, magnified, or split between the two. This function
354 * determines the subranges in [0, n-1] that are to be minified or magnified.
357 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
358 GLuint
*minStart
, GLuint
*minEnd
,
359 GLuint
*magStart
, GLuint
*magEnd
)
361 ASSERT(lambda
!= NULL
);
363 /* Verify that lambda[] is monotonous.
364 * We can't really use this because the inaccuracy in the LOG2 function
365 * causes this test to fail, yet the resulting texturing is correct.
369 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
370 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
371 for (i
= 0; i
< n
- 1; i
++) {
372 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
375 else { /* increasing */
376 for (i
= 0; i
< n
- 1; i
++) {
377 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
383 /* since lambda is monotonous-array use this check first */
384 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
385 /* magnification for whole span */
388 *minStart
= *minEnd
= 0;
390 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
391 /* minification for whole span */
394 *magStart
= *magEnd
= 0;
397 /* a mix of minification and magnification */
399 if (lambda
[0] > minMagThresh
) {
400 /* start with minification */
401 for (i
= 1; i
< n
; i
++) {
402 if (lambda
[i
] <= minMagThresh
)
411 /* start with magnification */
412 for (i
= 1; i
< n
; i
++) {
413 if (lambda
[i
] > minMagThresh
)
424 /* Verify the min/mag Start/End values
425 * We don't use this either (see above)
429 for (i
= 0; i
< n
; i
++) {
430 if (lambda
[i
] > minMagThresh
) {
432 ASSERT(i
>= *minStart
);
437 ASSERT(i
>= *magStart
);
446 /**********************************************************************/
447 /* 1-D Texture Sampling Functions */
448 /**********************************************************************/
451 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
454 sample_1d_nearest(GLcontext
*ctx
,
455 const struct gl_texture_object
*tObj
,
456 const struct gl_texture_image
*img
,
457 const GLfloat texcoord
[4], GLchan rgba
[4])
459 const GLint width
= img
->Width2
; /* without border, power of two */
462 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
464 /* skip over the border, if any */
467 if (i
< 0 || i
>= (GLint
) img
->Width
) {
468 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
469 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
472 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
473 if (img
->Format
== GL_COLOR_INDEX
) {
474 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
482 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
485 sample_1d_linear(GLcontext
*ctx
,
486 const struct gl_texture_object
*tObj
,
487 const struct gl_texture_image
*img
,
488 const GLfloat texcoord
[4], GLchan rgba
[4])
490 const GLint width
= img
->Width2
;
493 GLuint useBorderColor
;
495 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
503 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
504 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
508 const GLfloat a
= FRAC(u
);
510 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
511 const GLfloat w0
= (1.0F
-a
);
512 const GLfloat w1
= a
;
513 #else /* CHAN_BITS == 8 */
514 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
515 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
516 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
518 GLchan t0
[4], t1
[4]; /* texels */
520 if (useBorderColor
& I0BIT
) {
521 COPY_CHAN4(t0
, tObj
->_BorderChan
);
524 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
525 if (img
->Format
== GL_COLOR_INDEX
) {
526 palette_sample(ctx
, tObj
, t0
[0], t0
);
529 if (useBorderColor
& I1BIT
) {
530 COPY_CHAN4(t1
, tObj
->_BorderChan
);
533 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
534 if (img
->Format
== GL_COLOR_INDEX
) {
535 palette_sample(ctx
, tObj
, t1
[0], t1
);
539 #if CHAN_TYPE == GL_FLOAT
540 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
541 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
542 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
543 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
544 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
545 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
546 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
547 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
548 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
549 #else /* CHAN_BITS == 8 */
550 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
551 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
552 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
553 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
561 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
562 const struct gl_texture_object
*tObj
,
563 GLuint n
, GLfloat texcoord
[][4],
564 const GLfloat lambda
[], GLchan rgba
[][4])
567 ASSERT(lambda
!= NULL
);
568 for (i
= 0; i
< n
; i
++) {
570 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
571 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
577 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
578 const struct gl_texture_object
*tObj
,
579 GLuint n
, GLfloat texcoord
[][4],
580 const GLfloat lambda
[], GLchan rgba
[][4])
583 ASSERT(lambda
!= NULL
);
584 for (i
= 0; i
< n
; i
++) {
586 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
587 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
594 * This is really just needed in order to prevent warnings with some compilers.
596 #if CHAN_TYPE == GL_FLOAT
599 #define CHAN_CAST (GLchan) (GLint)
604 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
605 const struct gl_texture_object
*tObj
,
606 GLuint n
, GLfloat texcoord
[][4],
607 const GLfloat lambda
[], GLchan rgba
[][4])
610 ASSERT(lambda
!= NULL
);
611 for (i
= 0; i
< n
; i
++) {
613 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
614 if (level
>= tObj
->_MaxLevel
) {
615 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
616 texcoord
[i
], rgba
[i
]);
620 const GLfloat f
= FRAC(lambda
[i
]);
621 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
622 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
623 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
624 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
625 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
626 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
634 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
635 const struct gl_texture_object
*tObj
,
636 GLuint n
, GLfloat texcoord
[][4],
637 const GLfloat lambda
[], GLchan rgba
[][4])
640 ASSERT(lambda
!= NULL
);
641 for (i
= 0; i
< n
; i
++) {
643 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
644 if (level
>= tObj
->_MaxLevel
) {
645 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
646 texcoord
[i
], rgba
[i
]);
650 const GLfloat f
= FRAC(lambda
[i
]);
651 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
652 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
653 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
654 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
655 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
656 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
664 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
665 const struct gl_texture_object
*tObj
, GLuint n
,
666 GLfloat texcoords
[][4], const GLfloat lambda
[],
670 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
673 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
680 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
681 const struct gl_texture_object
*tObj
, GLuint n
,
682 GLfloat texcoords
[][4], const GLfloat lambda
[],
686 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
689 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
695 * Given an (s) texture coordinate and lambda (level of detail) value,
696 * return a texture sample.
700 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
701 const struct gl_texture_object
*tObj
, GLuint n
,
702 GLfloat texcoords
[][4],
703 const GLfloat lambda
[], GLchan rgba
[][4] )
705 GLuint minStart
, minEnd
; /* texels with minification */
706 GLuint magStart
, magEnd
; /* texels with magnification */
709 ASSERT(lambda
!= NULL
);
710 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
711 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
713 if (minStart
< minEnd
) {
714 /* do the minified texels */
715 const GLuint m
= minEnd
- minStart
;
716 switch (tObj
->MinFilter
) {
718 for (i
= minStart
; i
< minEnd
; i
++)
719 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
720 texcoords
[i
], rgba
[i
]);
723 for (i
= minStart
; i
< minEnd
; i
++)
724 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
725 texcoords
[i
], rgba
[i
]);
727 case GL_NEAREST_MIPMAP_NEAREST
:
728 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
729 lambda
+ minStart
, rgba
+ minStart
);
731 case GL_LINEAR_MIPMAP_NEAREST
:
732 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
733 lambda
+ minStart
, rgba
+ minStart
);
735 case GL_NEAREST_MIPMAP_LINEAR
:
736 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
737 lambda
+ minStart
, rgba
+ minStart
);
739 case GL_LINEAR_MIPMAP_LINEAR
:
740 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
741 lambda
+ minStart
, rgba
+ minStart
);
744 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
749 if (magStart
< magEnd
) {
750 /* do the magnified texels */
751 switch (tObj
->MagFilter
) {
753 for (i
= magStart
; i
< magEnd
; i
++)
754 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
755 texcoords
[i
], rgba
[i
]);
758 for (i
= magStart
; i
< magEnd
; i
++)
759 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
760 texcoords
[i
], rgba
[i
]);
763 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
770 /**********************************************************************/
771 /* 2-D Texture Sampling Functions */
772 /**********************************************************************/
776 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
779 sample_2d_nearest(GLcontext
*ctx
,
780 const struct gl_texture_object
*tObj
,
781 const struct gl_texture_image
*img
,
782 const GLfloat texcoord
[4],
785 const GLint width
= img
->Width2
; /* without border, power of two */
786 const GLint height
= img
->Height2
; /* without border, power of two */
789 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
790 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
792 /* skip over the border, if any */
796 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
797 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
798 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
801 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
802 if (img
->Format
== GL_COLOR_INDEX
) {
803 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
811 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
812 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
815 sample_2d_linear(GLcontext
*ctx
,
816 const struct gl_texture_object
*tObj
,
817 const struct gl_texture_image
*img
,
818 const GLfloat texcoord
[4],
821 const GLint width
= img
->Width2
;
822 const GLint height
= img
->Height2
;
823 GLint i0
, j0
, i1
, j1
;
824 GLuint useBorderColor
;
827 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
828 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
838 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
839 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
840 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
841 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
845 const GLfloat a
= FRAC(u
);
846 const GLfloat b
= FRAC(v
);
848 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
849 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
850 const GLfloat w10
= a
* (1.0F
-b
);
851 const GLfloat w01
= (1.0F
-a
) * b
;
852 const GLfloat w11
= a
* b
;
853 #else /* CHAN_BITS == 8 */
854 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
855 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
856 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
857 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
858 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
865 if (useBorderColor
& (I0BIT
| J0BIT
)) {
866 COPY_CHAN4(t00
, tObj
->_BorderChan
);
869 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
870 if (img
->Format
== GL_COLOR_INDEX
) {
871 palette_sample(ctx
, tObj
, t00
[0], t00
);
874 if (useBorderColor
& (I1BIT
| J0BIT
)) {
875 COPY_CHAN4(t10
, tObj
->_BorderChan
);
878 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
879 if (img
->Format
== GL_COLOR_INDEX
) {
880 palette_sample(ctx
, tObj
, t10
[0], t10
);
883 if (useBorderColor
& (I0BIT
| J1BIT
)) {
884 COPY_CHAN4(t01
, tObj
->_BorderChan
);
887 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
888 if (img
->Format
== GL_COLOR_INDEX
) {
889 palette_sample(ctx
, tObj
, t01
[0], t01
);
892 if (useBorderColor
& (I1BIT
| J1BIT
)) {
893 COPY_CHAN4(t11
, tObj
->_BorderChan
);
896 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
897 if (img
->Format
== GL_COLOR_INDEX
) {
898 palette_sample(ctx
, tObj
, t11
[0], t11
);
901 #if CHAN_TYPE == GL_FLOAT
902 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
903 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
904 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
905 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
906 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
907 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
908 w01
* t01
[0] + w11
* t11
[0] + 0.5);
909 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
910 w01
* t01
[1] + w11
* t11
[1] + 0.5);
911 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
912 w01
* t01
[2] + w11
* t11
[2] + 0.5);
913 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
914 w01
* t01
[3] + w11
* t11
[3] + 0.5);
915 #else /* CHAN_BITS == 8 */
916 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
917 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
918 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
919 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
920 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
921 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
922 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
923 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
932 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
933 * and we're not using a paletted texture.
936 sample_2d_linear_repeat(GLcontext
*ctx
,
937 const struct gl_texture_object
*tObj
,
938 const struct gl_texture_image
*img
,
939 const GLfloat texcoord
[4],
942 const GLint width
= img
->Width2
;
943 const GLint height
= img
->Height2
;
944 GLint i0
, j0
, i1
, j1
;
947 ASSERT(tObj
->WrapS
== GL_REPEAT
);
948 ASSERT(tObj
->WrapT
== GL_REPEAT
);
949 ASSERT(img
->Border
== 0);
950 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
952 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
953 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
956 const GLfloat a
= FRAC(u
);
957 const GLfloat b
= FRAC(v
);
959 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
960 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
961 const GLfloat w10
= a
* (1.0F
-b
);
962 const GLfloat w01
= (1.0F
-a
) * b
;
963 const GLfloat w11
= a
* b
;
964 #else /* CHAN_BITS == 8 */
965 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
966 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
967 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
968 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
969 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
976 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
977 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
978 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
979 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
981 #if CHAN_TYPE == GL_FLOAT
982 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
983 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
984 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
985 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
986 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
987 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
988 w01
* t01
[0] + w11
* t11
[0] + 0.5);
989 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
990 w01
* t01
[1] + w11
* t11
[1] + 0.5);
991 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
992 w01
* t01
[2] + w11
* t11
[2] + 0.5);
993 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
994 w01
* t01
[3] + w11
* t11
[3] + 0.5);
995 #else /* CHAN_BITS == 8 */
996 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
997 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
998 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
999 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1000 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1001 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1002 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1003 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1013 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1014 const struct gl_texture_object
*tObj
,
1015 GLuint n
, GLfloat texcoord
[][4],
1016 const GLfloat lambda
[], GLchan rgba
[][4])
1019 for (i
= 0; i
< n
; i
++) {
1021 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1022 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1029 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1030 const struct gl_texture_object
*tObj
,
1031 GLuint n
, GLfloat texcoord
[][4],
1032 const GLfloat lambda
[], GLchan rgba
[][4])
1035 ASSERT(lambda
!= NULL
);
1036 for (i
= 0; i
< n
; i
++) {
1038 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1039 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1046 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1047 const struct gl_texture_object
*tObj
,
1048 GLuint n
, GLfloat texcoord
[][4],
1049 const GLfloat lambda
[], GLchan rgba
[][4])
1052 ASSERT(lambda
!= NULL
);
1053 for (i
= 0; i
< n
; i
++) {
1055 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1056 if (level
>= tObj
->_MaxLevel
) {
1057 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1058 texcoord
[i
], rgba
[i
]);
1061 GLchan t0
[4], t1
[4]; /* texels */
1062 const GLfloat f
= FRAC(lambda
[i
]);
1063 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1064 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1065 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1066 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1067 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1068 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1075 /* Trilinear filtering */
1077 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1078 const struct gl_texture_object
*tObj
,
1079 GLuint n
, GLfloat texcoord
[][4],
1080 const GLfloat lambda
[], GLchan rgba
[][4] )
1083 ASSERT(lambda
!= NULL
);
1084 for (i
= 0; i
< n
; i
++) {
1086 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1087 if (level
>= tObj
->_MaxLevel
) {
1088 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1089 texcoord
[i
], rgba
[i
]);
1092 GLchan t0
[4], t1
[4]; /* texels */
1093 const GLfloat f
= FRAC(lambda
[i
]);
1094 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1095 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1096 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1097 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1098 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1099 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1106 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1107 const struct gl_texture_object
*tObj
,
1108 GLuint n
, GLfloat texcoord
[][4],
1109 const GLfloat lambda
[], GLchan rgba
[][4] )
1112 ASSERT(lambda
!= NULL
);
1113 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1114 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1115 for (i
= 0; i
< n
; i
++) {
1117 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1118 if (level
>= tObj
->_MaxLevel
) {
1119 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1120 texcoord
[i
], rgba
[i
]);
1123 GLchan t0
[4], t1
[4]; /* texels */
1124 const GLfloat f
= FRAC(lambda
[i
]);
1125 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1126 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1127 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1128 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1129 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1130 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1137 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1138 const struct gl_texture_object
*tObj
, GLuint n
,
1139 GLfloat texcoords
[][4],
1140 const GLfloat lambda
[], GLchan rgba
[][4] )
1143 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1146 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1153 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1154 const struct gl_texture_object
*tObj
, GLuint n
,
1155 GLfloat texcoords
[][4],
1156 const GLfloat lambda
[], GLchan rgba
[][4] )
1159 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1162 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1168 * Optimized 2-D texture sampling:
1169 * S and T wrap mode == GL_REPEAT
1170 * GL_NEAREST min/mag filter
1172 * RowStride == Width,
1176 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1177 const struct gl_texture_object
*tObj
,
1178 GLuint n
, GLfloat texcoords
[][4],
1179 const GLfloat lambda
[], GLchan rgba
[][4] )
1181 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1182 const GLfloat width
= (GLfloat
) img
->Width
;
1183 const GLfloat height
= (GLfloat
) img
->Height
;
1184 const GLint colMask
= img
->Width
- 1;
1185 const GLint rowMask
= img
->Height
- 1;
1186 const GLint shift
= img
->WidthLog2
;
1189 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1190 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1191 ASSERT(img
->Border
==0);
1192 ASSERT(img
->Format
==GL_RGB
);
1194 for (k
=0; k
<n
; k
++) {
1195 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1196 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1197 GLint pos
= (j
<< shift
) | i
;
1198 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1199 rgba
[k
][RCOMP
] = texel
[0];
1200 rgba
[k
][GCOMP
] = texel
[1];
1201 rgba
[k
][BCOMP
] = texel
[2];
1207 * Optimized 2-D texture sampling:
1208 * S and T wrap mode == GL_REPEAT
1209 * GL_NEAREST min/mag filter
1211 * RowStride == Width,
1215 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1216 const struct gl_texture_object
*tObj
,
1217 GLuint n
, GLfloat texcoords
[][4],
1218 const GLfloat lambda
[], GLchan rgba
[][4] )
1220 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1221 const GLfloat width
= (GLfloat
) img
->Width
;
1222 const GLfloat height
= (GLfloat
) img
->Height
;
1223 const GLint colMask
= img
->Width
- 1;
1224 const GLint rowMask
= img
->Height
- 1;
1225 const GLint shift
= img
->WidthLog2
;
1228 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1229 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1230 ASSERT(img
->Border
==0);
1231 ASSERT(img
->Format
==GL_RGBA
);
1233 for (i
= 0; i
< n
; i
++) {
1234 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1235 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1236 const GLint pos
= (row
<< shift
) | col
;
1237 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1238 COPY_CHAN4(rgba
[i
], texel
);
1244 * Given an array of texture coordinate and lambda (level of detail)
1245 * values, return an array of texture sample.
1248 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1249 const struct gl_texture_object
*tObj
,
1250 GLuint n
, GLfloat texcoords
[][4],
1251 const GLfloat lambda
[], GLchan rgba
[][4] )
1253 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1254 GLuint minStart
, minEnd
; /* texels with minification */
1255 GLuint magStart
, magEnd
; /* texels with magnification */
1257 const GLboolean repeatNoBorder
= (tObj
->WrapS
== GL_REPEAT
)
1258 && (tObj
->WrapT
== GL_REPEAT
)
1259 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1260 && (tImg
->Format
!= GL_COLOR_INDEX
);
1262 ASSERT(lambda
!= NULL
);
1263 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1264 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1266 if (minStart
< minEnd
) {
1267 /* do the minified texels */
1268 const GLuint m
= minEnd
- minStart
;
1269 switch (tObj
->MinFilter
) {
1271 if (repeatNoBorder
) {
1272 switch (tImg
->Format
) {
1274 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1275 NULL
, rgba
+ minStart
);
1278 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1279 NULL
, rgba
+ minStart
);
1282 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1283 NULL
, rgba
+ minStart
);
1287 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1288 NULL
, rgba
+ minStart
);
1292 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1293 NULL
, rgba
+ minStart
);
1295 case GL_NEAREST_MIPMAP_NEAREST
:
1296 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1297 lambda
+ minStart
, rgba
+ minStart
);
1299 case GL_LINEAR_MIPMAP_NEAREST
:
1300 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1301 lambda
+ minStart
, rgba
+ minStart
);
1303 case GL_NEAREST_MIPMAP_LINEAR
:
1304 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1305 lambda
+ minStart
, rgba
+ minStart
);
1307 case GL_LINEAR_MIPMAP_LINEAR
:
1309 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1310 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1312 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1313 lambda
+ minStart
, rgba
+ minStart
);
1316 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1321 if (magStart
< magEnd
) {
1322 /* do the magnified texels */
1323 const GLuint m
= magEnd
- magStart
;
1325 switch (tObj
->MagFilter
) {
1327 if (repeatNoBorder
) {
1328 switch (tImg
->Format
) {
1330 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1331 NULL
, rgba
+ magStart
);
1334 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1335 NULL
, rgba
+ magStart
);
1338 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1339 NULL
, rgba
+ magStart
);
1343 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1344 NULL
, rgba
+ magStart
);
1348 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1349 NULL
, rgba
+ magStart
);
1352 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1359 /**********************************************************************/
1360 /* 3-D Texture Sampling Functions */
1361 /**********************************************************************/
1364 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1367 sample_3d_nearest(GLcontext
*ctx
,
1368 const struct gl_texture_object
*tObj
,
1369 const struct gl_texture_image
*img
,
1370 const GLfloat texcoord
[4],
1373 const GLint width
= img
->Width2
; /* without border, power of two */
1374 const GLint height
= img
->Height2
; /* without border, power of two */
1375 const GLint depth
= img
->Depth2
; /* without border, power of two */
1378 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1379 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1380 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1382 if (i
< 0 || i
>= (GLint
) img
->Width
||
1383 j
< 0 || j
>= (GLint
) img
->Height
||
1384 k
< 0 || k
>= (GLint
) img
->Depth
) {
1385 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1386 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1389 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1390 if (img
->Format
== GL_COLOR_INDEX
) {
1391 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1399 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1402 sample_3d_linear(GLcontext
*ctx
,
1403 const struct gl_texture_object
*tObj
,
1404 const struct gl_texture_image
*img
,
1405 const GLfloat texcoord
[4],
1408 const GLint width
= img
->Width2
;
1409 const GLint height
= img
->Height2
;
1410 const GLint depth
= img
->Depth2
;
1411 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1412 GLuint useBorderColor
;
1415 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1416 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1417 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1429 /* check if sampling texture border color */
1430 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1431 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1432 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1433 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1434 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1435 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1439 const GLfloat a
= FRAC(u
);
1440 const GLfloat b
= FRAC(v
);
1441 const GLfloat c
= FRAC(w
);
1443 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1444 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1445 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1446 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1447 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1448 GLfloat w110
= a
* b
* (1.0F
-c
);
1449 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1450 GLfloat w101
= a
* (1.0F
-b
) * c
;
1451 GLfloat w011
= (1.0F
-a
) * b
* c
;
1452 GLfloat w111
= a
* b
* c
;
1453 #else /* CHAN_BITS == 8 */
1454 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1455 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1456 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1457 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1458 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1459 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1460 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1461 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1462 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1465 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1466 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1468 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1469 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1472 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1473 if (img
->Format
== GL_COLOR_INDEX
) {
1474 palette_sample(ctx
, tObj
, t000
[0], t000
);
1477 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1478 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1481 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1482 if (img
->Format
== GL_COLOR_INDEX
) {
1483 palette_sample(ctx
, tObj
, t100
[0], t100
);
1486 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1487 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1490 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1491 if (img
->Format
== GL_COLOR_INDEX
) {
1492 palette_sample(ctx
, tObj
, t010
[0], t010
);
1495 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1496 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1499 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1500 if (img
->Format
== GL_COLOR_INDEX
) {
1501 palette_sample(ctx
, tObj
, t110
[0], t110
);
1505 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1506 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1509 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1510 if (img
->Format
== GL_COLOR_INDEX
) {
1511 palette_sample(ctx
, tObj
, t001
[0], t001
);
1514 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1515 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1518 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1519 if (img
->Format
== GL_COLOR_INDEX
) {
1520 palette_sample(ctx
, tObj
, t101
[0], t101
);
1523 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1524 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1527 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1528 if (img
->Format
== GL_COLOR_INDEX
) {
1529 palette_sample(ctx
, tObj
, t011
[0], t011
);
1532 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1533 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1536 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1537 if (img
->Format
== GL_COLOR_INDEX
) {
1538 palette_sample(ctx
, tObj
, t111
[0], t111
);
1542 #if CHAN_TYPE == GL_FLOAT
1543 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1544 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1545 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1546 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1547 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1548 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1549 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1550 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1551 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1552 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1553 w001
*t001
[0] + w011
*t011
[0] +
1554 w100
*t100
[0] + w110
*t110
[0] +
1555 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1556 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1557 w001
*t001
[1] + w011
*t011
[1] +
1558 w100
*t100
[1] + w110
*t110
[1] +
1559 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1560 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1561 w001
*t001
[2] + w011
*t011
[2] +
1562 w100
*t100
[2] + w110
*t110
[2] +
1563 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1564 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1565 w001
*t001
[3] + w011
*t011
[3] +
1566 w100
*t100
[3] + w110
*t110
[3] +
1567 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1568 #else /* CHAN_BITS == 8 */
1569 rgba
[0] = (GLchan
) (
1570 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1571 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1573 rgba
[1] = (GLchan
) (
1574 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1575 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1577 rgba
[2] = (GLchan
) (
1578 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1579 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1581 rgba
[3] = (GLchan
) (
1582 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1583 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1593 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1594 const struct gl_texture_object
*tObj
,
1595 GLuint n
, GLfloat texcoord
[][4],
1596 const GLfloat lambda
[], GLchan rgba
[][4] )
1599 for (i
= 0; i
< n
; i
++) {
1601 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1602 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1608 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1609 const struct gl_texture_object
*tObj
,
1610 GLuint n
, GLfloat texcoord
[][4],
1611 const GLfloat lambda
[], GLchan rgba
[][4])
1614 ASSERT(lambda
!= NULL
);
1615 for (i
= 0; i
< n
; i
++) {
1617 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1618 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1624 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1625 const struct gl_texture_object
*tObj
,
1626 GLuint n
, GLfloat texcoord
[][4],
1627 const GLfloat lambda
[], GLchan rgba
[][4])
1630 ASSERT(lambda
!= NULL
);
1631 for (i
= 0; i
< n
; i
++) {
1633 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1634 if (level
>= tObj
->_MaxLevel
) {
1635 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1636 texcoord
[i
], rgba
[i
]);
1639 GLchan t0
[4], t1
[4]; /* texels */
1640 const GLfloat f
= FRAC(lambda
[i
]);
1641 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1642 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1643 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1644 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1645 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1646 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1653 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1654 const struct gl_texture_object
*tObj
,
1655 GLuint n
, GLfloat texcoord
[][4],
1656 const GLfloat lambda
[], GLchan rgba
[][4])
1659 ASSERT(lambda
!= NULL
);
1660 for (i
= 0; i
< n
; i
++) {
1662 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1663 if (level
>= tObj
->_MaxLevel
) {
1664 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1665 texcoord
[i
], rgba
[i
]);
1668 GLchan t0
[4], t1
[4]; /* texels */
1669 const GLfloat f
= FRAC(lambda
[i
]);
1670 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1671 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1672 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1673 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1674 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1675 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1682 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1683 const struct gl_texture_object
*tObj
, GLuint n
,
1684 GLfloat texcoords
[][4], const GLfloat lambda
[],
1688 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1691 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1698 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1699 const struct gl_texture_object
*tObj
, GLuint n
,
1700 GLfloat texcoords
[][4],
1701 const GLfloat lambda
[], GLchan rgba
[][4] )
1704 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1707 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1713 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1714 * return a texture sample.
1717 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1718 const struct gl_texture_object
*tObj
, GLuint n
,
1719 GLfloat texcoords
[][4], const GLfloat lambda
[],
1722 GLuint minStart
, minEnd
; /* texels with minification */
1723 GLuint magStart
, magEnd
; /* texels with magnification */
1726 ASSERT(lambda
!= NULL
);
1727 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1728 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1730 if (minStart
< minEnd
) {
1731 /* do the minified texels */
1732 GLuint m
= minEnd
- minStart
;
1733 switch (tObj
->MinFilter
) {
1735 for (i
= minStart
; i
< minEnd
; i
++)
1736 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1737 texcoords
[i
], rgba
[i
]);
1740 for (i
= minStart
; i
< minEnd
; i
++)
1741 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1742 texcoords
[i
], rgba
[i
]);
1744 case GL_NEAREST_MIPMAP_NEAREST
:
1745 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1746 lambda
+ minStart
, rgba
+ minStart
);
1748 case GL_LINEAR_MIPMAP_NEAREST
:
1749 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1750 lambda
+ minStart
, rgba
+ minStart
);
1752 case GL_NEAREST_MIPMAP_LINEAR
:
1753 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1754 lambda
+ minStart
, rgba
+ minStart
);
1756 case GL_LINEAR_MIPMAP_LINEAR
:
1757 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1758 lambda
+ minStart
, rgba
+ minStart
);
1761 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1766 if (magStart
< magEnd
) {
1767 /* do the magnified texels */
1768 switch (tObj
->MagFilter
) {
1770 for (i
= magStart
; i
< magEnd
; i
++)
1771 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1772 texcoords
[i
], rgba
[i
]);
1775 for (i
= magStart
; i
< magEnd
; i
++)
1776 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1777 texcoords
[i
], rgba
[i
]);
1780 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1787 /**********************************************************************/
1788 /* Texture Cube Map Sampling Functions */
1789 /**********************************************************************/
1792 * Choose one of six sides of a texture cube map given the texture
1793 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1796 static const struct gl_texture_image
**
1797 choose_cube_face(const struct gl_texture_object
*texObj
,
1798 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1802 direction target sc tc ma
1803 ---------- ------------------------------- --- --- ---
1804 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1805 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1806 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1807 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1808 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1809 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1811 const GLfloat rx
= texcoord
[0];
1812 const GLfloat ry
= texcoord
[1];
1813 const GLfloat rz
= texcoord
[2];
1814 const struct gl_texture_image
**imgArray
;
1815 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
1818 if (arx
> ary
&& arx
> arz
) {
1820 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
1826 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
1832 else if (ary
> arx
&& ary
> arz
) {
1834 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
1840 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
1848 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
1854 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
1861 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1862 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1868 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1869 const struct gl_texture_object
*tObj
, GLuint n
,
1870 GLfloat texcoords
[][4], const GLfloat lambda
[],
1875 for (i
= 0; i
< n
; i
++) {
1876 const struct gl_texture_image
**images
;
1877 GLfloat newCoord
[4];
1878 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1879 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1886 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1887 const struct gl_texture_object
*tObj
, GLuint n
,
1888 GLfloat texcoords
[][4],
1889 const GLfloat lambda
[], GLchan rgba
[][4])
1893 for (i
= 0; i
< n
; i
++) {
1894 const struct gl_texture_image
**images
;
1895 GLfloat newCoord
[4];
1896 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1897 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1904 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1905 const struct gl_texture_object
*tObj
,
1906 GLuint n
, GLfloat texcoord
[][4],
1907 const GLfloat lambda
[], GLchan rgba
[][4])
1910 ASSERT(lambda
!= NULL
);
1911 for (i
= 0; i
< n
; i
++) {
1912 const struct gl_texture_image
**images
;
1913 GLfloat newCoord
[4];
1915 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1916 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1917 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1923 sample_cube_linear_mipmap_nearest(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_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1935 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1936 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1942 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1943 const struct gl_texture_object
*tObj
,
1944 GLuint n
, GLfloat texcoord
[][4],
1945 const GLfloat lambda
[], GLchan rgba
[][4])
1948 ASSERT(lambda
!= NULL
);
1949 for (i
= 0; i
< n
; i
++) {
1950 const struct gl_texture_image
**images
;
1951 GLfloat newCoord
[4];
1953 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1954 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1955 if (level
>= tObj
->_MaxLevel
) {
1956 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1960 GLchan t0
[4], t1
[4]; /* texels */
1961 const GLfloat f
= FRAC(lambda
[i
]);
1962 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1963 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1964 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1965 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1966 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1967 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1974 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1975 const struct gl_texture_object
*tObj
,
1976 GLuint n
, GLfloat texcoord
[][4],
1977 const GLfloat lambda
[], GLchan rgba
[][4])
1980 ASSERT(lambda
!= NULL
);
1981 for (i
= 0; i
< n
; i
++) {
1982 const struct gl_texture_image
**images
;
1983 GLfloat newCoord
[4];
1985 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1986 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1987 if (level
>= tObj
->_MaxLevel
) {
1988 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1992 GLchan t0
[4], t1
[4];
1993 const GLfloat f
= FRAC(lambda
[i
]);
1994 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
1995 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1996 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1997 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1998 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1999 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2006 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2007 const struct gl_texture_object
*tObj
, GLuint n
,
2008 GLfloat texcoords
[][4], const GLfloat lambda
[],
2011 GLuint minStart
, minEnd
; /* texels with minification */
2012 GLuint magStart
, magEnd
; /* texels with magnification */
2014 ASSERT(lambda
!= NULL
);
2015 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2016 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2018 if (minStart
< minEnd
) {
2019 /* do the minified texels */
2020 const GLuint m
= minEnd
- minStart
;
2021 switch (tObj
->MinFilter
) {
2023 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2024 lambda
+ minStart
, rgba
+ minStart
);
2027 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2028 lambda
+ minStart
, rgba
+ minStart
);
2030 case GL_NEAREST_MIPMAP_NEAREST
:
2031 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2032 lambda
+ minStart
, rgba
+ minStart
);
2034 case GL_LINEAR_MIPMAP_NEAREST
:
2035 sample_cube_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2036 lambda
+ minStart
, rgba
+ minStart
);
2038 case GL_NEAREST_MIPMAP_LINEAR
:
2039 sample_cube_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2040 lambda
+ minStart
, rgba
+ minStart
);
2042 case GL_LINEAR_MIPMAP_LINEAR
:
2043 sample_cube_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2044 lambda
+ minStart
, rgba
+ minStart
);
2047 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2051 if (magStart
< magEnd
) {
2052 /* do the magnified texels */
2053 const GLuint m
= magEnd
- magStart
;
2054 switch (tObj
->MagFilter
) {
2056 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2057 lambda
+ magStart
, rgba
+ magStart
);
2060 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2061 lambda
+ magStart
, rgba
+ magStart
);
2064 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2070 /**********************************************************************/
2071 /* Texture Rectangle Sampling Functions */
2072 /**********************************************************************/
2075 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2076 const struct gl_texture_object
*tObj
, GLuint n
,
2077 GLfloat texcoords
[][4], const GLfloat lambda
[],
2080 const struct gl_texture_image
*img
= tObj
->Image
[0];
2081 const GLfloat width
= (GLfloat
) img
->Width
;
2082 const GLfloat height
= (GLfloat
) img
->Height
;
2083 const GLint width_minus_1
= img
->Width
- 1;
2084 const GLint height_minus_1
= img
->Height
- 1;
2090 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2091 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2092 tObj
->WrapS
== GL_CLAMP_TO_BORDER_ARB
);
2093 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2094 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2095 tObj
->WrapT
== GL_CLAMP_TO_BORDER_ARB
);
2096 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2098 /* XXX move Wrap mode tests outside of loops for common cases */
2099 for (i
= 0; i
< n
; i
++) {
2101 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2102 if (tObj
->WrapS
== GL_CLAMP
) {
2103 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2105 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2106 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2109 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2111 if (tObj
->WrapT
== GL_CLAMP
) {
2112 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2114 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2115 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2118 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2121 col
= CLAMP(col
, 0, width_minus_1
);
2122 row
= CLAMP(row
, 0, height_minus_1
);
2124 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2130 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2131 const struct gl_texture_object
*tObj
, GLuint n
,
2132 GLfloat texcoords
[][4],
2133 const GLfloat lambda
[], GLchan rgba
[][4])
2135 const struct gl_texture_image
*img
= tObj
->Image
[0];
2136 const GLfloat width
= (GLfloat
) img
->Width
;
2137 const GLfloat height
= (GLfloat
) img
->Height
;
2138 const GLint width_minus_1
= img
->Width
- 1;
2139 const GLint height_minus_1
= img
->Height
- 1;
2145 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2146 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2147 tObj
->WrapS
== GL_CLAMP_TO_BORDER_ARB
);
2148 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2149 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2150 tObj
->WrapT
== GL_CLAMP_TO_BORDER_ARB
);
2151 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2153 /* XXX lots of opportunity for optimization in this loop */
2154 for (i
= 0; i
< n
; i
++) {
2156 GLint row0
, col0
, row1
, col1
;
2157 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2158 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2160 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2161 if (tObj
->WrapS
== GL_CLAMP
) {
2162 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2164 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2165 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2168 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2170 if (tObj
->WrapT
== GL_CLAMP
) {
2171 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2173 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2174 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2177 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2180 /* compute integer rows/columns */
2181 col0
= IFLOOR(fcol
);
2183 col0
= CLAMP(col0
, 0, width_minus_1
);
2184 col1
= CLAMP(col1
, 0, width_minus_1
);
2185 row0
= IFLOOR(frow
);
2187 row0
= CLAMP(row0
, 0, height_minus_1
);
2188 row1
= CLAMP(row1
, 0, height_minus_1
);
2190 /* get four texel samples */
2191 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2192 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2193 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2194 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2196 /* compute sample weights */
2199 w00
= (1.0F
-a
) * (1.0F
-b
);
2201 w01
= (1.0F
-a
) * b
;
2204 /* compute weighted average of samples */
2206 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2208 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2210 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2212 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2218 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2219 const struct gl_texture_object
*tObj
, GLuint n
,
2220 GLfloat texcoords
[][4], const GLfloat lambda
[],
2223 GLuint minStart
, minEnd
, magStart
, magEnd
;
2225 /* We only need lambda to decide between minification and magnification.
2226 * There is no mipmapping with rectangular textures.
2228 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2229 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2231 if (minStart
< minEnd
) {
2232 if (tObj
->MinFilter
== GL_NEAREST
) {
2233 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2234 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2237 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2238 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2241 if (magStart
< magEnd
) {
2242 if (tObj
->MagFilter
== GL_NEAREST
) {
2243 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2244 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2247 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2248 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2256 * Sample a shadow/depth texture.
2259 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2260 const struct gl_texture_object
*tObj
, GLuint n
,
2261 GLfloat texcoords
[][4], const GLfloat lambda
[],
2264 const GLint baseLevel
= tObj
->BaseLevel
;
2265 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2266 const GLuint width
= texImage
->Width
;
2267 const GLuint height
= texImage
->Height
;
2274 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2275 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2276 tObj
->Target
== GL_TEXTURE_2D
||
2277 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2279 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2281 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2283 /* XXX this could be precomputed and saved in the texture object */
2284 if (tObj
->CompareFlag
) {
2285 /* GL_SGIX_shadow */
2286 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2287 function
= GL_LEQUAL
;
2290 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2291 function
= GL_GEQUAL
;
2294 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2296 function
= tObj
->CompareFunc
;
2299 function
= GL_NONE
; /* pass depth through as grayscale */
2302 if (tObj
->MagFilter
== GL_NEAREST
) {
2304 for (i
= 0; i
< n
; i
++) {
2305 GLfloat depthSample
;
2307 /* XXX fix for texture rectangle! */
2308 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2309 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2310 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2314 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2317 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2320 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2323 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2326 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2329 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2338 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2341 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2345 switch (tObj
->DepthMode
) {
2347 texel
[i
][RCOMP
] = result
;
2348 texel
[i
][GCOMP
] = result
;
2349 texel
[i
][BCOMP
] = result
;
2350 texel
[i
][ACOMP
] = CHAN_MAX
;
2353 texel
[i
][RCOMP
] = result
;
2354 texel
[i
][GCOMP
] = result
;
2355 texel
[i
][BCOMP
] = result
;
2356 texel
[i
][ACOMP
] = result
;
2359 texel
[i
][RCOMP
] = 0;
2360 texel
[i
][GCOMP
] = 0;
2361 texel
[i
][BCOMP
] = 0;
2362 texel
[i
][ACOMP
] = result
;
2365 _mesa_problem(ctx
, "Bad depth texture mode");
2371 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2372 for (i
= 0; i
< n
; i
++) {
2373 GLfloat depth00
, depth01
, depth10
, depth11
;
2374 GLint i0
, i1
, j0
, j1
;
2376 GLuint useBorderTexel
;
2378 /* XXX fix for texture rectangle! */
2379 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2380 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2383 if (texImage
->Border
) {
2384 i0
+= texImage
->Border
;
2385 i1
+= texImage
->Border
;
2386 j0
+= texImage
->Border
;
2387 j1
+= texImage
->Border
;
2390 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2391 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2392 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2393 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2396 /* get four depth samples from the texture */
2397 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2401 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2403 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2407 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2409 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2413 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2415 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2419 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2423 /* compute a single weighted depth sample and do one comparison */
2424 const GLfloat a
= FRAC(u
+ 1.0F
);
2425 const GLfloat b
= FRAC(v
+ 1.0F
);
2426 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2427 const GLfloat w10
= ( a
) * (1.0F
- b
);
2428 const GLfloat w01
= (1.0F
- a
) * ( b
);
2429 const GLfloat w11
= ( a
) * ( b
);
2430 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2431 + w01
* depth01
+ w11
* depth11
;
2432 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2433 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2441 /* Do four depth/R comparisons and compute a weighted result.
2442 * If this touches on somebody's I.P., I'll remove this code
2445 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2446 GLfloat luminance
= CHAN_MAXF
;
2450 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2451 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2452 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2453 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2454 result
= (GLchan
) luminance
;
2457 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2458 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2459 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2460 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2461 result
= (GLchan
) luminance
;
2464 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2465 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2466 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2467 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2468 result
= (GLchan
) luminance
;
2471 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2472 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2473 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2474 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2475 result
= (GLchan
) luminance
;
2478 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2479 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2480 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2481 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2482 result
= (GLchan
) luminance
;
2485 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2486 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2487 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2488 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2489 result
= (GLchan
) luminance
;
2498 /* ordinary bilinear filtering */
2500 const GLfloat a
= FRAC(u
+ 1.0F
);
2501 const GLfloat b
= FRAC(v
+ 1.0F
);
2502 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2503 const GLfloat w10
= ( a
) * (1.0F
- b
);
2504 const GLfloat w01
= (1.0F
- a
) * ( b
);
2505 const GLfloat w11
= ( a
) * ( b
);
2506 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2507 + w01
* depth01
+ w11
* depth11
;
2508 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2512 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2517 switch (tObj
->DepthMode
) {
2519 texel
[i
][RCOMP
] = result
;
2520 texel
[i
][GCOMP
] = result
;
2521 texel
[i
][BCOMP
] = result
;
2522 texel
[i
][ACOMP
] = CHAN_MAX
;
2525 texel
[i
][RCOMP
] = result
;
2526 texel
[i
][GCOMP
] = result
;
2527 texel
[i
][BCOMP
] = result
;
2528 texel
[i
][ACOMP
] = result
;
2531 texel
[i
][RCOMP
] = 0;
2532 texel
[i
][GCOMP
] = 0;
2533 texel
[i
][BCOMP
] = 0;
2534 texel
[i
][ACOMP
] = result
;
2537 _mesa_problem(ctx
, "Bad depth texture mode");
2546 * Experimental depth texture sampling function.
2549 sample_depth_texture2(const GLcontext
*ctx
,
2550 const struct gl_texture_unit
*texUnit
,
2551 GLuint n
, GLfloat texcoords
[][4],
2554 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2555 const GLint baseLevel
= texObj
->BaseLevel
;
2556 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2557 const GLuint width
= texImage
->Width
;
2558 const GLuint height
= texImage
->Height
;
2560 GLboolean lequal
, gequal
;
2562 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2563 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2567 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2568 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2572 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2573 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2574 * isn't a depth texture.
2576 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2577 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2581 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2583 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2594 for (i
= 0; i
< n
; i
++) {
2596 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2599 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2601 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2609 if (imin
< 0) imin
= 0;
2610 if (imax
>= width
) imax
= width
- 1;
2611 if (jmin
< 0) jmin
= 0;
2612 if (jmax
>= height
) jmax
= height
- 1;
2614 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2616 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2617 for (ii
= imin
; ii
<= imax
; ii
++) {
2618 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2620 if ((depthSample
<= r
[i
] && lequal
) ||
2621 (depthSample
>= r
[i
] && gequal
)) {
2627 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2628 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2631 texel
[i
][RCOMP
] = lum
;
2632 texel
[i
][GCOMP
] = lum
;
2633 texel
[i
][BCOMP
] = lum
;
2634 texel
[i
][ACOMP
] = CHAN_MAX
;
2642 * We use this function when a texture object is in an "incomplete" state.
2645 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2646 const struct gl_texture_object
*tObj
, GLuint n
,
2647 GLfloat texcoords
[][4], const GLfloat lambda
[],
2655 * Setup the texture sampling function for this texture object.
2658 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2659 const struct gl_texture_object
*t
)
2661 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2664 swrast
->TextureSample
[texUnit
] = null_sample_func
;
2667 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2668 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2671 /* Compute min/mag filter threshold */
2672 if (t
->MagFilter
== GL_LINEAR
2673 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
2674 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
2675 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
2678 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
2682 switch (t
->Target
) {
2684 if (format
== GL_DEPTH_COMPONENT
) {
2685 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2687 else if (needLambda
) {
2688 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
2690 else if (t
->MinFilter
== GL_LINEAR
) {
2691 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
2694 ASSERT(t
->MinFilter
== GL_NEAREST
);
2695 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
2699 if (format
== GL_DEPTH_COMPONENT
) {
2700 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2702 else if (needLambda
) {
2703 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
2705 else if (t
->MinFilter
== GL_LINEAR
) {
2706 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
2709 GLint baseLevel
= t
->BaseLevel
;
2710 ASSERT(t
->MinFilter
== GL_NEAREST
);
2711 if (t
->WrapS
== GL_REPEAT
&&
2712 t
->WrapT
== GL_REPEAT
&&
2713 t
->Image
[baseLevel
]->Border
== 0 &&
2714 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2715 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
2717 else if (t
->WrapS
== GL_REPEAT
&&
2718 t
->WrapT
== GL_REPEAT
&&
2719 t
->Image
[baseLevel
]->Border
== 0 &&
2720 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2721 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
2724 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
2729 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
2731 else if (t
->MinFilter
== GL_LINEAR
) {
2732 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
2735 ASSERT(t
->MinFilter
== GL_NEAREST
);
2736 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
2739 case GL_TEXTURE_CUBE_MAP_ARB
:
2741 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
2743 else if (t
->MinFilter
== GL_LINEAR
) {
2744 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
2747 ASSERT(t
->MinFilter
== GL_NEAREST
);
2748 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
2751 case GL_TEXTURE_RECTANGLE_NV
:
2753 swrast
->TextureSample
[texUnit
] = sample_lambda_rect
;
2755 else if (t
->MinFilter
== GL_LINEAR
) {
2756 swrast
->TextureSample
[texUnit
] = sample_linear_rect
;
2759 ASSERT(t
->MinFilter
== GL_NEAREST
);
2760 swrast
->TextureSample
[texUnit
] = sample_nearest_rect
;
2764 _mesa_problem(ctx
, "invalid target in _swrast_choose_texture_sample_func");
2770 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2771 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2775 * Do texture application for GL_ARB/EXT_texture_env_combine.
2777 * ctx - rendering context
2778 * textureUnit - the texture unit to apply
2779 * n - number of fragments to process (span width)
2780 * primary_rgba - incoming fragment color array
2781 * texelBuffer - pointer to texel colors for all texture units
2783 * rgba - incoming colors, which get modified here
2786 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
2787 CONST
GLchan (*primary_rgba
)[4],
2788 CONST GLchan
*texelBuffer
,
2791 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
2792 const GLchan (*argRGB
[3])[4];
2793 const GLchan (*argA
[3])[4];
2794 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
2795 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
2796 #if CHAN_TYPE == GL_FLOAT
2797 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2798 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2800 const GLint half
= (CHAN_MAX
+ 1) / 2;
2804 /* GLchan ccolor[3][4]; */
2805 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2806 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2808 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2809 ctx
->Extensions
.ARB_texture_env_combine
);
2810 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
2814 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
2815 textureUnit->CombineModeRGB,
2816 textureUnit->CombineModeA,
2817 textureUnit->CombineSourceRGB[0],
2818 textureUnit->CombineSourceA[0],
2819 textureUnit->CombineSourceRGB[1],
2820 textureUnit->CombineSourceA[1]);
2824 * Do operand setup for up to 3 operands. Loop over the terms.
2826 for (j
= 0; j
< 3; j
++) {
2827 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
2828 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
2832 argA
[j
] = (const GLchan (*)[4])
2833 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2835 case GL_PRIMARY_COLOR_EXT
:
2836 argA
[j
] = primary_rgba
;
2838 case GL_PREVIOUS_EXT
:
2839 argA
[j
] = (const GLchan (*)[4]) rgba
;
2841 case GL_CONSTANT_EXT
:
2843 GLchan alpha
, (*c
)[4] = ccolor
[j
];
2844 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2845 for (i
= 0; i
< n
; i
++)
2846 c
[i
][ACOMP
] = alpha
;
2847 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2851 /* ARB_texture_env_crossbar source */
2853 const GLuint srcUnit
= srcA
- GL_TEXTURE0_ARB
;
2854 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2855 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2857 argA
[j
] = (const GLchan (*)[4])
2858 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2864 argRGB
[j
] = (const GLchan (*)[4])
2865 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2867 case GL_PRIMARY_COLOR_EXT
:
2868 argRGB
[j
] = primary_rgba
;
2870 case GL_PREVIOUS_EXT
:
2871 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2873 case GL_CONSTANT_EXT
:
2875 GLchan (*c
)[4] = ccolor
[j
];
2876 GLchan red
, green
, blue
, alpha
;
2877 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2878 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2879 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2880 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2881 for (i
= 0; i
< n
; i
++) {
2883 c
[i
][GCOMP
] = green
;
2885 c
[i
][ACOMP
] = alpha
;
2887 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2891 /* ARB_texture_env_crossbar source */
2893 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0_ARB
;
2894 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2895 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2897 argRGB
[j
] = (const GLchan (*)[4])
2898 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2902 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
2903 const GLchan (*src
)[4] = argRGB
[j
];
2904 GLchan (*dst
)[4] = ccolor
[j
];
2906 /* point to new arg[j] storage */
2907 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2909 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2910 for (i
= 0; i
< n
; i
++) {
2911 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2912 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2913 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2916 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
2917 for (i
= 0; i
< n
; i
++) {
2918 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2919 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2920 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2924 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2925 for (i
= 0; i
< n
; i
++) {
2926 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2927 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2928 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2933 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
2934 const GLchan (*src
)[4] = argA
[j
];
2935 GLchan (*dst
)[4] = ccolor
[j
];
2936 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2937 for (i
= 0; i
< n
; i
++) {
2938 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2942 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
2943 textureUnit
->CombineModeA
== GL_REPLACE
) {
2944 break; /* done, we need only arg0 */
2948 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
2949 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
2950 break; /* arg0 and arg1 are done. we don't need arg2. */
2955 * Do the texture combine.
2957 switch (textureUnit
->CombineModeRGB
) {
2960 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2962 for (i
= 0; i
< n
; i
++) {
2963 #if CHAN_TYPE == GL_FLOAT
2964 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
2965 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
2966 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
2968 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
2969 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
2970 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
2971 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2972 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2973 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2978 for (i
= 0; i
< n
; i
++) {
2979 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
2980 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
2981 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
2988 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2989 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2990 #if CHAN_TYPE != GL_FLOAT
2991 const GLint shift
= CHAN_BITS
- RGBshift
;
2993 for (i
= 0; i
< n
; i
++) {
2994 #if CHAN_TYPE == GL_FLOAT
2995 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
2996 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
2997 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
2999 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3000 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3001 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3002 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3003 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3004 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3011 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3012 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3013 for (i
= 0; i
< n
; i
++) {
3014 #if CHAN_TYPE == GL_FLOAT
3015 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3016 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3017 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3019 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3020 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3021 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3022 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3023 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3024 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3029 case GL_ADD_SIGNED_EXT
:
3031 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3032 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3033 for (i
= 0; i
< n
; i
++) {
3034 #if CHAN_TYPE == GL_FLOAT
3035 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3036 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3037 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3039 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3040 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3041 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3042 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3043 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3044 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3045 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3046 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3047 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3052 case GL_INTERPOLATE_EXT
:
3054 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3055 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3056 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3057 #if CHAN_TYPE != GL_FLOAT
3058 const GLint shift
= CHAN_BITS
- RGBshift
;
3060 for (i
= 0; i
< n
; i
++) {
3061 #if CHAN_TYPE == GL_FLOAT
3062 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3063 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3064 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3065 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3066 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3067 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3069 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3070 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3072 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3073 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3075 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3076 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3078 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3079 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3080 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3085 case GL_SUBTRACT_ARB
:
3087 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3088 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3089 for (i
= 0; i
< n
; i
++) {
3090 #if CHAN_TYPE == GL_FLOAT
3091 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3092 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3093 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3095 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3096 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3097 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3098 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3099 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3100 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3105 case GL_DOT3_RGB_EXT
:
3106 case GL_DOT3_RGBA_EXT
:
3108 /* Do not scale the result by 1 2 or 4 */
3109 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3110 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3111 for (i
= 0; i
< n
; i
++) {
3112 #if CHAN_TYPE == GL_FLOAT
3113 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3114 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3115 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3117 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3119 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3120 (GLint
)arg1
[i
][RCOMP
] - half
) +
3121 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3122 (GLint
)arg1
[i
][GCOMP
] - half
) +
3123 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3124 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3125 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3127 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3131 case GL_DOT3_RGB_ARB
:
3132 case GL_DOT3_RGBA_ARB
:
3134 /* DO scale the result by 1 2 or 4 */
3135 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3136 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3137 for (i
= 0; i
< n
; i
++) {
3138 #if CHAN_TYPE == GL_FLOAT
3139 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3140 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3141 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3143 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
) * RGBmult
;
3145 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3146 (GLint
)arg1
[i
][RCOMP
] - half
) +
3147 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3148 (GLint
)arg1
[i
][GCOMP
] - half
) +
3149 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3150 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3151 dot
= CLAMP(dot
, 0, CHAN_MAX
) << RGBshift
;
3153 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3158 _mesa_problem(ctx
, "invalid combine mode");
3161 switch (textureUnit
->CombineModeA
) {
3164 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3166 for (i
= 0; i
< n
; i
++) {
3167 #if CHAN_TYPE == GL_FLOAT
3168 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3170 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3172 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3176 for (i
= 0; i
< n
; i
++) {
3177 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3184 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3185 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3186 #if CHAN_TYPE != GL_FLOAT
3187 const GLint shift
= CHAN_BITS
- Ashift
;
3189 for (i
= 0; i
< n
; i
++) {
3190 #if CHAN_TYPE == GL_FLOAT
3191 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3193 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3194 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3201 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3202 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3203 for (i
= 0; i
< n
; i
++) {
3204 #if CHAN_TYPE == GL_FLOAT
3205 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3207 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3208 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3213 case GL_ADD_SIGNED_EXT
:
3215 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3216 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3217 for (i
= 0; i
< n
; i
++) {
3218 #if CHAN_TYPE == GL_FLOAT
3219 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3221 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3222 a
= (a
< 0) ? 0 : a
<< Ashift
;
3223 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3228 case GL_INTERPOLATE_EXT
:
3230 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3231 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3232 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3233 #if CHAN_TYPE != GL_FLOAT
3234 const GLint shift
= CHAN_BITS
- Ashift
;
3236 for (i
=0; i
<n
; i
++) {
3237 #if CHAN_TYPE == GL_FLOAT
3238 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3239 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3242 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3243 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3245 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3250 case GL_SUBTRACT_ARB
:
3252 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3253 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3254 for (i
= 0; i
< n
; i
++) {
3255 #if CHAN_TYPE == GL_FLOAT
3256 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3258 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3259 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3266 _mesa_problem(ctx
, "invalid combine mode");
3269 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3270 * This is kind of a kludge. It would have been better if the spec
3271 * were written such that the GL_COMBINE_ALPHA value could be set to
3274 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3275 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
3276 for (i
= 0; i
< n
; i
++) {
3277 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3280 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3286 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3287 * texUnit->EnvMode == GL_COMBINE4_NV.
3290 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3291 CONST
GLchan (*primary_rgba
)[4],
3292 CONST GLchan
*texelBuffer
,
3300 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3301 * MODULATE, or DECAL) to an array of fragments.
3302 * Input: textureUnit - pointer to texture unit to apply
3303 * format - base internal texture format
3304 * n - number of fragments
3305 * primary_rgba - primary colors (may alias rgba for single texture)
3306 * texels - array of texel colors
3307 * InOut: rgba - incoming fragment colors modified by texel colors
3308 * according to the texture environment mode.
3311 texture_apply( const GLcontext
*ctx
,
3312 const struct gl_texture_unit
*texUnit
,
3314 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3319 GLint Rc
, Gc
, Bc
, Ac
;
3323 ASSERT(texUnit
->_Current
);
3325 baseLevel
= texUnit
->_Current
->BaseLevel
;
3326 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3328 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3330 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
3331 || format
== GL_YCBCR_MESA
) {
3332 format
= GL_RGBA
; /* a bit of a hack */
3335 switch (texUnit
->EnvMode
) {
3342 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3348 GLchan Lt
= texel
[i
][RCOMP
];
3349 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3353 case GL_LUMINANCE_ALPHA
:
3355 GLchan Lt
= texel
[i
][RCOMP
];
3357 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3359 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3365 GLchan It
= texel
[i
][RCOMP
];
3366 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3368 rgba
[i
][ACOMP
] = It
;
3374 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3375 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3376 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3383 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3384 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3385 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3387 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3391 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3402 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3408 GLchan Lt
= texel
[i
][RCOMP
];
3409 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3410 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3411 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3415 case GL_LUMINANCE_ALPHA
:
3418 GLchan Lt
= texel
[i
][RCOMP
];
3419 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3420 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3421 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3423 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3429 GLchan It
= texel
[i
][RCOMP
];
3430 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3431 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3432 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3434 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3440 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3441 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3442 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3449 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3450 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3451 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3453 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3457 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3466 case GL_LUMINANCE_ALPHA
:
3473 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3474 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3475 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3481 /* Cv = Cf(1-At) + CtAt */
3482 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3483 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3484 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3485 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3490 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3496 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3497 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3498 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3499 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3505 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3510 /* Cv = Cf(1-Lt) + CcLt */
3511 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3512 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3513 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3514 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3518 case GL_LUMINANCE_ALPHA
:
3520 /* Cv = Cf(1-Lt) + CcLt */
3521 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3522 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3523 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3524 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3526 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3531 /* Cv = Cf(1-It) + CcLt */
3532 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3533 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3534 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3535 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3536 /* Av = Af(1-It) + Ac*It */
3537 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
3542 /* Cv = Cf(1-Ct) + CcCt */
3543 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3544 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3545 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3551 /* Cv = Cf(1-Ct) + CcCt */
3552 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3553 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3554 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3556 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3560 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
3565 /* XXX don't clamp results if GLchan is float??? */
3567 case GL_ADD
: /* GL_EXT_texture_add_env */
3574 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3579 GLuint Lt
= texel
[i
][RCOMP
];
3580 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3581 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3582 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3583 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3584 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3585 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3589 case GL_LUMINANCE_ALPHA
:
3591 GLuint Lt
= texel
[i
][RCOMP
];
3592 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3593 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3594 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3595 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3596 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3597 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3598 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3603 GLchan It
= texel
[i
][RCOMP
];
3604 GLuint r
= rgba
[i
][RCOMP
] + It
;
3605 GLuint g
= rgba
[i
][GCOMP
] + It
;
3606 GLuint b
= rgba
[i
][BCOMP
] + It
;
3607 GLuint a
= rgba
[i
][ACOMP
] + It
;
3608 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3609 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3610 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3611 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
3616 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3617 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3618 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3619 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3620 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3621 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3627 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3628 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3629 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3630 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3631 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3632 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3633 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3637 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
3643 _mesa_problem(ctx
, "Bad env mode in texture_apply");
3651 * Apply texture mapping to a span of fragments.
3654 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
3656 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
3657 GLchan primary_rgba
[MAX_WIDTH
][4];
3660 ASSERT(span
->end
< MAX_WIDTH
);
3661 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3664 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
3666 if (swrast
->_AnyTextureCombine
)
3667 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
3670 * Must do all texture sampling before combining in order to
3671 * accomodate GL_ARB_texture_env_crossbar.
3673 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3674 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3675 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3676 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
3677 GLfloat
*lambda
= span
->array
->lambda
[unit
];
3678 GLchan (*texels
)[4] = (GLchan (*)[4])
3679 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
3681 /* adjust texture lod (lambda) */
3682 if (span
->arrayMask
| SPAN_LAMBDA
) {
3683 if (texUnit
->LodBias
!= 0.0F
) {
3684 /* apply LOD bias, but don't clamp yet */
3686 for (i
= 0; i
< span
->end
; i
++) {
3687 lambda
[i
] += texUnit
->LodBias
;
3691 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
3692 /* apply LOD clamping to lambda */
3693 const GLfloat min
= curObj
->MinLod
;
3694 const GLfloat max
= curObj
->MaxLod
;
3696 for (i
= 0; i
< span
->end
; i
++) {
3697 GLfloat l
= lambda
[i
];
3698 lambda
[i
] = CLAMP(l
, min
, max
);
3703 /* Sample the texture (span->end fragments) */
3704 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
,
3705 span
->end
, span
->array
->texcoords
[unit
],
3711 * OK, now apply the texture (aka texture combine/blend).
3712 * We modify the span->color.rgba values.
3714 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3715 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3716 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3717 if (texUnit
->EnvMode
== GL_COMBINE_EXT
) {
3718 /* GL_ARB/EXT_texture_env_combine */
3719 texture_combine( ctx
, unit
, span
->end
,
3720 (CONST
GLchan (*)[4]) primary_rgba
,
3721 swrast
->TexelBuffer
,
3722 span
->array
->rgba
);
3724 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
3725 /* GL_NV_texture_env_combine4 */
3726 texture_combine4( ctx
, unit
, span
->end
,
3727 (CONST
GLchan (*)[4]) primary_rgba
,
3728 swrast
->TexelBuffer
,
3729 span
->array
->rgba
);
3732 /* conventional texture blend */
3733 const GLchan (*texels
)[4] = (const GLchan (*)[4])
3734 (swrast
->TexelBuffer
+ unit
*
3735 (span
->end
* 4 * sizeof(GLchan
)));
3736 texture_apply( ctx
, texUnit
, span
->end
,
3737 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
3738 span
->array
->rgba
);