1 /* $Id: s_texture.c,v 1.33 2001/07/13 20:07:37 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 #if CHAN_TYPE == GL_FLOAT
1807 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
1808 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
1810 const GLint half
= (CHAN_MAX
+ 1) / 2;
1813 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
1814 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
1816 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
1817 ctx
->Extensions
.ARB_texture_env_combine
);
1820 * Do operand setup for up to 3 operands. Loop over the terms.
1822 for (j
= 0; j
< 3; j
++) {
1823 switch (textureUnit
->CombineSourceA
[j
]) {
1827 case GL_PRIMARY_COLOR_EXT
:
1828 argA
[j
] = primary_rgba
;
1830 case GL_PREVIOUS_EXT
:
1831 argA
[j
] = (const GLchan (*)[4]) rgba
;
1833 case GL_CONSTANT_EXT
:
1835 GLchan alpha
, (*c
)[4] = ccolor
[j
];
1836 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
1837 for (i
= 0; i
< n
; i
++)
1838 c
[i
][ACOMP
] = alpha
;
1839 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1843 _mesa_problem(NULL
, "invalid combine source");
1846 switch (textureUnit
->CombineSourceRGB
[j
]) {
1850 case GL_PRIMARY_COLOR_EXT
:
1851 argRGB
[j
] = primary_rgba
;
1853 case GL_PREVIOUS_EXT
:
1854 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
1856 case GL_CONSTANT_EXT
:
1858 GLchan (*c
)[4] = ccolor
[j
];
1859 GLchan red
, green
, blue
, alpha
;
1860 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
1861 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
1862 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
1863 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
1864 for (i
= 0; i
< n
; i
++) {
1866 c
[i
][GCOMP
] = green
;
1868 c
[i
][ACOMP
] = alpha
;
1870 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1874 _mesa_problem(NULL
, "invalid combine source");
1877 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
1878 const GLchan (*src
)[4] = argRGB
[j
];
1879 GLchan (*dst
)[4] = ccolor
[j
];
1881 /* point to new arg[j] storage */
1882 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1884 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
1885 for (i
= 0; i
< n
; i
++) {
1886 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
1887 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
1888 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
1891 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
1892 for (i
= 0; i
< n
; i
++) {
1893 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
1894 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
1895 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
1899 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
1900 for (i
= 0; i
< n
; i
++) {
1901 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1902 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1903 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1908 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
1909 const GLchan (*src
)[4] = argA
[j
];
1910 GLchan (*dst
)[4] = ccolor
[j
];
1911 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1912 for (i
= 0; i
< n
; i
++) {
1913 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1917 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
1918 textureUnit
->CombineModeA
== GL_REPLACE
) {
1919 break; /* done, we need only arg0 */
1923 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
1924 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
1925 break; /* arg0 and arg1 are done. we don't need arg2. */
1930 * Do the texture combine.
1932 switch (textureUnit
->CombineModeRGB
) {
1935 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1937 for (i
= 0; i
< n
; i
++) {
1938 #if CHAN_TYPE == GL_FLOAT
1939 GLchan r
= arg0
[i
][RCOMP
] * RGBmult
;
1940 GLchan g
= arg0
[i
][GCOMP
] * RGBmult
;
1941 GLchan b
= arg0
[i
][BCOMP
] * RGBmult
;
1943 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
1944 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
1945 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
1947 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
1948 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
1949 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
1953 for (i
= 0; i
< n
; i
++) {
1954 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
1955 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
1956 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
1963 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1964 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1965 #if CHAN_TYPE != GL_FLOAT
1966 const GLint shift
= 8 - RGBshift
;
1968 for (i
= 0; i
< n
; i
++) {
1969 #if CHAN_TYPE == GL_FLOAT
1970 GLchan r
= arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
1971 GLuint g
= arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
1972 GLuint b
= arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
1974 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
1975 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
1976 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
1978 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1979 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1980 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1986 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1987 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1988 for (i
= 0; i
< n
; i
++) {
1989 #if CHAN_TYPE == GL_FLOAT
1990 GLchan r
= (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
1991 GLchan g
= (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
1992 GLchan b
= (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
1994 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
1995 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
1996 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
1998 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1999 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2000 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2004 case GL_ADD_SIGNED_EXT
:
2006 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2007 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2008 for (i
= 0; i
< n
; i
++) {
2009 #if CHAN_TYPE == GL_FLOAT
2010 GLchan r
= (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
2011 GLchan g
= (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
2012 GLchan b
= (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
2014 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
2015 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
2016 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
2017 r
= (r
< 0) ? 0 : r
<< RGBshift
;
2018 g
= (g
< 0) ? 0 : g
<< RGBshift
;
2019 b
= (b
< 0) ? 0 : b
<< RGBshift
;
2021 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2022 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2023 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2027 case GL_INTERPOLATE_EXT
:
2029 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2030 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2031 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
2032 #if CHAN_TYPE != GL_FLOAT
2033 const GLint shift
= 8 - RGBshift
;
2035 for (i
= 0; i
< n
; i
++) {
2036 #if CHAN_TYPE == GL_FLOAT
2037 GLchan r
= (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
2038 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
2039 GLchan g
= (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
2040 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
2041 GLchan b
= (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
2042 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
2044 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
2045 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
2047 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
2048 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
2050 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
2051 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
2054 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2055 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2056 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2060 case GL_SUBTRACT_ARB
:
2062 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2063 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2064 for (i
= 0; i
< n
; i
++) {
2065 #if CHAN_TYPE == GL_FLOAT
2066 GLchan r
= (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
2067 GLchan g
= (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
2068 GLchan b
= (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
2070 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2071 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2072 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2074 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
2075 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
2076 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
2080 case GL_DOT3_RGB_EXT
:
2081 case GL_DOT3_RGBA_EXT
:
2082 case GL_DOT3_RGB_ARB
:
2083 case GL_DOT3_RGBA_ARB
:
2085 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2086 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2087 /* ATI's EXT extension has a constant scale by 4. The ARB
2088 * one will likely remove this restriction, and we should
2089 * drop the EXT extension in favour of the ARB one.
2091 for (i
= 0; i
< n
; i
++) {
2092 #if CHAN_TYPE == GL_FLOAT
2093 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
2094 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
2095 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
2098 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
2099 (GLint
)arg1
[i
][RCOMP
] - half
) +
2100 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
2101 (GLint
)arg1
[i
][GCOMP
] - half
) +
2102 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
2103 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
2105 dot
= CLAMP(dot
, 0, CHAN_MAX
);
2106 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
2111 _mesa_problem(NULL
, "invalid combine mode");
2114 switch (textureUnit
->CombineModeA
) {
2117 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2119 for (i
= 0; i
< n
; i
++) {
2120 #if CHAN_TYPE == GL_FLOAT
2121 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
2123 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
2125 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2129 for (i
= 0; i
< n
; i
++) {
2130 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
2137 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2138 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2139 #if CHAN_TYPE != GL_FLOAT
2140 const GLint shift
= 8 - Ashift
;
2142 for (i
= 0; i
< n
; i
++) {
2143 #if CHAN_TYPE == GL_FLOAT
2144 GLchan a
= arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
2146 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
2148 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2154 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2155 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2156 for (i
= 0; i
< n
; i
++) {
2157 #if CHAN_TYPE == GL_FLOAT
2158 GLchan a
= (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
2159 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAXF
);
2161 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
2162 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2167 case GL_ADD_SIGNED_EXT
:
2169 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2170 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2171 for (i
= 0; i
< n
; i
++) {
2172 #if CHAN_TYPE == GL_FLOAT
2173 GLchan a
= (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
2175 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
2176 a
= (a
< 0) ? 0 : a
<< Ashift
;
2178 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2182 case GL_INTERPOLATE_EXT
:
2184 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2185 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2186 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
2187 #if CHAN_TYPE != GL_FLOAT
2188 const GLint shift
= 8 - Ashift
;
2190 for (i
=0; i
<n
; i
++) {
2191 #if CHAN_TYPE == GL_FLOAT
2192 GLchan a
= (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
2193 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
2196 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
2197 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
2200 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2204 case GL_SUBTRACT_ARB
:
2206 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2207 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2208 for (i
= 0; i
< n
; i
++) {
2209 #if CHAN_TYPE == GL_FLOAT
2210 GLchan a
= (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
2212 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << RGBshift
;
2214 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
2220 _mesa_problem(NULL
, "invalid combine mode");
2223 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2225 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
2226 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
2227 for (i
= 0; i
< n
; i
++) {
2228 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
2231 UNDEFARRAY(ccolor
); /* mac 32k limitation */
2237 /**********************************************************************/
2238 /* Texture Application */
2239 /**********************************************************************/
2243 * Combine incoming fragment color with texel color to produce output color.
2244 * Input: textureUnit - pointer to texture unit to apply
2245 * format - base internal texture format
2246 * n - number of fragments
2247 * primary_rgba - primary colors (may alias rgba for single texture)
2248 * texels - array of texel colors
2249 * InOut: rgba - incoming fragment colors modified by texel colors
2250 * according to the texture environment mode.
2253 apply_texture( const GLcontext
*ctx
,
2254 const struct gl_texture_unit
*texUnit
,
2256 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
2261 GLint Rc
, Gc
, Bc
, Ac
;
2265 ASSERT(texUnit
->_Current
);
2267 baseLevel
= texUnit
->_Current
->BaseLevel
;
2268 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
2270 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
2272 if (format
==GL_COLOR_INDEX
|| format
==GL_DEPTH_COMPONENT
) {
2273 format
= GL_RGBA
; /* XXXX a hack! */
2276 switch (texUnit
->EnvMode
) {
2283 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2289 GLchan Lt
= texel
[i
][RCOMP
];
2290 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2294 case GL_LUMINANCE_ALPHA
:
2296 GLchan Lt
= texel
[i
][RCOMP
];
2298 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2300 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2306 GLchan It
= texel
[i
][RCOMP
];
2307 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
2309 rgba
[i
][ACOMP
] = It
;
2315 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2316 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2317 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2324 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2325 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2326 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2328 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2332 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in apply_texture");
2343 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2349 GLchan Lt
= texel
[i
][RCOMP
];
2350 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2351 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2352 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2356 case GL_LUMINANCE_ALPHA
:
2359 GLchan Lt
= texel
[i
][RCOMP
];
2360 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2361 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2362 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2364 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2370 GLchan It
= texel
[i
][RCOMP
];
2371 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
2372 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
2373 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
2375 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
2381 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2382 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2383 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2390 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2391 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2392 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2394 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2398 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in apply_texture");
2407 case GL_LUMINANCE_ALPHA
:
2414 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2415 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2416 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2422 /* Cv = Cf(1-At) + CtAt */
2423 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
2424 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
2425 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
2426 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
2431 _mesa_problem(ctx
, "Bad format (GL_DECAL) in apply_texture");
2437 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
2438 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
2439 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
2440 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
2446 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2451 /* Cv = Cf(1-Lt) + CcLt */
2452 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2453 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2454 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2455 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2459 case GL_LUMINANCE_ALPHA
:
2461 /* Cv = Cf(1-Lt) + CcLt */
2462 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2463 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2464 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2465 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2467 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2472 /* Cv = Cf(1-It) + CcLt */
2473 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
2474 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
2475 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
2476 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
2477 /* Av = Af(1-It) + Ac*It */
2478 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
2483 /* Cv = Cf(1-Ct) + CcCt */
2484 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2485 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2486 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2492 /* Cv = Cf(1-Ct) + CcCt */
2493 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2494 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2495 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2497 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2501 _mesa_problem(ctx
, "Bad format (GL_BLEND) in apply_texture");
2506 case GL_ADD
: /* GL_EXT_texture_add_env */
2513 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2518 GLuint Lt
= texel
[i
][RCOMP
];
2519 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2520 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2521 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2522 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2523 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2524 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2528 case GL_LUMINANCE_ALPHA
:
2530 GLuint Lt
= texel
[i
][RCOMP
];
2531 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2532 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2533 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2534 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2535 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2536 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2537 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2542 GLchan It
= texel
[i
][RCOMP
];
2543 GLuint r
= rgba
[i
][RCOMP
] + It
;
2544 GLuint g
= rgba
[i
][GCOMP
] + It
;
2545 GLuint b
= rgba
[i
][BCOMP
] + It
;
2546 GLuint a
= rgba
[i
][ACOMP
] + It
;
2547 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2548 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2549 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2550 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
2555 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2556 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2557 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2558 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2559 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2560 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2566 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2567 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2568 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2569 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2570 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2571 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2572 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2576 _mesa_problem(ctx
, "Bad format (GL_ADD) in apply_texture");
2581 case GL_COMBINE_EXT
:
2582 texture_combine(ctx
, texUnit
, n
, primary_rgba
, texel
, rgba
);
2586 _mesa_problem(ctx
, "Bad env mode in apply_texture");
2594 * Sample a shadow/depth texture.
2595 * Input: ctx - context
2596 * texUnit - the texture unit
2597 * n - number of samples
2598 * s,t,r - array [n] of texture coordinates
2599 * In/Out: rgba - array [n] of texel colors.
2602 sample_depth_texture(const GLcontext
*ctx
,
2603 const struct gl_texture_unit
*texUnit
,
2605 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2608 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2609 const GLint baseLevel
= texObj
->BaseLevel
;
2610 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2611 const GLuint width
= texImage
->Width
;
2612 const GLuint height
= texImage
->Height
;
2613 const GLchan ambient
= texObj
->ShadowAmbient
;
2614 GLboolean lequal
, gequal
;
2616 if (texObj
->Dimensions
!= 2) {
2617 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2621 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2622 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2626 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2627 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2628 * isn't a depth texture.
2630 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2631 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2635 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2644 if (texObj
->MagFilter
== GL_NEAREST
) {
2646 for (i
= 0; i
< n
; i
++) {
2647 GLfloat depthSample
;
2649 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2650 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2651 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2652 if ((r
[i
] <= depthSample
&& lequal
) ||
2653 (r
[i
] >= depthSample
&& gequal
)) {
2654 texel
[i
][RCOMP
] = CHAN_MAX
;
2655 texel
[i
][GCOMP
] = CHAN_MAX
;
2656 texel
[i
][BCOMP
] = CHAN_MAX
;
2657 texel
[i
][ACOMP
] = CHAN_MAX
;
2660 texel
[i
][RCOMP
] = ambient
;
2661 texel
[i
][GCOMP
] = ambient
;
2662 texel
[i
][BCOMP
] = ambient
;
2663 texel
[i
][ACOMP
] = CHAN_MAX
;
2669 ASSERT(texObj
->MagFilter
== GL_LINEAR
);
2670 for (i
= 0; i
< n
; i
++) {
2671 GLfloat depth00
, depth01
, depth10
, depth11
;
2672 GLint i0
, i1
, j0
, j1
;
2674 GLuint useBorderTexel
;
2676 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapS
, s
[i
], u
, width
, i0
, i1
);
2677 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapT
, t
[i
], v
, height
,j0
, j1
);
2680 if (texImage
->Border
) {
2681 i0
+= texImage
->Border
;
2682 i1
+= texImage
->Border
;
2683 j0
+= texImage
->Border
;
2684 j1
+= texImage
->Border
;
2687 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2688 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2689 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2690 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2693 /* get four depth samples from the texture */
2694 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2698 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2700 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2704 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2706 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2710 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2712 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2716 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2720 /* compute a single weighted depth sample and do one comparison */
2721 const GLfloat a
= FRAC(u
+ 1.0F
);
2722 const GLfloat b
= FRAC(v
+ 1.0F
);
2723 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2724 const GLfloat w10
= ( a
) * (1.0F
- b
);
2725 const GLfloat w01
= (1.0F
- a
) * ( b
);
2726 const GLfloat w11
= ( a
) * ( b
);
2727 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2728 + w01
* depth01
+ w11
* depth11
;
2729 if ((depthSample
<= r
[i
] && lequal
) ||
2730 (depthSample
>= r
[i
] && gequal
)) {
2731 texel
[i
][RCOMP
] = ambient
;
2732 texel
[i
][GCOMP
] = ambient
;
2733 texel
[i
][BCOMP
] = ambient
;
2734 texel
[i
][ACOMP
] = CHAN_MAX
;
2737 texel
[i
][RCOMP
] = CHAN_MAX
;
2738 texel
[i
][GCOMP
] = CHAN_MAX
;
2739 texel
[i
][BCOMP
] = CHAN_MAX
;
2740 texel
[i
][ACOMP
] = CHAN_MAX
;
2744 /* Do four depth/R comparisons and compute a weighted result.
2745 * If this touches on somebody's I.P., I'll remove this code
2748 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2749 GLfloat luminance
= CHAN_MAXF
;
2752 if (depth00
<= r
[i
]) luminance
-= d
;
2753 if (depth01
<= r
[i
]) luminance
-= d
;
2754 if (depth10
<= r
[i
]) luminance
-= d
;
2755 if (depth11
<= r
[i
]) luminance
-= d
;
2758 if (depth00
>= r
[i
]) luminance
-= d
;
2759 if (depth01
>= r
[i
]) luminance
-= d
;
2760 if (depth10
>= r
[i
]) luminance
-= d
;
2761 if (depth11
>= r
[i
]) luminance
-= d
;
2763 lum
= (GLchan
) luminance
;
2764 texel
[i
][RCOMP
] = lum
;
2765 texel
[i
][GCOMP
] = lum
;
2766 texel
[i
][BCOMP
] = lum
;
2767 texel
[i
][ACOMP
] = CHAN_MAX
;
2776 * Experimental depth texture sampling function.
2779 sample_depth_texture2(const GLcontext
*ctx
,
2780 const struct gl_texture_unit
*texUnit
,
2782 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2785 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2786 const GLint baseLevel
= texObj
->BaseLevel
;
2787 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2788 const GLuint width
= texImage
->Width
;
2789 const GLuint height
= texImage
->Height
;
2790 const GLchan ambient
= texObj
->ShadowAmbient
;
2791 GLboolean lequal
, gequal
;
2793 if (texObj
->Dimensions
!= 2) {
2794 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2798 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2799 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2803 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2804 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2805 * isn't a depth texture.
2807 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2808 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2812 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2823 for (i
= 0; i
< n
; i
++) {
2825 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2828 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2829 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2836 if (imin
< 0) imin
= 0;
2837 if (imax
>= width
) imax
= width
- 1;
2838 if (jmin
< 0) jmin
= 0;
2839 if (jmax
>= height
) jmax
= height
- 1;
2841 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2843 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2844 for (ii
= imin
; ii
<= imax
; ii
++) {
2845 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2847 if ((depthSample
<= r
[i
] && lequal
) ||
2848 (depthSample
>= r
[i
] && gequal
)) {
2854 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2855 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2858 texel
[i
][RCOMP
] = lum
;
2859 texel
[i
][GCOMP
] = lum
;
2860 texel
[i
][BCOMP
] = lum
;
2861 texel
[i
][ACOMP
] = CHAN_MAX
;
2869 * Apply a unit of texture mapping to the incoming fragments.
2872 _swrast_texture_fragments( GLcontext
*ctx
, GLuint texUnit
, GLuint n
,
2873 const GLfloat s
[], const GLfloat t
[],
2874 const GLfloat r
[], GLfloat lambda
[],
2875 CONST GLchan primary_rgba
[][4], GLchan rgba
[][4] )
2877 const GLuint mask
= TEXTURE0_ANY
<< (texUnit
* 4);
2879 if (ctx
->Texture
._ReallyEnabled
& mask
) {
2880 const struct gl_texture_unit
*textureUnit
= &ctx
->Texture
.Unit
[texUnit
];
2882 if (textureUnit
->_Current
) { /* XXX need this? */
2883 GLchan texel
[PB_SIZE
][4];
2885 if (textureUnit
->LodBias
!= 0.0F
) {
2886 /* apply LOD bias, but don't clamp yet */
2889 lambda
[i
] += textureUnit
->LodBias
;
2893 if ((textureUnit
->_Current
->MinLod
!= -1000.0
2894 || textureUnit
->_Current
->MaxLod
!= 1000.0)
2896 /* apply LOD clamping to lambda */
2897 const GLfloat min
= textureUnit
->_Current
->MinLod
;
2898 const GLfloat max
= textureUnit
->_Current
->MaxLod
;
2901 GLfloat l
= lambda
[i
];
2902 lambda
[i
] = CLAMP(l
, min
, max
);
2906 /* Sample the texture. */
2907 if (textureUnit
->_Current
->CompareFlag
) {
2909 sample_depth_texture(ctx
, textureUnit
, n
, s
, t
, r
, texel
);
2913 SWRAST_CONTEXT(ctx
)->TextureSample
[texUnit
]( ctx
, texUnit
,
2914 textureUnit
->_Current
,
2918 apply_texture( ctx
, textureUnit
, n
, primary_rgba
,
2919 (const GLchan (*)[4]) texel
, rgba
);