1 /* $Id: s_texture.c,v 1.32 2001/06/01 13:23:27 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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"
39 #include "s_texture.h"
43 * These values are used in the fixed-point arithmetic used
44 * for linear filtering.
46 #define WEIGHT_SCALE 65536.0F
47 #define WEIGHT_SHIFT 16
51 * Used to compute texel locations for linear sampling.
53 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB
54 * S = texcoord in [0,1]
55 * SIZE = width (or height or depth) of texture
57 * U = texcoord in [0, width]
58 * I0, I1 = two nearest texel indexes
60 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
62 if (wrapMode == GL_REPEAT) { \
63 U = S * SIZE - 0.5F; \
64 I0 = IFLOOR(U) & (SIZE - 1); \
65 I1 = (I0 + 1) & (SIZE - 1); \
67 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
79 if (I1 >= (GLint) SIZE) \
82 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
83 const GLfloat min = -1.0F / (2.0F * SIZE); \
84 const GLfloat max = 1.0F - min; \
96 ASSERT(wrapMode == GL_CLAMP); \
111 * Used to compute texel location for nearest sampling.
113 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
115 if (wrapMode == GL_REPEAT) { \
116 /* s limited to [0,1) */ \
117 /* i limited to [0,size-1] */ \
118 I = IFLOOR(S * SIZE); \
121 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
122 /* s limited to [min,max] */ \
123 /* i limited to [0, size-1] */ \
124 const GLfloat min = 1.0F / (2.0F * SIZE); \
125 const GLfloat max = 1.0F - min; \
131 I = IFLOOR(S * SIZE); \
133 else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
134 /* s limited to [min,max] */ \
135 /* i limited to [-1, size] */ \
136 const GLfloat min = -1.0F / (2.0F * SIZE); \
137 const GLfloat max = 1.0F - min; \
143 I = IFLOOR(S * SIZE); \
146 ASSERT(wrapMode == GL_CLAMP); \
147 /* s limited to [0,1] */ \
148 /* i limited to [0,size-1] */ \
151 else if (S >= 1.0F) \
154 I = IFLOOR(S * SIZE); \
160 * Compute linear mipmap levels for given lambda.
162 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
166 else if (lambda > tObj->_MaxLambda) \
167 lambda = tObj->_MaxLambda; \
168 level = (GLint) (tObj->BaseLevel + lambda); \
173 * Compute nearest mipmap level for given lambda.
175 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
177 if (lambda <= 0.5F) \
179 else if (lambda > tObj->_MaxLambda + 0.4999F) \
180 lambda = tObj->_MaxLambda + 0.4999F; \
181 level = (GLint) (tObj->BaseLevel + lambda + 0.5F); \
182 if (level > tObj->_MaxLevel) \
183 level = tObj->_MaxLevel; \
189 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
190 * see 1-pixel bands of improperly weighted linear-sampled texels. The
191 * tests/texwrap.c demo is a good test.
192 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
193 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
195 #define FRAC(f) ((f) - IFLOOR(f))
200 * Bitflags for texture border color sampling.
212 * Get texture palette entry.
215 palette_sample(const GLcontext
*ctx
,
216 const struct gl_texture_object
*tObj
,
217 GLint index
, GLchan rgba
[4] )
219 const GLchan
*palette
;
222 if (ctx
->Texture
.SharedPalette
) {
223 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
224 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
225 format
= ctx
->Texture
.Palette
.Format
;
228 ASSERT(!tObj
->Palette
.FloatTable
);
229 palette
= (const GLchan
*) tObj
->Palette
.Table
;
230 format
= tObj
->Palette
.Format
;
235 rgba
[ACOMP
] = palette
[index
];
239 rgba
[RCOMP
] = palette
[index
];
241 case GL_LUMINANCE_ALPHA
:
242 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
243 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
246 rgba
[RCOMP
] = palette
[index
* 3 + 0];
247 rgba
[GCOMP
] = palette
[index
* 3 + 1];
248 rgba
[BCOMP
] = palette
[index
* 3 + 2];
251 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
252 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
253 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
254 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
257 _mesa_problem(ctx
, "Bad palette format in palette_sample");
263 /**********************************************************************/
264 /* 1-D Texture Sampling Functions */
265 /**********************************************************************/
268 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
271 sample_1d_nearest(GLcontext
*ctx
,
272 const struct gl_texture_object
*tObj
,
273 const struct gl_texture_image
*img
,
274 GLfloat s
, GLchan rgba
[4])
276 const GLint width
= img
->Width2
; /* without border, power of two */
279 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
281 /* skip over the border, if any */
284 if (i
< 0 || i
>= (GLint
) img
->Width
) {
285 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
286 COPY_CHAN4(rgba
, tObj
->BorderColor
);
289 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
290 if (img
->Format
== GL_COLOR_INDEX
) {
291 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
299 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
302 sample_1d_linear(GLcontext
*ctx
,
303 const struct gl_texture_object
*tObj
,
304 const struct gl_texture_image
*img
,
305 GLfloat s
, GLchan rgba
[4])
307 const GLint width
= img
->Width2
;
310 GLuint useBorderColor
;
312 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
320 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
321 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
325 const GLfloat a
= FRAC(u
);
328 const GLfloat w0
= (1.0F
-a
);
329 const GLfloat w1
= a
;
330 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
331 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
332 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
333 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
336 GLchan t0
[4], t1
[4]; /* texels */
338 if (useBorderColor
& I0BIT
) {
339 COPY_CHAN4(t0
, tObj
->BorderColor
);
342 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
343 if (img
->Format
== GL_COLOR_INDEX
) {
344 palette_sample(ctx
, tObj
, t0
[0], t0
);
347 if (useBorderColor
& I1BIT
) {
348 COPY_CHAN4(t1
, tObj
->BorderColor
);
351 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
352 if (img
->Format
== GL_COLOR_INDEX
) {
353 palette_sample(ctx
, tObj
, t1
[0], t1
);
358 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
359 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
360 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
361 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
362 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
363 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
364 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
365 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
366 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
374 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
375 const struct gl_texture_object
*tObj
,
376 GLfloat s
, GLfloat lambda
,
380 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
381 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, rgba
);
386 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
387 const struct gl_texture_object
*tObj
,
388 GLfloat s
, GLfloat lambda
,
392 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
393 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, rgba
);
399 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
400 const struct gl_texture_object
*tObj
,
401 GLfloat s
, GLfloat lambda
,
406 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
408 if (level
>= tObj
->_MaxLevel
) {
409 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, rgba
);
413 const GLfloat f
= FRAC(lambda
);
414 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t0
);
415 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t1
);
416 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
417 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
418 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
419 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
426 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
427 const struct gl_texture_object
*tObj
,
428 GLfloat s
, GLfloat lambda
,
433 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
435 if (level
>= tObj
->_MaxLevel
) {
436 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, rgba
);
440 const GLfloat f
= FRAC(lambda
);
441 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t0
);
442 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t1
);
443 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
444 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
445 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
446 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
453 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
454 const struct gl_texture_object
*tObj
, GLuint n
,
455 const GLfloat s
[], const GLfloat t
[],
456 const GLfloat u
[], const GLfloat lambda
[],
460 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
465 sample_1d_nearest(ctx
, tObj
, image
, s
[i
], rgba
[i
]);
472 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
473 const struct gl_texture_object
*tObj
, GLuint n
,
474 const GLfloat s
[], const GLfloat t
[],
475 const GLfloat u
[], const GLfloat lambda
[],
479 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
484 sample_1d_linear(ctx
, tObj
, image
, s
[i
], rgba
[i
]);
490 * Given an (s) texture coordinate and lambda (level of detail) value,
491 * return a texture sample.
495 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
496 const struct gl_texture_object
*tObj
, GLuint n
,
497 const GLfloat s
[], const GLfloat t
[],
498 const GLfloat u
[], const GLfloat lambda
[],
501 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
508 if (lambda
[i
] > MinMagThresh
) {
510 switch (tObj
->MinFilter
) {
512 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
516 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
519 case GL_NEAREST_MIPMAP_NEAREST
:
520 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, lambda
[i
], s
[i
],
523 case GL_LINEAR_MIPMAP_NEAREST
:
524 sample_1d_linear_mipmap_nearest(ctx
, tObj
, s
[i
], lambda
[i
],
527 case GL_NEAREST_MIPMAP_LINEAR
:
528 sample_1d_nearest_mipmap_linear(ctx
, tObj
, s
[i
], lambda
[i
],
531 case GL_LINEAR_MIPMAP_LINEAR
:
532 sample_1d_linear_mipmap_linear(ctx
, tObj
, s
[i
], lambda
[i
],
536 _mesa_problem(NULL
, "Bad min filter in sample_1d_texture");
542 switch (tObj
->MagFilter
) {
544 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
548 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
552 _mesa_problem(NULL
, "Bad mag filter in sample_1d_texture");
562 /**********************************************************************/
563 /* 2-D Texture Sampling Functions */
564 /**********************************************************************/
568 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
571 sample_2d_nearest(GLcontext
*ctx
,
572 const struct gl_texture_object
*tObj
,
573 const struct gl_texture_image
*img
,
574 GLfloat s
, GLfloat t
,
577 const GLint width
= img
->Width2
; /* without border, power of two */
578 const GLint height
= img
->Height2
; /* without border, power of two */
581 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
582 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, t
, height
, j
);
584 /* skip over the border, if any */
588 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
589 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
590 COPY_CHAN4(rgba
, tObj
->BorderColor
);
593 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
594 if (img
->Format
== GL_COLOR_INDEX
) {
595 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
603 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
604 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
607 sample_2d_linear(GLcontext
*ctx
,
608 const struct gl_texture_object
*tObj
,
609 const struct gl_texture_image
*img
,
610 GLfloat s
, GLfloat t
,
613 const GLint width
= img
->Width2
;
614 const GLint height
= img
->Height2
;
615 GLint i0
, j0
, i1
, j1
;
616 GLuint useBorderColor
;
619 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
620 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, t
, v
, height
, j0
, j1
);
630 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
631 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
632 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
633 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
637 const GLfloat a
= FRAC(u
);
638 const GLfloat b
= FRAC(v
);
641 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
642 const GLfloat w10
= a
* (1.0F
-b
);
643 const GLfloat w01
= (1.0F
-a
) * b
;
644 const GLfloat w11
= a
* b
;
645 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
646 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
647 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
648 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
649 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
650 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
658 if (useBorderColor
& (I0BIT
| J0BIT
)) {
659 COPY_CHAN4(t00
, tObj
->BorderColor
);
662 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
663 if (img
->Format
== GL_COLOR_INDEX
) {
664 palette_sample(ctx
, tObj
, t00
[0], t00
);
667 if (useBorderColor
& (I1BIT
| J0BIT
)) {
668 COPY_CHAN4(t10
, tObj
->BorderColor
);
671 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
672 if (img
->Format
== GL_COLOR_INDEX
) {
673 palette_sample(ctx
, tObj
, t10
[0], t10
);
676 if (useBorderColor
& (I0BIT
| J1BIT
)) {
677 COPY_CHAN4(t01
, tObj
->BorderColor
);
680 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
681 if (img
->Format
== GL_COLOR_INDEX
) {
682 palette_sample(ctx
, tObj
, t01
[0], t01
);
685 if (useBorderColor
& (I1BIT
| J1BIT
)) {
686 COPY_CHAN4(t11
, tObj
->BorderColor
);
689 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
690 if (img
->Format
== GL_COLOR_INDEX
) {
691 palette_sample(ctx
, tObj
, t11
[0], t11
);
695 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
696 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
697 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
698 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
699 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
700 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
701 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
702 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
703 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
713 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
714 const struct gl_texture_object
*tObj
,
715 GLfloat s
, GLfloat t
, GLfloat lambda
,
719 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
720 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, rgba
);
726 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
727 const struct gl_texture_object
*tObj
,
728 GLfloat s
, GLfloat t
, GLfloat lambda
,
732 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
733 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, rgba
);
739 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
740 const struct gl_texture_object
*tObj
,
741 GLfloat s
, GLfloat t
, GLfloat lambda
,
746 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
748 if (level
>= tObj
->_MaxLevel
) {
749 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, rgba
);
752 GLchan t0
[4], t1
[4]; /* texels */
753 const GLfloat f
= FRAC(lambda
);
754 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, t0
);
755 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, t1
);
756 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
757 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
758 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
759 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
766 sample_2d_linear_mipmap_linear(GLcontext
*ctx
,
767 const struct gl_texture_object
*tObj
,
768 GLfloat s
, GLfloat t
, GLfloat lambda
,
773 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
775 if (level
>= tObj
->_MaxLevel
) {
776 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, rgba
);
779 GLchan t0
[4], t1
[4]; /* texels */
780 const GLfloat f
= FRAC(lambda
);
781 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, t0
);
782 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, t1
);
783 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
784 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
785 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
786 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
793 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
794 const struct gl_texture_object
*tObj
, GLuint n
,
795 const GLfloat s
[], const GLfloat t
[],
796 const GLfloat u
[], const GLfloat lambda
[],
800 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
804 sample_2d_nearest(ctx
, tObj
, image
, s
[i
], t
[i
], rgba
[i
]);
811 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
812 const struct gl_texture_object
*tObj
, GLuint n
,
813 const GLfloat s
[], const GLfloat t
[],
814 const GLfloat u
[], const GLfloat lambda
[],
818 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
822 sample_2d_linear(ctx
, tObj
, image
, s
[i
], t
[i
], rgba
[i
]);
828 * Given an array of (s,t) texture coordinate and lambda (level of detail)
829 * values, return an array of texture sample.
832 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
833 const struct gl_texture_object
*tObj
,
835 const GLfloat s
[], const GLfloat t
[],
836 const GLfloat u
[], const GLfloat lambda
[],
839 const GLfloat minMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
843 /* since lambda is monotonous-array use this check first */
844 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
845 /* magnification for whole span */
846 switch (tObj
->MagFilter
) {
848 sample_nearest_2d(ctx
, texUnit
, tObj
, n
, s
, t
, u
,
852 sample_linear_2d(ctx
, texUnit
, tObj
, n
, s
, t
, u
,
856 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_2d");
860 for (i
= 0; i
< n
; i
++) {
861 if (lambda
[i
] > minMagThresh
) {
863 switch (tObj
->MinFilter
) {
865 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
866 s
[i
], t
[i
], rgba
[i
]);
869 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
870 s
[i
], t
[i
], rgba
[i
]);
872 case GL_NEAREST_MIPMAP_NEAREST
:
873 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
],
876 case GL_LINEAR_MIPMAP_NEAREST
:
877 sample_2d_linear_mipmap_nearest(ctx
,tObj
, s
[i
], t
[i
],
880 case GL_NEAREST_MIPMAP_LINEAR
:
881 sample_2d_nearest_mipmap_linear(ctx
,tObj
, s
[i
], t
[i
],
884 case GL_LINEAR_MIPMAP_LINEAR
:
885 sample_2d_linear_mipmap_linear(ctx
,tObj
, s
[i
], t
[i
],
886 lambda
[i
], rgba
[i
] );
889 _mesa_problem(NULL
, "Bad min filter in sample_2d_texture");
895 switch (tObj
->MagFilter
) {
897 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
898 s
[i
], t
[i
], rgba
[i
]);
901 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
902 s
[i
], t
[i
], rgba
[i
] );
905 _mesa_problem(NULL
, "Bad mag filter in sample_2d_texture");
914 * Optimized 2-D texture sampling:
915 * S and T wrap mode == GL_REPEAT
916 * GL_NEAREST min/mag filter
921 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
922 const struct gl_texture_object
*tObj
,
923 GLuint n
, const GLfloat s
[], const GLfloat t
[],
924 const GLfloat u
[], const GLfloat lambda
[],
927 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
928 const GLfloat width
= (GLfloat
) img
->Width
;
929 const GLfloat height
= (GLfloat
) img
->Height
;
930 const GLint colMask
= img
->Width
- 1;
931 const GLint rowMask
= img
->Height
- 1;
932 const GLint shift
= img
->WidthLog2
;
936 ASSERT(tObj
->WrapS
==GL_REPEAT
);
937 ASSERT(tObj
->WrapT
==GL_REPEAT
);
938 ASSERT(tObj
->MinFilter
==GL_NEAREST
);
939 ASSERT(tObj
->MagFilter
==GL_NEAREST
);
940 ASSERT(img
->Border
==0);
941 ASSERT(img
->Format
==GL_RGB
);
943 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
945 GLint i
= (GLint
) ((s
[k
] + 10000.0) * width
) & colMask
;
946 GLint j
= (GLint
) ((t
[k
] + 10000.0) * height
) & rowMask
;
947 GLint pos
= (j
<< shift
) | i
;
948 GLchan
*texel
= ((GLchan
*) img
->Data
) + pos
+ pos
+ pos
; /* pos*3 */
949 rgba
[k
][RCOMP
] = texel
[0];
950 rgba
[k
][GCOMP
] = texel
[1];
951 rgba
[k
][BCOMP
] = texel
[2];
957 * Optimized 2-D texture sampling:
958 * S and T wrap mode == GL_REPEAT
959 * GL_NEAREST min/mag filter
964 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
965 const struct gl_texture_object
*tObj
,
966 GLuint n
, const GLfloat s
[], const GLfloat t
[],
967 const GLfloat u
[], const GLfloat lambda
[],
970 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
971 const GLfloat width
= (GLfloat
) img
->Width
;
972 const GLfloat height
= (GLfloat
) img
->Height
;
973 const GLint colMask
= img
->Width
- 1;
974 const GLint rowMask
= img
->Height
- 1;
975 const GLint shift
= img
->WidthLog2
;
979 ASSERT(tObj
->WrapS
==GL_REPEAT
);
980 ASSERT(tObj
->WrapT
==GL_REPEAT
);
981 ASSERT(tObj
->MinFilter
==GL_NEAREST
);
982 ASSERT(tObj
->MagFilter
==GL_NEAREST
);
983 ASSERT(img
->Border
==0);
984 ASSERT(img
->Format
==GL_RGBA
);
986 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
988 GLint i
= (GLint
) ((s
[k
] + 10000.0) * width
) & colMask
;
989 GLint j
= (GLint
) ((t
[k
] + 10000.0) * height
) & rowMask
;
990 GLint pos
= (j
<< shift
) | i
;
991 GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
992 rgba
[k
][RCOMP
] = texel
[0];
993 rgba
[k
][GCOMP
] = texel
[1];
994 rgba
[k
][BCOMP
] = texel
[2];
995 rgba
[k
][ACOMP
] = texel
[3];
1001 /**********************************************************************/
1002 /* 3-D Texture Sampling Functions */
1003 /**********************************************************************/
1006 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1009 sample_3d_nearest(GLcontext
*ctx
,
1010 const struct gl_texture_object
*tObj
,
1011 const struct gl_texture_image
*img
,
1012 GLfloat s
, GLfloat t
, GLfloat r
,
1015 const GLint width
= img
->Width2
; /* without border, power of two */
1016 const GLint height
= img
->Height2
; /* without border, power of two */
1017 const GLint depth
= img
->Depth2
; /* without border, power of two */
1020 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
1021 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, t
, height
, j
);
1022 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, r
, depth
, k
);
1024 if (i
< 0 || i
>= (GLint
) img
->Width
||
1025 j
< 0 || j
>= (GLint
) img
->Height
||
1026 k
< 0 || k
>= (GLint
) img
->Depth
) {
1027 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1028 COPY_CHAN4(rgba
, tObj
->BorderColor
);
1031 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1032 if (img
->Format
== GL_COLOR_INDEX
) {
1033 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1041 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1044 sample_3d_linear(GLcontext
*ctx
,
1045 const struct gl_texture_object
*tObj
,
1046 const struct gl_texture_image
*img
,
1047 GLfloat s
, GLfloat t
, GLfloat r
,
1050 const GLint width
= img
->Width2
;
1051 const GLint height
= img
->Height2
;
1052 const GLint depth
= img
->Depth2
;
1053 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1054 GLuint useBorderColor
;
1057 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
1058 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, t
, v
, height
, j0
, j1
);
1059 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, r
, w
, depth
, k0
, k1
);
1071 /* check if sampling texture border color */
1072 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1073 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1074 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1075 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1076 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1077 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1081 const GLfloat a
= FRAC(u
);
1082 const GLfloat b
= FRAC(v
);
1083 const GLfloat c
= FRAC(w
);
1086 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1087 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1088 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1089 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1090 GLfloat w110
= a
* b
* (1.0F
-c
);
1091 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1092 GLfloat w101
= a
* (1.0F
-b
) * c
;
1093 GLfloat w011
= (1.0F
-a
) * b
* c
;
1094 GLfloat w111
= a
* b
* c
;
1095 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
1096 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1097 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1098 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1099 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1100 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1101 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1102 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1103 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1104 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1107 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1108 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1110 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1111 COPY_CHAN4(t000
, tObj
->BorderColor
);
1114 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1115 if (img
->Format
== GL_COLOR_INDEX
) {
1116 palette_sample(ctx
, tObj
, t000
[0], t000
);
1119 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1120 COPY_CHAN4(t100
, tObj
->BorderColor
);
1123 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1124 if (img
->Format
== GL_COLOR_INDEX
) {
1125 palette_sample(ctx
, tObj
, t100
[0], t100
);
1128 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1129 COPY_CHAN4(t010
, tObj
->BorderColor
);
1132 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1133 if (img
->Format
== GL_COLOR_INDEX
) {
1134 palette_sample(ctx
, tObj
, t010
[0], t010
);
1137 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1138 COPY_CHAN4(t110
, tObj
->BorderColor
);
1141 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1142 if (img
->Format
== GL_COLOR_INDEX
) {
1143 palette_sample(ctx
, tObj
, t110
[0], t110
);
1147 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1148 COPY_CHAN4(t001
, tObj
->BorderColor
);
1151 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1152 if (img
->Format
== GL_COLOR_INDEX
) {
1153 palette_sample(ctx
, tObj
, t001
[0], t001
);
1156 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1157 COPY_CHAN4(t101
, tObj
->BorderColor
);
1160 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1161 if (img
->Format
== GL_COLOR_INDEX
) {
1162 palette_sample(ctx
, tObj
, t101
[0], t101
);
1165 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1166 COPY_CHAN4(t011
, tObj
->BorderColor
);
1169 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1170 if (img
->Format
== GL_COLOR_INDEX
) {
1171 palette_sample(ctx
, tObj
, t011
[0], t011
);
1174 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1175 COPY_CHAN4(t111
, tObj
->BorderColor
);
1178 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1179 if (img
->Format
== GL_COLOR_INDEX
) {
1180 palette_sample(ctx
, tObj
, t111
[0], t111
);
1185 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1186 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1187 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1188 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1189 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1190 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1191 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1192 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1193 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
1194 rgba
[0] = (GLchan
) (
1195 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1196 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1198 rgba
[1] = (GLchan
) (
1199 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1200 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1202 rgba
[2] = (GLchan
) (
1203 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1204 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1206 rgba
[3] = (GLchan
) (
1207 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1208 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1218 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1219 const struct gl_texture_object
*tObj
,
1220 GLfloat s
, GLfloat t
, GLfloat r
,
1221 GLfloat lambda
, GLchan rgba
[4] )
1224 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1225 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, rgba
);
1230 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1231 const struct gl_texture_object
*tObj
,
1232 GLfloat s
, GLfloat t
, GLfloat r
,
1233 GLfloat lambda
, GLchan rgba
[4])
1236 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1237 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, rgba
);
1242 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1243 const struct gl_texture_object
*tObj
,
1244 GLfloat s
, GLfloat t
, GLfloat r
,
1245 GLfloat lambda
, GLchan rgba
[4])
1249 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1251 if (level
>= tObj
->_MaxLevel
) {
1252 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1256 GLchan t0
[4], t1
[4]; /* texels */
1257 const GLfloat f
= FRAC(lambda
);
1258 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, t0
);
1259 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, r
, t1
);
1260 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1261 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1262 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1263 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1269 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1270 const struct gl_texture_object
*tObj
,
1271 GLfloat s
, GLfloat t
, GLfloat r
,
1272 GLfloat lambda
, GLchan rgba
[4] )
1276 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1278 if (level
>= tObj
->_MaxLevel
) {
1279 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, r
, rgba
);
1282 GLchan t0
[4], t1
[4]; /* texels */
1283 const GLfloat f
= FRAC(lambda
);
1284 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, t0
);
1285 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, r
, t1
);
1286 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1287 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1288 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1289 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1295 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1296 const struct gl_texture_object
*tObj
, GLuint n
,
1297 const GLfloat s
[], const GLfloat t
[],
1298 const GLfloat u
[], const GLfloat lambda
[],
1302 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1305 sample_3d_nearest(ctx
, tObj
, image
, s
[i
], t
[i
], u
[i
], rgba
[i
]);
1312 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1313 const struct gl_texture_object
*tObj
, GLuint n
,
1314 const GLfloat s
[], const GLfloat t
[],
1315 const GLfloat u
[], const GLfloat lambda
[],
1319 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1322 sample_3d_linear(ctx
, tObj
, image
, s
[i
], t
[i
], u
[i
], rgba
[i
]);
1328 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1329 * return a texture sample.
1332 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1333 const struct gl_texture_object
*tObj
, GLuint n
,
1334 const GLfloat s
[], const GLfloat t
[],
1335 const GLfloat u
[], const GLfloat lambda
[],
1339 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1343 if (lambda
[i
] > MinMagThresh
) {
1345 switch (tObj
->MinFilter
) {
1347 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1348 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1351 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1352 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1354 case GL_NEAREST_MIPMAP_NEAREST
:
1355 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1356 lambda
[i
], rgba
[i
]);
1358 case GL_LINEAR_MIPMAP_NEAREST
:
1359 sample_3d_linear_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1360 lambda
[i
], rgba
[i
]);
1362 case GL_NEAREST_MIPMAP_LINEAR
:
1363 sample_3d_nearest_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1364 lambda
[i
], rgba
[i
]);
1366 case GL_LINEAR_MIPMAP_LINEAR
:
1367 sample_3d_linear_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1368 lambda
[i
], rgba
[i
]);
1371 _mesa_problem(NULL
, "Bad min filterin sample_3d_texture");
1376 switch (tObj
->MagFilter
) {
1378 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1379 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1382 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1383 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1386 _mesa_problem(NULL
, "Bad mag filter in sample_3d_texture");
1393 /**********************************************************************/
1394 /* Texture Cube Map Sampling Functions */
1395 /**********************************************************************/
1398 * Choose one of six sides of a texture cube map given the texture
1399 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1402 static const struct gl_texture_image
**
1403 choose_cube_face(const struct gl_texture_object
*texObj
,
1404 GLfloat rx
, GLfloat ry
, GLfloat rz
,
1405 GLfloat
*newS
, GLfloat
*newT
)
1409 direction target sc tc ma
1410 ---------- ------------------------------- --- --- ---
1411 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1412 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1413 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1414 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1415 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1416 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1418 const struct gl_texture_image
**imgArray
;
1419 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
1422 if (arx
> ary
&& arx
> arz
) {
1424 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
1430 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
1436 else if (ary
> arx
&& ary
> arz
) {
1438 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
1444 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
1452 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
1458 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
1465 *newS
= ( sc
/ ma
+ 1.0F
) * 0.5F
;
1466 *newT
= ( tc
/ ma
+ 1.0F
) * 0.5F
;
1472 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1473 const struct gl_texture_object
*tObj
, GLuint n
,
1474 const GLfloat s
[], const GLfloat t
[],
1475 const GLfloat u
[], const GLfloat lambda
[],
1480 for (i
= 0; i
< n
; i
++) {
1481 const struct gl_texture_image
**images
;
1483 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
], &newS
, &newT
);
1484 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1485 newS
, newT
, rgba
[i
]);
1491 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1492 const struct gl_texture_object
*tObj
, GLuint n
,
1493 const GLfloat s
[], const GLfloat t
[],
1494 const GLfloat u
[], const GLfloat lambda
[],
1499 for (i
= 0; i
< n
; i
++) {
1500 const struct gl_texture_image
**images
;
1502 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
], &newS
, &newT
);
1503 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1504 newS
, newT
, rgba
[i
]);
1510 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1511 const struct gl_texture_object
*tObj
,
1512 GLfloat s
, GLfloat t
, GLfloat u
,
1513 GLfloat lambda
, GLchan rgba
[4])
1515 const struct gl_texture_image
**images
;
1519 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1521 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1522 sample_2d_nearest(ctx
, tObj
, images
[level
], newS
, newT
, rgba
);
1527 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1528 const struct gl_texture_object
*tObj
,
1529 GLfloat s
, GLfloat t
, GLfloat u
,
1530 GLfloat lambda
, GLchan rgba
[4])
1532 const struct gl_texture_image
**images
;
1536 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1538 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1539 sample_2d_linear(ctx
, tObj
, images
[level
], newS
, newT
, rgba
);
1544 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1545 const struct gl_texture_object
*tObj
,
1546 GLfloat s
, GLfloat t
, GLfloat u
,
1547 GLfloat lambda
, GLchan rgba
[4])
1549 const struct gl_texture_image
**images
;
1553 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1555 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1557 if (level
>= tObj
->_MaxLevel
) {
1558 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
], newS
, newT
, rgba
);
1561 GLchan t0
[4], t1
[4]; /* texels */
1562 const GLfloat f
= FRAC(lambda
);
1563 sample_2d_nearest(ctx
, tObj
, images
[level
], newS
, newT
, t0
);
1564 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newS
, newT
, t1
);
1565 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1566 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1567 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1568 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1574 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1575 const struct gl_texture_object
*tObj
,
1576 GLfloat s
, GLfloat t
, GLfloat u
,
1577 GLfloat lambda
, GLchan rgba
[4])
1579 const struct gl_texture_image
**images
;
1583 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1585 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1587 if (level
>= tObj
->_MaxLevel
) {
1588 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
], newS
, newT
, rgba
);
1591 GLchan t0
[4], t1
[4];
1592 const GLfloat f
= FRAC(lambda
);
1593 sample_2d_linear(ctx
, tObj
, images
[level
], newS
, newT
, t0
);
1594 sample_2d_linear(ctx
, tObj
, images
[level
+1], newS
, newT
, t1
);
1595 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1596 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1597 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1598 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1604 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1605 const struct gl_texture_object
*tObj
, GLuint n
,
1606 const GLfloat s
[], const GLfloat t
[],
1607 const GLfloat u
[], const GLfloat lambda
[],
1610 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1613 for (i
= 0; i
< n
; i
++) {
1614 if (lambda
[i
] > MinMagThresh
) {
1616 switch (tObj
->MinFilter
) {
1619 const struct gl_texture_image
**images
;
1621 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1623 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1624 newS
, newT
, rgba
[i
]);
1629 const struct gl_texture_image
**images
;
1631 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1633 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1634 newS
, newT
, rgba
[i
]);
1637 case GL_NEAREST_MIPMAP_NEAREST
:
1638 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1639 lambda
[i
], rgba
[i
]);
1641 case GL_LINEAR_MIPMAP_NEAREST
:
1642 sample_cube_linear_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1643 lambda
[i
], rgba
[i
]);
1645 case GL_NEAREST_MIPMAP_LINEAR
:
1646 sample_cube_nearest_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1647 lambda
[i
], rgba
[i
]);
1649 case GL_LINEAR_MIPMAP_LINEAR
:
1650 sample_cube_linear_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1651 lambda
[i
], rgba
[i
]);
1654 _mesa_problem(NULL
, "Bad min filter in sample_lambda_cube");
1659 const struct gl_texture_image
**images
;
1661 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1663 switch (tObj
->MagFilter
) {
1665 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1666 newS
, newT
, rgba
[i
]);
1669 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1670 newS
, newT
, rgba
[i
]);
1673 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_cube");
1680 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
1681 const struct gl_texture_object
*tObj
, GLuint n
,
1682 const GLfloat s
[], const GLfloat t
[],
1683 const GLfloat u
[], const GLfloat lambda
[],
1688 /**********************************************************************/
1689 /* Texture Sampling Setup */
1690 /**********************************************************************/
1694 * Setup the texture sampling function for this texture object.
1697 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
1698 const struct gl_texture_object
*t
)
1700 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1703 swrast
->TextureSample
[texUnit
] = null_sample_func
;
1706 GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
1709 /* Compute min/mag filter threshold */
1710 if (t
->MagFilter
== GL_LINEAR
1711 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
1712 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
1713 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
1716 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
1720 switch (t
->Dimensions
) {
1723 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
1725 else if (t
->MinFilter
==GL_LINEAR
) {
1726 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
1729 ASSERT(t
->MinFilter
==GL_NEAREST
);
1730 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
1735 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
1737 else if (t
->MinFilter
==GL_LINEAR
) {
1738 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
1741 GLint baseLevel
= t
->BaseLevel
;
1742 ASSERT(t
->MinFilter
==GL_NEAREST
);
1743 if (t
->WrapS
== GL_REPEAT
&&
1744 t
->WrapT
== GL_REPEAT
&&
1745 t
->Image
[baseLevel
]->Border
== 0 &&
1746 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
1747 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
1749 else if (t
->WrapS
== GL_REPEAT
&&
1750 t
->WrapT
== GL_REPEAT
&&
1751 t
->Image
[baseLevel
]->Border
== 0 &&
1752 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
1753 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
1756 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
1761 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
1763 else if (t
->MinFilter
==GL_LINEAR
) {
1764 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
1767 ASSERT(t
->MinFilter
==GL_NEAREST
);
1768 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
1771 case 6: /* cube map */
1773 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
1775 else if (t
->MinFilter
==GL_LINEAR
) {
1776 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
1779 ASSERT(t
->MinFilter
==GL_NEAREST
);
1780 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
1784 _mesa_problem(NULL
, "invalid dimensions in _mesa_set_texture_sampler");
1790 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
1791 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
1794 texture_combine(const GLcontext
*ctx
,
1795 const struct gl_texture_unit
*textureUnit
,
1797 CONST
GLchan (*primary_rgba
)[4],
1798 CONST
GLchan (*texel
)[4],
1801 const GLchan (*argRGB
[3])[4];
1802 const GLchan (*argA
[3])[4];
1804 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
1805 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
1806 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
1807 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
1809 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
1810 ctx
->Extensions
.ARB_texture_env_combine
);
1813 * Do operand setup for up to 3 operands. Loop over the terms.
1815 for (j
= 0; j
< 3; j
++) {
1816 switch (textureUnit
->CombineSourceA
[j
]) {
1820 case GL_PRIMARY_COLOR_EXT
:
1821 argA
[j
] = primary_rgba
;
1823 case GL_PREVIOUS_EXT
:
1824 argA
[j
] = (const GLchan (*)[4]) rgba
;
1826 case GL_CONSTANT_EXT
:
1828 GLchan alpha
, (*c
)[4] = ccolor
[j
];
1829 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
1830 for (i
= 0; i
< n
; i
++)
1831 c
[i
][ACOMP
] = alpha
;
1832 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1836 _mesa_problem(NULL
, "invalid combine source");
1839 switch (textureUnit
->CombineSourceRGB
[j
]) {
1843 case GL_PRIMARY_COLOR_EXT
:
1844 argRGB
[j
] = primary_rgba
;
1846 case GL_PREVIOUS_EXT
:
1847 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
1849 case GL_CONSTANT_EXT
:
1851 GLchan (*c
)[4] = ccolor
[j
];
1852 GLchan red
, green
, blue
, alpha
;
1853 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
1854 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
1855 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
1856 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
1857 for (i
= 0; i
< n
; i
++) {
1859 c
[i
][GCOMP
] = green
;
1861 c
[i
][ACOMP
] = alpha
;
1863 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1867 _mesa_problem(NULL
, "invalid combine source");
1870 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
1871 const GLchan (*src
)[4] = argRGB
[j
];
1872 GLchan (*dst
)[4] = ccolor
[j
];
1874 /* point to new arg[j] storage */
1875 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1877 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
1878 for (i
= 0; i
< n
; i
++) {
1879 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
1880 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
1881 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
1884 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
1885 for (i
= 0; i
< n
; i
++) {
1886 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
1887 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
1888 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
1892 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
1893 for (i
= 0; i
< n
; i
++) {
1894 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1895 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1896 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1901 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
1902 const GLchan (*src
)[4] = argA
[j
];
1903 GLchan (*dst
)[4] = ccolor
[j
];
1904 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1905 for (i
= 0; i
< n
; i
++) {
1906 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1910 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
1911 textureUnit
->CombineModeA
== GL_REPLACE
) {
1912 break; /* done, we need only arg0 */
1916 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
1917 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
1918 break; /* arg0 and arg1 are done. we don't need arg2. */
1923 * Do the texture combine.
1925 switch (textureUnit
->CombineModeRGB
) {
1928 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1930 for (i
= 0; i
< n
; i
++) {
1931 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
1932 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
1933 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
1934 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
1935 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
1936 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
1940 for (i
= 0; i
< n
; i
++) {
1941 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
1942 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
1943 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
1950 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1951 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1952 const GLint shift
= 8 - RGBshift
;
1953 for (i
= 0; i
< n
; i
++) {
1954 GLuint r
= PROD(arg0
[i
][0], arg1
[i
][RCOMP
]) >> shift
;
1955 GLuint g
= PROD(arg0
[i
][1], arg1
[i
][GCOMP
]) >> shift
;
1956 GLuint b
= PROD(arg0
[i
][2], arg1
[i
][BCOMP
]) >> shift
;
1957 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1958 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1959 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1965 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1966 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1967 for (i
= 0; i
< n
; i
++) {
1968 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
1969 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
1970 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
1971 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1972 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1973 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1977 case GL_ADD_SIGNED_EXT
:
1979 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1980 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1981 for (i
= 0; i
< n
; i
++) {
1982 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] - 128;
1983 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] - 128;
1984 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] - 128;
1985 r
= (r
< 0) ? 0 : r
<< RGBshift
;
1986 g
= (g
< 0) ? 0 : g
<< RGBshift
;
1987 b
= (b
< 0) ? 0 : b
<< RGBshift
;
1988 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1989 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1990 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1994 case GL_INTERPOLATE_EXT
:
1996 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1997 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1998 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
1999 const GLint shift
= 8 - RGBshift
;
2000 for (i
= 0; i
< n
; i
++) {
2001 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
2002 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
2004 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
2005 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
2007 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
2008 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
2010 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2011 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2012 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2016 case GL_SUBTRACT_ARB
:
2018 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2019 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2020 for (i
= 0; i
< n
; i
++) {
2021 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2022 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2023 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2024 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
2025 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
2026 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
2030 case GL_DOT3_RGB_EXT
:
2031 case GL_DOT3_RGBA_EXT
:
2032 case GL_DOT3_RGB_ARB
:
2033 case GL_DOT3_RGBA_ARB
:
2035 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2036 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2037 /* ATI's EXT extension has a constant scale by 4. The ARB
2038 * one will likely remove this restriction, and we should
2039 * drop the EXT extension in favour of the ARB one.
2041 for (i
= 0; i
< n
; i
++) {
2042 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - 128,
2043 (GLint
)arg1
[i
][RCOMP
] - 128) +
2044 S_PROD((GLint
)arg0
[i
][GCOMP
] - 128,
2045 (GLint
)arg1
[i
][GCOMP
] - 128) +
2046 S_PROD((GLint
)arg0
[i
][BCOMP
] - 128,
2047 (GLint
)arg1
[i
][BCOMP
] - 128)) >> 6;
2048 dot
= CLAMP(dot
, 0, 255);
2049 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
2054 _mesa_problem(NULL
, "invalid combine mode");
2057 switch (textureUnit
->CombineModeA
) {
2060 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2062 for (i
= 0; i
< n
; i
++) {
2063 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
2064 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2068 for (i
= 0; i
< n
; i
++) {
2069 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
2076 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2077 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2078 const GLint shift
= 8 - Ashift
;
2079 for (i
= 0; i
< n
; i
++) {
2080 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
2081 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2087 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2088 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2089 for (i
= 0; i
< n
; i
++) {
2090 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
2091 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2095 case GL_ADD_SIGNED_EXT
:
2097 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2098 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2099 for (i
= 0; i
< n
; i
++) {
2100 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] - 128;
2101 a
= (a
< 0) ? 0 : a
<< Ashift
;
2102 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2106 case GL_INTERPOLATE_EXT
:
2108 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2109 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2110 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
2111 const GLint shift
= 8 - Ashift
;
2112 for (i
=0; i
<n
; i
++) {
2113 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
2114 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
2116 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2120 case GL_SUBTRACT_ARB
:
2122 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2123 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2124 for (i
= 0; i
< n
; i
++) {
2125 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << RGBshift
;
2126 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
2132 _mesa_problem(NULL
, "invalid combine mode");
2135 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2137 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
2138 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
2139 for (i
= 0; i
< n
; i
++) {
2140 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
2143 UNDEFARRAY(ccolor
); /* mac 32k limitation */
2149 /**********************************************************************/
2150 /* Texture Application */
2151 /**********************************************************************/
2155 * Combine incoming fragment color with texel color to produce output color.
2156 * Input: textureUnit - pointer to texture unit to apply
2157 * format - base internal texture format
2158 * n - number of fragments
2159 * primary_rgba - primary colors (may alias rgba for single texture)
2160 * texels - array of texel colors
2161 * InOut: rgba - incoming fragment colors modified by texel colors
2162 * according to the texture environment mode.
2165 apply_texture( const GLcontext
*ctx
,
2166 const struct gl_texture_unit
*texUnit
,
2168 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
2173 GLint Rc
, Gc
, Bc
, Ac
;
2177 ASSERT(texUnit
->_Current
);
2179 baseLevel
= texUnit
->_Current
->BaseLevel
;
2180 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
2182 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
2184 if (format
==GL_COLOR_INDEX
|| format
==GL_DEPTH_COMPONENT
) {
2185 format
= GL_RGBA
; /* XXXX a hack! */
2188 switch (texUnit
->EnvMode
) {
2195 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2201 GLchan Lt
= texel
[i
][RCOMP
];
2202 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2206 case GL_LUMINANCE_ALPHA
:
2208 GLchan Lt
= texel
[i
][RCOMP
];
2210 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2212 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2218 GLchan It
= texel
[i
][RCOMP
];
2219 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
2221 rgba
[i
][ACOMP
] = It
;
2227 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2228 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2229 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2236 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2237 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2238 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2240 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2244 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in apply_texture");
2255 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2261 GLchan Lt
= texel
[i
][RCOMP
];
2262 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2263 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2264 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2268 case GL_LUMINANCE_ALPHA
:
2271 GLchan Lt
= texel
[i
][RCOMP
];
2272 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2273 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2274 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2276 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2282 GLchan It
= texel
[i
][RCOMP
];
2283 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
2284 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
2285 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
2287 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
2293 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2294 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2295 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2302 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2303 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2304 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2306 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2310 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in apply_texture");
2319 case GL_LUMINANCE_ALPHA
:
2326 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2327 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2328 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2334 /* Cv = Cf(1-At) + CtAt */
2335 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
2336 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
2337 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
2338 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
2343 _mesa_problem(ctx
, "Bad format (GL_DECAL) in apply_texture");
2349 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
2350 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
2351 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
2352 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
2358 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2363 /* Cv = Cf(1-Lt) + CcLt */
2364 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2365 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2366 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2367 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2371 case GL_LUMINANCE_ALPHA
:
2373 /* Cv = Cf(1-Lt) + CcLt */
2374 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2375 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2376 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2377 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2379 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2384 /* Cv = Cf(1-It) + CcLt */
2385 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
2386 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
2387 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
2388 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
2389 /* Av = Af(1-It) + Ac*It */
2390 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
2395 /* Cv = Cf(1-Ct) + CcCt */
2396 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2397 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2398 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2404 /* Cv = Cf(1-Ct) + CcCt */
2405 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2406 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2407 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2409 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2413 _mesa_problem(ctx
, "Bad format (GL_BLEND) in apply_texture");
2418 case GL_ADD
: /* GL_EXT_texture_add_env */
2425 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2430 GLuint Lt
= texel
[i
][RCOMP
];
2431 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2432 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2433 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2434 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2435 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2436 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2440 case GL_LUMINANCE_ALPHA
:
2442 GLuint Lt
= texel
[i
][RCOMP
];
2443 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2444 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2445 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2446 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2447 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2448 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2449 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2454 GLchan It
= texel
[i
][RCOMP
];
2455 GLuint r
= rgba
[i
][RCOMP
] + It
;
2456 GLuint g
= rgba
[i
][GCOMP
] + It
;
2457 GLuint b
= rgba
[i
][BCOMP
] + It
;
2458 GLuint a
= rgba
[i
][ACOMP
] + It
;
2459 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2460 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2461 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2462 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
2467 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2468 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2469 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2470 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2471 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2472 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2478 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2479 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2480 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2481 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2482 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2483 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2484 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2488 _mesa_problem(ctx
, "Bad format (GL_ADD) in apply_texture");
2493 case GL_COMBINE_EXT
:
2494 texture_combine(ctx
, texUnit
, n
, primary_rgba
, texel
, rgba
);
2498 _mesa_problem(ctx
, "Bad env mode in apply_texture");
2506 * Sample a shadow/depth texture.
2507 * Input: ctx - context
2508 * texUnit - the texture unit
2509 * n - number of samples
2510 * s,t,r - array [n] of texture coordinates
2511 * In/Out: rgba - array [n] of texel colors.
2514 sample_depth_texture(const GLcontext
*ctx
,
2515 const struct gl_texture_unit
*texUnit
,
2517 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2520 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2521 const GLint baseLevel
= texObj
->BaseLevel
;
2522 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2523 const GLuint width
= texImage
->Width
;
2524 const GLuint height
= texImage
->Height
;
2525 const GLchan ambient
= texObj
->ShadowAmbient
;
2526 GLboolean lequal
, gequal
;
2528 if (texObj
->Dimensions
!= 2) {
2529 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2533 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2534 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2538 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2539 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2540 * isn't a depth texture.
2542 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2543 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2547 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2556 if (texObj
->MagFilter
== GL_NEAREST
) {
2558 for (i
= 0; i
< n
; i
++) {
2559 GLfloat depthSample
;
2561 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2562 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2563 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2564 if ((r
[i
] <= depthSample
&& lequal
) ||
2565 (r
[i
] >= depthSample
&& gequal
)) {
2566 texel
[i
][RCOMP
] = CHAN_MAX
;
2567 texel
[i
][GCOMP
] = CHAN_MAX
;
2568 texel
[i
][BCOMP
] = CHAN_MAX
;
2569 texel
[i
][ACOMP
] = CHAN_MAX
;
2572 texel
[i
][RCOMP
] = ambient
;
2573 texel
[i
][GCOMP
] = ambient
;
2574 texel
[i
][BCOMP
] = ambient
;
2575 texel
[i
][ACOMP
] = CHAN_MAX
;
2581 ASSERT(texObj
->MagFilter
== GL_LINEAR
);
2582 for (i
= 0; i
< n
; i
++) {
2583 GLfloat depth00
, depth01
, depth10
, depth11
;
2584 GLint i0
, i1
, j0
, j1
;
2586 GLuint useBorderTexel
;
2588 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapS
, s
[i
], u
, width
, i0
, i1
);
2589 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapT
, t
[i
], v
, height
,j0
, j1
);
2592 if (texImage
->Border
) {
2593 i0
+= texImage
->Border
;
2594 i1
+= texImage
->Border
;
2595 j0
+= texImage
->Border
;
2596 j1
+= texImage
->Border
;
2599 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2600 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2601 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2602 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2605 /* get four depth samples from the texture */
2606 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2610 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2612 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2616 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2618 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2622 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2624 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2628 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2632 /* compute a single weighted depth sample and do one comparison */
2633 const GLfloat a
= FRAC(u
+ 1.0F
);
2634 const GLfloat b
= FRAC(v
+ 1.0F
);
2635 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2636 const GLfloat w10
= ( a
) * (1.0F
- b
);
2637 const GLfloat w01
= (1.0F
- a
) * ( b
);
2638 const GLfloat w11
= ( a
) * ( b
);
2639 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2640 + w01
* depth01
+ w11
* depth11
;
2641 if ((depthSample
<= r
[i
] && lequal
) ||
2642 (depthSample
>= r
[i
] && gequal
)) {
2643 texel
[i
][RCOMP
] = ambient
;
2644 texel
[i
][GCOMP
] = ambient
;
2645 texel
[i
][BCOMP
] = ambient
;
2646 texel
[i
][ACOMP
] = CHAN_MAX
;
2649 texel
[i
][RCOMP
] = CHAN_MAX
;
2650 texel
[i
][GCOMP
] = CHAN_MAX
;
2651 texel
[i
][BCOMP
] = CHAN_MAX
;
2652 texel
[i
][ACOMP
] = CHAN_MAX
;
2656 /* Do four depth/R comparisons and compute a weighted result.
2657 * If this touches on somebody's I.P., I'll remove this code
2660 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2661 GLfloat luminance
= CHAN_MAXF
;
2664 if (depth00
<= r
[i
]) luminance
-= d
;
2665 if (depth01
<= r
[i
]) luminance
-= d
;
2666 if (depth10
<= r
[i
]) luminance
-= d
;
2667 if (depth11
<= r
[i
]) luminance
-= d
;
2670 if (depth00
>= r
[i
]) luminance
-= d
;
2671 if (depth01
>= r
[i
]) luminance
-= d
;
2672 if (depth10
>= r
[i
]) luminance
-= d
;
2673 if (depth11
>= r
[i
]) luminance
-= d
;
2675 lum
= (GLchan
) luminance
;
2676 texel
[i
][RCOMP
] = lum
;
2677 texel
[i
][GCOMP
] = lum
;
2678 texel
[i
][BCOMP
] = lum
;
2679 texel
[i
][ACOMP
] = CHAN_MAX
;
2688 * Experimental depth texture sampling function.
2691 sample_depth_texture2(const GLcontext
*ctx
,
2692 const struct gl_texture_unit
*texUnit
,
2694 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2697 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2698 const GLint baseLevel
= texObj
->BaseLevel
;
2699 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2700 const GLuint width
= texImage
->Width
;
2701 const GLuint height
= texImage
->Height
;
2702 const GLchan ambient
= texObj
->ShadowAmbient
;
2703 GLboolean lequal
, gequal
;
2705 if (texObj
->Dimensions
!= 2) {
2706 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2710 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2711 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2715 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2716 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2717 * isn't a depth texture.
2719 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2720 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2724 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2735 for (i
= 0; i
< n
; i
++) {
2737 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2740 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2741 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2748 if (imin
< 0) imin
= 0;
2749 if (imax
>= width
) imax
= width
- 1;
2750 if (jmin
< 0) jmin
= 0;
2751 if (jmax
>= height
) jmax
= height
- 1;
2753 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2755 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2756 for (ii
= imin
; ii
<= imax
; ii
++) {
2757 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2759 if ((depthSample
<= r
[i
] && lequal
) ||
2760 (depthSample
>= r
[i
] && gequal
)) {
2766 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2767 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2770 texel
[i
][RCOMP
] = lum
;
2771 texel
[i
][GCOMP
] = lum
;
2772 texel
[i
][BCOMP
] = lum
;
2773 texel
[i
][ACOMP
] = CHAN_MAX
;
2781 * Apply a unit of texture mapping to the incoming fragments.
2784 _swrast_texture_fragments( GLcontext
*ctx
, GLuint texUnit
, GLuint n
,
2785 const GLfloat s
[], const GLfloat t
[],
2786 const GLfloat r
[], GLfloat lambda
[],
2787 CONST GLchan primary_rgba
[][4], GLchan rgba
[][4] )
2789 const GLuint mask
= TEXTURE0_ANY
<< (texUnit
* 4);
2791 if (ctx
->Texture
._ReallyEnabled
& mask
) {
2792 const struct gl_texture_unit
*textureUnit
= &ctx
->Texture
.Unit
[texUnit
];
2794 if (textureUnit
->_Current
) { /* XXX need this? */
2795 GLchan texel
[PB_SIZE
][4];
2797 if (textureUnit
->LodBias
!= 0.0F
) {
2798 /* apply LOD bias, but don't clamp yet */
2801 lambda
[i
] += textureUnit
->LodBias
;
2805 if ((textureUnit
->_Current
->MinLod
!= -1000.0
2806 || textureUnit
->_Current
->MaxLod
!= 1000.0)
2808 /* apply LOD clamping to lambda */
2809 const GLfloat min
= textureUnit
->_Current
->MinLod
;
2810 const GLfloat max
= textureUnit
->_Current
->MaxLod
;
2813 GLfloat l
= lambda
[i
];
2814 lambda
[i
] = CLAMP(l
, min
, max
);
2818 /* Sample the texture. */
2819 if (textureUnit
->_Current
->CompareFlag
) {
2821 sample_depth_texture(ctx
, textureUnit
, n
, s
, t
, r
, texel
);
2825 SWRAST_CONTEXT(ctx
)->TextureSample
[texUnit
]( ctx
, texUnit
,
2826 textureUnit
->_Current
,
2830 apply_texture( ctx
, textureUnit
, n
, primary_rgba
,
2831 (const GLchan (*)[4]) texel
, rgba
);