1 /* $Id: s_texture.c,v 1.70 2002/10/18 13:40:59 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include "texformat.h"
37 #include "s_context.h"
38 #include "s_texture.h"
42 * These values are used in the fixed-point arithmetic used
43 * for linear filtering.
45 #define WEIGHT_SCALE 65536.0F
46 #define WEIGHT_SHIFT 16
50 * Used to compute texel locations for linear sampling.
52 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB
53 * S = texcoord in [0,1]
54 * SIZE = width (or height or depth) of texture
56 * U = texcoord in [0, width]
57 * I0, I1 = two nearest texel indexes
59 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
61 if (wrapMode == GL_REPEAT) { \
62 U = S * SIZE - 0.5F; \
63 I0 = IFLOOR(U) & (SIZE - 1); \
64 I1 = (I0 + 1) & (SIZE - 1); \
66 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
78 if (I1 >= (GLint) SIZE) \
81 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
82 const GLfloat min = -1.0F / (2.0F * SIZE); \
83 const GLfloat max = 1.0F - min; \
94 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
95 const GLint flr = IFLOOR(S); \
97 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
99 U = S - (GLfloat) flr; /* flr is even */ \
100 U = (U * SIZE) - 0.5; \
105 if (I1 >= (GLint) SIZE) \
109 ASSERT(wrapMode == GL_CLAMP); \
112 else if (S >= 1.0F) \
113 U = (GLfloat) SIZE; \
124 * Used to compute texel location for nearest sampling.
126 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
128 if (wrapMode == GL_REPEAT) { \
129 /* s limited to [0,1) */ \
130 /* i limited to [0,size-1] */ \
131 I = IFLOOR(S * SIZE); \
134 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
135 /* s limited to [min,max] */ \
136 /* i limited to [0, size-1] */ \
137 const GLfloat min = 1.0F / (2.0F * SIZE); \
138 const GLfloat max = 1.0F - min; \
144 I = IFLOOR(S * SIZE); \
146 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
147 /* s limited to [min,max] */ \
148 /* i limited to [-1, size] */ \
149 const GLfloat min = -1.0F / (2.0F * SIZE); \
150 const GLfloat max = 1.0F - min; \
156 I = IFLOOR(S * SIZE); \
158 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
159 const GLfloat min = 1.0F / (2.0F * SIZE); \
160 const GLfloat max = 1.0F - min; \
161 const GLint flr = IFLOOR(S); \
164 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
166 u = S - (GLfloat) flr; /* flr is even */ \
172 I = IFLOOR(u * SIZE); \
175 ASSERT(wrapMode == GL_CLAMP); \
176 /* s limited to [0,1] */ \
177 /* i limited to [0,size-1] */ \
180 else if (S >= 1.0F) \
183 I = IFLOOR(S * SIZE); \
188 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
190 U = S * SIZE - 0.5F; \
191 I0 = IFLOOR(U) & (SIZE - 1); \
192 I1 = (I0 + 1) & (SIZE - 1); \
197 * Compute linear mipmap levels for given lambda.
199 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
202 level = tObj->BaseLevel; \
203 else if (lambda > tObj->_MaxLambda) \
204 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
206 level = (GLint) (tObj->BaseLevel + lambda); \
211 * Compute nearest mipmap level for given lambda.
213 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
216 if (lambda <= 0.5F) \
218 else if (lambda > tObj->_MaxLambda + 0.4999F) \
219 l = tObj->_MaxLambda + 0.4999F; \
222 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
223 if (level > tObj->_MaxLevel) \
224 level = tObj->_MaxLevel; \
230 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
231 * see 1-pixel bands of improperly weighted linear-sampled texels. The
232 * tests/texwrap.c demo is a good test.
233 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
234 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
236 #define FRAC(f) ((f) - IFLOOR(f))
241 * Bitflags for texture border color sampling.
253 * Get texture palette entry.
256 palette_sample(const GLcontext
*ctx
,
257 const struct gl_texture_object
*tObj
,
258 GLint index
, GLchan rgba
[4] )
260 const GLchan
*palette
;
263 if (ctx
->Texture
.SharedPalette
) {
264 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
265 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
266 format
= ctx
->Texture
.Palette
.Format
;
269 ASSERT(!tObj
->Palette
.FloatTable
);
270 palette
= (const GLchan
*) tObj
->Palette
.Table
;
271 format
= tObj
->Palette
.Format
;
276 rgba
[ACOMP
] = palette
[index
];
280 rgba
[RCOMP
] = palette
[index
];
282 case GL_LUMINANCE_ALPHA
:
283 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
284 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
287 rgba
[RCOMP
] = palette
[index
* 3 + 0];
288 rgba
[GCOMP
] = palette
[index
* 3 + 1];
289 rgba
[BCOMP
] = palette
[index
* 3 + 2];
292 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
293 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
294 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
295 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
298 _mesa_problem(ctx
, "Bad palette format in palette_sample");
304 * The lambda[] array values are always monotonic. Either the whole span
305 * will be minified, magnified, or split between the two. This function
306 * determines the subranges in [0, n-1] that are to be minified or magnified.
309 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
310 GLuint
*minStart
, GLuint
*minEnd
,
311 GLuint
*magStart
, GLuint
*magEnd
)
313 ASSERT(lambda
!= NULL
);
315 /* Verify that lambda[] is monotonous.
316 * We can't really use this because the inaccuracy in the LOG2 function
317 * causes this test to fail, yet the resulting texturing is correct.
321 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
322 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
323 for (i
= 0; i
< n
- 1; i
++) {
324 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
327 else { /* increasing */
328 for (i
= 0; i
< n
- 1; i
++) {
329 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
335 /* since lambda is monotonous-array use this check first */
336 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
337 /* magnification for whole span */
340 *minStart
= *minEnd
= 0;
342 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
343 /* minification for whole span */
346 *magStart
= *magEnd
= 0;
349 /* a mix of minification and magnification */
351 if (lambda
[0] > minMagThresh
) {
352 /* start with minification */
353 for (i
= 1; i
< n
; i
++) {
354 if (lambda
[i
] <= minMagThresh
)
363 /* start with magnification */
364 for (i
= 1; i
< n
; i
++) {
365 if (lambda
[i
] > minMagThresh
)
376 /* Verify the min/mag Start/End values
377 * We don't use this either (see above)
381 for (i
= 0; i
< n
; i
++) {
382 if (lambda
[i
] > minMagThresh
) {
384 ASSERT(i
>= *minStart
);
389 ASSERT(i
>= *magStart
);
398 /**********************************************************************/
399 /* 1-D Texture Sampling Functions */
400 /**********************************************************************/
403 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
406 sample_1d_nearest(GLcontext
*ctx
,
407 const struct gl_texture_object
*tObj
,
408 const struct gl_texture_image
*img
,
409 const GLfloat texcoord
[4], GLchan rgba
[4])
411 const GLint width
= img
->Width2
; /* without border, power of two */
414 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
416 /* skip over the border, if any */
419 if (i
< 0 || i
>= (GLint
) img
->Width
) {
420 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
421 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
424 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
425 if (img
->Format
== GL_COLOR_INDEX
) {
426 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
434 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
437 sample_1d_linear(GLcontext
*ctx
,
438 const struct gl_texture_object
*tObj
,
439 const struct gl_texture_image
*img
,
440 const GLfloat texcoord
[4], GLchan rgba
[4])
442 const GLint width
= img
->Width2
;
445 GLuint useBorderColor
;
447 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
455 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
456 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
460 const GLfloat a
= FRAC(u
);
462 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
463 const GLfloat w0
= (1.0F
-a
);
464 const GLfloat w1
= a
;
465 #else /* CHAN_BITS == 8 */
466 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
467 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
468 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
470 GLchan t0
[4], t1
[4]; /* texels */
472 if (useBorderColor
& I0BIT
) {
473 COPY_CHAN4(t0
, tObj
->_BorderChan
);
476 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
477 if (img
->Format
== GL_COLOR_INDEX
) {
478 palette_sample(ctx
, tObj
, t0
[0], t0
);
481 if (useBorderColor
& I1BIT
) {
482 COPY_CHAN4(t1
, tObj
->_BorderChan
);
485 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
486 if (img
->Format
== GL_COLOR_INDEX
) {
487 palette_sample(ctx
, tObj
, t1
[0], t1
);
491 #if CHAN_TYPE == GL_FLOAT
492 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
493 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
494 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
495 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
496 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
497 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
498 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
499 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
500 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
501 #else /* CHAN_BITS == 8 */
502 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
503 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
504 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
505 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
513 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
514 const struct gl_texture_object
*tObj
,
515 GLuint n
, GLfloat texcoord
[][4],
516 const GLfloat lambda
[], GLchan rgba
[][4])
519 ASSERT(lambda
!= NULL
);
520 for (i
= 0; i
< n
; i
++) {
522 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
523 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
529 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
530 const struct gl_texture_object
*tObj
,
531 GLuint n
, GLfloat texcoord
[][4],
532 const GLfloat lambda
[], GLchan rgba
[][4])
535 ASSERT(lambda
!= NULL
);
536 for (i
= 0; i
< n
; i
++) {
538 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
539 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
546 * This is really just needed in order to prevent warnings with some compilers.
548 #if CHAN_TYPE == GL_FLOAT
551 #define CHAN_CAST (GLchan) (GLint)
556 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
557 const struct gl_texture_object
*tObj
,
558 GLuint n
, GLfloat texcoord
[][4],
559 const GLfloat lambda
[], GLchan rgba
[][4])
562 ASSERT(lambda
!= NULL
);
563 for (i
= 0; i
< n
; i
++) {
565 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
566 if (level
>= tObj
->_MaxLevel
) {
567 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
568 texcoord
[i
], rgba
[i
]);
572 const GLfloat f
= FRAC(lambda
[i
]);
573 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
574 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
575 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
576 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
577 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
578 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
586 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
587 const struct gl_texture_object
*tObj
,
588 GLuint n
, GLfloat texcoord
[][4],
589 const GLfloat lambda
[], GLchan rgba
[][4])
592 ASSERT(lambda
!= NULL
);
593 for (i
= 0; i
< n
; i
++) {
595 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
596 if (level
>= tObj
->_MaxLevel
) {
597 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
598 texcoord
[i
], rgba
[i
]);
602 const GLfloat f
= FRAC(lambda
[i
]);
603 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
604 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
605 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
606 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
607 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
608 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
616 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
617 const struct gl_texture_object
*tObj
, GLuint n
,
618 GLfloat texcoords
[][4], const GLfloat lambda
[],
622 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
625 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
632 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
633 const struct gl_texture_object
*tObj
, GLuint n
,
634 GLfloat texcoords
[][4], const GLfloat lambda
[],
638 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
641 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
647 * Given an (s) texture coordinate and lambda (level of detail) value,
648 * return a texture sample.
652 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
653 const struct gl_texture_object
*tObj
, GLuint n
,
654 GLfloat texcoords
[][4],
655 const GLfloat lambda
[], GLchan rgba
[][4] )
657 GLuint minStart
, minEnd
; /* texels with minification */
658 GLuint magStart
, magEnd
; /* texels with magnification */
661 ASSERT(lambda
!= NULL
);
662 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
663 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
665 if (minStart
< minEnd
) {
666 /* do the minified texels */
667 const GLuint m
= minEnd
- minStart
;
668 switch (tObj
->MinFilter
) {
670 for (i
= minStart
; i
< minEnd
; i
++)
671 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
672 texcoords
[i
], rgba
[i
]);
675 for (i
= minStart
; i
< minEnd
; i
++)
676 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
677 texcoords
[i
], rgba
[i
]);
679 case GL_NEAREST_MIPMAP_NEAREST
:
680 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
681 lambda
+ minStart
, rgba
+ minStart
);
683 case GL_LINEAR_MIPMAP_NEAREST
:
684 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
685 lambda
+ minStart
, rgba
+ minStart
);
687 case GL_NEAREST_MIPMAP_LINEAR
:
688 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
689 lambda
+ minStart
, rgba
+ minStart
);
691 case GL_LINEAR_MIPMAP_LINEAR
:
692 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
693 lambda
+ minStart
, rgba
+ minStart
);
696 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
701 if (magStart
< magEnd
) {
702 /* do the magnified texels */
703 switch (tObj
->MagFilter
) {
705 for (i
= magStart
; i
< magEnd
; i
++)
706 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
707 texcoords
[i
], rgba
[i
]);
710 for (i
= magStart
; i
< magEnd
; i
++)
711 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
712 texcoords
[i
], rgba
[i
]);
715 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
722 /**********************************************************************/
723 /* 2-D Texture Sampling Functions */
724 /**********************************************************************/
728 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
731 sample_2d_nearest(GLcontext
*ctx
,
732 const struct gl_texture_object
*tObj
,
733 const struct gl_texture_image
*img
,
734 const GLfloat texcoord
[4],
737 const GLint width
= img
->Width2
; /* without border, power of two */
738 const GLint height
= img
->Height2
; /* without border, power of two */
741 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
742 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
744 /* skip over the border, if any */
748 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
749 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
750 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
753 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
754 if (img
->Format
== GL_COLOR_INDEX
) {
755 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
763 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
764 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
767 sample_2d_linear(GLcontext
*ctx
,
768 const struct gl_texture_object
*tObj
,
769 const struct gl_texture_image
*img
,
770 const GLfloat texcoord
[4],
773 const GLint width
= img
->Width2
;
774 const GLint height
= img
->Height2
;
775 GLint i0
, j0
, i1
, j1
;
776 GLuint useBorderColor
;
779 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
780 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
790 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
791 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
792 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
793 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
797 const GLfloat a
= FRAC(u
);
798 const GLfloat b
= FRAC(v
);
800 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
801 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
802 const GLfloat w10
= a
* (1.0F
-b
);
803 const GLfloat w01
= (1.0F
-a
) * b
;
804 const GLfloat w11
= a
* b
;
805 #else /* CHAN_BITS == 8 */
806 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
807 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
808 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
809 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
810 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
817 if (useBorderColor
& (I0BIT
| J0BIT
)) {
818 COPY_CHAN4(t00
, tObj
->_BorderChan
);
821 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
822 if (img
->Format
== GL_COLOR_INDEX
) {
823 palette_sample(ctx
, tObj
, t00
[0], t00
);
826 if (useBorderColor
& (I1BIT
| J0BIT
)) {
827 COPY_CHAN4(t10
, tObj
->_BorderChan
);
830 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
831 if (img
->Format
== GL_COLOR_INDEX
) {
832 palette_sample(ctx
, tObj
, t10
[0], t10
);
835 if (useBorderColor
& (I0BIT
| J1BIT
)) {
836 COPY_CHAN4(t01
, tObj
->_BorderChan
);
839 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
840 if (img
->Format
== GL_COLOR_INDEX
) {
841 palette_sample(ctx
, tObj
, t01
[0], t01
);
844 if (useBorderColor
& (I1BIT
| J1BIT
)) {
845 COPY_CHAN4(t11
, tObj
->_BorderChan
);
848 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
849 if (img
->Format
== GL_COLOR_INDEX
) {
850 palette_sample(ctx
, tObj
, t11
[0], t11
);
853 #if CHAN_TYPE == GL_FLOAT
854 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
855 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
856 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
857 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
858 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
859 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
860 w01
* t01
[0] + w11
* t11
[0] + 0.5);
861 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
862 w01
* t01
[1] + w11
* t11
[1] + 0.5);
863 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
864 w01
* t01
[2] + w11
* t11
[2] + 0.5);
865 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
866 w01
* t01
[3] + w11
* t11
[3] + 0.5);
867 #else /* CHAN_BITS == 8 */
868 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
869 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
870 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
871 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
872 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
873 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
874 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
875 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
884 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
885 * and we're not using a paletted texture.
888 sample_2d_linear_repeat(GLcontext
*ctx
,
889 const struct gl_texture_object
*tObj
,
890 const struct gl_texture_image
*img
,
891 const GLfloat texcoord
[4],
894 const GLint width
= img
->Width2
;
895 const GLint height
= img
->Height2
;
896 GLint i0
, j0
, i1
, j1
;
899 ASSERT(tObj
->WrapS
== GL_REPEAT
);
900 ASSERT(tObj
->WrapT
== GL_REPEAT
);
901 ASSERT(img
->Border
== 0);
902 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
904 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
905 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
908 const GLfloat a
= FRAC(u
);
909 const GLfloat b
= FRAC(v
);
911 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
912 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
913 const GLfloat w10
= a
* (1.0F
-b
);
914 const GLfloat w01
= (1.0F
-a
) * b
;
915 const GLfloat w11
= a
* b
;
916 #else /* CHAN_BITS == 8 */
917 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
918 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
919 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
920 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
921 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
928 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
929 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
930 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
931 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
933 #if CHAN_TYPE == GL_FLOAT
934 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
935 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
936 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
937 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
938 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
939 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
940 w01
* t01
[0] + w11
* t11
[0] + 0.5);
941 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
942 w01
* t01
[1] + w11
* t11
[1] + 0.5);
943 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
944 w01
* t01
[2] + w11
* t11
[2] + 0.5);
945 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
946 w01
* t01
[3] + w11
* t11
[3] + 0.5);
947 #else /* CHAN_BITS == 8 */
948 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
949 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
950 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
951 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
952 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
953 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
954 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
955 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
965 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
966 const struct gl_texture_object
*tObj
,
967 GLuint n
, GLfloat texcoord
[][4],
968 const GLfloat lambda
[], GLchan rgba
[][4])
971 for (i
= 0; i
< n
; i
++) {
973 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
974 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
981 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
982 const struct gl_texture_object
*tObj
,
983 GLuint n
, GLfloat texcoord
[][4],
984 const GLfloat lambda
[], GLchan rgba
[][4])
987 ASSERT(lambda
!= NULL
);
988 for (i
= 0; i
< n
; i
++) {
990 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
991 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
998 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
999 const struct gl_texture_object
*tObj
,
1000 GLuint n
, GLfloat texcoord
[][4],
1001 const GLfloat lambda
[], GLchan rgba
[][4])
1004 ASSERT(lambda
!= NULL
);
1005 for (i
= 0; i
< n
; i
++) {
1007 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1008 if (level
>= tObj
->_MaxLevel
) {
1009 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1010 texcoord
[i
], rgba
[i
]);
1013 GLchan t0
[4], t1
[4]; /* texels */
1014 const GLfloat f
= FRAC(lambda
[i
]);
1015 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1016 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1017 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1018 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1019 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1020 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1027 /* Trilinear filtering */
1029 sample_2d_linear_mipmap_linear( 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_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1039 if (level
>= tObj
->_MaxLevel
) {
1040 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1041 texcoord
[i
], rgba
[i
]);
1044 GLchan t0
[4], t1
[4]; /* texels */
1045 const GLfloat f
= FRAC(lambda
[i
]);
1046 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1047 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1048 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1049 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1050 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1051 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1058 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1059 const struct gl_texture_object
*tObj
,
1060 GLuint n
, GLfloat texcoord
[][4],
1061 const GLfloat lambda
[], GLchan rgba
[][4] )
1064 ASSERT(lambda
!= NULL
);
1065 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1066 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1067 for (i
= 0; i
< n
; i
++) {
1069 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1070 if (level
>= tObj
->_MaxLevel
) {
1071 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1072 texcoord
[i
], rgba
[i
]);
1075 GLchan t0
[4], t1
[4]; /* texels */
1076 const GLfloat f
= FRAC(lambda
[i
]);
1077 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1078 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1079 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1080 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1081 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1082 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1089 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1090 const struct gl_texture_object
*tObj
, GLuint n
,
1091 GLfloat texcoords
[][4],
1092 const GLfloat lambda
[], GLchan rgba
[][4] )
1095 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1098 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1105 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1106 const struct gl_texture_object
*tObj
, GLuint n
,
1107 GLfloat texcoords
[][4],
1108 const GLfloat lambda
[], GLchan rgba
[][4] )
1111 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1114 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1120 * Optimized 2-D texture sampling:
1121 * S and T wrap mode == GL_REPEAT
1122 * GL_NEAREST min/mag filter
1124 * RowStride == Width,
1128 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1129 const struct gl_texture_object
*tObj
,
1130 GLuint n
, GLfloat texcoords
[][4],
1131 const GLfloat lambda
[], GLchan rgba
[][4] )
1133 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1134 const GLfloat width
= (GLfloat
) img
->Width
;
1135 const GLfloat height
= (GLfloat
) img
->Height
;
1136 const GLint colMask
= img
->Width
- 1;
1137 const GLint rowMask
= img
->Height
- 1;
1138 const GLint shift
= img
->WidthLog2
;
1141 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1142 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1143 ASSERT(img
->Border
==0);
1144 ASSERT(img
->Format
==GL_RGB
);
1146 for (k
=0; k
<n
; k
++) {
1147 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1148 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1149 GLint pos
= (j
<< shift
) | i
;
1150 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1151 rgba
[k
][RCOMP
] = texel
[0];
1152 rgba
[k
][GCOMP
] = texel
[1];
1153 rgba
[k
][BCOMP
] = texel
[2];
1159 * Optimized 2-D texture sampling:
1160 * S and T wrap mode == GL_REPEAT
1161 * GL_NEAREST min/mag filter
1163 * RowStride == Width,
1167 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1168 const struct gl_texture_object
*tObj
,
1169 GLuint n
, GLfloat texcoords
[][4],
1170 const GLfloat lambda
[], GLchan rgba
[][4] )
1172 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1173 const GLfloat width
= (GLfloat
) img
->Width
;
1174 const GLfloat height
= (GLfloat
) img
->Height
;
1175 const GLint colMask
= img
->Width
- 1;
1176 const GLint rowMask
= img
->Height
- 1;
1177 const GLint shift
= img
->WidthLog2
;
1180 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1181 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1182 ASSERT(img
->Border
==0);
1183 ASSERT(img
->Format
==GL_RGBA
);
1185 for (i
= 0; i
< n
; i
++) {
1186 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1187 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1188 const GLint pos
= (row
<< shift
) | col
;
1189 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1190 COPY_CHAN4(rgba
[i
], texel
);
1196 * Given an array of texture coordinate and lambda (level of detail)
1197 * values, return an array of texture sample.
1200 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1201 const struct gl_texture_object
*tObj
,
1202 GLuint n
, GLfloat texcoords
[][4],
1203 const GLfloat lambda
[], GLchan rgba
[][4] )
1205 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1206 GLuint minStart
, minEnd
; /* texels with minification */
1207 GLuint magStart
, magEnd
; /* texels with magnification */
1209 const GLboolean repeatNoBorder
= (tObj
->WrapS
== GL_REPEAT
)
1210 && (tObj
->WrapT
== GL_REPEAT
)
1211 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1212 && (tImg
->Format
!= GL_COLOR_INDEX
);
1214 ASSERT(lambda
!= NULL
);
1215 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1216 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1218 if (minStart
< minEnd
) {
1219 /* do the minified texels */
1220 const GLuint m
= minEnd
- minStart
;
1221 switch (tObj
->MinFilter
) {
1223 if (repeatNoBorder
) {
1224 switch (tImg
->Format
) {
1226 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1227 NULL
, rgba
+ minStart
);
1230 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1231 NULL
, rgba
+ minStart
);
1234 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1235 NULL
, rgba
+ minStart
);
1239 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1240 NULL
, rgba
+ minStart
);
1244 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1245 NULL
, rgba
+ minStart
);
1247 case GL_NEAREST_MIPMAP_NEAREST
:
1248 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1249 lambda
+ minStart
, rgba
+ minStart
);
1251 case GL_LINEAR_MIPMAP_NEAREST
:
1252 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1253 lambda
+ minStart
, rgba
+ minStart
);
1255 case GL_NEAREST_MIPMAP_LINEAR
:
1256 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1257 lambda
+ minStart
, rgba
+ minStart
);
1259 case GL_LINEAR_MIPMAP_LINEAR
:
1261 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1262 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1264 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1265 lambda
+ minStart
, rgba
+ minStart
);
1268 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1273 if (magStart
< magEnd
) {
1274 /* do the magnified texels */
1275 const GLuint m
= magEnd
- magStart
;
1277 switch (tObj
->MagFilter
) {
1279 if (repeatNoBorder
) {
1280 switch (tImg
->Format
) {
1282 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1283 NULL
, rgba
+ magStart
);
1286 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1287 NULL
, rgba
+ magStart
);
1290 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1291 NULL
, rgba
+ magStart
);
1295 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1296 NULL
, rgba
+ magStart
);
1300 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1301 NULL
, rgba
+ magStart
);
1304 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1311 /**********************************************************************/
1312 /* 3-D Texture Sampling Functions */
1313 /**********************************************************************/
1316 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1319 sample_3d_nearest(GLcontext
*ctx
,
1320 const struct gl_texture_object
*tObj
,
1321 const struct gl_texture_image
*img
,
1322 const GLfloat texcoord
[4],
1325 const GLint width
= img
->Width2
; /* without border, power of two */
1326 const GLint height
= img
->Height2
; /* without border, power of two */
1327 const GLint depth
= img
->Depth2
; /* without border, power of two */
1330 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1331 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1332 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1334 if (i
< 0 || i
>= (GLint
) img
->Width
||
1335 j
< 0 || j
>= (GLint
) img
->Height
||
1336 k
< 0 || k
>= (GLint
) img
->Depth
) {
1337 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1338 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1341 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1342 if (img
->Format
== GL_COLOR_INDEX
) {
1343 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1351 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1354 sample_3d_linear(GLcontext
*ctx
,
1355 const struct gl_texture_object
*tObj
,
1356 const struct gl_texture_image
*img
,
1357 const GLfloat texcoord
[4],
1360 const GLint width
= img
->Width2
;
1361 const GLint height
= img
->Height2
;
1362 const GLint depth
= img
->Depth2
;
1363 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1364 GLuint useBorderColor
;
1367 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1368 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1369 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1381 /* check if sampling texture border color */
1382 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1383 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1384 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1385 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1386 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1387 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1391 const GLfloat a
= FRAC(u
);
1392 const GLfloat b
= FRAC(v
);
1393 const GLfloat c
= FRAC(w
);
1395 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1396 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1397 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1398 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1399 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1400 GLfloat w110
= a
* b
* (1.0F
-c
);
1401 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1402 GLfloat w101
= a
* (1.0F
-b
) * c
;
1403 GLfloat w011
= (1.0F
-a
) * b
* c
;
1404 GLfloat w111
= a
* b
* c
;
1405 #else /* CHAN_BITS == 8 */
1406 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1407 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1408 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1409 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1410 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1411 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1412 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1413 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1414 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1417 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1418 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1420 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1421 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1424 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1425 if (img
->Format
== GL_COLOR_INDEX
) {
1426 palette_sample(ctx
, tObj
, t000
[0], t000
);
1429 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1430 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1433 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1434 if (img
->Format
== GL_COLOR_INDEX
) {
1435 palette_sample(ctx
, tObj
, t100
[0], t100
);
1438 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1439 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1442 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1443 if (img
->Format
== GL_COLOR_INDEX
) {
1444 palette_sample(ctx
, tObj
, t010
[0], t010
);
1447 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1448 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1451 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1452 if (img
->Format
== GL_COLOR_INDEX
) {
1453 palette_sample(ctx
, tObj
, t110
[0], t110
);
1457 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1458 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1461 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1462 if (img
->Format
== GL_COLOR_INDEX
) {
1463 palette_sample(ctx
, tObj
, t001
[0], t001
);
1466 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1467 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1470 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1471 if (img
->Format
== GL_COLOR_INDEX
) {
1472 palette_sample(ctx
, tObj
, t101
[0], t101
);
1475 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1476 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1479 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1480 if (img
->Format
== GL_COLOR_INDEX
) {
1481 palette_sample(ctx
, tObj
, t011
[0], t011
);
1484 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1485 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1488 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1489 if (img
->Format
== GL_COLOR_INDEX
) {
1490 palette_sample(ctx
, tObj
, t111
[0], t111
);
1494 #if CHAN_TYPE == GL_FLOAT
1495 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1496 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1497 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1498 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1499 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1500 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1501 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1502 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1503 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1504 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1505 w001
*t001
[0] + w011
*t011
[0] +
1506 w100
*t100
[0] + w110
*t110
[0] +
1507 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1508 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1509 w001
*t001
[1] + w011
*t011
[1] +
1510 w100
*t100
[1] + w110
*t110
[1] +
1511 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1512 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1513 w001
*t001
[2] + w011
*t011
[2] +
1514 w100
*t100
[2] + w110
*t110
[2] +
1515 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1516 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1517 w001
*t001
[3] + w011
*t011
[3] +
1518 w100
*t100
[3] + w110
*t110
[3] +
1519 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1520 #else /* CHAN_BITS == 8 */
1521 rgba
[0] = (GLchan
) (
1522 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1523 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1525 rgba
[1] = (GLchan
) (
1526 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1527 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1529 rgba
[2] = (GLchan
) (
1530 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1531 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1533 rgba
[3] = (GLchan
) (
1534 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1535 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1545 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1546 const struct gl_texture_object
*tObj
,
1547 GLuint n
, GLfloat texcoord
[][4],
1548 const GLfloat lambda
[], GLchan rgba
[][4] )
1551 for (i
= 0; i
< n
; i
++) {
1553 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1554 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1560 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1561 const struct gl_texture_object
*tObj
,
1562 GLuint n
, GLfloat texcoord
[][4],
1563 const GLfloat lambda
[], GLchan rgba
[][4])
1566 ASSERT(lambda
!= NULL
);
1567 for (i
= 0; i
< n
; i
++) {
1569 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1570 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1576 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1577 const struct gl_texture_object
*tObj
,
1578 GLuint n
, GLfloat texcoord
[][4],
1579 const GLfloat lambda
[], GLchan rgba
[][4])
1582 ASSERT(lambda
!= NULL
);
1583 for (i
= 0; i
< n
; i
++) {
1585 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1586 if (level
>= tObj
->_MaxLevel
) {
1587 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1588 texcoord
[i
], rgba
[i
]);
1591 GLchan t0
[4], t1
[4]; /* texels */
1592 const GLfloat f
= FRAC(lambda
[i
]);
1593 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1594 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1595 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1596 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1597 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1598 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1605 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1606 const struct gl_texture_object
*tObj
,
1607 GLuint n
, GLfloat texcoord
[][4],
1608 const GLfloat lambda
[], GLchan rgba
[][4])
1611 ASSERT(lambda
!= NULL
);
1612 for (i
= 0; i
< n
; i
++) {
1614 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1615 if (level
>= tObj
->_MaxLevel
) {
1616 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1617 texcoord
[i
], rgba
[i
]);
1620 GLchan t0
[4], t1
[4]; /* texels */
1621 const GLfloat f
= FRAC(lambda
[i
]);
1622 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1623 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1624 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1625 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1626 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1627 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1634 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1635 const struct gl_texture_object
*tObj
, GLuint n
,
1636 GLfloat texcoords
[][4], const GLfloat lambda
[],
1640 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1643 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1650 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1651 const struct gl_texture_object
*tObj
, GLuint n
,
1652 GLfloat texcoords
[][4],
1653 const GLfloat lambda
[], GLchan rgba
[][4] )
1656 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1659 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1665 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1666 * return a texture sample.
1669 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1670 const struct gl_texture_object
*tObj
, GLuint n
,
1671 GLfloat texcoords
[][4], const GLfloat lambda
[],
1674 GLuint minStart
, minEnd
; /* texels with minification */
1675 GLuint magStart
, magEnd
; /* texels with magnification */
1678 ASSERT(lambda
!= NULL
);
1679 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1680 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1682 if (minStart
< minEnd
) {
1683 /* do the minified texels */
1684 GLuint m
= minEnd
- minStart
;
1685 switch (tObj
->MinFilter
) {
1687 for (i
= minStart
; i
< minEnd
; i
++)
1688 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1689 texcoords
[i
], rgba
[i
]);
1692 for (i
= minStart
; i
< minEnd
; i
++)
1693 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1694 texcoords
[i
], rgba
[i
]);
1696 case GL_NEAREST_MIPMAP_NEAREST
:
1697 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1698 lambda
+ minStart
, rgba
+ minStart
);
1700 case GL_LINEAR_MIPMAP_NEAREST
:
1701 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1702 lambda
+ minStart
, rgba
+ minStart
);
1704 case GL_NEAREST_MIPMAP_LINEAR
:
1705 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1706 lambda
+ minStart
, rgba
+ minStart
);
1708 case GL_LINEAR_MIPMAP_LINEAR
:
1709 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1710 lambda
+ minStart
, rgba
+ minStart
);
1713 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1718 if (magStart
< magEnd
) {
1719 /* do the magnified texels */
1720 switch (tObj
->MagFilter
) {
1722 for (i
= magStart
; i
< magEnd
; i
++)
1723 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1724 texcoords
[i
], rgba
[i
]);
1727 for (i
= magStart
; i
< magEnd
; i
++)
1728 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1729 texcoords
[i
], rgba
[i
]);
1732 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1739 /**********************************************************************/
1740 /* Texture Cube Map Sampling Functions */
1741 /**********************************************************************/
1744 * Choose one of six sides of a texture cube map given the texture
1745 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1748 static const struct gl_texture_image
**
1749 choose_cube_face(const struct gl_texture_object
*texObj
,
1750 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1754 direction target sc tc ma
1755 ---------- ------------------------------- --- --- ---
1756 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1757 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1758 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1759 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1760 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1761 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1763 const GLfloat rx
= texcoord
[0];
1764 const GLfloat ry
= texcoord
[1];
1765 const GLfloat rz
= texcoord
[2];
1766 const struct gl_texture_image
**imgArray
;
1767 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
1770 if (arx
> ary
&& arx
> arz
) {
1772 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
1778 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
1784 else if (ary
> arx
&& ary
> arz
) {
1786 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
1792 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
1800 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
1806 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
1813 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1814 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1820 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1821 const struct gl_texture_object
*tObj
, GLuint n
,
1822 GLfloat texcoords
[][4], const GLfloat lambda
[],
1827 for (i
= 0; i
< n
; i
++) {
1828 const struct gl_texture_image
**images
;
1829 GLfloat newCoord
[4];
1830 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1831 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1838 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1839 const struct gl_texture_object
*tObj
, GLuint n
,
1840 GLfloat texcoords
[][4],
1841 const GLfloat lambda
[], GLchan rgba
[][4])
1845 for (i
= 0; i
< n
; i
++) {
1846 const struct gl_texture_image
**images
;
1847 GLfloat newCoord
[4];
1848 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1849 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1856 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1857 const struct gl_texture_object
*tObj
,
1858 GLuint n
, GLfloat texcoord
[][4],
1859 const GLfloat lambda
[], GLchan rgba
[][4])
1862 ASSERT(lambda
!= NULL
);
1863 for (i
= 0; i
< n
; i
++) {
1864 const struct gl_texture_image
**images
;
1865 GLfloat newCoord
[4];
1867 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1868 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1869 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1875 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1876 const struct gl_texture_object
*tObj
,
1877 GLuint n
, GLfloat texcoord
[][4],
1878 const GLfloat lambda
[], GLchan rgba
[][4])
1881 ASSERT(lambda
!= NULL
);
1882 for (i
= 0; i
< n
; i
++) {
1883 const struct gl_texture_image
**images
;
1884 GLfloat newCoord
[4];
1886 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1887 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1888 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1894 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1895 const struct gl_texture_object
*tObj
,
1896 GLuint n
, GLfloat texcoord
[][4],
1897 const GLfloat lambda
[], GLchan rgba
[][4])
1900 ASSERT(lambda
!= NULL
);
1901 for (i
= 0; i
< n
; i
++) {
1902 const struct gl_texture_image
**images
;
1903 GLfloat newCoord
[4];
1905 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1906 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1907 if (level
>= tObj
->_MaxLevel
) {
1908 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1912 GLchan t0
[4], t1
[4]; /* texels */
1913 const GLfloat f
= FRAC(lambda
[i
]);
1914 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1915 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1916 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1917 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1918 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1919 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1926 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1927 const struct gl_texture_object
*tObj
,
1928 GLuint n
, GLfloat texcoord
[][4],
1929 const GLfloat lambda
[], GLchan rgba
[][4])
1932 ASSERT(lambda
!= NULL
);
1933 for (i
= 0; i
< n
; i
++) {
1934 const struct gl_texture_image
**images
;
1935 GLfloat newCoord
[4];
1937 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1938 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1939 if (level
>= tObj
->_MaxLevel
) {
1940 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1944 GLchan t0
[4], t1
[4];
1945 const GLfloat f
= FRAC(lambda
[i
]);
1946 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
1947 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1948 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1949 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1950 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1951 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1958 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1959 const struct gl_texture_object
*tObj
, GLuint n
,
1960 GLfloat texcoords
[][4], const GLfloat lambda
[],
1963 GLuint minStart
, minEnd
; /* texels with minification */
1964 GLuint magStart
, magEnd
; /* texels with magnification */
1966 ASSERT(lambda
!= NULL
);
1967 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1968 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1970 if (minStart
< minEnd
) {
1971 /* do the minified texels */
1972 const GLuint m
= minEnd
- minStart
;
1973 switch (tObj
->MinFilter
) {
1975 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1976 lambda
+ minStart
, rgba
+ minStart
);
1979 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1980 lambda
+ minStart
, rgba
+ minStart
);
1982 case GL_NEAREST_MIPMAP_NEAREST
:
1983 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1984 lambda
+ minStart
, rgba
+ minStart
);
1986 case GL_LINEAR_MIPMAP_NEAREST
:
1987 sample_cube_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1988 lambda
+ minStart
, rgba
+ minStart
);
1990 case GL_NEAREST_MIPMAP_LINEAR
:
1991 sample_cube_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1992 lambda
+ minStart
, rgba
+ minStart
);
1994 case GL_LINEAR_MIPMAP_LINEAR
:
1995 sample_cube_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1996 lambda
+ minStart
, rgba
+ minStart
);
1999 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2003 if (magStart
< magEnd
) {
2004 /* do the magnified texels */
2005 const GLuint m
= magEnd
- magStart
;
2006 switch (tObj
->MagFilter
) {
2008 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2009 lambda
+ magStart
, rgba
+ magStart
);
2012 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2013 lambda
+ magStart
, rgba
+ magStart
);
2016 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2022 /**********************************************************************/
2023 /* Texture Rectangle Sampling Functions */
2024 /**********************************************************************/
2027 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2028 const struct gl_texture_object
*tObj
, GLuint n
,
2029 GLfloat texcoords
[][4], const GLfloat lambda
[],
2032 const struct gl_texture_image
*img
= tObj
->Image
[0];
2033 const GLfloat width
= (GLfloat
) img
->Width
;
2034 const GLfloat height
= (GLfloat
) img
->Height
;
2035 const GLint width_minus_1
= img
->Width
- 1;
2036 const GLint height_minus_1
= img
->Height
- 1;
2042 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2043 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2044 tObj
->WrapS
== GL_CLAMP_TO_BORDER_ARB
);
2045 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2046 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2047 tObj
->WrapT
== GL_CLAMP_TO_BORDER_ARB
);
2048 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2050 /* XXX move Wrap mode tests outside of loops for common cases */
2051 for (i
= 0; i
< n
; i
++) {
2053 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2054 if (tObj
->WrapS
== GL_CLAMP
) {
2055 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2057 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2058 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2061 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2063 if (tObj
->WrapT
== GL_CLAMP
) {
2064 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2066 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2067 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2070 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2073 col
= CLAMP(col
, 0, width_minus_1
);
2074 row
= CLAMP(row
, 0, height_minus_1
);
2076 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2082 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2083 const struct gl_texture_object
*tObj
, GLuint n
,
2084 GLfloat texcoords
[][4],
2085 const GLfloat lambda
[], GLchan rgba
[][4])
2087 const struct gl_texture_image
*img
= tObj
->Image
[0];
2088 const GLfloat width
= (GLfloat
) img
->Width
;
2089 const GLfloat height
= (GLfloat
) img
->Height
;
2090 const GLint width_minus_1
= img
->Width
- 1;
2091 const GLint height_minus_1
= img
->Height
- 1;
2097 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2098 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2099 tObj
->WrapS
== GL_CLAMP_TO_BORDER_ARB
);
2100 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2101 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2102 tObj
->WrapT
== GL_CLAMP_TO_BORDER_ARB
);
2103 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2105 /* XXX lots of opportunity for optimization in this loop */
2106 for (i
= 0; i
< n
; i
++) {
2108 GLint row0
, col0
, row1
, col1
;
2109 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2110 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2112 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2113 if (tObj
->WrapS
== GL_CLAMP
) {
2114 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2116 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2117 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2120 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2122 if (tObj
->WrapT
== GL_CLAMP
) {
2123 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2125 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2126 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2129 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2132 /* compute integer rows/columns */
2133 col0
= IFLOOR(fcol
);
2135 col0
= CLAMP(col0
, 0, width_minus_1
);
2136 col1
= CLAMP(col1
, 0, width_minus_1
);
2137 row0
= IFLOOR(frow
);
2139 row0
= CLAMP(row0
, 0, height_minus_1
);
2140 row1
= CLAMP(row1
, 0, height_minus_1
);
2142 /* get four texel samples */
2143 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2144 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2145 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2146 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2148 /* compute sample weights */
2151 w00
= (1.0F
-a
) * (1.0F
-b
);
2153 w01
= (1.0F
-a
) * b
;
2156 /* compute weighted average of samples */
2157 rgba
[i
][0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
2158 rgba
[i
][1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
2159 rgba
[i
][2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
2160 rgba
[i
][3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
2166 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2167 const struct gl_texture_object
*tObj
, GLuint n
,
2168 GLfloat texcoords
[][4], const GLfloat lambda
[],
2171 GLuint minStart
, minEnd
, magStart
, magEnd
;
2173 /* We only need lambda to decide between minification and magnification.
2174 * There is no mipmapping with rectangular textures.
2176 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2177 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2179 if (minStart
< minEnd
) {
2180 if (tObj
->MinFilter
== GL_NEAREST
) {
2181 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2182 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2185 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2186 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2189 if (magStart
< magEnd
) {
2190 if (tObj
->MagFilter
== GL_NEAREST
) {
2191 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2192 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2195 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2196 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2204 * Sample a shadow/depth texture.
2207 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2208 const struct gl_texture_object
*tObj
, GLuint n
,
2209 GLfloat texcoords
[][4], const GLfloat lambda
[],
2212 const GLint baseLevel
= tObj
->BaseLevel
;
2213 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2214 const GLuint width
= texImage
->Width
;
2215 const GLuint height
= texImage
->Height
;
2222 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2223 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2224 tObj
->Target
== GL_TEXTURE_2D
||
2225 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2227 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2229 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2231 /* XXX this could be precomputed and saved in the texture object */
2232 if (tObj
->CompareFlag
) {
2233 /* GL_SGIX_shadow */
2234 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2235 function
= GL_LEQUAL
;
2238 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2239 function
= GL_GEQUAL
;
2242 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2244 function
= tObj
->CompareFunc
;
2247 function
= GL_NONE
; /* pass depth through as grayscale */
2250 if (tObj
->MagFilter
== GL_NEAREST
) {
2252 for (i
= 0; i
< n
; i
++) {
2253 GLfloat depthSample
;
2255 /* XXX fix for texture rectangle! */
2256 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2257 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2258 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2262 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2265 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2268 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2271 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2274 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2277 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2286 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2289 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2293 switch (tObj
->DepthMode
) {
2295 texel
[i
][RCOMP
] = result
;
2296 texel
[i
][GCOMP
] = result
;
2297 texel
[i
][BCOMP
] = result
;
2298 texel
[i
][ACOMP
] = CHAN_MAX
;
2301 texel
[i
][RCOMP
] = result
;
2302 texel
[i
][GCOMP
] = result
;
2303 texel
[i
][BCOMP
] = result
;
2304 texel
[i
][ACOMP
] = result
;
2307 texel
[i
][RCOMP
] = 0;
2308 texel
[i
][GCOMP
] = 0;
2309 texel
[i
][BCOMP
] = 0;
2310 texel
[i
][ACOMP
] = result
;
2313 _mesa_problem(ctx
, "Bad depth texture mode");
2319 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2320 for (i
= 0; i
< n
; i
++) {
2321 GLfloat depth00
, depth01
, depth10
, depth11
;
2322 GLint i0
, i1
, j0
, j1
;
2324 GLuint useBorderTexel
;
2326 /* XXX fix for texture rectangle! */
2327 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2328 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2331 if (texImage
->Border
) {
2332 i0
+= texImage
->Border
;
2333 i1
+= texImage
->Border
;
2334 j0
+= texImage
->Border
;
2335 j1
+= texImage
->Border
;
2338 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2339 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2340 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2341 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2344 /* get four depth samples from the texture */
2345 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2349 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2351 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2355 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2357 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2361 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2363 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2367 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2371 /* compute a single weighted depth sample and do one comparison */
2372 const GLfloat a
= FRAC(u
+ 1.0F
);
2373 const GLfloat b
= FRAC(v
+ 1.0F
);
2374 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2375 const GLfloat w10
= ( a
) * (1.0F
- b
);
2376 const GLfloat w01
= (1.0F
- a
) * ( b
);
2377 const GLfloat w11
= ( a
) * ( b
);
2378 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2379 + w01
* depth01
+ w11
* depth11
;
2380 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2381 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2389 /* Do four depth/R comparisons and compute a weighted result.
2390 * If this touches on somebody's I.P., I'll remove this code
2393 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2394 GLfloat luminance
= CHAN_MAXF
;
2398 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2399 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2400 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2401 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2402 result
= (GLchan
) luminance
;
2405 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2406 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2407 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2408 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2409 result
= (GLchan
) luminance
;
2412 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2413 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2414 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2415 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2416 result
= (GLchan
) luminance
;
2419 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2420 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2421 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2422 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2423 result
= (GLchan
) luminance
;
2426 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2427 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2428 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2429 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2430 result
= (GLchan
) luminance
;
2433 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2434 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2435 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2436 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2437 result
= (GLchan
) luminance
;
2446 /* ordinary bilinear filtering */
2448 const GLfloat a
= FRAC(u
+ 1.0F
);
2449 const GLfloat b
= FRAC(v
+ 1.0F
);
2450 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2451 const GLfloat w10
= ( a
) * (1.0F
- b
);
2452 const GLfloat w01
= (1.0F
- a
) * ( b
);
2453 const GLfloat w11
= ( a
) * ( b
);
2454 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2455 + w01
* depth01
+ w11
* depth11
;
2456 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2460 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2465 switch (tObj
->DepthMode
) {
2467 texel
[i
][RCOMP
] = result
;
2468 texel
[i
][GCOMP
] = result
;
2469 texel
[i
][BCOMP
] = result
;
2470 texel
[i
][ACOMP
] = CHAN_MAX
;
2473 texel
[i
][RCOMP
] = result
;
2474 texel
[i
][GCOMP
] = result
;
2475 texel
[i
][BCOMP
] = result
;
2476 texel
[i
][ACOMP
] = result
;
2479 texel
[i
][RCOMP
] = 0;
2480 texel
[i
][GCOMP
] = 0;
2481 texel
[i
][BCOMP
] = 0;
2482 texel
[i
][ACOMP
] = result
;
2485 _mesa_problem(ctx
, "Bad depth texture mode");
2494 * Experimental depth texture sampling function.
2497 sample_depth_texture2(const GLcontext
*ctx
,
2498 const struct gl_texture_unit
*texUnit
,
2499 GLuint n
, GLfloat texcoords
[][4],
2502 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2503 const GLint baseLevel
= texObj
->BaseLevel
;
2504 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2505 const GLuint width
= texImage
->Width
;
2506 const GLuint height
= texImage
->Height
;
2508 GLboolean lequal
, gequal
;
2510 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2511 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2515 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2516 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2520 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2521 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2522 * isn't a depth texture.
2524 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2525 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2529 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2531 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2542 for (i
= 0; i
< n
; i
++) {
2544 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2547 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2549 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2557 if (imin
< 0) imin
= 0;
2558 if (imax
>= width
) imax
= width
- 1;
2559 if (jmin
< 0) jmin
= 0;
2560 if (jmax
>= height
) jmax
= height
- 1;
2562 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2564 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2565 for (ii
= imin
; ii
<= imax
; ii
++) {
2566 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2568 if ((depthSample
<= r
[i
] && lequal
) ||
2569 (depthSample
>= r
[i
] && gequal
)) {
2575 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2576 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2579 texel
[i
][RCOMP
] = lum
;
2580 texel
[i
][GCOMP
] = lum
;
2581 texel
[i
][BCOMP
] = lum
;
2582 texel
[i
][ACOMP
] = CHAN_MAX
;
2590 * We use this function when a texture object is in an "incomplete" state.
2593 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2594 const struct gl_texture_object
*tObj
, GLuint n
,
2595 GLfloat texcoords
[][4], const GLfloat lambda
[],
2603 * Setup the texture sampling function for this texture object.
2606 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2607 const struct gl_texture_object
*t
)
2609 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2612 swrast
->TextureSample
[texUnit
] = null_sample_func
;
2615 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2616 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2619 /* Compute min/mag filter threshold */
2620 if (t
->MagFilter
== GL_LINEAR
2621 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
2622 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
2623 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
2626 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
2630 switch (t
->Target
) {
2632 if (format
== GL_DEPTH_COMPONENT
) {
2633 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2635 else if (needLambda
) {
2636 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
2638 else if (t
->MinFilter
== GL_LINEAR
) {
2639 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
2642 ASSERT(t
->MinFilter
== GL_NEAREST
);
2643 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
2647 if (format
== GL_DEPTH_COMPONENT
) {
2648 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2650 else if (needLambda
) {
2651 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
2653 else if (t
->MinFilter
== GL_LINEAR
) {
2654 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
2657 GLint baseLevel
= t
->BaseLevel
;
2658 ASSERT(t
->MinFilter
== GL_NEAREST
);
2659 if (t
->WrapS
== GL_REPEAT
&&
2660 t
->WrapT
== GL_REPEAT
&&
2661 t
->Image
[baseLevel
]->Border
== 0 &&
2662 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2663 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
2665 else if (t
->WrapS
== GL_REPEAT
&&
2666 t
->WrapT
== GL_REPEAT
&&
2667 t
->Image
[baseLevel
]->Border
== 0 &&
2668 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2669 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
2672 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
2677 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
2679 else if (t
->MinFilter
== GL_LINEAR
) {
2680 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
2683 ASSERT(t
->MinFilter
== GL_NEAREST
);
2684 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
2687 case GL_TEXTURE_CUBE_MAP_ARB
:
2689 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
2691 else if (t
->MinFilter
== GL_LINEAR
) {
2692 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
2695 ASSERT(t
->MinFilter
== GL_NEAREST
);
2696 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
2699 case GL_TEXTURE_RECTANGLE_NV
:
2701 swrast
->TextureSample
[texUnit
] = sample_lambda_rect
;
2703 else if (t
->MinFilter
== GL_LINEAR
) {
2704 swrast
->TextureSample
[texUnit
] = sample_linear_rect
;
2707 ASSERT(t
->MinFilter
== GL_NEAREST
);
2708 swrast
->TextureSample
[texUnit
] = sample_nearest_rect
;
2712 _mesa_problem(ctx
, "invalid target in _swrast_choose_texture_sample_func");
2718 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2719 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2723 * Do texture application for GL_ARB/EXT_texture_env_combine.
2725 * ctx - rendering context
2726 * textureUnit - the texture unit to apply
2727 * n - number of fragments to process (span width)
2728 * primary_rgba - incoming fragment color array
2729 * texelBuffer - pointer to texel colors for all texture units
2731 * rgba - incoming colors, which get modified here
2734 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
2735 CONST
GLchan (*primary_rgba
)[4],
2736 CONST GLchan
*texelBuffer
,
2739 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
2740 const GLchan (*argRGB
[3])[4];
2741 const GLchan (*argA
[3])[4];
2742 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
2743 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
2744 #if CHAN_TYPE == GL_FLOAT
2745 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2746 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2748 const GLint half
= (CHAN_MAX
+ 1) / 2;
2752 /* GLchan ccolor[3][4]; */
2753 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2754 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2756 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2757 ctx
->Extensions
.ARB_texture_env_combine
);
2758 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
2762 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
2763 textureUnit->CombineModeRGB,
2764 textureUnit->CombineModeA,
2765 textureUnit->CombineSourceRGB[0],
2766 textureUnit->CombineSourceA[0],
2767 textureUnit->CombineSourceRGB[1],
2768 textureUnit->CombineSourceA[1]);
2772 * Do operand setup for up to 3 operands. Loop over the terms.
2774 for (j
= 0; j
< 3; j
++) {
2775 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
2776 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
2780 argA
[j
] = (const GLchan (*)[4])
2781 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2783 case GL_PRIMARY_COLOR_EXT
:
2784 argA
[j
] = primary_rgba
;
2786 case GL_PREVIOUS_EXT
:
2787 argA
[j
] = (const GLchan (*)[4]) rgba
;
2789 case GL_CONSTANT_EXT
:
2791 GLchan alpha
, (*c
)[4] = ccolor
[j
];
2792 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2793 for (i
= 0; i
< n
; i
++)
2794 c
[i
][ACOMP
] = alpha
;
2795 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2799 /* ARB_texture_env_crossbar source */
2801 const GLuint srcUnit
= srcA
- GL_TEXTURE0_ARB
;
2802 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2803 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2805 argA
[j
] = (const GLchan (*)[4])
2806 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2812 argRGB
[j
] = (const GLchan (*)[4])
2813 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
2815 case GL_PRIMARY_COLOR_EXT
:
2816 argRGB
[j
] = primary_rgba
;
2818 case GL_PREVIOUS_EXT
:
2819 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2821 case GL_CONSTANT_EXT
:
2823 GLchan (*c
)[4] = ccolor
[j
];
2824 GLchan red
, green
, blue
, alpha
;
2825 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2826 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2827 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2828 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2829 for (i
= 0; i
< n
; i
++) {
2831 c
[i
][GCOMP
] = green
;
2833 c
[i
][ACOMP
] = alpha
;
2835 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2839 /* ARB_texture_env_crossbar source */
2841 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0_ARB
;
2842 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
2843 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
2845 argRGB
[j
] = (const GLchan (*)[4])
2846 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
2850 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
2851 const GLchan (*src
)[4] = argRGB
[j
];
2852 GLchan (*dst
)[4] = ccolor
[j
];
2854 /* point to new arg[j] storage */
2855 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2857 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2858 for (i
= 0; i
< n
; i
++) {
2859 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2860 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2861 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2864 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
2865 for (i
= 0; i
< n
; i
++) {
2866 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2867 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2868 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2872 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2873 for (i
= 0; i
< n
; i
++) {
2874 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2875 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2876 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2881 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
2882 const GLchan (*src
)[4] = argA
[j
];
2883 GLchan (*dst
)[4] = ccolor
[j
];
2884 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2885 for (i
= 0; i
< n
; i
++) {
2886 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2890 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
2891 textureUnit
->CombineModeA
== GL_REPLACE
) {
2892 break; /* done, we need only arg0 */
2896 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
2897 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
2898 break; /* arg0 and arg1 are done. we don't need arg2. */
2903 * Do the texture combine.
2905 switch (textureUnit
->CombineModeRGB
) {
2908 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2910 for (i
= 0; i
< n
; i
++) {
2911 #if CHAN_TYPE == GL_FLOAT
2912 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
2913 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
2914 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
2916 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
2917 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
2918 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
2919 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2920 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2921 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2926 for (i
= 0; i
< n
; i
++) {
2927 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
2928 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
2929 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
2936 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2937 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2938 #if CHAN_TYPE != GL_FLOAT
2939 const GLint shift
= CHAN_BITS
- RGBshift
;
2941 for (i
= 0; i
< n
; i
++) {
2942 #if CHAN_TYPE == GL_FLOAT
2943 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
2944 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
2945 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
2947 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
2948 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
2949 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
2950 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2951 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2952 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2959 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2960 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2961 for (i
= 0; i
< n
; i
++) {
2962 #if CHAN_TYPE == GL_FLOAT
2963 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
2964 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
2965 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
2967 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2968 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2969 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2970 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2971 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2972 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2977 case GL_ADD_SIGNED_EXT
:
2979 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2980 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2981 for (i
= 0; i
< n
; i
++) {
2982 #if CHAN_TYPE == GL_FLOAT
2983 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
2984 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
2985 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
2987 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
2988 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
2989 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
2990 r
= (r
< 0) ? 0 : r
<< RGBshift
;
2991 g
= (g
< 0) ? 0 : g
<< RGBshift
;
2992 b
= (b
< 0) ? 0 : b
<< RGBshift
;
2993 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2994 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2995 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3000 case GL_INTERPOLATE_EXT
:
3002 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3003 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3004 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3005 #if CHAN_TYPE != GL_FLOAT
3006 const GLint shift
= CHAN_BITS
- RGBshift
;
3008 for (i
= 0; i
< n
; i
++) {
3009 #if CHAN_TYPE == GL_FLOAT
3010 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3011 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3012 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3013 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3014 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3015 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3017 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3018 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3020 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3021 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3023 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3024 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3026 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3027 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3028 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3033 case GL_SUBTRACT_ARB
:
3035 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3036 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3037 for (i
= 0; i
< n
; i
++) {
3038 #if CHAN_TYPE == GL_FLOAT
3039 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3040 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3041 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3043 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3044 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3045 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3046 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3047 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3048 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3053 case GL_DOT3_RGB_EXT
:
3054 case GL_DOT3_RGBA_EXT
:
3056 /* Do not scale the result by 1 2 or 4 */
3057 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3058 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3059 for (i
= 0; i
< n
; i
++) {
3060 #if CHAN_TYPE == GL_FLOAT
3061 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3062 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3063 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3065 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3067 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3068 (GLint
)arg1
[i
][RCOMP
] - half
) +
3069 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3070 (GLint
)arg1
[i
][GCOMP
] - half
) +
3071 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3072 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3073 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3075 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3079 case GL_DOT3_RGB_ARB
:
3080 case GL_DOT3_RGBA_ARB
:
3082 /* DO scale the result by 1 2 or 4 */
3083 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3084 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3085 for (i
= 0; i
< n
; i
++) {
3086 #if CHAN_TYPE == GL_FLOAT
3087 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3088 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3089 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3091 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
) * RGBmult
;
3093 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3094 (GLint
)arg1
[i
][RCOMP
] - half
) +
3095 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3096 (GLint
)arg1
[i
][GCOMP
] - half
) +
3097 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3098 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3099 dot
= CLAMP(dot
, 0, CHAN_MAX
) << RGBshift
;
3101 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3106 _mesa_problem(ctx
, "invalid combine mode");
3109 switch (textureUnit
->CombineModeA
) {
3112 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3114 for (i
= 0; i
< n
; i
++) {
3115 #if CHAN_TYPE == GL_FLOAT
3116 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3118 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3120 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3124 for (i
= 0; i
< n
; i
++) {
3125 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3132 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3133 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3134 #if CHAN_TYPE != GL_FLOAT
3135 const GLint shift
= CHAN_BITS
- Ashift
;
3137 for (i
= 0; i
< n
; i
++) {
3138 #if CHAN_TYPE == GL_FLOAT
3139 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3141 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3142 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3149 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3150 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3151 for (i
= 0; i
< n
; i
++) {
3152 #if CHAN_TYPE == GL_FLOAT
3153 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3155 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3156 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3161 case GL_ADD_SIGNED_EXT
:
3163 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3164 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3165 for (i
= 0; i
< n
; i
++) {
3166 #if CHAN_TYPE == GL_FLOAT
3167 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3169 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3170 a
= (a
< 0) ? 0 : a
<< Ashift
;
3171 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3176 case GL_INTERPOLATE_EXT
:
3178 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3179 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3180 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3181 #if CHAN_TYPE != GL_FLOAT
3182 const GLint shift
= CHAN_BITS
- Ashift
;
3184 for (i
=0; i
<n
; i
++) {
3185 #if CHAN_TYPE == GL_FLOAT
3186 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3187 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3190 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3191 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3193 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3198 case GL_SUBTRACT_ARB
:
3200 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3201 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3202 for (i
= 0; i
< n
; i
++) {
3203 #if CHAN_TYPE == GL_FLOAT
3204 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3206 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3207 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3214 _mesa_problem(ctx
, "invalid combine mode");
3217 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3218 * This is kind of a kludge. It would have been better if the spec
3219 * were written such that the GL_COMBINE_ALPHA value could be set to
3222 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3223 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
3224 for (i
= 0; i
< n
; i
++) {
3225 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3228 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3234 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3235 * texUnit->EnvMode == GL_COMBINE4_NV.
3238 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3239 CONST
GLchan (*primary_rgba
)[4],
3240 CONST GLchan
*texelBuffer
,
3248 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3249 * MODULATE, or DECAL) to an array of fragments.
3250 * Input: textureUnit - pointer to texture unit to apply
3251 * format - base internal texture format
3252 * n - number of fragments
3253 * primary_rgba - primary colors (may alias rgba for single texture)
3254 * texels - array of texel colors
3255 * InOut: rgba - incoming fragment colors modified by texel colors
3256 * according to the texture environment mode.
3259 texture_apply( const GLcontext
*ctx
,
3260 const struct gl_texture_unit
*texUnit
,
3262 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3267 GLint Rc
, Gc
, Bc
, Ac
;
3271 ASSERT(texUnit
->_Current
);
3273 baseLevel
= texUnit
->_Current
->BaseLevel
;
3274 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3276 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3278 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
3279 || format
== GL_YCBCR_MESA
) {
3280 format
= GL_RGBA
; /* a bit of a hack */
3283 switch (texUnit
->EnvMode
) {
3290 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3296 GLchan Lt
= texel
[i
][RCOMP
];
3297 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3301 case GL_LUMINANCE_ALPHA
:
3303 GLchan Lt
= texel
[i
][RCOMP
];
3305 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3307 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3313 GLchan It
= texel
[i
][RCOMP
];
3314 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3316 rgba
[i
][ACOMP
] = It
;
3322 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3323 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3324 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3331 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3332 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3333 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3335 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3339 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3350 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3356 GLchan Lt
= texel
[i
][RCOMP
];
3357 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3358 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3359 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3363 case GL_LUMINANCE_ALPHA
:
3366 GLchan Lt
= texel
[i
][RCOMP
];
3367 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3368 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3369 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3371 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3377 GLchan It
= texel
[i
][RCOMP
];
3378 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3379 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3380 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3382 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3388 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3389 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3390 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3397 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3398 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3399 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3401 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3405 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3414 case GL_LUMINANCE_ALPHA
:
3421 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3422 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3423 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3429 /* Cv = Cf(1-At) + CtAt */
3430 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3431 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3432 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3433 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3438 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3444 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3445 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3446 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3447 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3453 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3458 /* Cv = Cf(1-Lt) + CcLt */
3459 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3460 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3461 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3462 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3466 case GL_LUMINANCE_ALPHA
:
3468 /* Cv = Cf(1-Lt) + CcLt */
3469 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3470 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3471 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3472 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3474 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3479 /* Cv = Cf(1-It) + CcLt */
3480 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3481 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3482 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3483 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3484 /* Av = Af(1-It) + Ac*It */
3485 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
3490 /* Cv = Cf(1-Ct) + CcCt */
3491 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3492 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3493 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3499 /* Cv = Cf(1-Ct) + CcCt */
3500 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
3501 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
3502 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
3504 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3508 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
3513 /* XXX don't clamp results if GLchan is float??? */
3515 case GL_ADD
: /* GL_EXT_texture_add_env */
3522 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3527 GLuint Lt
= texel
[i
][RCOMP
];
3528 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3529 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3530 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3531 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3532 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3533 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3537 case GL_LUMINANCE_ALPHA
:
3539 GLuint Lt
= texel
[i
][RCOMP
];
3540 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
3541 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
3542 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
3543 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3544 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3545 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3546 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3551 GLchan It
= texel
[i
][RCOMP
];
3552 GLuint r
= rgba
[i
][RCOMP
] + It
;
3553 GLuint g
= rgba
[i
][GCOMP
] + It
;
3554 GLuint b
= rgba
[i
][BCOMP
] + It
;
3555 GLuint a
= rgba
[i
][ACOMP
] + It
;
3556 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3557 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3558 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3559 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
3564 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3565 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3566 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3567 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3568 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3569 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3575 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
3576 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
3577 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
3578 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3579 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3580 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3581 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3585 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
3591 _mesa_problem(ctx
, "Bad env mode in texture_apply");
3599 * Apply texture mapping to a span of fragments.
3602 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
3604 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
3605 GLchan primary_rgba
[MAX_WIDTH
][4];
3608 ASSERT(span
->end
< MAX_WIDTH
);
3609 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
3612 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
3614 if (swrast
->_AnyTextureCombine
)
3615 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
3618 * Must do all texture sampling before combining in order to
3619 * accomodate GL_ARB_texture_env_crossbar.
3621 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3622 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3623 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3624 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
3625 GLfloat
*lambda
= span
->array
->lambda
[unit
];
3626 GLchan (*texels
)[4] = (GLchan (*)[4])
3627 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
3629 /* adjust texture lod (lambda) */
3630 if (span
->arrayMask
| SPAN_LAMBDA
) {
3631 if (texUnit
->LodBias
!= 0.0F
) {
3632 /* apply LOD bias, but don't clamp yet */
3634 for (i
= 0; i
< span
->end
; i
++) {
3635 lambda
[i
] += texUnit
->LodBias
;
3639 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
3640 /* apply LOD clamping to lambda */
3641 const GLfloat min
= curObj
->MinLod
;
3642 const GLfloat max
= curObj
->MaxLod
;
3644 for (i
= 0; i
< span
->end
; i
++) {
3645 GLfloat l
= lambda
[i
];
3646 lambda
[i
] = CLAMP(l
, min
, max
);
3651 /* Sample the texture (span->end fragments) */
3652 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
,
3653 span
->end
, span
->array
->texcoords
[unit
],
3659 * OK, now apply the texture (aka texture combine/blend).
3660 * We modify the span->color.rgba values.
3662 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3663 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3664 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
3665 if (texUnit
->EnvMode
== GL_COMBINE_EXT
) {
3666 /* GL_ARB/EXT_texture_env_combine */
3667 texture_combine( ctx
, unit
, span
->end
,
3668 (CONST
GLchan (*)[4]) primary_rgba
,
3669 swrast
->TexelBuffer
,
3670 span
->array
->rgba
);
3672 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
3673 /* GL_NV_texture_env_combine4 */
3674 texture_combine4( ctx
, unit
, span
->end
,
3675 (CONST
GLchan (*)[4]) primary_rgba
,
3676 swrast
->TexelBuffer
,
3677 span
->array
->rgba
);
3680 /* conventional texture blend */
3681 const GLchan (*texels
)[4] = (const GLchan (*)[4])
3682 (swrast
->TexelBuffer
+ unit
*
3683 (span
->end
* 4 * sizeof(GLchan
)));
3684 texture_apply( ctx
, texUnit
, span
->end
,
3685 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
3686 span
->array
->rgba
);