1 /* $Id: s_texture.c,v 1.52 2002/02/16 23:44:46 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include "texformat.h"
37 #include "s_context.h"
38 #include "s_texture.h"
42 * These values are used in the fixed-point arithmetic used
43 * for linear filtering.
45 #define WEIGHT_SCALE 65536.0F
46 #define WEIGHT_SHIFT 16
50 * Used to compute texel locations for linear sampling.
52 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB
53 * S = texcoord in [0,1]
54 * SIZE = width (or height or depth) of texture
56 * U = texcoord in [0, width]
57 * I0, I1 = two nearest texel indexes
59 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
61 if (wrapMode == GL_REPEAT) { \
62 U = S * SIZE - 0.5F; \
63 I0 = IFLOOR(U) & (SIZE - 1); \
64 I1 = (I0 + 1) & (SIZE - 1); \
66 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
78 if (I1 >= (GLint) SIZE) \
81 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
82 const GLfloat min = -1.0F / (2.0F * SIZE); \
83 const GLfloat max = 1.0F - min; \
94 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
95 const GLint flr = IFLOOR(S); \
97 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
99 U = S - (GLfloat) flr; /* flr is even */ \
104 if (I1 >= (GLint) SIZE) \
108 ASSERT(wrapMode == GL_CLAMP); \
111 else if (S >= 1.0F) \
112 U = (GLfloat) SIZE; \
123 * Used to compute texel location for nearest sampling.
125 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
127 if (wrapMode == GL_REPEAT) { \
128 /* s limited to [0,1) */ \
129 /* i limited to [0,size-1] */ \
130 I = IFLOOR(S * SIZE); \
133 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
134 /* s limited to [min,max] */ \
135 /* i limited to [0, size-1] */ \
136 const GLfloat min = 1.0F / (2.0F * SIZE); \
137 const GLfloat max = 1.0F - min; \
143 I = IFLOOR(S * SIZE); \
145 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
146 /* s limited to [min,max] */ \
147 /* i limited to [-1, size] */ \
148 const GLfloat min = -1.0F / (2.0F * SIZE); \
149 const GLfloat max = 1.0F - min; \
155 I = IFLOOR(S * SIZE); \
157 else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \
158 const GLfloat min = 1.0F / (2.0F * SIZE); \
159 const GLfloat max = 1.0F - min; \
160 const GLint flr = IFLOOR(S); \
163 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
165 u = S - (GLfloat) flr; /* flr is even */ \
171 I = IFLOOR(u * SIZE); \
174 ASSERT(wrapMode == GL_CLAMP); \
175 /* s limited to [0,1] */ \
176 /* i limited to [0,size-1] */ \
179 else if (S >= 1.0F) \
182 I = IFLOOR(S * SIZE); \
188 * Compute linear mipmap levels for given lambda.
190 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
194 else if (lambda > tObj->_MaxLambda) \
195 lambda = tObj->_MaxLambda; \
196 level = (GLint) (tObj->BaseLevel + lambda); \
201 * Compute nearest mipmap level for given lambda.
203 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
205 if (lambda <= 0.5F) \
207 else if (lambda > tObj->_MaxLambda + 0.4999F) \
208 lambda = tObj->_MaxLambda + 0.4999F; \
209 level = (GLint) (tObj->BaseLevel + lambda + 0.5F); \
210 if (level > tObj->_MaxLevel) \
211 level = tObj->_MaxLevel; \
217 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
218 * see 1-pixel bands of improperly weighted linear-sampled texels. The
219 * tests/texwrap.c demo is a good test.
220 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
221 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
223 #define FRAC(f) ((f) - IFLOOR(f))
228 * Bitflags for texture border color sampling.
240 * Get texture palette entry.
243 palette_sample(const GLcontext
*ctx
,
244 const struct gl_texture_object
*tObj
,
245 GLint index
, GLchan rgba
[4] )
247 const GLchan
*palette
;
250 if (ctx
->Texture
.SharedPalette
) {
251 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
252 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
253 format
= ctx
->Texture
.Palette
.Format
;
256 ASSERT(!tObj
->Palette
.FloatTable
);
257 palette
= (const GLchan
*) tObj
->Palette
.Table
;
258 format
= tObj
->Palette
.Format
;
263 rgba
[ACOMP
] = palette
[index
];
267 rgba
[RCOMP
] = palette
[index
];
269 case GL_LUMINANCE_ALPHA
:
270 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
271 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
274 rgba
[RCOMP
] = palette
[index
* 3 + 0];
275 rgba
[GCOMP
] = palette
[index
* 3 + 1];
276 rgba
[BCOMP
] = palette
[index
* 3 + 2];
279 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
280 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
281 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
282 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
285 _mesa_problem(ctx
, "Bad palette format in palette_sample");
291 /**********************************************************************/
292 /* 1-D Texture Sampling Functions */
293 /**********************************************************************/
296 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
299 sample_1d_nearest(GLcontext
*ctx
,
300 const struct gl_texture_object
*tObj
,
301 const struct gl_texture_image
*img
,
302 const GLfloat texcoord
[4], GLchan rgba
[4])
304 const GLint width
= img
->Width2
; /* without border, power of two */
307 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
309 /* skip over the border, if any */
312 if (i
< 0 || i
>= (GLint
) img
->Width
) {
313 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
314 COPY_CHAN4(rgba
, tObj
->BorderColor
);
317 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
318 if (img
->Format
== GL_COLOR_INDEX
) {
319 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
327 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
330 sample_1d_linear(GLcontext
*ctx
,
331 const struct gl_texture_object
*tObj
,
332 const struct gl_texture_image
*img
,
333 const GLfloat texcoord
[4], GLchan rgba
[4])
335 const GLint width
= img
->Width2
;
338 GLuint useBorderColor
;
340 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
348 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
349 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
353 const GLfloat a
= FRAC(u
);
355 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
356 const GLfloat w0
= (1.0F
-a
);
357 const GLfloat w1
= a
;
358 #else /* CHAN_BITS == 8 */
359 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
360 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
361 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
363 GLchan t0
[4], t1
[4]; /* texels */
365 if (useBorderColor
& I0BIT
) {
366 COPY_CHAN4(t0
, tObj
->BorderColor
);
369 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
370 if (img
->Format
== GL_COLOR_INDEX
) {
371 palette_sample(ctx
, tObj
, t0
[0], t0
);
374 if (useBorderColor
& I1BIT
) {
375 COPY_CHAN4(t1
, tObj
->BorderColor
);
378 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
379 if (img
->Format
== GL_COLOR_INDEX
) {
380 palette_sample(ctx
, tObj
, t1
[0], t1
);
384 #if CHAN_TYPE == GL_FLOAT
385 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
386 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
387 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
388 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
389 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
390 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
391 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
392 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
393 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
394 #else /* CHAN_BITS == 8 */
395 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
396 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
397 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
398 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
406 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
407 const struct gl_texture_object
*tObj
,
408 const GLfloat texcoord
[4], GLfloat lambda
,
412 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
413 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
, rgba
);
418 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
419 const struct gl_texture_object
*tObj
,
420 const GLfloat texcoord
[4], GLfloat lambda
,
424 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
425 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
, rgba
);
431 * This is really just needed in order to prevent warnings with some compilers.
433 #if CHAN_TYPE == GL_FLOAT
436 #define INTCAST (GLint)
441 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
442 const struct gl_texture_object
*tObj
,
443 const GLfloat texcoord
[4], GLfloat lambda
,
448 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
450 if (level
>= tObj
->_MaxLevel
) {
451 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], texcoord
, rgba
);
455 const GLfloat f
= FRAC(lambda
);
456 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
, t0
);
457 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
, t1
);
458 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
459 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
460 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
461 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
468 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
469 const struct gl_texture_object
*tObj
,
470 const GLfloat texcoord
[4], GLfloat lambda
,
475 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
477 if (level
>= tObj
->_MaxLevel
) {
478 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], texcoord
, rgba
);
482 const GLfloat f
= FRAC(lambda
);
483 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
, t0
);
484 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
, t1
);
485 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
486 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
487 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
488 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
495 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
496 const struct gl_texture_object
*tObj
, GLuint n
,
497 GLfloat texcoords
[][4], const GLfloat lambda
[],
501 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
504 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
511 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
512 const struct gl_texture_object
*tObj
, GLuint n
,
513 GLfloat texcoords
[][4], const GLfloat lambda
[],
517 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
520 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
526 * Given an (s) texture coordinate and lambda (level of detail) value,
527 * return a texture sample.
531 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
532 const struct gl_texture_object
*tObj
, GLuint n
,
533 GLfloat texcoords
[][4],
534 const GLfloat lambda
[], GLchan rgba
[][4] )
536 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
540 if (lambda
[i
] > MinMagThresh
) {
542 switch (tObj
->MinFilter
) {
544 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
545 texcoords
[i
], rgba
[i
]);
548 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
549 texcoords
[i
], rgba
[i
]);
551 case GL_NEAREST_MIPMAP_NEAREST
:
552 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
555 case GL_LINEAR_MIPMAP_NEAREST
:
556 sample_1d_linear_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
559 case GL_NEAREST_MIPMAP_LINEAR
:
560 sample_1d_nearest_mipmap_linear(ctx
, tObj
, texcoords
[i
],
563 case GL_LINEAR_MIPMAP_LINEAR
:
564 sample_1d_linear_mipmap_linear(ctx
, tObj
, texcoords
[i
],
568 _mesa_problem(NULL
, "Bad min filter in sample_1d_texture");
574 switch (tObj
->MagFilter
) {
576 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
577 texcoords
[i
], rgba
[i
]);
580 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
581 texcoords
[i
], rgba
[i
]);
584 _mesa_problem(NULL
, "Bad mag filter in sample_1d_texture");
594 /**********************************************************************/
595 /* 2-D Texture Sampling Functions */
596 /**********************************************************************/
600 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
603 sample_2d_nearest(GLcontext
*ctx
,
604 const struct gl_texture_object
*tObj
,
605 const struct gl_texture_image
*img
,
606 const GLfloat texcoord
[4],
609 const GLint width
= img
->Width2
; /* without border, power of two */
610 const GLint height
= img
->Height2
; /* without border, power of two */
613 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
614 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
616 /* skip over the border, if any */
620 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
621 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
622 COPY_CHAN4(rgba
, tObj
->BorderColor
);
625 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
626 if (img
->Format
== GL_COLOR_INDEX
) {
627 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
635 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
636 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
639 sample_2d_linear(GLcontext
*ctx
,
640 const struct gl_texture_object
*tObj
,
641 const struct gl_texture_image
*img
,
642 const GLfloat texcoord
[4],
645 const GLint width
= img
->Width2
;
646 const GLint height
= img
->Height2
;
647 GLint i0
, j0
, i1
, j1
;
648 GLuint useBorderColor
;
651 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
652 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
662 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
663 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
664 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
665 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
669 const GLfloat a
= FRAC(u
);
670 const GLfloat b
= FRAC(v
);
672 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
673 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
674 const GLfloat w10
= a
* (1.0F
-b
);
675 const GLfloat w01
= (1.0F
-a
) * b
;
676 const GLfloat w11
= a
* b
;
677 #else /* CHAN_BITS == 8 */
678 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
679 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
680 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
681 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
682 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
689 if (useBorderColor
& (I0BIT
| J0BIT
)) {
690 COPY_CHAN4(t00
, tObj
->BorderColor
);
693 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
694 if (img
->Format
== GL_COLOR_INDEX
) {
695 palette_sample(ctx
, tObj
, t00
[0], t00
);
698 if (useBorderColor
& (I1BIT
| J0BIT
)) {
699 COPY_CHAN4(t10
, tObj
->BorderColor
);
702 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
703 if (img
->Format
== GL_COLOR_INDEX
) {
704 palette_sample(ctx
, tObj
, t10
[0], t10
);
707 if (useBorderColor
& (I0BIT
| J1BIT
)) {
708 COPY_CHAN4(t01
, tObj
->BorderColor
);
711 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
712 if (img
->Format
== GL_COLOR_INDEX
) {
713 palette_sample(ctx
, tObj
, t01
[0], t01
);
716 if (useBorderColor
& (I1BIT
| J1BIT
)) {
717 COPY_CHAN4(t11
, tObj
->BorderColor
);
720 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
721 if (img
->Format
== GL_COLOR_INDEX
) {
722 palette_sample(ctx
, tObj
, t11
[0], t11
);
725 #if CHAN_TYPE == GL_FLOAT
726 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
727 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
728 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
729 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
730 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
731 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
732 w01
* t01
[0] + w11
* t11
[0] + 0.5);
733 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
734 w01
* t01
[1] + w11
* t11
[1] + 0.5);
735 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
736 w01
* t01
[2] + w11
* t11
[2] + 0.5);
737 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
738 w01
* t01
[3] + w11
* t11
[3] + 0.5);
739 #else /* CHAN_BITS == 8 */
740 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
741 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
742 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
743 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
744 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
745 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
746 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
747 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
757 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
758 const struct gl_texture_object
*tObj
,
759 const GLfloat texcoord
[4], GLfloat lambda
,
763 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
764 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
, rgba
);
770 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
771 const struct gl_texture_object
*tObj
,
772 const GLfloat texcoord
[4], GLfloat lambda
,
776 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
777 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
, rgba
);
783 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
784 const struct gl_texture_object
*tObj
,
785 const GLfloat texcoord
[4], GLfloat lambda
,
790 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
792 if (level
>= tObj
->_MaxLevel
) {
793 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], texcoord
, rgba
);
796 GLchan t0
[4], t1
[4]; /* texels */
797 const GLfloat f
= FRAC(lambda
);
798 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
, t0
);
799 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
, t1
);
800 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
801 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
802 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
803 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
810 sample_2d_linear_mipmap_linear(GLcontext
*ctx
,
811 const struct gl_texture_object
*tObj
,
812 const GLfloat texcoord
[4], GLfloat lambda
,
817 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
819 if (level
>= tObj
->_MaxLevel
) {
820 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], texcoord
, rgba
);
823 GLchan t0
[4], t1
[4]; /* texels */
824 const GLfloat f
= FRAC(lambda
);
825 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
, t0
);
826 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
, t1
);
827 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
828 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
829 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
830 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
837 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
838 const struct gl_texture_object
*tObj
, GLuint n
,
839 GLfloat texcoords
[][4],
840 const GLfloat lambda
[], GLchan rgba
[][4] )
843 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
846 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
853 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
854 const struct gl_texture_object
*tObj
, GLuint n
,
855 GLfloat texcoords
[][4],
856 const GLfloat lambda
[], GLchan rgba
[][4] )
859 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
862 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
868 * Optimized 2-D texture sampling:
869 * S and T wrap mode == GL_REPEAT
870 * GL_NEAREST min/mag filter
875 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
876 const struct gl_texture_object
*tObj
,
877 GLuint n
, GLfloat texcoords
[][4],
878 const GLfloat lambda
[], GLchan rgba
[][4] )
880 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
881 const GLfloat width
= (GLfloat
) img
->Width
;
882 const GLfloat height
= (GLfloat
) img
->Height
;
883 const GLint colMask
= img
->Width
- 1;
884 const GLint rowMask
= img
->Height
- 1;
885 const GLint shift
= img
->WidthLog2
;
888 ASSERT(tObj
->WrapS
==GL_REPEAT
);
889 ASSERT(tObj
->WrapT
==GL_REPEAT
);
890 ASSERT(img
->Border
==0);
891 ASSERT(img
->Format
==GL_RGB
);
893 for (k
=0; k
<n
; k
++) {
894 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
895 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
896 GLint pos
= (j
<< shift
) | i
;
897 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
898 rgba
[k
][RCOMP
] = texel
[0];
899 rgba
[k
][GCOMP
] = texel
[1];
900 rgba
[k
][BCOMP
] = texel
[2];
906 * Optimized 2-D texture sampling:
907 * S and T wrap mode == GL_REPEAT
908 * GL_NEAREST min/mag filter
913 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
914 const struct gl_texture_object
*tObj
,
915 GLuint n
, GLfloat texcoords
[][4],
916 const GLfloat lambda
[], GLchan rgba
[][4] )
918 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
919 const GLfloat width
= (GLfloat
) img
->Width
;
920 const GLfloat height
= (GLfloat
) img
->Height
;
921 const GLint colMask
= img
->Width
- 1;
922 const GLint rowMask
= img
->Height
- 1;
923 const GLint shift
= img
->WidthLog2
;
926 ASSERT(tObj
->WrapS
==GL_REPEAT
);
927 ASSERT(tObj
->WrapT
==GL_REPEAT
);
928 ASSERT(img
->Border
==0);
929 ASSERT(img
->Format
==GL_RGBA
);
931 for (i
= 0; i
< n
; i
++) {
932 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
933 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
934 const GLint pos
= (row
<< shift
) | col
;
935 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
936 COPY_CHAN4(rgba
[i
], texel
);
942 span_is_monotonous (GLuint n
, const GLfloat lambda
[])
946 if (n
<= 1) /* array too short */
948 else if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
949 for (i
=0; i
<n
-1; i
++)
950 if (lambda
[i
] < lambda
[i
+1])
953 else { /* increasing */
954 for (i
=0; i
<n
-1; i
++)
955 if (lambda
[i
] > lambda
[i
+1])
964 * Given an array of (s,t) texture coordinate and lambda (level of detail)
965 * values, return an array of texture sample.
968 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
969 const struct gl_texture_object
*tObj
,
970 GLuint n
, GLfloat texcoords
[][4],
971 const GLfloat lambda
[], GLchan rgba
[][4] )
973 const GLfloat minMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
977 ASSERT (span_is_monotonous(n
, lambda
) == GL_TRUE
);
980 /* since lambda is monotonous-array use this check first */
981 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
982 /* magnification for whole span */
983 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
984 switch (tObj
->MagFilter
) {
986 if (tObj
->WrapS
== GL_REPEAT
&& tObj
->WrapT
== GL_REPEAT
&&
988 switch (img
->Format
) {
990 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, n
, texcoords
,
994 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, n
, texcoords
,
998 sample_nearest_2d(ctx
, texUnit
, tObj
, n
, texcoords
,
1003 sample_nearest_2d(ctx
, texUnit
, tObj
, n
, texcoords
,
1008 sample_linear_2d(ctx
, texUnit
, tObj
, n
, texcoords
,
1012 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_2d");
1016 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1017 for (i
= 0; i
< n
; i
++) {
1018 if (lambda
[i
] > minMagThresh
) {
1020 switch (tObj
->MinFilter
) {
1022 sample_2d_nearest(ctx
, tObj
, tImg
, texcoords
[i
], rgba
[i
]);
1025 sample_2d_linear(ctx
, tObj
, tImg
, texcoords
[i
], rgba
[i
]);
1027 case GL_NEAREST_MIPMAP_NEAREST
:
1028 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
1029 lambda
[i
], rgba
[i
]);
1031 case GL_LINEAR_MIPMAP_NEAREST
:
1032 sample_2d_linear_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
1033 lambda
[i
], rgba
[i
]);
1035 case GL_NEAREST_MIPMAP_LINEAR
:
1036 sample_2d_nearest_mipmap_linear(ctx
, tObj
, texcoords
[i
],
1037 lambda
[i
], rgba
[i
]);
1039 case GL_LINEAR_MIPMAP_LINEAR
:
1040 sample_2d_linear_mipmap_linear(ctx
, tObj
, texcoords
[i
],
1041 lambda
[i
], rgba
[i
] );
1044 _mesa_problem(NULL
, "Bad min filter in sample_2d_texture");
1050 switch (tObj
->MagFilter
) {
1052 sample_2d_nearest(ctx
, tObj
, tImg
, texcoords
[i
], rgba
[i
]);
1055 sample_2d_linear(ctx
, tObj
, tImg
, texcoords
[i
], rgba
[i
] );
1058 _mesa_problem(NULL
, "Bad mag filter in sample_2d_texture");
1067 /**********************************************************************/
1068 /* 3-D Texture Sampling Functions */
1069 /**********************************************************************/
1072 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1075 sample_3d_nearest(GLcontext
*ctx
,
1076 const struct gl_texture_object
*tObj
,
1077 const struct gl_texture_image
*img
,
1078 const GLfloat texcoord
[4],
1081 const GLint width
= img
->Width2
; /* without border, power of two */
1082 const GLint height
= img
->Height2
; /* without border, power of two */
1083 const GLint depth
= img
->Depth2
; /* without border, power of two */
1086 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1087 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1088 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1090 if (i
< 0 || i
>= (GLint
) img
->Width
||
1091 j
< 0 || j
>= (GLint
) img
->Height
||
1092 k
< 0 || k
>= (GLint
) img
->Depth
) {
1093 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1094 COPY_CHAN4(rgba
, tObj
->BorderColor
);
1097 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1098 if (img
->Format
== GL_COLOR_INDEX
) {
1099 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1107 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1110 sample_3d_linear(GLcontext
*ctx
,
1111 const struct gl_texture_object
*tObj
,
1112 const struct gl_texture_image
*img
,
1113 const GLfloat texcoord
[4],
1116 const GLint width
= img
->Width2
;
1117 const GLint height
= img
->Height2
;
1118 const GLint depth
= img
->Depth2
;
1119 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1120 GLuint useBorderColor
;
1123 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1124 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1125 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1137 /* check if sampling texture border color */
1138 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1139 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1140 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1141 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1142 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1143 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1147 const GLfloat a
= FRAC(u
);
1148 const GLfloat b
= FRAC(v
);
1149 const GLfloat c
= FRAC(w
);
1151 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1152 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1153 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1154 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1155 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1156 GLfloat w110
= a
* b
* (1.0F
-c
);
1157 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1158 GLfloat w101
= a
* (1.0F
-b
) * c
;
1159 GLfloat w011
= (1.0F
-a
) * b
* c
;
1160 GLfloat w111
= a
* b
* c
;
1161 #else /* CHAN_BITS == 8 */
1162 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1163 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1164 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1165 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1166 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1167 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1168 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1169 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1170 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1173 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1174 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1176 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1177 COPY_CHAN4(t000
, tObj
->BorderColor
);
1180 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1181 if (img
->Format
== GL_COLOR_INDEX
) {
1182 palette_sample(ctx
, tObj
, t000
[0], t000
);
1185 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1186 COPY_CHAN4(t100
, tObj
->BorderColor
);
1189 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1190 if (img
->Format
== GL_COLOR_INDEX
) {
1191 palette_sample(ctx
, tObj
, t100
[0], t100
);
1194 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1195 COPY_CHAN4(t010
, tObj
->BorderColor
);
1198 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1199 if (img
->Format
== GL_COLOR_INDEX
) {
1200 palette_sample(ctx
, tObj
, t010
[0], t010
);
1203 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1204 COPY_CHAN4(t110
, tObj
->BorderColor
);
1207 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1208 if (img
->Format
== GL_COLOR_INDEX
) {
1209 palette_sample(ctx
, tObj
, t110
[0], t110
);
1213 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1214 COPY_CHAN4(t001
, tObj
->BorderColor
);
1217 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1218 if (img
->Format
== GL_COLOR_INDEX
) {
1219 palette_sample(ctx
, tObj
, t001
[0], t001
);
1222 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1223 COPY_CHAN4(t101
, tObj
->BorderColor
);
1226 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1227 if (img
->Format
== GL_COLOR_INDEX
) {
1228 palette_sample(ctx
, tObj
, t101
[0], t101
);
1231 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1232 COPY_CHAN4(t011
, tObj
->BorderColor
);
1235 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1236 if (img
->Format
== GL_COLOR_INDEX
) {
1237 palette_sample(ctx
, tObj
, t011
[0], t011
);
1240 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1241 COPY_CHAN4(t111
, tObj
->BorderColor
);
1244 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1245 if (img
->Format
== GL_COLOR_INDEX
) {
1246 palette_sample(ctx
, tObj
, t111
[0], t111
);
1250 #if CHAN_TYPE == GL_FLOAT
1251 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1252 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1253 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1254 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1255 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1256 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1257 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1258 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1259 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1260 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1261 w001
*t001
[0] + w011
*t011
[0] +
1262 w100
*t100
[0] + w110
*t110
[0] +
1263 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1264 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1265 w001
*t001
[1] + w011
*t011
[1] +
1266 w100
*t100
[1] + w110
*t110
[1] +
1267 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1268 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1269 w001
*t001
[2] + w011
*t011
[2] +
1270 w100
*t100
[2] + w110
*t110
[2] +
1271 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1272 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1273 w001
*t001
[3] + w011
*t011
[3] +
1274 w100
*t100
[3] + w110
*t110
[3] +
1275 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1276 #else /* CHAN_BITS == 8 */
1277 rgba
[0] = (GLchan
) (
1278 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1279 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1281 rgba
[1] = (GLchan
) (
1282 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1283 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1285 rgba
[2] = (GLchan
) (
1286 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1287 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1289 rgba
[3] = (GLchan
) (
1290 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1291 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1301 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1302 const struct gl_texture_object
*tObj
,
1303 const GLfloat texcoord
[4],
1304 GLfloat lambda
, GLchan rgba
[4] )
1307 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1308 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
, rgba
);
1313 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1314 const struct gl_texture_object
*tObj
,
1315 const GLfloat texcoord
[4],
1316 GLfloat lambda
, GLchan rgba
[4])
1319 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1320 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
, rgba
);
1325 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1326 const struct gl_texture_object
*tObj
,
1327 const GLfloat texcoord
[4],
1328 GLfloat lambda
, GLchan rgba
[4])
1332 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1334 if (level
>= tObj
->_MaxLevel
) {
1335 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1339 GLchan t0
[4], t1
[4]; /* texels */
1340 const GLfloat f
= FRAC(lambda
);
1341 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
, t0
);
1342 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
, t1
);
1343 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1344 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1345 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1346 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1352 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1353 const struct gl_texture_object
*tObj
,
1354 const GLfloat texcoord
[4],
1355 GLfloat lambda
, GLchan rgba
[4] )
1359 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1361 if (level
>= tObj
->_MaxLevel
) {
1362 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], texcoord
, rgba
);
1365 GLchan t0
[4], t1
[4]; /* texels */
1366 const GLfloat f
= FRAC(lambda
);
1367 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
, t0
);
1368 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
, t1
);
1369 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1370 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1371 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1372 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1378 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1379 const struct gl_texture_object
*tObj
, GLuint n
,
1380 GLfloat texcoords
[][4], const GLfloat lambda
[],
1384 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1387 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1394 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1395 const struct gl_texture_object
*tObj
, GLuint n
,
1396 GLfloat texcoords
[][4],
1397 const GLfloat lambda
[], GLchan rgba
[][4] )
1400 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1403 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1409 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1410 * return a texture sample.
1413 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1414 const struct gl_texture_object
*tObj
, GLuint n
,
1415 GLfloat texcoords
[][4], const GLfloat lambda
[],
1419 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1423 if (lambda
[i
] > MinMagThresh
) {
1425 switch (tObj
->MinFilter
) {
1427 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1428 texcoords
[i
], rgba
[i
]);
1431 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1432 texcoords
[i
], rgba
[i
]);
1434 case GL_NEAREST_MIPMAP_NEAREST
:
1435 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
1436 lambda
[i
], rgba
[i
]);
1438 case GL_LINEAR_MIPMAP_NEAREST
:
1439 sample_3d_linear_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
1440 lambda
[i
], rgba
[i
]);
1442 case GL_NEAREST_MIPMAP_LINEAR
:
1443 sample_3d_nearest_mipmap_linear(ctx
, tObj
, texcoords
[i
],
1444 lambda
[i
], rgba
[i
]);
1446 case GL_LINEAR_MIPMAP_LINEAR
:
1447 sample_3d_linear_mipmap_linear(ctx
, tObj
, texcoords
[i
],
1448 lambda
[i
], rgba
[i
]);
1451 _mesa_problem(NULL
, "Bad min filterin sample_3d_texture");
1456 switch (tObj
->MagFilter
) {
1458 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1459 texcoords
[i
], rgba
[i
]);
1462 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1463 texcoords
[i
], rgba
[i
]);
1466 _mesa_problem(NULL
, "Bad mag filter in sample_3d_texture");
1473 /**********************************************************************/
1474 /* Texture Cube Map Sampling Functions */
1475 /**********************************************************************/
1478 * Choose one of six sides of a texture cube map given the texture
1479 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1482 static const struct gl_texture_image
**
1483 choose_cube_face(const struct gl_texture_object
*texObj
,
1484 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1488 direction target sc tc ma
1489 ---------- ------------------------------- --- --- ---
1490 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1491 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1492 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1493 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1494 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1495 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1497 const GLfloat rx
= texcoord
[0];
1498 const GLfloat ry
= texcoord
[1];
1499 const GLfloat rz
= texcoord
[2];
1500 const struct gl_texture_image
**imgArray
;
1501 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
1504 if (arx
> ary
&& arx
> arz
) {
1506 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
1512 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
1518 else if (ary
> arx
&& ary
> arz
) {
1520 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
1526 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
1534 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
1540 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
1547 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1548 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1554 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1555 const struct gl_texture_object
*tObj
, GLuint n
,
1556 GLfloat texcoords
[][4], const GLfloat lambda
[],
1561 for (i
= 0; i
< n
; i
++) {
1562 const struct gl_texture_image
**images
;
1563 GLfloat newCoord
[4];
1564 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1565 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1572 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1573 const struct gl_texture_object
*tObj
, GLuint n
,
1574 GLfloat texcoords
[][4],
1575 const GLfloat lambda
[], GLchan rgba
[][4])
1579 for (i
= 0; i
< n
; i
++) {
1580 const struct gl_texture_image
**images
;
1581 GLfloat newCoord
[4];
1582 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1583 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1590 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1591 const struct gl_texture_object
*tObj
,
1592 const GLfloat texcoord
[4],
1593 GLfloat lambda
, GLchan rgba
[4])
1595 const struct gl_texture_image
**images
;
1596 GLfloat newCoord
[4];
1599 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1601 images
= choose_cube_face(tObj
, texcoord
, newCoord
);
1602 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
);
1607 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1608 const struct gl_texture_object
*tObj
,
1609 const GLfloat texcoord
[4],
1610 GLfloat lambda
, GLchan rgba
[4])
1612 const struct gl_texture_image
**images
;
1613 GLfloat newCoord
[4];
1616 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1618 images
= choose_cube_face(tObj
, texcoord
, newCoord
);
1619 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
);
1624 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1625 const struct gl_texture_object
*tObj
,
1626 const GLfloat texcoord
[4],
1627 GLfloat lambda
, GLchan rgba
[4])
1629 const struct gl_texture_image
**images
;
1630 GLfloat newCoord
[4];
1633 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1635 images
= choose_cube_face(tObj
, texcoord
, newCoord
);
1637 if (level
>= tObj
->_MaxLevel
) {
1638 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
], newCoord
, rgba
);
1641 GLchan t0
[4], t1
[4]; /* texels */
1642 const GLfloat f
= FRAC(lambda
);
1643 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1644 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1645 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1646 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1647 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1648 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1654 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1655 const struct gl_texture_object
*tObj
,
1656 const GLfloat texcoord
[4],
1657 GLfloat lambda
, GLchan rgba
[4])
1659 const struct gl_texture_image
**images
;
1660 GLfloat newCoord
[4];
1663 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1665 images
= choose_cube_face(tObj
, texcoord
, newCoord
);
1667 if (level
>= tObj
->_MaxLevel
) {
1668 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
], newCoord
, rgba
);
1671 GLchan t0
[4], t1
[4];
1672 const GLfloat f
= FRAC(lambda
);
1673 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
1674 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1675 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1676 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1677 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1678 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1684 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1685 const struct gl_texture_object
*tObj
, GLuint n
,
1686 GLfloat texcoords
[][4], const GLfloat lambda
[],
1689 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1692 for (i
= 0; i
< n
; i
++) {
1693 if (lambda
[i
] > MinMagThresh
) {
1695 switch (tObj
->MinFilter
) {
1698 const struct gl_texture_image
**images
;
1699 GLfloat newCoord
[4];
1700 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1701 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1707 const struct gl_texture_image
**images
;
1708 GLfloat newCoord
[4];
1709 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1710 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1714 case GL_NEAREST_MIPMAP_NEAREST
:
1715 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
1716 lambda
[i
], rgba
[i
]);
1718 case GL_LINEAR_MIPMAP_NEAREST
:
1719 sample_cube_linear_mipmap_nearest(ctx
, tObj
, texcoords
[i
],
1720 lambda
[i
], rgba
[i
]);
1722 case GL_NEAREST_MIPMAP_LINEAR
:
1723 sample_cube_nearest_mipmap_linear(ctx
, tObj
, texcoords
[i
],
1724 lambda
[i
], rgba
[i
]);
1726 case GL_LINEAR_MIPMAP_LINEAR
:
1727 sample_cube_linear_mipmap_linear(ctx
, tObj
, texcoords
[i
],
1728 lambda
[i
], rgba
[i
]);
1731 _mesa_problem(NULL
, "Bad min filter in sample_lambda_cube");
1736 const struct gl_texture_image
**images
;
1737 GLfloat newCoord
[4];
1738 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1739 switch (tObj
->MagFilter
) {
1741 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1745 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1749 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_cube");
1757 * Sample a shadow/depth texture.
1760 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
1761 const struct gl_texture_object
*tObj
, GLuint n
,
1762 GLfloat texcoords
[][4], const GLfloat lambda
[],
1765 const GLint baseLevel
= tObj
->BaseLevel
;
1766 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
1767 const GLuint width
= texImage
->Width
;
1768 const GLuint height
= texImage
->Height
;
1769 const GLchan ambient
= tObj
->ShadowAmbient
;
1770 GLboolean lequal
, gequal
;
1775 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
1776 ASSERT(tObj
->Dimensions
== 1 || tObj
->Dimensions
== 2);
1778 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
1780 /* XXX this could be precomputed and saved in the texture object */
1781 if (tObj
->CompareFlag
) {
1782 /* GL_SGIX_shadow */
1783 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
1788 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
1793 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
1795 if (tObj
->CompareFunc
== GL_LEQUAL
) {
1800 ASSERT(tObj
->CompareFunc
== GL_GEQUAL
);
1806 lequal
= gequal
= GL_FALSE
;
1809 if (tObj
->MagFilter
== GL_NEAREST
) {
1811 for (i
= 0; i
< n
; i
++) {
1812 GLfloat depthSample
;
1814 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
1815 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
1816 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
1819 if (texcoords
[i
][2] <= depthSample
)
1825 if (texcoords
[i
][2] >= depthSample
)
1832 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
1835 switch (tObj
->DepthMode
) {
1837 texel
[i
][RCOMP
] = result
;
1838 texel
[i
][GCOMP
] = result
;
1839 texel
[i
][BCOMP
] = result
;
1840 texel
[i
][ACOMP
] = CHAN_MAX
;
1843 texel
[i
][RCOMP
] = result
;
1844 texel
[i
][GCOMP
] = result
;
1845 texel
[i
][BCOMP
] = result
;
1846 texel
[i
][ACOMP
] = result
;
1849 texel
[i
][RCOMP
] = 0;
1850 texel
[i
][GCOMP
] = 0;
1851 texel
[i
][BCOMP
] = 0;
1852 texel
[i
][ACOMP
] = result
;
1855 _mesa_problem(ctx
, "Bad depth texture mode");
1861 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
1862 for (i
= 0; i
< n
; i
++) {
1863 GLfloat depth00
, depth01
, depth10
, depth11
;
1864 GLint i0
, i1
, j0
, j1
;
1866 GLuint useBorderTexel
;
1868 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
1869 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
1872 if (texImage
->Border
) {
1873 i0
+= texImage
->Border
;
1874 i1
+= texImage
->Border
;
1875 j0
+= texImage
->Border
;
1876 j1
+= texImage
->Border
;
1879 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
1880 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
1881 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
1882 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
1885 /* get four depth samples from the texture */
1886 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
1890 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
1892 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
1896 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
1898 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
1902 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
1904 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
1908 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
1912 /* compute a single weighted depth sample and do one comparison */
1913 const GLfloat a
= FRAC(u
+ 1.0F
);
1914 const GLfloat b
= FRAC(v
+ 1.0F
);
1915 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
1916 const GLfloat w10
= ( a
) * (1.0F
- b
);
1917 const GLfloat w01
= (1.0F
- a
) * ( b
);
1918 const GLfloat w11
= ( a
) * ( b
);
1919 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
1920 + w01
* depth01
+ w11
* depth11
;
1921 if ((depthSample
<= texcoords
[i
][2] && lequal
) ||
1922 (depthSample
>= texcoords
[i
][2] && gequal
)) {
1930 /* Do four depth/R comparisons and compute a weighted result.
1931 * If this touches on somebody's I.P., I'll remove this code
1934 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
1935 GLfloat luminance
= CHAN_MAXF
;
1937 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
1938 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
1939 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
1940 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
1941 result
= (GLchan
) luminance
;
1944 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
1945 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
1946 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
1947 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
1948 result
= (GLchan
) luminance
;
1951 /* no comparison, just bilinear sampling */
1952 const GLfloat a
= FRAC(u
+ 1.0F
);
1953 const GLfloat b
= FRAC(v
+ 1.0F
);
1954 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
1955 const GLfloat w10
= ( a
) * (1.0F
- b
);
1956 const GLfloat w01
= (1.0F
- a
) * ( b
);
1957 const GLfloat w11
= ( a
) * ( b
);
1958 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
1959 + w01
* depth01
+ w11
* depth11
;
1960 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
1964 switch (tObj
->DepthMode
) {
1966 texel
[i
][RCOMP
] = result
;
1967 texel
[i
][GCOMP
] = result
;
1968 texel
[i
][BCOMP
] = result
;
1969 texel
[i
][ACOMP
] = CHAN_MAX
;
1972 texel
[i
][RCOMP
] = result
;
1973 texel
[i
][GCOMP
] = result
;
1974 texel
[i
][BCOMP
] = result
;
1975 texel
[i
][ACOMP
] = result
;
1978 texel
[i
][RCOMP
] = 0;
1979 texel
[i
][GCOMP
] = 0;
1980 texel
[i
][BCOMP
] = 0;
1981 texel
[i
][ACOMP
] = result
;
1984 _mesa_problem(ctx
, "Bad depth texture mode");
1993 * Experimental depth texture sampling function.
1996 sample_depth_texture2(const GLcontext
*ctx
,
1997 const struct gl_texture_unit
*texUnit
,
1998 GLuint n
, GLfloat texcoords
[][4],
2001 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2002 const GLint baseLevel
= texObj
->BaseLevel
;
2003 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2004 const GLuint width
= texImage
->Width
;
2005 const GLuint height
= texImage
->Height
;
2006 const GLchan ambient
= texObj
->ShadowAmbient
;
2007 GLboolean lequal
, gequal
;
2009 if (texObj
->Dimensions
!= 2) {
2010 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2014 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2015 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2019 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2020 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2021 * isn't a depth texture.
2023 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2024 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2028 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2039 for (i
= 0; i
< n
; i
++) {
2041 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2044 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2046 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2054 if (imin
< 0) imin
= 0;
2055 if (imax
>= width
) imax
= width
- 1;
2056 if (jmin
< 0) jmin
= 0;
2057 if (jmax
>= height
) jmax
= height
- 1;
2059 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2061 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2062 for (ii
= imin
; ii
<= imax
; ii
++) {
2063 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2065 if ((depthSample
<= r
[i
] && lequal
) ||
2066 (depthSample
>= r
[i
] && gequal
)) {
2072 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2073 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2076 texel
[i
][RCOMP
] = lum
;
2077 texel
[i
][GCOMP
] = lum
;
2078 texel
[i
][BCOMP
] = lum
;
2079 texel
[i
][ACOMP
] = CHAN_MAX
;
2087 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2088 const struct gl_texture_object
*tObj
, GLuint n
,
2089 GLfloat texcoords
[][4], const GLfloat lambda
[],
2096 /**********************************************************************/
2097 /* Texture Sampling Setup */
2098 /**********************************************************************/
2102 * Setup the texture sampling function for this texture object.
2105 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2106 const struct gl_texture_object
*t
)
2108 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2111 swrast
->TextureSample
[texUnit
] = null_sample_func
;
2114 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2115 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2118 /* Compute min/mag filter threshold */
2119 if (t
->MagFilter
== GL_LINEAR
2120 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
2121 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
2122 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
2125 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
2129 switch (t
->Dimensions
) {
2131 if (format
== GL_DEPTH_COMPONENT
) {
2132 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2134 else if (needLambda
) {
2135 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
2137 else if (t
->MinFilter
== GL_LINEAR
) {
2138 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
2141 ASSERT(t
->MinFilter
== GL_NEAREST
);
2142 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
2146 if (format
== GL_DEPTH_COMPONENT
) {
2147 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2149 else if (needLambda
) {
2150 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
2152 else if (t
->MinFilter
== GL_LINEAR
) {
2153 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
2156 GLint baseLevel
= t
->BaseLevel
;
2157 ASSERT(t
->MinFilter
== GL_NEAREST
);
2158 if (t
->WrapS
== GL_REPEAT
&&
2159 t
->WrapT
== GL_REPEAT
&&
2160 t
->Image
[baseLevel
]->Border
== 0 &&
2161 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2162 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
2164 else if (t
->WrapS
== GL_REPEAT
&&
2165 t
->WrapT
== GL_REPEAT
&&
2166 t
->Image
[baseLevel
]->Border
== 0 &&
2167 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2168 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
2171 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
2176 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
2178 else if (t
->MinFilter
== GL_LINEAR
) {
2179 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
2182 ASSERT(t
->MinFilter
== GL_NEAREST
);
2183 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
2186 case 6: /* cube map */
2188 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
2190 else if (t
->MinFilter
== GL_LINEAR
) {
2191 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
2194 ASSERT(t
->MinFilter
== GL_NEAREST
);
2195 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
2199 _mesa_problem(NULL
, "invalid dimensions in _mesa_set_texture_sampler");
2205 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
2206 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2209 texture_combine(const GLcontext
*ctx
,
2210 const struct gl_texture_unit
*textureUnit
,
2212 CONST
GLchan (*primary_rgba
)[4],
2213 CONST
GLchan (*texel
)[4],
2216 const GLchan (*argRGB
[3])[4];
2217 const GLchan (*argA
[3])[4];
2219 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
2220 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
2221 #if CHAN_TYPE == GL_FLOAT
2222 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
2223 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
2225 const GLint half
= (CHAN_MAX
+ 1) / 2;
2228 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
2229 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
2231 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
2232 ctx
->Extensions
.ARB_texture_env_combine
);
2235 * Do operand setup for up to 3 operands. Loop over the terms.
2237 for (j
= 0; j
< 3; j
++) {
2238 switch (textureUnit
->CombineSourceA
[j
]) {
2242 case GL_PRIMARY_COLOR_EXT
:
2243 argA
[j
] = primary_rgba
;
2245 case GL_PREVIOUS_EXT
:
2246 argA
[j
] = (const GLchan (*)[4]) rgba
;
2248 case GL_CONSTANT_EXT
:
2250 GLchan alpha
, (*c
)[4] = ccolor
[j
];
2251 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2252 for (i
= 0; i
< n
; i
++)
2253 c
[i
][ACOMP
] = alpha
;
2254 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2258 _mesa_problem(NULL
, "invalid combine source");
2261 switch (textureUnit
->CombineSourceRGB
[j
]) {
2265 case GL_PRIMARY_COLOR_EXT
:
2266 argRGB
[j
] = primary_rgba
;
2268 case GL_PREVIOUS_EXT
:
2269 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
2271 case GL_CONSTANT_EXT
:
2273 GLchan (*c
)[4] = ccolor
[j
];
2274 GLchan red
, green
, blue
, alpha
;
2275 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
2276 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
2277 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
2278 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
2279 for (i
= 0; i
< n
; i
++) {
2281 c
[i
][GCOMP
] = green
;
2283 c
[i
][ACOMP
] = alpha
;
2285 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2289 _mesa_problem(NULL
, "invalid combine source");
2292 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
2293 const GLchan (*src
)[4] = argRGB
[j
];
2294 GLchan (*dst
)[4] = ccolor
[j
];
2296 /* point to new arg[j] storage */
2297 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2299 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
2300 for (i
= 0; i
< n
; i
++) {
2301 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
2302 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
2303 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
2306 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
2307 for (i
= 0; i
< n
; i
++) {
2308 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
2309 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
2310 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
2314 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
2315 for (i
= 0; i
< n
; i
++) {
2316 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2317 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2318 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2323 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
2324 const GLchan (*src
)[4] = argA
[j
];
2325 GLchan (*dst
)[4] = ccolor
[j
];
2326 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
2327 for (i
= 0; i
< n
; i
++) {
2328 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
2332 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
2333 textureUnit
->CombineModeA
== GL_REPLACE
) {
2334 break; /* done, we need only arg0 */
2338 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
2339 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
2340 break; /* arg0 and arg1 are done. we don't need arg2. */
2345 * Do the texture combine.
2347 switch (textureUnit
->CombineModeRGB
) {
2350 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2352 for (i
= 0; i
< n
; i
++) {
2353 #if CHAN_TYPE == GL_FLOAT
2354 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
2355 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
2356 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
2358 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
2359 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
2360 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
2361 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2362 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2363 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2368 for (i
= 0; i
< n
; i
++) {
2369 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
2370 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
2371 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
2378 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2379 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2380 #if CHAN_TYPE != GL_FLOAT
2381 const GLint shift
= 8 - RGBshift
;
2383 for (i
= 0; i
< n
; i
++) {
2384 #if CHAN_TYPE == GL_FLOAT
2385 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
2386 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
2387 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
2389 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
2390 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
2391 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
2392 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2393 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2394 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2401 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2402 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2403 for (i
= 0; i
< n
; i
++) {
2404 #if CHAN_TYPE == GL_FLOAT
2405 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
2406 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
2407 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
2409 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2410 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2411 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2412 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2413 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2414 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2419 case GL_ADD_SIGNED_EXT
:
2421 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2422 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2423 for (i
= 0; i
< n
; i
++) {
2424 #if CHAN_TYPE == GL_FLOAT
2425 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
2426 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
2427 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
2429 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
2430 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
2431 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
2432 r
= (r
< 0) ? 0 : r
<< RGBshift
;
2433 g
= (g
< 0) ? 0 : g
<< RGBshift
;
2434 b
= (b
< 0) ? 0 : b
<< RGBshift
;
2435 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2436 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2437 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2442 case GL_INTERPOLATE_EXT
:
2444 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2445 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2446 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
2447 #if CHAN_TYPE != GL_FLOAT
2448 const GLint shift
= 8 - RGBshift
;
2450 for (i
= 0; i
< n
; i
++) {
2451 #if CHAN_TYPE == GL_FLOAT
2452 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
2453 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
2454 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
2455 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
2456 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
2457 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
2459 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
2460 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
2462 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
2463 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
2465 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
2466 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
2468 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2469 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2470 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2475 case GL_SUBTRACT_ARB
:
2477 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2478 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2479 for (i
= 0; i
< n
; i
++) {
2480 #if CHAN_TYPE == GL_FLOAT
2481 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
2482 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
2483 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
2485 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2486 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2487 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2488 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
2489 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
2490 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
2495 case GL_DOT3_RGB_ARB
:
2496 case GL_DOT3_RGBA_ARB
:
2498 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2499 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2500 /* ATI's EXT extension has a constant scale by 4. The ARB
2501 * one will likely remove this restriction, and we should
2502 * drop the EXT extension in favour of the ARB one.
2504 for (i
= 0; i
< n
; i
++) {
2505 #if CHAN_TYPE == GL_FLOAT
2506 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
2507 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
2508 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
2511 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
2512 (GLint
)arg1
[i
][RCOMP
] - half
) +
2513 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
2514 (GLint
)arg1
[i
][GCOMP
] - half
) +
2515 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
2516 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
2518 dot
= CLAMP(dot
, 0, CHAN_MAX
);
2519 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
2524 _mesa_problem(NULL
, "invalid combine mode");
2527 switch (textureUnit
->CombineModeA
) {
2530 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2532 for (i
= 0; i
< n
; i
++) {
2533 #if CHAN_TYPE == GL_FLOAT
2534 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
2536 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
2538 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2542 for (i
= 0; i
< n
; i
++) {
2543 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
2550 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2551 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2552 #if CHAN_TYPE != GL_FLOAT
2553 const GLint shift
= 8 - Ashift
;
2555 for (i
= 0; i
< n
; i
++) {
2556 #if CHAN_TYPE == GL_FLOAT
2557 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
2559 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
2560 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2567 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2568 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2569 for (i
= 0; i
< n
; i
++) {
2570 #if CHAN_TYPE == GL_FLOAT
2571 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
2573 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
2574 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2579 case GL_ADD_SIGNED_EXT
:
2581 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2582 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2583 for (i
= 0; i
< n
; i
++) {
2584 #if CHAN_TYPE == GL_FLOAT
2585 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
2587 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
2588 a
= (a
< 0) ? 0 : a
<< Ashift
;
2589 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2594 case GL_INTERPOLATE_EXT
:
2596 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2597 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2598 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
2599 #if CHAN_TYPE != GL_FLOAT
2600 const GLint shift
= 8 - Ashift
;
2602 for (i
=0; i
<n
; i
++) {
2603 #if CHAN_TYPE == GL_FLOAT
2604 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
2605 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
2608 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
2609 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
2611 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2616 case GL_SUBTRACT_ARB
:
2618 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2619 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2620 for (i
= 0; i
< n
; i
++) {
2621 #if CHAN_TYPE == GL_FLOAT
2622 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
2624 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << RGBshift
;
2625 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
2632 _mesa_problem(NULL
, "invalid combine mode");
2635 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2637 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
2638 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
2639 for (i
= 0; i
< n
; i
++) {
2640 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
2643 UNDEFARRAY(ccolor
); /* mac 32k limitation */
2649 /**********************************************************************/
2650 /* Texture Application */
2651 /**********************************************************************/
2655 * Combine incoming fragment color with texel color to produce output color.
2656 * Input: textureUnit - pointer to texture unit to apply
2657 * format - base internal texture format
2658 * n - number of fragments
2659 * primary_rgba - primary colors (may alias rgba for single texture)
2660 * texels - array of texel colors
2661 * InOut: rgba - incoming fragment colors modified by texel colors
2662 * according to the texture environment mode.
2665 apply_texture( const GLcontext
*ctx
,
2666 const struct gl_texture_unit
*texUnit
,
2668 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
2673 GLint Rc
, Gc
, Bc
, Ac
;
2677 ASSERT(texUnit
->_Current
);
2679 baseLevel
= texUnit
->_Current
->BaseLevel
;
2680 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
2682 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
2684 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
) {
2685 format
= GL_RGBA
; /* a bit of a hack */
2688 switch (texUnit
->EnvMode
) {
2695 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2701 GLchan Lt
= texel
[i
][RCOMP
];
2702 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2706 case GL_LUMINANCE_ALPHA
:
2708 GLchan Lt
= texel
[i
][RCOMP
];
2710 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2712 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2718 GLchan It
= texel
[i
][RCOMP
];
2719 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
2721 rgba
[i
][ACOMP
] = It
;
2727 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2728 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2729 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2736 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2737 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2738 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2740 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2744 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in apply_texture");
2755 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2761 GLchan Lt
= texel
[i
][RCOMP
];
2762 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2763 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2764 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2768 case GL_LUMINANCE_ALPHA
:
2771 GLchan Lt
= texel
[i
][RCOMP
];
2772 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2773 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2774 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2776 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2782 GLchan It
= texel
[i
][RCOMP
];
2783 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
2784 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
2785 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
2787 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
2793 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2794 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2795 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2802 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2803 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2804 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2806 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2810 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in apply_texture");
2819 case GL_LUMINANCE_ALPHA
:
2826 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2827 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2828 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2834 /* Cv = Cf(1-At) + CtAt */
2835 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
2836 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
2837 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
2838 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
2843 _mesa_problem(ctx
, "Bad format (GL_DECAL) in apply_texture");
2849 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
2850 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
2851 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
2852 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
2858 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2863 /* Cv = Cf(1-Lt) + CcLt */
2864 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2865 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2866 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2867 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2871 case GL_LUMINANCE_ALPHA
:
2873 /* Cv = Cf(1-Lt) + CcLt */
2874 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2875 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2876 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2877 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2879 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2884 /* Cv = Cf(1-It) + CcLt */
2885 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
2886 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
2887 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
2888 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
2889 /* Av = Af(1-It) + Ac*It */
2890 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
2895 /* Cv = Cf(1-Ct) + CcCt */
2896 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2897 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2898 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2904 /* Cv = Cf(1-Ct) + CcCt */
2905 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2906 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2907 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2909 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2913 _mesa_problem(ctx
, "Bad format (GL_BLEND) in apply_texture");
2918 /* XXX don't clamp results if GLchan is float??? */
2920 case GL_ADD
: /* GL_EXT_texture_add_env */
2927 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2932 GLuint Lt
= texel
[i
][RCOMP
];
2933 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2934 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2935 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2936 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2937 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2938 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2942 case GL_LUMINANCE_ALPHA
:
2944 GLuint Lt
= texel
[i
][RCOMP
];
2945 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2946 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2947 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2948 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2949 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2950 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2951 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2956 GLchan It
= texel
[i
][RCOMP
];
2957 GLuint r
= rgba
[i
][RCOMP
] + It
;
2958 GLuint g
= rgba
[i
][GCOMP
] + It
;
2959 GLuint b
= rgba
[i
][BCOMP
] + It
;
2960 GLuint a
= rgba
[i
][ACOMP
] + It
;
2961 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2962 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2963 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2964 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
2969 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2970 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2971 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2972 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2973 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2974 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2980 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2981 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2982 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2983 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2984 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2985 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2986 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2990 _mesa_problem(ctx
, "Bad format (GL_ADD) in apply_texture");
2995 case GL_COMBINE_EXT
:
2996 texture_combine(ctx
, texUnit
, n
, primary_rgba
, texel
, rgba
);
3000 _mesa_problem(ctx
, "Bad env mode in apply_texture");
3008 * Apply a unit of texture mapping to the incoming fragments.
3011 _swrast_texture_fragments( GLcontext
*ctx
, GLuint texUnit
, GLuint n
,
3012 GLfloat texcoords
[][4], GLfloat lambda
[],
3013 CONST GLchan primary_rgba
[][4],
3016 const GLuint mask
= TEXTURE0_ANY
<< (texUnit
* 4);
3018 if (ctx
->Texture
._ReallyEnabled
& mask
) {
3019 const struct gl_texture_unit
*textureUnit
= &ctx
->Texture
.Unit
[texUnit
];
3021 if (textureUnit
->_Current
) { /* XXX need this? */
3022 const struct gl_texture_object
*curObj
= textureUnit
->_Current
;
3023 GLchan texel
[MAX_WIDTH
][4];
3025 if (textureUnit
->LodBias
!= 0.0F
) {
3026 /* apply LOD bias, but don't clamp yet */
3029 lambda
[i
] += textureUnit
->LodBias
;
3033 if ((curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0)
3035 /* apply LOD clamping to lambda */
3036 const GLfloat min
= curObj
->MinLod
;
3037 const GLfloat max
= curObj
->MaxLod
;
3040 GLfloat l
= lambda
[i
];
3041 lambda
[i
] = CLAMP(l
, min
, max
);
3045 /* Sample the texture for n fragments */
3046 SWRAST_CONTEXT(ctx
)->TextureSample
[texUnit
]( ctx
, texUnit
,
3047 textureUnit
->_Current
,
3051 apply_texture( ctx
, textureUnit
, n
, primary_rgba
,
3052 (const GLchan (*)[4]) texel
, rgba
);
3059 * Apply multiple texture stages (or just unit 0) to the span.
3060 * At some point in the future we'll probably modify this so that
3061 * texels from any texture unit are available in any combiner unit.
3062 * That'll require doing all the texture sampling first, and then
3063 * all the application (blending) afterward.
3066 _swrast_multitexture_fragments( GLcontext
*ctx
, struct sw_span
*span
)
3068 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
3070 GLchan primary_rgba
[MAX_WIDTH
][4];
3073 ASSERT(span
->end
< MAX_WIDTH
);
3075 /* save copy of the span colors (the GL_PRIMARY_COLOR) */
3076 MEMCPY(primary_rgba
, span
->color
.rgba
, 4 * span
->end
* sizeof(GLchan
));
3078 /* loop over texture units, modifying the span->color.rgba values */
3079 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
3080 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
3081 _swrast_texture_fragments( ctx
, unit
, span
->end
,
3082 span
->texcoords
[unit
],
3083 (span
->arrayMask
& SPAN_LAMBDA
) ?
3084 span
->lambda
[unit
] : NULL
,
3085 (CONST
GLchan (*)[4]) primary_rgba
,
3091 /* Just unit 0 enabled */
3092 ASSERT(ctx
->Texture
._ReallyEnabled
& TEXTURE0_ANY
);
3094 _swrast_texture_fragments( ctx
, 0, span
->end
,
3096 (span
->arrayMask
& SPAN_LAMBDA
) ?
3097 span
->lambda
[0] : NULL
,
3098 (CONST
GLchan (*)[4]) span
->color
.rgba
,