1 /* $Id: s_texture.c,v 1.34 2001/07/14 17:53:04 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
);
327 #if CHAN_TYPE == GL_FLOAT
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
);
357 #if CHAN_TYPE == GL_FLOAT
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 * This is really just needed in order to prevent warnings with some compilers.
401 #if CHAN_TYPE == GL_FLOAT
404 #define INTCAST (GLint)
409 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
410 const struct gl_texture_object
*tObj
,
411 GLfloat s
, GLfloat lambda
,
416 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
418 if (level
>= tObj
->_MaxLevel
) {
419 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, rgba
);
423 const GLfloat f
= FRAC(lambda
);
424 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t0
);
425 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t1
);
426 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
427 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
428 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
429 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
436 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
437 const struct gl_texture_object
*tObj
,
438 GLfloat s
, GLfloat lambda
,
443 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
445 if (level
>= tObj
->_MaxLevel
) {
446 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, rgba
);
450 const GLfloat f
= FRAC(lambda
);
451 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t0
);
452 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t1
);
453 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
454 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
455 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
456 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
463 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
464 const struct gl_texture_object
*tObj
, GLuint n
,
465 const GLfloat s
[], const GLfloat t
[],
466 const GLfloat u
[], const GLfloat lambda
[],
470 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
475 sample_1d_nearest(ctx
, tObj
, image
, s
[i
], rgba
[i
]);
482 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
483 const struct gl_texture_object
*tObj
, GLuint n
,
484 const GLfloat s
[], const GLfloat t
[],
485 const GLfloat u
[], const GLfloat lambda
[],
489 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
494 sample_1d_linear(ctx
, tObj
, image
, s
[i
], rgba
[i
]);
500 * Given an (s) texture coordinate and lambda (level of detail) value,
501 * return a texture sample.
505 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
506 const struct gl_texture_object
*tObj
, GLuint n
,
507 const GLfloat s
[], const GLfloat t
[],
508 const GLfloat u
[], const GLfloat lambda
[],
511 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
518 if (lambda
[i
] > MinMagThresh
) {
520 switch (tObj
->MinFilter
) {
522 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
526 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
529 case GL_NEAREST_MIPMAP_NEAREST
:
530 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, lambda
[i
], s
[i
],
533 case GL_LINEAR_MIPMAP_NEAREST
:
534 sample_1d_linear_mipmap_nearest(ctx
, tObj
, s
[i
], lambda
[i
],
537 case GL_NEAREST_MIPMAP_LINEAR
:
538 sample_1d_nearest_mipmap_linear(ctx
, tObj
, s
[i
], lambda
[i
],
541 case GL_LINEAR_MIPMAP_LINEAR
:
542 sample_1d_linear_mipmap_linear(ctx
, tObj
, s
[i
], lambda
[i
],
546 _mesa_problem(NULL
, "Bad min filter in sample_1d_texture");
552 switch (tObj
->MagFilter
) {
554 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
558 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
562 _mesa_problem(NULL
, "Bad mag filter in sample_1d_texture");
572 /**********************************************************************/
573 /* 2-D Texture Sampling Functions */
574 /**********************************************************************/
578 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
581 sample_2d_nearest(GLcontext
*ctx
,
582 const struct gl_texture_object
*tObj
,
583 const struct gl_texture_image
*img
,
584 GLfloat s
, GLfloat t
,
587 const GLint width
= img
->Width2
; /* without border, power of two */
588 const GLint height
= img
->Height2
; /* without border, power of two */
591 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
592 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, t
, height
, j
);
594 /* skip over the border, if any */
598 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
599 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
600 COPY_CHAN4(rgba
, tObj
->BorderColor
);
603 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
604 if (img
->Format
== GL_COLOR_INDEX
) {
605 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
613 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
614 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
617 sample_2d_linear(GLcontext
*ctx
,
618 const struct gl_texture_object
*tObj
,
619 const struct gl_texture_image
*img
,
620 GLfloat s
, GLfloat t
,
623 const GLint width
= img
->Width2
;
624 const GLint height
= img
->Height2
;
625 GLint i0
, j0
, i1
, j1
;
626 GLuint useBorderColor
;
629 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
630 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, t
, v
, height
, j0
, j1
);
640 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
641 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
642 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
643 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
647 const GLfloat a
= FRAC(u
);
648 const GLfloat b
= FRAC(v
);
650 #if CHAN_TYPE == GL_FLOAT
651 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
652 const GLfloat w10
= a
* (1.0F
-b
);
653 const GLfloat w01
= (1.0F
-a
) * b
;
654 const GLfloat w11
= a
* b
;
655 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
656 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
657 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
658 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
659 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
660 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
668 if (useBorderColor
& (I0BIT
| J0BIT
)) {
669 COPY_CHAN4(t00
, tObj
->BorderColor
);
672 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
673 if (img
->Format
== GL_COLOR_INDEX
) {
674 palette_sample(ctx
, tObj
, t00
[0], t00
);
677 if (useBorderColor
& (I1BIT
| J0BIT
)) {
678 COPY_CHAN4(t10
, tObj
->BorderColor
);
681 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
682 if (img
->Format
== GL_COLOR_INDEX
) {
683 palette_sample(ctx
, tObj
, t10
[0], t10
);
686 if (useBorderColor
& (I0BIT
| J1BIT
)) {
687 COPY_CHAN4(t01
, tObj
->BorderColor
);
690 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
691 if (img
->Format
== GL_COLOR_INDEX
) {
692 palette_sample(ctx
, tObj
, t01
[0], t01
);
695 if (useBorderColor
& (I1BIT
| J1BIT
)) {
696 COPY_CHAN4(t11
, tObj
->BorderColor
);
699 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
700 if (img
->Format
== GL_COLOR_INDEX
) {
701 palette_sample(ctx
, tObj
, t11
[0], t11
);
704 #if CHAN_TYPE == GL_FLOAT
705 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
706 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
707 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
708 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
709 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
710 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
711 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
712 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
713 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
723 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
724 const struct gl_texture_object
*tObj
,
725 GLfloat s
, GLfloat t
, GLfloat lambda
,
729 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
730 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, rgba
);
736 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
737 const struct gl_texture_object
*tObj
,
738 GLfloat s
, GLfloat t
, GLfloat lambda
,
742 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
743 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, rgba
);
749 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
750 const struct gl_texture_object
*tObj
,
751 GLfloat s
, GLfloat t
, GLfloat lambda
,
756 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
758 if (level
>= tObj
->_MaxLevel
) {
759 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, rgba
);
762 GLchan t0
[4], t1
[4]; /* texels */
763 const GLfloat f
= FRAC(lambda
);
764 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, t0
);
765 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, t1
);
766 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
767 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
768 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
769 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
776 sample_2d_linear_mipmap_linear(GLcontext
*ctx
,
777 const struct gl_texture_object
*tObj
,
778 GLfloat s
, GLfloat t
, GLfloat lambda
,
783 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
785 if (level
>= tObj
->_MaxLevel
) {
786 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, rgba
);
789 GLchan t0
[4], t1
[4]; /* texels */
790 const GLfloat f
= FRAC(lambda
);
791 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, t0
);
792 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, t1
);
793 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
794 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
795 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
796 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
803 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
804 const struct gl_texture_object
*tObj
, GLuint n
,
805 const GLfloat s
[], const GLfloat t
[],
806 const GLfloat u
[], const GLfloat lambda
[],
810 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
814 sample_2d_nearest(ctx
, tObj
, image
, s
[i
], t
[i
], rgba
[i
]);
821 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
822 const struct gl_texture_object
*tObj
, GLuint n
,
823 const GLfloat s
[], const GLfloat t
[],
824 const GLfloat u
[], const GLfloat lambda
[],
828 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
832 sample_2d_linear(ctx
, tObj
, image
, s
[i
], t
[i
], rgba
[i
]);
838 * Given an array of (s,t) texture coordinate and lambda (level of detail)
839 * values, return an array of texture sample.
842 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
843 const struct gl_texture_object
*tObj
,
845 const GLfloat s
[], const GLfloat t
[],
846 const GLfloat u
[], const GLfloat lambda
[],
849 const GLfloat minMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
853 /* since lambda is monotonous-array use this check first */
854 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
855 /* magnification for whole span */
856 switch (tObj
->MagFilter
) {
858 sample_nearest_2d(ctx
, texUnit
, tObj
, n
, s
, t
, u
,
862 sample_linear_2d(ctx
, texUnit
, tObj
, n
, s
, t
, u
,
866 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_2d");
870 for (i
= 0; i
< n
; i
++) {
871 if (lambda
[i
] > minMagThresh
) {
873 switch (tObj
->MinFilter
) {
875 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
876 s
[i
], t
[i
], rgba
[i
]);
879 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
880 s
[i
], t
[i
], rgba
[i
]);
882 case GL_NEAREST_MIPMAP_NEAREST
:
883 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
],
886 case GL_LINEAR_MIPMAP_NEAREST
:
887 sample_2d_linear_mipmap_nearest(ctx
,tObj
, s
[i
], t
[i
],
890 case GL_NEAREST_MIPMAP_LINEAR
:
891 sample_2d_nearest_mipmap_linear(ctx
,tObj
, s
[i
], t
[i
],
894 case GL_LINEAR_MIPMAP_LINEAR
:
895 sample_2d_linear_mipmap_linear(ctx
,tObj
, s
[i
], t
[i
],
896 lambda
[i
], rgba
[i
] );
899 _mesa_problem(NULL
, "Bad min filter in sample_2d_texture");
905 switch (tObj
->MagFilter
) {
907 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
908 s
[i
], t
[i
], rgba
[i
]);
911 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
912 s
[i
], t
[i
], rgba
[i
] );
915 _mesa_problem(NULL
, "Bad mag filter in sample_2d_texture");
924 * Optimized 2-D texture sampling:
925 * S and T wrap mode == GL_REPEAT
926 * GL_NEAREST min/mag filter
931 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
932 const struct gl_texture_object
*tObj
,
933 GLuint n
, const GLfloat s
[], const GLfloat t
[],
934 const GLfloat u
[], const GLfloat lambda
[],
937 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
938 const GLfloat width
= (GLfloat
) img
->Width
;
939 const GLfloat height
= (GLfloat
) img
->Height
;
940 const GLint colMask
= img
->Width
- 1;
941 const GLint rowMask
= img
->Height
- 1;
942 const GLint shift
= img
->WidthLog2
;
946 ASSERT(tObj
->WrapS
==GL_REPEAT
);
947 ASSERT(tObj
->WrapT
==GL_REPEAT
);
948 ASSERT(tObj
->MinFilter
==GL_NEAREST
);
949 ASSERT(tObj
->MagFilter
==GL_NEAREST
);
950 ASSERT(img
->Border
==0);
951 ASSERT(img
->Format
==GL_RGB
);
953 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
955 GLint i
= (GLint
) ((s
[k
] + 10000.0) * width
) & colMask
;
956 GLint j
= (GLint
) ((t
[k
] + 10000.0) * height
) & rowMask
;
957 GLint pos
= (j
<< shift
) | i
;
958 GLchan
*texel
= ((GLchan
*) img
->Data
) + pos
+ pos
+ pos
; /* pos*3 */
959 rgba
[k
][RCOMP
] = texel
[0];
960 rgba
[k
][GCOMP
] = texel
[1];
961 rgba
[k
][BCOMP
] = texel
[2];
967 * Optimized 2-D texture sampling:
968 * S and T wrap mode == GL_REPEAT
969 * GL_NEAREST min/mag filter
974 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
975 const struct gl_texture_object
*tObj
,
976 GLuint n
, const GLfloat s
[], const GLfloat t
[],
977 const GLfloat u
[], const GLfloat lambda
[],
980 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
981 const GLfloat width
= (GLfloat
) img
->Width
;
982 const GLfloat height
= (GLfloat
) img
->Height
;
983 const GLint colMask
= img
->Width
- 1;
984 const GLint rowMask
= img
->Height
- 1;
985 const GLint shift
= img
->WidthLog2
;
989 ASSERT(tObj
->WrapS
==GL_REPEAT
);
990 ASSERT(tObj
->WrapT
==GL_REPEAT
);
991 ASSERT(tObj
->MinFilter
==GL_NEAREST
);
992 ASSERT(tObj
->MagFilter
==GL_NEAREST
);
993 ASSERT(img
->Border
==0);
994 ASSERT(img
->Format
==GL_RGBA
);
996 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
998 GLint i
= (GLint
) ((s
[k
] + 10000.0) * width
) & colMask
;
999 GLint j
= (GLint
) ((t
[k
] + 10000.0) * height
) & rowMask
;
1000 GLint pos
= (j
<< shift
) | i
;
1001 GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1002 rgba
[k
][RCOMP
] = texel
[0];
1003 rgba
[k
][GCOMP
] = texel
[1];
1004 rgba
[k
][BCOMP
] = texel
[2];
1005 rgba
[k
][ACOMP
] = texel
[3];
1011 /**********************************************************************/
1012 /* 3-D Texture Sampling Functions */
1013 /**********************************************************************/
1016 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1019 sample_3d_nearest(GLcontext
*ctx
,
1020 const struct gl_texture_object
*tObj
,
1021 const struct gl_texture_image
*img
,
1022 GLfloat s
, GLfloat t
, GLfloat r
,
1025 const GLint width
= img
->Width2
; /* without border, power of two */
1026 const GLint height
= img
->Height2
; /* without border, power of two */
1027 const GLint depth
= img
->Depth2
; /* without border, power of two */
1030 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
1031 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, t
, height
, j
);
1032 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, r
, depth
, k
);
1034 if (i
< 0 || i
>= (GLint
) img
->Width
||
1035 j
< 0 || j
>= (GLint
) img
->Height
||
1036 k
< 0 || k
>= (GLint
) img
->Depth
) {
1037 /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1038 COPY_CHAN4(rgba
, tObj
->BorderColor
);
1041 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1042 if (img
->Format
== GL_COLOR_INDEX
) {
1043 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1051 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1054 sample_3d_linear(GLcontext
*ctx
,
1055 const struct gl_texture_object
*tObj
,
1056 const struct gl_texture_image
*img
,
1057 GLfloat s
, GLfloat t
, GLfloat r
,
1060 const GLint width
= img
->Width2
;
1061 const GLint height
= img
->Height2
;
1062 const GLint depth
= img
->Depth2
;
1063 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1064 GLuint useBorderColor
;
1067 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
1068 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, t
, v
, height
, j0
, j1
);
1069 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, r
, w
, depth
, k0
, k1
);
1081 /* check if sampling texture border color */
1082 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1083 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1084 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1085 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1086 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1087 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1091 const GLfloat a
= FRAC(u
);
1092 const GLfloat b
= FRAC(v
);
1093 const GLfloat c
= FRAC(w
);
1095 #if CHAN_TYPE == GL_FLOAT
1096 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1097 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1098 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1099 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1100 GLfloat w110
= a
* b
* (1.0F
-c
);
1101 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1102 GLfloat w101
= a
* (1.0F
-b
) * c
;
1103 GLfloat w011
= (1.0F
-a
) * b
* c
;
1104 GLfloat w111
= a
* b
* c
;
1105 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
1106 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1107 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1108 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1109 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1110 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1111 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1112 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1113 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1114 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1117 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1118 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1120 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1121 COPY_CHAN4(t000
, tObj
->BorderColor
);
1124 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1125 if (img
->Format
== GL_COLOR_INDEX
) {
1126 palette_sample(ctx
, tObj
, t000
[0], t000
);
1129 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1130 COPY_CHAN4(t100
, tObj
->BorderColor
);
1133 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1134 if (img
->Format
== GL_COLOR_INDEX
) {
1135 palette_sample(ctx
, tObj
, t100
[0], t100
);
1138 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1139 COPY_CHAN4(t010
, tObj
->BorderColor
);
1142 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1143 if (img
->Format
== GL_COLOR_INDEX
) {
1144 palette_sample(ctx
, tObj
, t010
[0], t010
);
1147 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1148 COPY_CHAN4(t110
, tObj
->BorderColor
);
1151 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1152 if (img
->Format
== GL_COLOR_INDEX
) {
1153 palette_sample(ctx
, tObj
, t110
[0], t110
);
1157 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1158 COPY_CHAN4(t001
, tObj
->BorderColor
);
1161 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1162 if (img
->Format
== GL_COLOR_INDEX
) {
1163 palette_sample(ctx
, tObj
, t001
[0], t001
);
1166 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1167 COPY_CHAN4(t101
, tObj
->BorderColor
);
1170 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1171 if (img
->Format
== GL_COLOR_INDEX
) {
1172 palette_sample(ctx
, tObj
, t101
[0], t101
);
1175 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1176 COPY_CHAN4(t011
, tObj
->BorderColor
);
1179 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1180 if (img
->Format
== GL_COLOR_INDEX
) {
1181 palette_sample(ctx
, tObj
, t011
[0], t011
);
1184 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1185 COPY_CHAN4(t111
, tObj
->BorderColor
);
1188 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1189 if (img
->Format
== GL_COLOR_INDEX
) {
1190 palette_sample(ctx
, tObj
, t111
[0], t111
);
1194 #if CHAN_TYPE == GL_FLOAT
1195 rgba
[0] = 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];
1197 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1198 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1199 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1200 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1201 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1202 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1203 #else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
1204 rgba
[0] = (GLchan
) (
1205 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1206 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1208 rgba
[1] = (GLchan
) (
1209 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1210 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1212 rgba
[2] = (GLchan
) (
1213 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1214 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1216 rgba
[3] = (GLchan
) (
1217 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1218 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1228 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1229 const struct gl_texture_object
*tObj
,
1230 GLfloat s
, GLfloat t
, GLfloat r
,
1231 GLfloat lambda
, GLchan rgba
[4] )
1234 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1235 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, rgba
);
1240 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1241 const struct gl_texture_object
*tObj
,
1242 GLfloat s
, GLfloat t
, GLfloat r
,
1243 GLfloat lambda
, GLchan rgba
[4])
1246 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1247 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, rgba
);
1252 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1253 const struct gl_texture_object
*tObj
,
1254 GLfloat s
, GLfloat t
, GLfloat r
,
1255 GLfloat lambda
, GLchan rgba
[4])
1259 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1261 if (level
>= tObj
->_MaxLevel
) {
1262 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1266 GLchan t0
[4], t1
[4]; /* texels */
1267 const GLfloat f
= FRAC(lambda
);
1268 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, t0
);
1269 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, r
, t1
);
1270 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1271 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1272 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1273 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1279 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1280 const struct gl_texture_object
*tObj
,
1281 GLfloat s
, GLfloat t
, GLfloat r
,
1282 GLfloat lambda
, GLchan rgba
[4] )
1286 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1288 if (level
>= tObj
->_MaxLevel
) {
1289 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, r
, rgba
);
1292 GLchan t0
[4], t1
[4]; /* texels */
1293 const GLfloat f
= FRAC(lambda
);
1294 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, t0
);
1295 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, r
, t1
);
1296 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1297 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1298 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1299 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1305 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1306 const struct gl_texture_object
*tObj
, GLuint n
,
1307 const GLfloat s
[], const GLfloat t
[],
1308 const GLfloat u
[], const GLfloat lambda
[],
1312 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1315 sample_3d_nearest(ctx
, tObj
, image
, s
[i
], t
[i
], u
[i
], rgba
[i
]);
1322 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1323 const struct gl_texture_object
*tObj
, GLuint n
,
1324 const GLfloat s
[], const GLfloat t
[],
1325 const GLfloat u
[], const GLfloat lambda
[],
1329 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1332 sample_3d_linear(ctx
, tObj
, image
, s
[i
], t
[i
], u
[i
], rgba
[i
]);
1338 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1339 * return a texture sample.
1342 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1343 const struct gl_texture_object
*tObj
, GLuint n
,
1344 const GLfloat s
[], const GLfloat t
[],
1345 const GLfloat u
[], const GLfloat lambda
[],
1349 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1353 if (lambda
[i
] > MinMagThresh
) {
1355 switch (tObj
->MinFilter
) {
1357 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1358 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1361 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1362 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1364 case GL_NEAREST_MIPMAP_NEAREST
:
1365 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1366 lambda
[i
], rgba
[i
]);
1368 case GL_LINEAR_MIPMAP_NEAREST
:
1369 sample_3d_linear_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1370 lambda
[i
], rgba
[i
]);
1372 case GL_NEAREST_MIPMAP_LINEAR
:
1373 sample_3d_nearest_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1374 lambda
[i
], rgba
[i
]);
1376 case GL_LINEAR_MIPMAP_LINEAR
:
1377 sample_3d_linear_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1378 lambda
[i
], rgba
[i
]);
1381 _mesa_problem(NULL
, "Bad min filterin sample_3d_texture");
1386 switch (tObj
->MagFilter
) {
1388 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1389 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1392 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1393 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1396 _mesa_problem(NULL
, "Bad mag filter in sample_3d_texture");
1403 /**********************************************************************/
1404 /* Texture Cube Map Sampling Functions */
1405 /**********************************************************************/
1408 * Choose one of six sides of a texture cube map given the texture
1409 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1412 static const struct gl_texture_image
**
1413 choose_cube_face(const struct gl_texture_object
*texObj
,
1414 GLfloat rx
, GLfloat ry
, GLfloat rz
,
1415 GLfloat
*newS
, GLfloat
*newT
)
1419 direction target sc tc ma
1420 ---------- ------------------------------- --- --- ---
1421 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1422 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1423 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1424 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1425 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1426 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1428 const struct gl_texture_image
**imgArray
;
1429 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
1432 if (arx
> ary
&& arx
> arz
) {
1434 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
1440 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
1446 else if (ary
> arx
&& ary
> arz
) {
1448 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
1454 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
1462 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
1468 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
1475 *newS
= ( sc
/ ma
+ 1.0F
) * 0.5F
;
1476 *newT
= ( tc
/ ma
+ 1.0F
) * 0.5F
;
1482 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1483 const struct gl_texture_object
*tObj
, GLuint n
,
1484 const GLfloat s
[], const GLfloat t
[],
1485 const GLfloat u
[], const GLfloat lambda
[],
1490 for (i
= 0; i
< n
; i
++) {
1491 const struct gl_texture_image
**images
;
1493 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
], &newS
, &newT
);
1494 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1495 newS
, newT
, rgba
[i
]);
1501 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1502 const struct gl_texture_object
*tObj
, GLuint n
,
1503 const GLfloat s
[], const GLfloat t
[],
1504 const GLfloat u
[], const GLfloat lambda
[],
1509 for (i
= 0; i
< n
; i
++) {
1510 const struct gl_texture_image
**images
;
1512 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
], &newS
, &newT
);
1513 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1514 newS
, newT
, rgba
[i
]);
1520 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1521 const struct gl_texture_object
*tObj
,
1522 GLfloat s
, GLfloat t
, GLfloat u
,
1523 GLfloat lambda
, GLchan rgba
[4])
1525 const struct gl_texture_image
**images
;
1529 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1531 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1532 sample_2d_nearest(ctx
, tObj
, images
[level
], newS
, newT
, rgba
);
1537 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1538 const struct gl_texture_object
*tObj
,
1539 GLfloat s
, GLfloat t
, GLfloat u
,
1540 GLfloat lambda
, GLchan rgba
[4])
1542 const struct gl_texture_image
**images
;
1546 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1548 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1549 sample_2d_linear(ctx
, tObj
, images
[level
], newS
, newT
, rgba
);
1554 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1555 const struct gl_texture_object
*tObj
,
1556 GLfloat s
, GLfloat t
, GLfloat u
,
1557 GLfloat lambda
, GLchan rgba
[4])
1559 const struct gl_texture_image
**images
;
1563 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1565 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1567 if (level
>= tObj
->_MaxLevel
) {
1568 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
], newS
, newT
, rgba
);
1571 GLchan t0
[4], t1
[4]; /* texels */
1572 const GLfloat f
= FRAC(lambda
);
1573 sample_2d_nearest(ctx
, tObj
, images
[level
], newS
, newT
, t0
);
1574 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newS
, newT
, t1
);
1575 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1576 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1577 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1578 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1584 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1585 const struct gl_texture_object
*tObj
,
1586 GLfloat s
, GLfloat t
, GLfloat u
,
1587 GLfloat lambda
, GLchan rgba
[4])
1589 const struct gl_texture_image
**images
;
1593 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1595 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1597 if (level
>= tObj
->_MaxLevel
) {
1598 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
], newS
, newT
, rgba
);
1601 GLchan t0
[4], t1
[4];
1602 const GLfloat f
= FRAC(lambda
);
1603 sample_2d_linear(ctx
, tObj
, images
[level
], newS
, newT
, t0
);
1604 sample_2d_linear(ctx
, tObj
, images
[level
+1], newS
, newT
, t1
);
1605 rgba
[RCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1606 rgba
[GCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1607 rgba
[BCOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1608 rgba
[ACOMP
] = (GLchan
) INTCAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1614 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1615 const struct gl_texture_object
*tObj
, GLuint n
,
1616 const GLfloat s
[], const GLfloat t
[],
1617 const GLfloat u
[], const GLfloat lambda
[],
1620 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1623 for (i
= 0; i
< n
; i
++) {
1624 if (lambda
[i
] > MinMagThresh
) {
1626 switch (tObj
->MinFilter
) {
1629 const struct gl_texture_image
**images
;
1631 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1633 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1634 newS
, newT
, rgba
[i
]);
1639 const struct gl_texture_image
**images
;
1641 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1643 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1644 newS
, newT
, rgba
[i
]);
1647 case GL_NEAREST_MIPMAP_NEAREST
:
1648 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1649 lambda
[i
], rgba
[i
]);
1651 case GL_LINEAR_MIPMAP_NEAREST
:
1652 sample_cube_linear_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1653 lambda
[i
], rgba
[i
]);
1655 case GL_NEAREST_MIPMAP_LINEAR
:
1656 sample_cube_nearest_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1657 lambda
[i
], rgba
[i
]);
1659 case GL_LINEAR_MIPMAP_LINEAR
:
1660 sample_cube_linear_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1661 lambda
[i
], rgba
[i
]);
1664 _mesa_problem(NULL
, "Bad min filter in sample_lambda_cube");
1669 const struct gl_texture_image
**images
;
1671 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1673 switch (tObj
->MagFilter
) {
1675 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1676 newS
, newT
, rgba
[i
]);
1679 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1680 newS
, newT
, rgba
[i
]);
1683 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_cube");
1691 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
1692 const struct gl_texture_object
*tObj
, GLuint n
,
1693 const GLfloat s
[], const GLfloat t
[],
1694 const GLfloat u
[], const GLfloat lambda
[],
1701 /**********************************************************************/
1702 /* Texture Sampling Setup */
1703 /**********************************************************************/
1707 * Setup the texture sampling function for this texture object.
1710 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
1711 const struct gl_texture_object
*t
)
1713 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1716 swrast
->TextureSample
[texUnit
] = null_sample_func
;
1719 GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
1722 /* Compute min/mag filter threshold */
1723 if (t
->MagFilter
== GL_LINEAR
1724 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
1725 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
1726 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
1729 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
1733 switch (t
->Dimensions
) {
1736 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
1738 else if (t
->MinFilter
==GL_LINEAR
) {
1739 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
1742 ASSERT(t
->MinFilter
==GL_NEAREST
);
1743 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
1748 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
1750 else if (t
->MinFilter
==GL_LINEAR
) {
1751 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
1754 GLint baseLevel
= t
->BaseLevel
;
1755 ASSERT(t
->MinFilter
==GL_NEAREST
);
1756 if (t
->WrapS
== GL_REPEAT
&&
1757 t
->WrapT
== GL_REPEAT
&&
1758 t
->Image
[baseLevel
]->Border
== 0 &&
1759 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
1760 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
1762 else if (t
->WrapS
== GL_REPEAT
&&
1763 t
->WrapT
== GL_REPEAT
&&
1764 t
->Image
[baseLevel
]->Border
== 0 &&
1765 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
1766 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
1769 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
1774 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
1776 else if (t
->MinFilter
==GL_LINEAR
) {
1777 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
1780 ASSERT(t
->MinFilter
==GL_NEAREST
);
1781 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
1784 case 6: /* cube map */
1786 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
1788 else if (t
->MinFilter
==GL_LINEAR
) {
1789 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
1792 ASSERT(t
->MinFilter
==GL_NEAREST
);
1793 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
1797 _mesa_problem(NULL
, "invalid dimensions in _mesa_set_texture_sampler");
1803 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
1804 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
1807 texture_combine(const GLcontext
*ctx
,
1808 const struct gl_texture_unit
*textureUnit
,
1810 CONST
GLchan (*primary_rgba
)[4],
1811 CONST
GLchan (*texel
)[4],
1814 const GLchan (*argRGB
[3])[4];
1815 const GLchan (*argA
[3])[4];
1817 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
1818 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
1819 #if CHAN_TYPE == GL_FLOAT
1820 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
1821 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
1823 const GLint half
= (CHAN_MAX
+ 1) / 2;
1826 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
1827 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
1829 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
1830 ctx
->Extensions
.ARB_texture_env_combine
);
1833 * Do operand setup for up to 3 operands. Loop over the terms.
1835 for (j
= 0; j
< 3; j
++) {
1836 switch (textureUnit
->CombineSourceA
[j
]) {
1840 case GL_PRIMARY_COLOR_EXT
:
1841 argA
[j
] = primary_rgba
;
1843 case GL_PREVIOUS_EXT
:
1844 argA
[j
] = (const GLchan (*)[4]) rgba
;
1846 case GL_CONSTANT_EXT
:
1848 GLchan alpha
, (*c
)[4] = ccolor
[j
];
1849 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
1850 for (i
= 0; i
< n
; i
++)
1851 c
[i
][ACOMP
] = alpha
;
1852 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1856 _mesa_problem(NULL
, "invalid combine source");
1859 switch (textureUnit
->CombineSourceRGB
[j
]) {
1863 case GL_PRIMARY_COLOR_EXT
:
1864 argRGB
[j
] = primary_rgba
;
1866 case GL_PREVIOUS_EXT
:
1867 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
1869 case GL_CONSTANT_EXT
:
1871 GLchan (*c
)[4] = ccolor
[j
];
1872 GLchan red
, green
, blue
, alpha
;
1873 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
1874 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
1875 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
1876 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
1877 for (i
= 0; i
< n
; i
++) {
1879 c
[i
][GCOMP
] = green
;
1881 c
[i
][ACOMP
] = alpha
;
1883 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1887 _mesa_problem(NULL
, "invalid combine source");
1890 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
1891 const GLchan (*src
)[4] = argRGB
[j
];
1892 GLchan (*dst
)[4] = ccolor
[j
];
1894 /* point to new arg[j] storage */
1895 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1897 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
1898 for (i
= 0; i
< n
; i
++) {
1899 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
1900 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
1901 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
1904 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
1905 for (i
= 0; i
< n
; i
++) {
1906 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
1907 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
1908 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
1912 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
1913 for (i
= 0; i
< n
; i
++) {
1914 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1915 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1916 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1921 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
1922 const GLchan (*src
)[4] = argA
[j
];
1923 GLchan (*dst
)[4] = ccolor
[j
];
1924 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1925 for (i
= 0; i
< n
; i
++) {
1926 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1930 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
1931 textureUnit
->CombineModeA
== GL_REPLACE
) {
1932 break; /* done, we need only arg0 */
1936 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
1937 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
1938 break; /* arg0 and arg1 are done. we don't need arg2. */
1943 * Do the texture combine.
1945 switch (textureUnit
->CombineModeRGB
) {
1948 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1950 for (i
= 0; i
< n
; i
++) {
1951 #if CHAN_TYPE == GL_FLOAT
1952 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
1953 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
1954 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
1956 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
1957 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
1958 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
1959 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
1960 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
1961 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
1966 for (i
= 0; i
< n
; i
++) {
1967 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
1968 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
1969 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
1976 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1977 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1978 #if CHAN_TYPE != GL_FLOAT
1979 const GLint shift
= 8 - RGBshift
;
1981 for (i
= 0; i
< n
; i
++) {
1982 #if CHAN_TYPE == GL_FLOAT
1983 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
1984 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
1985 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
1987 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
1988 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
1989 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
1990 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1991 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1992 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1999 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2000 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2001 for (i
= 0; i
< n
; i
++) {
2002 #if CHAN_TYPE == GL_FLOAT
2003 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
2004 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
2005 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
2007 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2008 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2009 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
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
);
2017 case GL_ADD_SIGNED_EXT
:
2019 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2020 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2021 for (i
= 0; i
< n
; i
++) {
2022 #if CHAN_TYPE == GL_FLOAT
2023 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
2024 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
2025 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
2027 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
2028 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
2029 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
2030 r
= (r
< 0) ? 0 : r
<< RGBshift
;
2031 g
= (g
< 0) ? 0 : g
<< RGBshift
;
2032 b
= (b
< 0) ? 0 : b
<< RGBshift
;
2033 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2034 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2035 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2040 case GL_INTERPOLATE_EXT
:
2042 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2043 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2044 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
2045 #if CHAN_TYPE != GL_FLOAT
2046 const GLint shift
= 8 - RGBshift
;
2048 for (i
= 0; i
< n
; i
++) {
2049 #if CHAN_TYPE == GL_FLOAT
2050 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
2051 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
2052 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
2053 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
2054 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
2055 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
2057 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
2058 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
2060 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
2061 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
2063 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
2064 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
2066 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
2067 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
2068 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
2073 case GL_SUBTRACT_ARB
:
2075 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2076 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2077 for (i
= 0; i
< n
; i
++) {
2078 #if CHAN_TYPE == GL_FLOAT
2079 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
2080 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
2081 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
2083 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
2084 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
2085 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
2086 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
2087 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
2088 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
2093 case GL_DOT3_RGB_EXT
:
2094 case GL_DOT3_RGBA_EXT
:
2095 case GL_DOT3_RGB_ARB
:
2096 case GL_DOT3_RGBA_ARB
:
2098 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2099 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2100 /* ATI's EXT extension has a constant scale by 4. The ARB
2101 * one will likely remove this restriction, and we should
2102 * drop the EXT extension in favour of the ARB one.
2104 for (i
= 0; i
< n
; i
++) {
2105 #if CHAN_TYPE == GL_FLOAT
2106 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
2107 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
2108 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
2111 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
2112 (GLint
)arg1
[i
][RCOMP
] - half
) +
2113 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
2114 (GLint
)arg1
[i
][GCOMP
] - half
) +
2115 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
2116 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
2118 dot
= CLAMP(dot
, 0, CHAN_MAX
);
2119 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
2124 _mesa_problem(NULL
, "invalid combine mode");
2127 switch (textureUnit
->CombineModeA
) {
2130 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2132 for (i
= 0; i
< n
; i
++) {
2133 #if CHAN_TYPE == GL_FLOAT
2134 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
2136 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
2138 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2142 for (i
= 0; i
< n
; i
++) {
2143 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
2150 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2151 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2152 #if CHAN_TYPE != GL_FLOAT
2153 const GLint shift
= 8 - Ashift
;
2155 for (i
= 0; i
< n
; i
++) {
2156 #if CHAN_TYPE == GL_FLOAT
2157 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
2159 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
2160 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2167 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2168 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2169 for (i
= 0; i
< n
; i
++) {
2170 #if CHAN_TYPE == GL_FLOAT
2171 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
2173 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
2174 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2179 case GL_ADD_SIGNED_EXT
:
2181 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2182 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2183 for (i
= 0; i
< n
; i
++) {
2184 #if CHAN_TYPE == GL_FLOAT
2185 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
2187 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
2188 a
= (a
< 0) ? 0 : a
<< Ashift
;
2189 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2194 case GL_INTERPOLATE_EXT
:
2196 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
2197 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
2198 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
2199 #if CHAN_TYPE != GL_FLOAT
2200 const GLint shift
= 8 - Ashift
;
2202 for (i
=0; i
<n
; i
++) {
2203 #if CHAN_TYPE == GL_FLOAT
2204 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
2205 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
2208 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
2209 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
2211 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
2216 case GL_SUBTRACT_ARB
:
2218 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
2219 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
2220 for (i
= 0; i
< n
; i
++) {
2221 #if CHAN_TYPE == GL_FLOAT
2222 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
2224 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << RGBshift
;
2225 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
2232 _mesa_problem(NULL
, "invalid combine mode");
2235 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2237 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
2238 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
2239 for (i
= 0; i
< n
; i
++) {
2240 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
2243 UNDEFARRAY(ccolor
); /* mac 32k limitation */
2249 /**********************************************************************/
2250 /* Texture Application */
2251 /**********************************************************************/
2255 * Combine incoming fragment color with texel color to produce output color.
2256 * Input: textureUnit - pointer to texture unit to apply
2257 * format - base internal texture format
2258 * n - number of fragments
2259 * primary_rgba - primary colors (may alias rgba for single texture)
2260 * texels - array of texel colors
2261 * InOut: rgba - incoming fragment colors modified by texel colors
2262 * according to the texture environment mode.
2265 apply_texture( const GLcontext
*ctx
,
2266 const struct gl_texture_unit
*texUnit
,
2268 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
2273 GLint Rc
, Gc
, Bc
, Ac
;
2277 ASSERT(texUnit
->_Current
);
2279 baseLevel
= texUnit
->_Current
->BaseLevel
;
2280 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
2282 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
2284 if (format
==GL_COLOR_INDEX
|| format
==GL_DEPTH_COMPONENT
) {
2285 format
= GL_RGBA
; /* XXXX a hack! */
2288 switch (texUnit
->EnvMode
) {
2295 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2301 GLchan Lt
= texel
[i
][RCOMP
];
2302 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2306 case GL_LUMINANCE_ALPHA
:
2308 GLchan Lt
= texel
[i
][RCOMP
];
2310 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2312 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2318 GLchan It
= texel
[i
][RCOMP
];
2319 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
2321 rgba
[i
][ACOMP
] = It
;
2327 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2328 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2329 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2336 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2337 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2338 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2340 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2344 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in apply_texture");
2355 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2361 GLchan Lt
= texel
[i
][RCOMP
];
2362 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2363 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2364 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2368 case GL_LUMINANCE_ALPHA
:
2371 GLchan Lt
= texel
[i
][RCOMP
];
2372 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2373 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2374 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2376 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2382 GLchan It
= texel
[i
][RCOMP
];
2383 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
2384 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
2385 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
2387 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
2393 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2394 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2395 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2402 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2403 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2404 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2406 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2410 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in apply_texture");
2419 case GL_LUMINANCE_ALPHA
:
2426 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2427 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2428 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2434 /* Cv = Cf(1-At) + CtAt */
2435 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
2436 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
2437 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
2438 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
2443 _mesa_problem(ctx
, "Bad format (GL_DECAL) in apply_texture");
2449 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
2450 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
2451 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
2452 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
2458 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2463 /* Cv = Cf(1-Lt) + CcLt */
2464 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2465 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2466 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2467 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2471 case GL_LUMINANCE_ALPHA
:
2473 /* Cv = Cf(1-Lt) + CcLt */
2474 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2475 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2476 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2477 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2479 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2484 /* Cv = Cf(1-It) + CcLt */
2485 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
2486 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
2487 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
2488 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
2489 /* Av = Af(1-It) + Ac*It */
2490 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
2495 /* Cv = Cf(1-Ct) + CcCt */
2496 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2497 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2498 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2504 /* Cv = Cf(1-Ct) + CcCt */
2505 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2506 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2507 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2509 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2513 _mesa_problem(ctx
, "Bad format (GL_BLEND) in apply_texture");
2518 /* XXX don't clamp results if GLchan is float??? */
2520 case GL_ADD
: /* GL_EXT_texture_add_env */
2527 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2532 GLuint Lt
= texel
[i
][RCOMP
];
2533 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2534 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2535 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2536 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2537 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2538 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2542 case GL_LUMINANCE_ALPHA
:
2544 GLuint Lt
= texel
[i
][RCOMP
];
2545 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2546 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2547 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2548 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2549 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2550 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2551 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2556 GLchan It
= texel
[i
][RCOMP
];
2557 GLuint r
= rgba
[i
][RCOMP
] + It
;
2558 GLuint g
= rgba
[i
][GCOMP
] + It
;
2559 GLuint b
= rgba
[i
][BCOMP
] + It
;
2560 GLuint a
= rgba
[i
][ACOMP
] + It
;
2561 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2562 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2563 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2564 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
2569 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2570 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2571 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2572 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2573 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2574 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2580 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2581 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2582 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2583 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2584 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2585 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2586 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2590 _mesa_problem(ctx
, "Bad format (GL_ADD) in apply_texture");
2595 case GL_COMBINE_EXT
:
2596 texture_combine(ctx
, texUnit
, n
, primary_rgba
, texel
, rgba
);
2600 _mesa_problem(ctx
, "Bad env mode in apply_texture");
2608 * Sample a shadow/depth texture.
2609 * Input: ctx - context
2610 * texUnit - the texture unit
2611 * n - number of samples
2612 * s,t,r - array [n] of texture coordinates
2613 * In/Out: rgba - array [n] of texel colors.
2616 sample_depth_texture(const GLcontext
*ctx
,
2617 const struct gl_texture_unit
*texUnit
,
2619 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2622 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2623 const GLint baseLevel
= texObj
->BaseLevel
;
2624 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2625 const GLuint width
= texImage
->Width
;
2626 const GLuint height
= texImage
->Height
;
2627 const GLchan ambient
= texObj
->ShadowAmbient
;
2628 GLboolean lequal
, gequal
;
2630 if (texObj
->Dimensions
!= 2) {
2631 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2635 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2636 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2640 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2641 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2642 * isn't a depth texture.
2644 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2645 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2649 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2658 if (texObj
->MagFilter
== GL_NEAREST
) {
2660 for (i
= 0; i
< n
; i
++) {
2661 GLfloat depthSample
;
2663 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2664 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2665 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2666 if ((r
[i
] <= depthSample
&& lequal
) ||
2667 (r
[i
] >= depthSample
&& gequal
)) {
2668 texel
[i
][RCOMP
] = CHAN_MAX
;
2669 texel
[i
][GCOMP
] = CHAN_MAX
;
2670 texel
[i
][BCOMP
] = CHAN_MAX
;
2671 texel
[i
][ACOMP
] = CHAN_MAX
;
2674 texel
[i
][RCOMP
] = ambient
;
2675 texel
[i
][GCOMP
] = ambient
;
2676 texel
[i
][BCOMP
] = ambient
;
2677 texel
[i
][ACOMP
] = CHAN_MAX
;
2683 ASSERT(texObj
->MagFilter
== GL_LINEAR
);
2684 for (i
= 0; i
< n
; i
++) {
2685 GLfloat depth00
, depth01
, depth10
, depth11
;
2686 GLint i0
, i1
, j0
, j1
;
2688 GLuint useBorderTexel
;
2690 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapS
, s
[i
], u
, width
, i0
, i1
);
2691 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapT
, t
[i
], v
, height
,j0
, j1
);
2694 if (texImage
->Border
) {
2695 i0
+= texImage
->Border
;
2696 i1
+= texImage
->Border
;
2697 j0
+= texImage
->Border
;
2698 j1
+= texImage
->Border
;
2701 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2702 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2703 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2704 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2707 /* get four depth samples from the texture */
2708 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2712 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2714 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2718 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2720 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2724 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2726 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2730 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2734 /* compute a single weighted depth sample and do one comparison */
2735 const GLfloat a
= FRAC(u
+ 1.0F
);
2736 const GLfloat b
= FRAC(v
+ 1.0F
);
2737 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2738 const GLfloat w10
= ( a
) * (1.0F
- b
);
2739 const GLfloat w01
= (1.0F
- a
) * ( b
);
2740 const GLfloat w11
= ( a
) * ( b
);
2741 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2742 + w01
* depth01
+ w11
* depth11
;
2743 if ((depthSample
<= r
[i
] && lequal
) ||
2744 (depthSample
>= r
[i
] && gequal
)) {
2745 texel
[i
][RCOMP
] = ambient
;
2746 texel
[i
][GCOMP
] = ambient
;
2747 texel
[i
][BCOMP
] = ambient
;
2748 texel
[i
][ACOMP
] = CHAN_MAX
;
2751 texel
[i
][RCOMP
] = CHAN_MAX
;
2752 texel
[i
][GCOMP
] = CHAN_MAX
;
2753 texel
[i
][BCOMP
] = CHAN_MAX
;
2754 texel
[i
][ACOMP
] = CHAN_MAX
;
2758 /* Do four depth/R comparisons and compute a weighted result.
2759 * If this touches on somebody's I.P., I'll remove this code
2762 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2763 GLfloat luminance
= CHAN_MAXF
;
2766 if (depth00
<= r
[i
]) luminance
-= d
;
2767 if (depth01
<= r
[i
]) luminance
-= d
;
2768 if (depth10
<= r
[i
]) luminance
-= d
;
2769 if (depth11
<= r
[i
]) luminance
-= d
;
2772 if (depth00
>= r
[i
]) luminance
-= d
;
2773 if (depth01
>= r
[i
]) luminance
-= d
;
2774 if (depth10
>= r
[i
]) luminance
-= d
;
2775 if (depth11
>= r
[i
]) luminance
-= d
;
2777 lum
= (GLchan
) luminance
;
2778 texel
[i
][RCOMP
] = lum
;
2779 texel
[i
][GCOMP
] = lum
;
2780 texel
[i
][BCOMP
] = lum
;
2781 texel
[i
][ACOMP
] = CHAN_MAX
;
2790 * Experimental depth texture sampling function.
2793 sample_depth_texture2(const GLcontext
*ctx
,
2794 const struct gl_texture_unit
*texUnit
,
2796 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2799 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2800 const GLint baseLevel
= texObj
->BaseLevel
;
2801 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2802 const GLuint width
= texImage
->Width
;
2803 const GLuint height
= texImage
->Height
;
2804 const GLchan ambient
= texObj
->ShadowAmbient
;
2805 GLboolean lequal
, gequal
;
2807 if (texObj
->Dimensions
!= 2) {
2808 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2812 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2813 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2817 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2818 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2819 * isn't a depth texture.
2821 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2822 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2826 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2837 for (i
= 0; i
< n
; i
++) {
2839 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2842 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2843 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2850 if (imin
< 0) imin
= 0;
2851 if (imax
>= width
) imax
= width
- 1;
2852 if (jmin
< 0) jmin
= 0;
2853 if (jmax
>= height
) jmax
= height
- 1;
2855 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2857 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2858 for (ii
= imin
; ii
<= imax
; ii
++) {
2859 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2861 if ((depthSample
<= r
[i
] && lequal
) ||
2862 (depthSample
>= r
[i
] && gequal
)) {
2868 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2869 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2872 texel
[i
][RCOMP
] = lum
;
2873 texel
[i
][GCOMP
] = lum
;
2874 texel
[i
][BCOMP
] = lum
;
2875 texel
[i
][ACOMP
] = CHAN_MAX
;
2883 * Apply a unit of texture mapping to the incoming fragments.
2886 _swrast_texture_fragments( GLcontext
*ctx
, GLuint texUnit
, GLuint n
,
2887 const GLfloat s
[], const GLfloat t
[],
2888 const GLfloat r
[], GLfloat lambda
[],
2889 CONST GLchan primary_rgba
[][4], GLchan rgba
[][4] )
2891 const GLuint mask
= TEXTURE0_ANY
<< (texUnit
* 4);
2893 if (ctx
->Texture
._ReallyEnabled
& mask
) {
2894 const struct gl_texture_unit
*textureUnit
= &ctx
->Texture
.Unit
[texUnit
];
2896 if (textureUnit
->_Current
) { /* XXX need this? */
2897 GLchan texel
[PB_SIZE
][4];
2899 if (textureUnit
->LodBias
!= 0.0F
) {
2900 /* apply LOD bias, but don't clamp yet */
2903 lambda
[i
] += textureUnit
->LodBias
;
2907 if ((textureUnit
->_Current
->MinLod
!= -1000.0
2908 || textureUnit
->_Current
->MaxLod
!= 1000.0)
2910 /* apply LOD clamping to lambda */
2911 const GLfloat min
= textureUnit
->_Current
->MinLod
;
2912 const GLfloat max
= textureUnit
->_Current
->MaxLod
;
2915 GLfloat l
= lambda
[i
];
2916 lambda
[i
] = CLAMP(l
, min
, max
);
2920 /* Sample the texture. */
2921 if (textureUnit
->_Current
->CompareFlag
) {
2923 sample_depth_texture(ctx
, textureUnit
, n
, s
, t
, r
, texel
);
2927 SWRAST_CONTEXT(ctx
)->TextureSample
[texUnit
]( ctx
, texUnit
,
2928 textureUnit
->_Current
,
2932 apply_texture( ctx
, textureUnit
, n
, primary_rgba
,
2933 (const GLchan (*)[4]) texel
, rgba
);