1 /* $Id: s_texture.c,v 1.19 2001/03/23 18:53:26 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.
36 #include "s_context.h"
38 #include "s_texture.h"
41 /* XXX this is temporary, until GL/glext.h is updated. */
42 #ifndef GL_DOT3_RGB_ARB
43 #define GL_DOT3_RGB_ARB 0x86AE
45 #ifndef GL_DOT3_RGBA_ARB
46 #define GL_DOT3_RGBA_ARB 0x86AF
51 * These values are used in the fixed-point arithmetic used
52 * for linear filtering.
54 #define WEIGHT_SCALE 65536.0F
55 #define WEIGHT_SHIFT 16
59 * Used to compute texel locations for linear sampling.
61 * wrapMode = GL_REPEAT, GL_CLAMP or GL_CLAMP_TO_EDGE
62 * S = texcoord in [0,1]
63 * SIZE = width (or height or depth) of texture
65 * U = texcoord in [0, width]
66 * I0, I1 = two nearest texel indexes
68 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
70 if (wrapMode == GL_REPEAT) { \
71 U = S * SIZE - 0.5F; \
72 I0 = IFLOOR(U) & (SIZE - 1); \
73 I1 = (I0 + 1) & (SIZE - 1); \
85 if (wrapMode == GL_CLAMP_TO_EDGE) { \
88 if (I1 >= (GLint) SIZE) \
96 * Used to compute texel location for nearest sampling.
98 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
100 if (wrapMode == GL_REPEAT) { \
101 /* s limited to [0,1) */ \
102 /* i limited to [0,width-1] */ \
103 I = (GLint) (S * SIZE); \
108 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
109 const GLfloat min = 1.0F / (2.0F * SIZE); \
110 const GLfloat max = 1.0F - min; \
116 I = (GLint) (S * SIZE); \
119 ASSERT(wrapMode == GL_CLAMP); \
120 /* s limited to [0,1] */ \
121 /* i limited to [0,width-1] */ \
124 else if (S >= 1.0F) \
127 I = (GLint) (S * SIZE); \
133 * Compute linear mipmap levels for given lambda.
135 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
139 else if (lambda > tObj->_MaxLambda) \
140 lambda = tObj->_MaxLambda; \
141 level = (GLint) (tObj->BaseLevel + lambda); \
146 * Compute nearest mipmap level for given lambda.
148 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
150 if (lambda <= 0.5F) \
152 else if (lambda > tObj->_MaxLambda + 0.4999F) \
153 lambda = tObj->_MaxLambda + 0.4999F; \
154 level = (GLint) (tObj->BaseLevel + lambda + 0.5F); \
155 if (level > tObj->_MaxLevel) \
156 level = tObj->_MaxLevel; \
163 * Bitflags for texture border color sampling.
175 * Get texture palette entry.
178 palette_sample(const GLcontext
*ctx
,
179 const struct gl_texture_object
*tObj
,
180 GLint index
, GLchan rgba
[4] )
182 const GLchan
*palette
;
185 if (ctx
->Texture
.SharedPalette
) {
186 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
187 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
188 format
= ctx
->Texture
.Palette
.Format
;
191 ASSERT(!tObj
->Palette
.FloatTable
);
192 palette
= (const GLchan
*) tObj
->Palette
.Table
;
193 format
= tObj
->Palette
.Format
;
198 rgba
[ACOMP
] = palette
[index
];
202 rgba
[RCOMP
] = palette
[index
];
204 case GL_LUMINANCE_ALPHA
:
205 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
206 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
209 rgba
[RCOMP
] = palette
[index
* 3 + 0];
210 rgba
[GCOMP
] = palette
[index
* 3 + 1];
211 rgba
[BCOMP
] = palette
[index
* 3 + 2];
214 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
215 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
216 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
217 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
220 _mesa_problem(ctx
, "Bad palette format in palette_sample");
226 /**********************************************************************/
227 /* 1-D Texture Sampling Functions */
228 /**********************************************************************/
231 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
234 sample_1d_nearest(GLcontext
*ctx
,
235 const struct gl_texture_object
*tObj
,
236 const struct gl_texture_image
*img
,
237 GLfloat s
, GLchan rgba
[4])
239 const GLint width
= img
->Width2
; /* without border, power of two */
242 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
244 /* skip over the border, if any */
247 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
248 if (img
->Format
== GL_COLOR_INDEX
) {
249 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
256 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
259 sample_1d_linear(GLcontext
*ctx
,
260 const struct gl_texture_object
*tObj
,
261 const struct gl_texture_image
*img
,
262 GLfloat s
, GLchan rgba
[4])
264 const GLint width
= img
->Width2
;
267 GLuint useBorderColor
;
269 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
277 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
278 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
282 const GLfloat a
= FRAC(u
);
283 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
284 const GLint w0
= IROUND((1.0F
-a
) * WEIGHT_SCALE
);
285 const GLint w1
= IROUND( a
* WEIGHT_SCALE
);
287 GLchan t0
[4], t1
[4]; /* texels */
289 if (useBorderColor
& I0BIT
) {
290 COPY_CHAN4(t0
, tObj
->BorderColor
);
293 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
294 if (img
->Format
== GL_COLOR_INDEX
) {
295 palette_sample(ctx
, tObj
, t0
[0], t0
);
298 if (useBorderColor
& I1BIT
) {
299 COPY_CHAN4(t1
, tObj
->BorderColor
);
302 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
303 if (img
->Format
== GL_COLOR_INDEX
) {
304 palette_sample(ctx
, tObj
, t1
[0], t1
);
308 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
309 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
310 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
311 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
317 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
318 const struct gl_texture_object
*tObj
,
319 GLfloat s
, GLfloat lambda
,
323 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
324 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, rgba
);
329 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
330 const struct gl_texture_object
*tObj
,
331 GLfloat s
, GLfloat lambda
,
335 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
336 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, rgba
);
342 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
343 const struct gl_texture_object
*tObj
,
344 GLfloat s
, GLfloat lambda
,
349 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
351 if (level
>= tObj
->_MaxLevel
) {
352 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, rgba
);
356 const GLfloat f
= FRAC(lambda
);
357 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t0
);
358 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t1
);
359 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
360 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
361 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
362 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
369 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
370 const struct gl_texture_object
*tObj
,
371 GLfloat s
, GLfloat lambda
,
376 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
378 if (level
>= tObj
->_MaxLevel
) {
379 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, rgba
);
383 const GLfloat f
= FRAC(lambda
);
384 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t0
);
385 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t1
);
386 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
387 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
388 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
389 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
396 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
397 const struct gl_texture_object
*tObj
, GLuint n
,
398 const GLfloat s
[], const GLfloat t
[],
399 const GLfloat u
[], const GLfloat lambda
[],
403 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
408 sample_1d_nearest(ctx
, tObj
, image
, s
[i
], rgba
[i
]);
415 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
416 const struct gl_texture_object
*tObj
, GLuint n
,
417 const GLfloat s
[], const GLfloat t
[],
418 const GLfloat u
[], const GLfloat lambda
[],
422 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
427 sample_1d_linear(ctx
, tObj
, image
, s
[i
], rgba
[i
]);
433 * Given an (s) texture coordinate and lambda (level of detail) value,
434 * return a texture sample.
438 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
439 const struct gl_texture_object
*tObj
, GLuint n
,
440 const GLfloat s
[], const GLfloat t
[],
441 const GLfloat u
[], const GLfloat lambda
[],
444 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
451 if (lambda
[i
] > MinMagThresh
) {
453 switch (tObj
->MinFilter
) {
455 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
459 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
462 case GL_NEAREST_MIPMAP_NEAREST
:
463 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, lambda
[i
], s
[i
],
466 case GL_LINEAR_MIPMAP_NEAREST
:
467 sample_1d_linear_mipmap_nearest(ctx
, tObj
, s
[i
], lambda
[i
],
470 case GL_NEAREST_MIPMAP_LINEAR
:
471 sample_1d_nearest_mipmap_linear(ctx
, tObj
, s
[i
], lambda
[i
],
474 case GL_LINEAR_MIPMAP_LINEAR
:
475 sample_1d_linear_mipmap_linear(ctx
, tObj
, s
[i
], lambda
[i
],
479 _mesa_problem(NULL
, "Bad min filter in sample_1d_texture");
485 switch (tObj
->MagFilter
) {
487 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
491 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
495 _mesa_problem(NULL
, "Bad mag filter in sample_1d_texture");
505 /**********************************************************************/
506 /* 2-D Texture Sampling Functions */
507 /**********************************************************************/
511 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
514 sample_2d_nearest(GLcontext
*ctx
,
515 const struct gl_texture_object
*tObj
,
516 const struct gl_texture_image
*img
,
517 GLfloat s
, GLfloat t
,
520 const GLint width
= img
->Width2
; /* without border, power of two */
521 const GLint height
= img
->Height2
; /* without border, power of two */
524 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
525 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, t
, height
, j
);
527 /* skip over the border, if any */
531 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
532 if (img
->Format
== GL_COLOR_INDEX
) {
533 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
540 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
541 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
544 sample_2d_linear(GLcontext
*ctx
,
545 const struct gl_texture_object
*tObj
,
546 const struct gl_texture_image
*img
,
547 GLfloat s
, GLfloat t
,
550 const GLint width
= img
->Width2
;
551 const GLint height
= img
->Height2
;
552 GLint i0
, j0
, i1
, j1
;
553 GLuint useBorderColor
;
556 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
557 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, t
, v
, height
, j0
, j1
);
567 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
568 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
569 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
570 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
574 const GLfloat a
= FRAC(u
);
575 const GLfloat b
= FRAC(v
);
576 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
577 const GLint w00
= IROUND((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
578 const GLint w10
= IROUND( a
* (1.0F
-b
) * WEIGHT_SCALE
);
579 const GLint w01
= IROUND((1.0F
-a
) * b
* WEIGHT_SCALE
);
580 const GLint w11
= IROUND( a
* b
* WEIGHT_SCALE
);
586 if (useBorderColor
& (I0BIT
| J0BIT
)) {
587 COPY_CHAN4(t00
, tObj
->BorderColor
);
590 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
591 if (img
->Format
== GL_COLOR_INDEX
) {
592 palette_sample(ctx
, tObj
, t00
[0], t00
);
595 if (useBorderColor
& (I1BIT
| J0BIT
)) {
596 COPY_CHAN4(t10
, tObj
->BorderColor
);
599 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
600 if (img
->Format
== GL_COLOR_INDEX
) {
601 palette_sample(ctx
, tObj
, t10
[0], t10
);
604 if (useBorderColor
& (I0BIT
| J1BIT
)) {
605 COPY_CHAN4(t01
, tObj
->BorderColor
);
608 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
609 if (img
->Format
== GL_COLOR_INDEX
) {
610 palette_sample(ctx
, tObj
, t01
[0], t01
);
613 if (useBorderColor
& (I1BIT
| J1BIT
)) {
614 COPY_CHAN4(t11
, tObj
->BorderColor
);
617 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
618 if (img
->Format
== GL_COLOR_INDEX
) {
619 palette_sample(ctx
, tObj
, t11
[0], t11
);
623 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
624 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
625 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
626 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
634 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
635 const struct gl_texture_object
*tObj
,
636 GLfloat s
, GLfloat t
, GLfloat lambda
,
640 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
641 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, rgba
);
647 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
648 const struct gl_texture_object
*tObj
,
649 GLfloat s
, GLfloat t
, GLfloat lambda
,
653 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
654 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, rgba
);
660 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
661 const struct gl_texture_object
*tObj
,
662 GLfloat s
, GLfloat t
, GLfloat lambda
,
667 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
669 if (level
>= tObj
->_MaxLevel
) {
670 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, rgba
);
673 GLchan t0
[4], t1
[4]; /* texels */
674 const GLfloat f
= FRAC(lambda
);
675 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, t0
);
676 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, t1
);
677 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
678 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
679 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
680 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
687 sample_2d_linear_mipmap_linear(GLcontext
*ctx
,
688 const struct gl_texture_object
*tObj
,
689 GLfloat s
, GLfloat t
, GLfloat lambda
,
694 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
696 if (level
>= tObj
->_MaxLevel
) {
697 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, rgba
);
700 GLchan t0
[4], t1
[4]; /* texels */
701 const GLfloat f
= FRAC(lambda
);
702 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, t0
);
703 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, t1
);
704 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
705 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
706 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
707 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
714 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
715 const struct gl_texture_object
*tObj
, GLuint n
,
716 const GLfloat s
[], const GLfloat t
[],
717 const GLfloat u
[], const GLfloat lambda
[],
721 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
725 sample_2d_nearest(ctx
, tObj
, image
, s
[i
], t
[i
], rgba
[i
]);
732 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
733 const struct gl_texture_object
*tObj
, GLuint n
,
734 const GLfloat s
[], const GLfloat t
[],
735 const GLfloat u
[], const GLfloat lambda
[],
739 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
743 sample_2d_linear(ctx
, tObj
, image
, s
[i
], t
[i
], rgba
[i
]);
749 * Given an array of (s,t) texture coordinate and lambda (level of detail)
750 * values, return an array of texture sample.
753 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
754 const struct gl_texture_object
*tObj
,
756 const GLfloat s
[], const GLfloat t
[],
757 const GLfloat u
[], const GLfloat lambda
[],
760 const GLfloat minMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
764 /* since lambda is monotonous-array use this check first */
765 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
766 /* magnification for whole span */
767 switch (tObj
->MagFilter
) {
769 sample_nearest_2d(ctx
, texUnit
, tObj
, n
, s
, t
, u
,
773 sample_linear_2d(ctx
, texUnit
, tObj
, n
, s
, t
, u
,
777 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_2d");
781 for (i
= 0; i
< n
; i
++) {
782 if (lambda
[i
] > minMagThresh
) {
784 switch (tObj
->MinFilter
) {
786 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
787 s
[i
], t
[i
], rgba
[i
]);
790 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
791 s
[i
], t
[i
], rgba
[i
]);
793 case GL_NEAREST_MIPMAP_NEAREST
:
794 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
],
797 case GL_LINEAR_MIPMAP_NEAREST
:
798 sample_2d_linear_mipmap_nearest(ctx
,tObj
, s
[i
], t
[i
],
801 case GL_NEAREST_MIPMAP_LINEAR
:
802 sample_2d_nearest_mipmap_linear(ctx
,tObj
, s
[i
], t
[i
],
805 case GL_LINEAR_MIPMAP_LINEAR
:
806 sample_2d_linear_mipmap_linear(ctx
,tObj
, s
[i
], t
[i
],
807 lambda
[i
], rgba
[i
] );
810 _mesa_problem(NULL
, "Bad min filter in sample_2d_texture");
816 switch (tObj
->MagFilter
) {
818 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
819 s
[i
], t
[i
], rgba
[i
]);
822 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
823 s
[i
], t
[i
], rgba
[i
] );
826 _mesa_problem(NULL
, "Bad mag filter in sample_2d_texture");
835 * Optimized 2-D texture sampling:
836 * S and T wrap mode == GL_REPEAT
837 * GL_NEAREST min/mag filter
842 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
843 const struct gl_texture_object
*tObj
,
844 GLuint n
, const GLfloat s
[], const GLfloat t
[],
845 const GLfloat u
[], const GLfloat lambda
[],
848 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
849 const GLfloat width
= (GLfloat
) img
->Width
;
850 const GLfloat height
= (GLfloat
) img
->Height
;
851 const GLint colMask
= img
->Width
- 1;
852 const GLint rowMask
= img
->Height
- 1;
853 const GLint shift
= img
->WidthLog2
;
857 ASSERT(tObj
->WrapS
==GL_REPEAT
);
858 ASSERT(tObj
->WrapT
==GL_REPEAT
);
859 ASSERT(tObj
->MinFilter
==GL_NEAREST
);
860 ASSERT(tObj
->MagFilter
==GL_NEAREST
);
861 ASSERT(img
->Border
==0);
862 ASSERT(img
->Format
==GL_RGB
);
864 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
866 GLint i
= (GLint
) ((s
[k
] + 10000.0) * width
) & colMask
;
867 GLint j
= (GLint
) ((t
[k
] + 10000.0) * height
) & rowMask
;
868 GLint pos
= (j
<< shift
) | i
;
869 GLchan
*texel
= ((GLchan
*) img
->Data
) + pos
+ pos
+ pos
; /* pos*3 */
870 rgba
[k
][RCOMP
] = texel
[0];
871 rgba
[k
][GCOMP
] = texel
[1];
872 rgba
[k
][BCOMP
] = texel
[2];
878 * Optimized 2-D texture sampling:
879 * S and T wrap mode == GL_REPEAT
880 * GL_NEAREST min/mag filter
885 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
886 const struct gl_texture_object
*tObj
,
887 GLuint n
, const GLfloat s
[], const GLfloat t
[],
888 const GLfloat u
[], const GLfloat lambda
[],
891 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
892 const GLfloat width
= (GLfloat
) img
->Width
;
893 const GLfloat height
= (GLfloat
) img
->Height
;
894 const GLint colMask
= img
->Width
- 1;
895 const GLint rowMask
= img
->Height
- 1;
896 const GLint shift
= img
->WidthLog2
;
900 ASSERT(tObj
->WrapS
==GL_REPEAT
);
901 ASSERT(tObj
->WrapT
==GL_REPEAT
);
902 ASSERT(tObj
->MinFilter
==GL_NEAREST
);
903 ASSERT(tObj
->MagFilter
==GL_NEAREST
);
904 ASSERT(img
->Border
==0);
905 ASSERT(img
->Format
==GL_RGBA
);
907 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
909 GLint i
= (GLint
) ((s
[k
] + 10000.0) * width
) & colMask
;
910 GLint j
= (GLint
) ((t
[k
] + 10000.0) * height
) & rowMask
;
911 GLint pos
= (j
<< shift
) | i
;
912 GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
913 rgba
[k
][RCOMP
] = texel
[0];
914 rgba
[k
][GCOMP
] = texel
[1];
915 rgba
[k
][BCOMP
] = texel
[2];
916 rgba
[k
][ACOMP
] = texel
[3];
922 /**********************************************************************/
923 /* 3-D Texture Sampling Functions */
924 /**********************************************************************/
927 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
930 sample_3d_nearest(GLcontext
*ctx
,
931 const struct gl_texture_object
*tObj
,
932 const struct gl_texture_image
*img
,
933 GLfloat s
, GLfloat t
, GLfloat r
,
936 const GLint width
= img
->Width2
; /* without border, power of two */
937 const GLint height
= img
->Height2
; /* without border, power of two */
938 const GLint depth
= img
->Depth2
; /* without border, power of two */
941 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, s
, width
, i
);
942 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, t
, height
, j
);
943 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, r
, depth
, k
);
945 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
946 if (img
->Format
== GL_COLOR_INDEX
) {
947 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
954 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
957 sample_3d_linear(GLcontext
*ctx
,
958 const struct gl_texture_object
*tObj
,
959 const struct gl_texture_image
*img
,
960 GLfloat s
, GLfloat t
, GLfloat r
,
963 const GLint width
= img
->Width2
;
964 const GLint height
= img
->Height2
;
965 const GLint depth
= img
->Depth2
;
966 GLint i0
, j0
, k0
, i1
, j1
, k1
;
967 GLuint useBorderColor
;
970 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, s
, u
, width
, i0
, i1
);
971 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, t
, v
, height
, j0
, j1
);
972 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, r
, w
, depth
, k0
, k1
);
984 /* check if sampling texture border color */
985 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
986 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
987 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
988 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
989 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
990 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
994 const GLfloat a
= FRAC(u
);
995 const GLfloat b
= FRAC(v
);
996 const GLfloat c
= FRAC(w
);
997 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
998 GLint w000
= IROUND((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
999 GLint w100
= IROUND( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1000 GLint w010
= IROUND((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1001 GLint w110
= IROUND( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1002 GLint w001
= IROUND((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1003 GLint w101
= IROUND( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1004 GLint w011
= IROUND((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1005 GLint w111
= IROUND( a
* b
* c
* WEIGHT_SCALE
);
1007 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1008 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1010 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1011 COPY_CHAN4(t000
, tObj
->BorderColor
);
1014 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1015 if (img
->Format
== GL_COLOR_INDEX
) {
1016 palette_sample(ctx
, tObj
, t000
[0], t000
);
1019 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1020 COPY_CHAN4(t100
, tObj
->BorderColor
);
1023 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1024 if (img
->Format
== GL_COLOR_INDEX
) {
1025 palette_sample(ctx
, tObj
, t100
[0], t100
);
1028 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1029 COPY_CHAN4(t010
, tObj
->BorderColor
);
1032 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1033 if (img
->Format
== GL_COLOR_INDEX
) {
1034 palette_sample(ctx
, tObj
, t010
[0], t010
);
1037 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1038 COPY_CHAN4(t110
, tObj
->BorderColor
);
1041 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1042 if (img
->Format
== GL_COLOR_INDEX
) {
1043 palette_sample(ctx
, tObj
, t110
[0], t110
);
1047 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1048 COPY_CHAN4(t001
, tObj
->BorderColor
);
1051 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1052 if (img
->Format
== GL_COLOR_INDEX
) {
1053 palette_sample(ctx
, tObj
, t001
[0], t001
);
1056 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1057 COPY_CHAN4(t101
, tObj
->BorderColor
);
1060 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1061 if (img
->Format
== GL_COLOR_INDEX
) {
1062 palette_sample(ctx
, tObj
, t101
[0], t101
);
1065 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1066 COPY_CHAN4(t011
, tObj
->BorderColor
);
1069 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1070 if (img
->Format
== GL_COLOR_INDEX
) {
1071 palette_sample(ctx
, tObj
, t011
[0], t011
);
1074 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1075 COPY_CHAN4(t111
, tObj
->BorderColor
);
1078 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1079 if (img
->Format
== GL_COLOR_INDEX
) {
1080 palette_sample(ctx
, tObj
, t111
[0], t111
);
1084 rgba
[0] = (GLchan
) (
1085 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1086 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1088 rgba
[1] = (GLchan
) (
1089 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1090 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1092 rgba
[2] = (GLchan
) (
1093 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1094 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1096 rgba
[3] = (GLchan
) (
1097 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1098 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1106 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1107 const struct gl_texture_object
*tObj
,
1108 GLfloat s
, GLfloat t
, GLfloat r
,
1109 GLfloat lambda
, GLchan rgba
[4] )
1112 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1113 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, rgba
);
1118 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1119 const struct gl_texture_object
*tObj
,
1120 GLfloat s
, GLfloat t
, GLfloat r
,
1121 GLfloat lambda
, GLchan rgba
[4])
1124 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1125 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, rgba
);
1130 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1131 const struct gl_texture_object
*tObj
,
1132 GLfloat s
, GLfloat t
, GLfloat r
,
1133 GLfloat lambda
, GLchan rgba
[4])
1137 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1139 if (level
>= tObj
->_MaxLevel
) {
1140 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1144 GLchan t0
[4], t1
[4]; /* texels */
1145 const GLfloat f
= FRAC(lambda
);
1146 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, t0
);
1147 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, r
, t1
);
1148 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1149 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1150 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1151 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1157 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1158 const struct gl_texture_object
*tObj
,
1159 GLfloat s
, GLfloat t
, GLfloat r
,
1160 GLfloat lambda
, GLchan rgba
[4] )
1164 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1166 if (level
>= tObj
->_MaxLevel
) {
1167 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
], s
, t
, r
, rgba
);
1170 GLchan t0
[4], t1
[4]; /* texels */
1171 const GLfloat f
= FRAC(lambda
);
1172 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], s
, t
, r
, t0
);
1173 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], s
, t
, r
, t1
);
1174 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1175 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1176 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1177 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1183 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1184 const struct gl_texture_object
*tObj
, GLuint n
,
1185 const GLfloat s
[], const GLfloat t
[],
1186 const GLfloat u
[], const GLfloat lambda
[],
1190 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1193 sample_3d_nearest(ctx
, tObj
, image
, s
[i
], t
[i
], u
[i
], rgba
[i
]);
1200 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1201 const struct gl_texture_object
*tObj
, GLuint n
,
1202 const GLfloat s
[], const GLfloat t
[],
1203 const GLfloat u
[], const GLfloat lambda
[],
1207 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1210 sample_3d_linear(ctx
, tObj
, image
, s
[i
], t
[i
], u
[i
], rgba
[i
]);
1216 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1217 * return a texture sample.
1220 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1221 const struct gl_texture_object
*tObj
, GLuint n
,
1222 const GLfloat s
[], const GLfloat t
[],
1223 const GLfloat u
[], const GLfloat lambda
[],
1227 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1231 if (lambda
[i
] > MinMagThresh
) {
1233 switch (tObj
->MinFilter
) {
1235 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1236 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1239 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1240 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1242 case GL_NEAREST_MIPMAP_NEAREST
:
1243 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1244 lambda
[i
], rgba
[i
]);
1246 case GL_LINEAR_MIPMAP_NEAREST
:
1247 sample_3d_linear_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1248 lambda
[i
], rgba
[i
]);
1250 case GL_NEAREST_MIPMAP_LINEAR
:
1251 sample_3d_nearest_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1252 lambda
[i
], rgba
[i
]);
1254 case GL_LINEAR_MIPMAP_LINEAR
:
1255 sample_3d_linear_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1256 lambda
[i
], rgba
[i
]);
1259 _mesa_problem(NULL
, "Bad min filterin sample_3d_texture");
1264 switch (tObj
->MagFilter
) {
1266 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1267 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1270 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1271 s
[i
], t
[i
], u
[i
], rgba
[i
]);
1274 _mesa_problem(NULL
, "Bad mag filter in sample_3d_texture");
1281 /**********************************************************************/
1282 /* Texture Cube Map Sampling Functions */
1283 /**********************************************************************/
1286 * Choose one of six sides of a texture cube map given the texture
1287 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1290 static const struct gl_texture_image
**
1291 choose_cube_face(const struct gl_texture_object
*texObj
,
1292 GLfloat rx
, GLfloat ry
, GLfloat rz
,
1293 GLfloat
*newS
, GLfloat
*newT
)
1297 direction target sc tc ma
1298 ---------- ------------------------------- --- --- ---
1299 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1300 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1301 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1302 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1303 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1304 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1306 const struct gl_texture_image
**imgArray
;
1307 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
1310 if (arx
> ary
&& arx
> arz
) {
1312 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
1318 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
1324 else if (ary
> arx
&& ary
> arz
) {
1326 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
1332 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
1340 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
1346 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
1353 *newS
= ( sc
/ ma
+ 1.0F
) * 0.5F
;
1354 *newT
= ( tc
/ ma
+ 1.0F
) * 0.5F
;
1360 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
1361 const struct gl_texture_object
*tObj
, GLuint n
,
1362 const GLfloat s
[], const GLfloat t
[],
1363 const GLfloat u
[], const GLfloat lambda
[],
1368 for (i
= 0; i
< n
; i
++) {
1369 const struct gl_texture_image
**images
;
1371 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
], &newS
, &newT
);
1372 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1373 newS
, newT
, rgba
[i
]);
1379 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
1380 const struct gl_texture_object
*tObj
, GLuint n
,
1381 const GLfloat s
[], const GLfloat t
[],
1382 const GLfloat u
[], const GLfloat lambda
[],
1387 for (i
= 0; i
< n
; i
++) {
1388 const struct gl_texture_image
**images
;
1390 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
], &newS
, &newT
);
1391 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1392 newS
, newT
, rgba
[i
]);
1398 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1399 const struct gl_texture_object
*tObj
,
1400 GLfloat s
, GLfloat t
, GLfloat u
,
1401 GLfloat lambda
, GLchan rgba
[4])
1403 const struct gl_texture_image
**images
;
1407 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1409 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1410 sample_2d_nearest(ctx
, tObj
, images
[level
], newS
, newT
, rgba
);
1415 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1416 const struct gl_texture_object
*tObj
,
1417 GLfloat s
, GLfloat t
, GLfloat u
,
1418 GLfloat lambda
, GLchan rgba
[4])
1420 const struct gl_texture_image
**images
;
1424 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
, level
);
1426 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1427 sample_2d_linear(ctx
, tObj
, images
[level
], newS
, newT
, rgba
);
1432 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1433 const struct gl_texture_object
*tObj
,
1434 GLfloat s
, GLfloat t
, GLfloat u
,
1435 GLfloat lambda
, GLchan rgba
[4])
1437 const struct gl_texture_image
**images
;
1441 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1443 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1445 if (level
>= tObj
->_MaxLevel
) {
1446 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
], newS
, newT
, rgba
);
1449 GLchan t0
[4], t1
[4]; /* texels */
1450 const GLfloat f
= FRAC(lambda
);
1451 sample_2d_nearest(ctx
, tObj
, images
[level
], newS
, newT
, t0
);
1452 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newS
, newT
, t1
);
1453 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1454 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1455 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1456 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1462 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1463 const struct gl_texture_object
*tObj
,
1464 GLfloat s
, GLfloat t
, GLfloat u
,
1465 GLfloat lambda
, GLchan rgba
[4])
1467 const struct gl_texture_image
**images
;
1471 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
, level
);
1473 images
= choose_cube_face(tObj
, s
, t
, u
, &newS
, &newT
);
1475 if (level
>= tObj
->_MaxLevel
) {
1476 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
], newS
, newT
, rgba
);
1479 GLchan t0
[4], t1
[4];
1480 const GLfloat f
= FRAC(lambda
);
1481 sample_2d_linear(ctx
, tObj
, images
[level
], newS
, newT
, t0
);
1482 sample_2d_linear(ctx
, tObj
, images
[level
+1], newS
, newT
, t1
);
1483 rgba
[RCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1484 rgba
[GCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1485 rgba
[BCOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1486 rgba
[ACOMP
] = (GLchan
) (GLint
) ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1492 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
1493 const struct gl_texture_object
*tObj
, GLuint n
,
1494 const GLfloat s
[], const GLfloat t
[],
1495 const GLfloat u
[], const GLfloat lambda
[],
1498 GLfloat MinMagThresh
= SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
];
1501 for (i
= 0; i
< n
; i
++) {
1502 if (lambda
[i
] > MinMagThresh
) {
1504 switch (tObj
->MinFilter
) {
1507 const struct gl_texture_image
**images
;
1509 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1511 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1512 newS
, newT
, rgba
[i
]);
1517 const struct gl_texture_image
**images
;
1519 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1521 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1522 newS
, newT
, rgba
[i
]);
1525 case GL_NEAREST_MIPMAP_NEAREST
:
1526 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1527 lambda
[i
], rgba
[i
]);
1529 case GL_LINEAR_MIPMAP_NEAREST
:
1530 sample_cube_linear_mipmap_nearest(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1531 lambda
[i
], rgba
[i
]);
1533 case GL_NEAREST_MIPMAP_LINEAR
:
1534 sample_cube_nearest_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1535 lambda
[i
], rgba
[i
]);
1537 case GL_LINEAR_MIPMAP_LINEAR
:
1538 sample_cube_linear_mipmap_linear(ctx
, tObj
, s
[i
], t
[i
], u
[i
],
1539 lambda
[i
], rgba
[i
]);
1542 _mesa_problem(NULL
, "Bad min filter in sample_lambda_cube");
1547 const struct gl_texture_image
**images
;
1549 images
= choose_cube_face(tObj
, s
[i
], t
[i
], u
[i
],
1551 switch (tObj
->MagFilter
) {
1553 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1554 newS
, newT
, rgba
[i
]);
1557 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1558 newS
, newT
, rgba
[i
]);
1561 _mesa_problem(NULL
, "Bad mag filter in sample_lambda_cube");
1568 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
1569 const struct gl_texture_object
*tObj
, GLuint n
,
1570 const GLfloat s
[], const GLfloat t
[],
1571 const GLfloat u
[], const GLfloat lambda
[],
1576 /**********************************************************************/
1577 /* Texture Sampling Setup */
1578 /**********************************************************************/
1582 * Setup the texture sampling function for this texture object.
1585 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
1586 const struct gl_texture_object
*t
)
1588 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1591 swrast
->TextureSample
[texUnit
] = null_sample_func
;
1594 GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
1597 /* Compute min/mag filter threshold */
1598 if (t
->MagFilter
== GL_LINEAR
1599 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
1600 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
1601 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
1604 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
1608 switch (t
->Dimensions
) {
1611 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
1613 else if (t
->MinFilter
==GL_LINEAR
) {
1614 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
1617 ASSERT(t
->MinFilter
==GL_NEAREST
);
1618 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
1623 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
1625 else if (t
->MinFilter
==GL_LINEAR
) {
1626 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
1629 GLint baseLevel
= t
->BaseLevel
;
1630 ASSERT(t
->MinFilter
==GL_NEAREST
);
1631 if (t
->WrapS
== GL_REPEAT
&&
1632 t
->WrapT
== GL_REPEAT
&&
1633 t
->Image
[baseLevel
]->Border
== 0 &&
1634 t
->Image
[baseLevel
]->Format
== GL_RGB
&&
1635 t
->Image
[baseLevel
]->Type
== CHAN_TYPE
) {
1636 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
1638 else if (t
->WrapS
== GL_REPEAT
&&
1639 t
->WrapT
== GL_REPEAT
&&
1640 t
->Image
[baseLevel
]->Border
== 0 &&
1641 t
->Image
[baseLevel
]->Format
==GL_RGBA
&&
1642 t
->Image
[baseLevel
]->Type
== CHAN_TYPE
) {
1643 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
1646 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
1651 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
1653 else if (t
->MinFilter
==GL_LINEAR
) {
1654 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
1657 ASSERT(t
->MinFilter
==GL_NEAREST
);
1658 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
1661 case 6: /* cube map */
1663 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
1665 else if (t
->MinFilter
==GL_LINEAR
) {
1666 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
1669 ASSERT(t
->MinFilter
==GL_NEAREST
);
1670 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
1674 _mesa_problem(NULL
, "invalid dimensions in _mesa_set_texture_sampler");
1680 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
1681 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
1684 texture_combine(const GLcontext
*ctx
,
1685 const struct gl_texture_unit
*textureUnit
,
1687 CONST
GLchan (*primary_rgba
)[4],
1688 CONST
GLchan (*texel
)[4],
1691 GLchan ccolor
[3][3*MAX_WIDTH
][4];
1692 const GLchan (*argRGB
[3])[4];
1693 const GLchan (*argA
[3])[4];
1695 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
1696 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
1698 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
);
1701 * Do operand setup for up to 3 operands. Loop over the terms.
1703 for (j
= 0; j
< 3; j
++) {
1704 switch (textureUnit
->CombineSourceA
[j
]) {
1708 case GL_PRIMARY_COLOR_EXT
:
1709 argA
[j
] = primary_rgba
;
1711 case GL_PREVIOUS_EXT
:
1712 argA
[j
] = (const GLchan (*)[4]) rgba
;
1714 case GL_CONSTANT_EXT
:
1716 GLchan alpha
, (*c
)[4] = ccolor
[j
];
1717 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
1718 for (i
= 0; i
< n
; i
++)
1719 c
[i
][ACOMP
] = alpha
;
1720 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1724 _mesa_problem(NULL
, "invalid combine source");
1727 switch (textureUnit
->CombineSourceRGB
[j
]) {
1731 case GL_PRIMARY_COLOR_EXT
:
1732 argRGB
[j
] = primary_rgba
;
1734 case GL_PREVIOUS_EXT
:
1735 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
1737 case GL_CONSTANT_EXT
:
1739 GLchan (*c
)[4] = ccolor
[j
];
1740 GLchan red
, green
, blue
;
1741 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
1742 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
1743 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
1744 for (i
= 0; i
< n
; i
++) {
1746 c
[i
][GCOMP
] = green
;
1749 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1753 _mesa_problem(NULL
, "invalid combine source");
1756 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
1757 const GLchan (*src
)[4] = argRGB
[j
];
1758 GLchan (*dst
)[4] = ccolor
[j
];
1760 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1762 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
1763 for (i
= 0; i
< n
; i
++) {
1764 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
1765 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
1766 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
1769 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
1770 src
= (const GLchan (*)[4]) argA
[j
];
1771 for (i
= 0; i
< n
; i
++) {
1772 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
1773 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
1774 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
1778 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
1779 src
= (const GLchan (*)[4]) argA
[j
];
1780 for (i
= 0; i
< n
; i
++) {
1781 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1782 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1783 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1788 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
1789 const GLchan (*src
)[4] = argA
[j
];
1790 GLchan (*dst
)[4] = ccolor
[j
];
1791 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
1792 for (i
= 0; i
< n
; i
++) {
1793 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
1797 if (textureUnit
->CombineModeRGB
== GL_REPLACE
&&
1798 textureUnit
->CombineModeA
== GL_REPLACE
) {
1799 break; /* done, we need only arg0 */
1803 textureUnit
->CombineModeRGB
!= GL_INTERPOLATE_EXT
&&
1804 textureUnit
->CombineModeA
!= GL_INTERPOLATE_EXT
) {
1805 break; /* arg0 and arg1 are done. we don't need arg2. */
1810 * Do the texture combine.
1812 switch (textureUnit
->CombineModeRGB
) {
1815 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1817 for (i
= 0; i
< n
; i
++) {
1818 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
1819 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
1820 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
1821 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
1822 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
1823 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
1827 for (i
= 0; i
< n
; i
++) {
1828 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
1829 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
1830 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
1837 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1838 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1839 const GLint shift
= 8 - RGBshift
;
1840 for (i
= 0; i
< n
; i
++) {
1841 GLuint r
= PROD(arg0
[i
][0], arg1
[i
][RCOMP
]) >> shift
;
1842 GLuint g
= PROD(arg0
[i
][1], arg1
[i
][GCOMP
]) >> shift
;
1843 GLuint b
= PROD(arg0
[i
][2], arg1
[i
][BCOMP
]) >> shift
;
1844 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1845 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1846 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1852 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1853 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1854 for (i
= 0; i
< n
; i
++) {
1855 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
1856 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
1857 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
1858 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1859 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1860 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1864 case GL_ADD_SIGNED_EXT
:
1866 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1867 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1868 for (i
= 0; i
< n
; i
++) {
1869 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] - 128;
1870 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] - 128;
1871 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] - 128;
1872 r
= (r
< 0) ? 0 : r
<< RGBshift
;
1873 g
= (g
< 0) ? 0 : g
<< RGBshift
;
1874 b
= (b
< 0) ? 0 : b
<< RGBshift
;
1875 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1876 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1877 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1881 case GL_INTERPOLATE_EXT
:
1883 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
1884 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
1885 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
1886 const GLint shift
= 8 - RGBshift
;
1887 for (i
= 0; i
< n
; i
++) {
1888 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
1889 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
1891 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
1892 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
1894 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
1895 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
1897 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1898 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1899 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1903 case GL_DOT3_RGB_EXT
:
1904 case GL_DOT3_RGBA_EXT
:
1905 case GL_DOT3_RGB_ARB
:
1906 case GL_DOT3_RGBA_ARB
:
1908 const GLubyte (*arg0
)[4] = (const GLubyte (*)[4]) argRGB
[0];
1909 const GLubyte (*arg1
)[4] = (const GLubyte (*)[4]) argRGB
[1];
1910 /* ATI's EXT extension has a constant scale by 4. The ARB
1911 * one will likely remove this restriction, and we should
1912 * drop the EXT extension in favour of the ARB one.
1914 for (i
= 0; i
< n
; i
++) {
1915 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - 128,
1916 (GLint
)arg1
[i
][RCOMP
] - 128) +
1917 S_PROD((GLint
)arg0
[i
][GCOMP
] - 128,
1918 (GLint
)arg1
[i
][GCOMP
] - 128) +
1919 S_PROD((GLint
)arg0
[i
][BCOMP
] - 128,
1920 (GLint
)arg1
[i
][BCOMP
] - 128)) >> 6;
1921 rgba
[i
][RCOMP
] = (GLubyte
) CLAMP(dot
, 0, 255);
1922 rgba
[i
][GCOMP
] = (GLubyte
) CLAMP(dot
, 0, 255);
1923 rgba
[i
][BCOMP
] = (GLubyte
) CLAMP(dot
, 0, 255);
1928 _mesa_problem(NULL
, "invalid combine mode");
1931 switch (textureUnit
->CombineModeA
) {
1934 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
1936 for (i
= 0; i
< n
; i
++) {
1937 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
1938 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
1942 for (i
= 0; i
< n
; i
++) {
1943 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
1950 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
1951 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
1952 const GLint shift
= 8 - Ashift
;
1953 for (i
= 0; i
< n
; i
++) {
1954 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
1955 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
1961 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
1962 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
1963 for (i
= 0; i
< n
; i
++) {
1964 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
1965 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
1969 case GL_ADD_SIGNED_EXT
:
1971 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
1972 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
1973 for (i
= 0; i
< n
; i
++) {
1974 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] - 128;
1975 a
= (a
< 0) ? 0 : a
<< Ashift
;
1976 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
1980 case GL_INTERPOLATE_EXT
:
1982 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
1983 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
1984 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
1985 const GLint shift
= 8 - Ashift
;
1986 for (i
=0; i
<n
; i
++) {
1987 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
1988 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
1990 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
1995 _mesa_problem(NULL
, "invalid combine mode");
1998 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
2000 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
2001 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_ARB
) {
2002 for (i
= 0; i
< n
; i
++) {
2003 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
2011 /**********************************************************************/
2012 /* Texture Application */
2013 /**********************************************************************/
2017 * Combine incoming fragment color with texel color to produce output color.
2018 * Input: textureUnit - pointer to texture unit to apply
2019 * format - base internal texture format
2020 * n - number of fragments
2021 * primary_rgba - primary colors (may alias rgba for single texture)
2022 * texels - array of texel colors
2023 * InOut: rgba - incoming fragment colors modified by texel colors
2024 * according to the texture environment mode.
2027 apply_texture( const GLcontext
*ctx
,
2028 const struct gl_texture_unit
*texUnit
,
2030 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
2035 GLint Rc
, Gc
, Bc
, Ac
;
2039 ASSERT(texUnit
->_Current
);
2041 baseLevel
= texUnit
->_Current
->BaseLevel
;
2042 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
2044 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
2046 if (format
==GL_COLOR_INDEX
|| format
==GL_DEPTH_COMPONENT
) {
2047 format
= GL_RGBA
; /* XXXX a hack! */
2050 switch (texUnit
->EnvMode
) {
2057 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2063 GLchan Lt
= texel
[i
][RCOMP
];
2064 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2068 case GL_LUMINANCE_ALPHA
:
2070 GLchan Lt
= texel
[i
][RCOMP
];
2072 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
2074 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2080 GLchan It
= texel
[i
][RCOMP
];
2081 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
2083 rgba
[i
][ACOMP
] = It
;
2089 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2090 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2091 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2098 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2099 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2100 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2102 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
2106 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in apply_texture");
2117 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2123 GLchan Lt
= texel
[i
][RCOMP
];
2124 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2125 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2126 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2130 case GL_LUMINANCE_ALPHA
:
2133 GLchan Lt
= texel
[i
][RCOMP
];
2134 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
2135 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
2136 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
2138 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2144 GLchan It
= texel
[i
][RCOMP
];
2145 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
2146 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
2147 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
2149 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
2155 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2156 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2157 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2164 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
2165 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
2166 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
2168 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
2172 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in apply_texture");
2181 case GL_LUMINANCE_ALPHA
:
2188 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
2189 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
2190 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
2196 /* Cv = Cf(1-At) + CtAt */
2197 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
2198 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
2199 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
2200 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
2205 _mesa_problem(ctx
, "Bad format (GL_DECAL) in apply_texture");
2211 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
2212 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
2213 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
2214 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
2220 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2225 /* Cv = Cf(1-Lt) + CcLt */
2226 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2227 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2228 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2229 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2233 case GL_LUMINANCE_ALPHA
:
2235 /* Cv = Cf(1-Lt) + CcLt */
2236 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
2237 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
2238 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
2239 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
2241 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2246 /* Cv = Cf(1-It) + CcLt */
2247 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
2248 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
2249 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
2250 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
2251 /* Av = Af(1-It) + Ac*It */
2252 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
2257 /* Cv = Cf(1-Ct) + CcCt */
2258 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2259 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2260 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2266 /* Cv = Cf(1-Ct) + CcCt */
2267 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
2268 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
2269 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
2271 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
2275 _mesa_problem(ctx
, "Bad format (GL_BLEND) in apply_texture");
2280 case GL_ADD
: /* GL_EXT_texture_add_env */
2287 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2292 GLuint Lt
= texel
[i
][RCOMP
];
2293 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2294 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2295 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2296 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2297 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2298 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2302 case GL_LUMINANCE_ALPHA
:
2304 GLuint Lt
= texel
[i
][RCOMP
];
2305 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
2306 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
2307 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
2308 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2309 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2310 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2311 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2316 GLchan It
= texel
[i
][RCOMP
];
2317 GLuint r
= rgba
[i
][RCOMP
] + It
;
2318 GLuint g
= rgba
[i
][GCOMP
] + It
;
2319 GLuint b
= rgba
[i
][BCOMP
] + It
;
2320 GLuint a
= rgba
[i
][ACOMP
] + It
;
2321 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2322 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2323 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2324 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
2329 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2330 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2331 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2332 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2333 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2334 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2340 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
2341 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
2342 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
2343 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
2344 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
2345 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
2346 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
2350 _mesa_problem(ctx
, "Bad format (GL_ADD) in apply_texture");
2355 case GL_COMBINE_EXT
:
2356 texture_combine(ctx
, texUnit
, n
, primary_rgba
, texel
, rgba
);
2360 _mesa_problem(ctx
, "Bad env mode in apply_texture");
2368 * Sample a shadow/depth texture.
2369 * Input: ctx - context
2370 * texUnit - the texture unit
2371 * n - number of samples
2372 * s,t,r - array [n] of texture coordinates
2373 * In/Out: rgba - array [n] of texel colors.
2376 sample_depth_texture(const GLcontext
*ctx
,
2377 const struct gl_texture_unit
*texUnit
,
2379 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2382 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2383 const GLint baseLevel
= texObj
->BaseLevel
;
2384 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2385 const GLuint width
= texImage
->Width
;
2386 const GLuint height
= texImage
->Height
;
2387 const GLchan ambient
= texObj
->ShadowAmbient
;
2388 GLboolean lequal
, gequal
;
2390 if (texObj
->Dimensions
!= 2) {
2391 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2395 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2396 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2400 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2401 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2402 * isn't a depth texture.
2404 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2405 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2409 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2418 if (texObj
->MagFilter
== GL_NEAREST
) {
2420 for (i
= 0; i
< n
; i
++) {
2421 GLfloat depthSample
;
2423 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2424 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2425 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2426 if ((r
[i
] <= depthSample
&& lequal
) ||
2427 (r
[i
] >= depthSample
&& gequal
)) {
2428 texel
[i
][RCOMP
] = CHAN_MAX
;
2429 texel
[i
][GCOMP
] = CHAN_MAX
;
2430 texel
[i
][BCOMP
] = CHAN_MAX
;
2431 texel
[i
][ACOMP
] = CHAN_MAX
;
2434 texel
[i
][RCOMP
] = ambient
;
2435 texel
[i
][GCOMP
] = ambient
;
2436 texel
[i
][BCOMP
] = ambient
;
2437 texel
[i
][ACOMP
] = CHAN_MAX
;
2443 ASSERT(texObj
->MagFilter
== GL_LINEAR
);
2444 for (i
= 0; i
< n
; i
++) {
2445 GLfloat depth00
, depth01
, depth10
, depth11
;
2446 GLint i0
, i1
, j0
, j1
;
2448 GLuint useBorderTexel
;
2450 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapS
, s
[i
], u
, width
, i0
, i1
);
2451 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj
->WrapT
, t
[i
], v
, height
,j0
, j1
);
2454 if (texImage
->Border
) {
2455 i0
+= texImage
->Border
;
2456 i1
+= texImage
->Border
;
2457 j0
+= texImage
->Border
;
2458 j1
+= texImage
->Border
;
2461 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2462 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2463 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2464 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2467 /* get four depth samples from the texture */
2468 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2472 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2474 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2478 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2480 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2484 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2486 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2490 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2494 /* compute a single weighted depth sample and do one comparison */
2495 const GLfloat a
= FRAC(u
);
2496 const GLfloat b
= FRAC(v
);
2497 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2498 const GLfloat w10
= ( a
) * (1.0F
- b
);
2499 const GLfloat w01
= (1.0F
- a
) * ( b
);
2500 const GLfloat w11
= ( a
) * ( b
);
2501 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2502 + w01
* depth01
+ w11
* depth11
;
2503 if ((depthSample
<= r
[i
] && lequal
) ||
2504 (depthSample
>= r
[i
] && gequal
)) {
2505 texel
[i
][RCOMP
] = ambient
;
2506 texel
[i
][GCOMP
] = ambient
;
2507 texel
[i
][BCOMP
] = ambient
;
2508 texel
[i
][ACOMP
] = CHAN_MAX
;
2511 texel
[i
][RCOMP
] = CHAN_MAX
;
2512 texel
[i
][GCOMP
] = CHAN_MAX
;
2513 texel
[i
][BCOMP
] = CHAN_MAX
;
2514 texel
[i
][ACOMP
] = CHAN_MAX
;
2518 /* Do four depth/R comparisons and compute a weighted result.
2519 * If this touches on somebody's I.P., I'll remove this code
2522 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2523 GLfloat luminance
= CHAN_MAXF
;
2526 if (depth00
<= r
[i
]) luminance
-= d
;
2527 if (depth01
<= r
[i
]) luminance
-= d
;
2528 if (depth10
<= r
[i
]) luminance
-= d
;
2529 if (depth11
<= r
[i
]) luminance
-= d
;
2532 if (depth00
>= r
[i
]) luminance
-= d
;
2533 if (depth01
>= r
[i
]) luminance
-= d
;
2534 if (depth10
>= r
[i
]) luminance
-= d
;
2535 if (depth11
>= r
[i
]) luminance
-= d
;
2537 lum
= (GLchan
) luminance
;
2538 texel
[i
][RCOMP
] = lum
;
2539 texel
[i
][GCOMP
] = lum
;
2540 texel
[i
][BCOMP
] = lum
;
2541 texel
[i
][ACOMP
] = CHAN_MAX
;
2550 * Experimental depth texture sampling function.
2553 sample_depth_texture2(const GLcontext
*ctx
,
2554 const struct gl_texture_unit
*texUnit
,
2556 const GLfloat s
[], const GLfloat t
[], const GLfloat r
[],
2559 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2560 const GLint baseLevel
= texObj
->BaseLevel
;
2561 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2562 const GLuint width
= texImage
->Width
;
2563 const GLuint height
= texImage
->Height
;
2564 const GLchan ambient
= texObj
->ShadowAmbient
;
2565 GLboolean lequal
, gequal
;
2567 if (texObj
->Dimensions
!= 2) {
2568 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2572 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2573 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2577 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2578 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2579 * isn't a depth texture.
2581 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2582 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2586 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2597 for (i
= 0; i
< n
; i
++) {
2599 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2602 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, s
[i
], width
, col
);
2603 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, t
[i
], height
, row
);
2610 if (imin
< 0) imin
= 0;
2611 if (imax
>= width
) imax
= width
- 1;
2612 if (jmin
< 0) jmin
= 0;
2613 if (jmax
>= height
) jmax
= height
- 1;
2615 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2617 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2618 for (ii
= imin
; ii
<= imax
; ii
++) {
2619 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2621 if ((depthSample
<= r
[i
] && lequal
) ||
2622 (depthSample
>= r
[i
] && gequal
)) {
2628 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2629 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2632 texel
[i
][RCOMP
] = lum
;
2633 texel
[i
][GCOMP
] = lum
;
2634 texel
[i
][BCOMP
] = lum
;
2635 texel
[i
][ACOMP
] = CHAN_MAX
;
2643 * Apply a unit of texture mapping to the incoming fragments.
2646 _swrast_texture_fragments( GLcontext
*ctx
, GLuint texUnit
, GLuint n
,
2647 const GLfloat s
[], const GLfloat t
[],
2648 const GLfloat r
[], GLfloat lambda
[],
2649 CONST GLchan primary_rgba
[][4], GLchan rgba
[][4] )
2651 const GLuint mask
= TEXTURE0_ANY
<< (texUnit
* 4);
2653 if (ctx
->Texture
._ReallyEnabled
& mask
) {
2654 const struct gl_texture_unit
*textureUnit
= &ctx
->Texture
.Unit
[texUnit
];
2656 if (textureUnit
->_Current
) { /* XXX need this? */
2657 GLchan texel
[PB_SIZE
][4];
2659 if (textureUnit
->LodBias
!= 0.0F
) {
2660 /* apply LOD bias, but don't clamp yet */
2663 lambda
[i
] += textureUnit
->LodBias
;
2667 if ((textureUnit
->_Current
->MinLod
!= -1000.0
2668 || textureUnit
->_Current
->MaxLod
!= 1000.0)
2670 /* apply LOD clamping to lambda */
2671 const GLfloat min
= textureUnit
->_Current
->MinLod
;
2672 const GLfloat max
= textureUnit
->_Current
->MaxLod
;
2675 GLfloat l
= lambda
[i
];
2676 lambda
[i
] = CLAMP(l
, min
, max
);
2680 /* Sample the texture. */
2681 if (textureUnit
->_Current
->CompareFlag
) {
2683 sample_depth_texture(ctx
, textureUnit
, n
, s
, t
, r
, texel
);
2687 SWRAST_CONTEXT(ctx
)->TextureSample
[texUnit
]( ctx
, texUnit
,
2688 textureUnit
->_Current
,
2692 apply_texture( ctx
, textureUnit
, n
, primary_rgba
,
2693 (const GLchan (*)[4]) texel
, rgba
);