2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include "main/glheader.h"
27 #include "main/context.h"
28 #include "main/colormac.h"
29 #include "main/imports.h"
30 #include "main/texformat.h"
32 #include "s_context.h"
33 #include "s_texfilter.h"
37 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
38 * see 1-pixel bands of improperly weighted linear-filtered textures.
39 * The tests/texwrap.c demo is a good test.
40 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
41 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
43 #define FRAC(f) ((f) - IFLOOR(f))
47 * Constants for integer linear interpolation.
49 #define ILERP_SCALE 65536.0F
50 #define ILERP_SHIFT 16
54 * Linear interpolation macros
56 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
57 #define ILERP(IT, A, B) ( (A) + (((IT) * ((B) - (A))) >> ILERP_SHIFT) )
61 * Do 2D/biliner interpolation of float values.
62 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
63 * a and b are the horizontal and vertical interpolants.
64 * It's important that this function is inlined when compiled with
65 * optimization! If we find that's not true on some systems, convert
69 lerp_2d(GLfloat a
, GLfloat b
,
70 GLfloat v00
, GLfloat v10
, GLfloat v01
, GLfloat v11
)
72 const GLfloat temp0
= LERP(a
, v00
, v10
);
73 const GLfloat temp1
= LERP(a
, v01
, v11
);
74 return LERP(b
, temp0
, temp1
);
79 * Do 2D/biliner interpolation of integer values.
83 ilerp_2d(GLint ia
, GLint ib
,
84 GLint v00
, GLint v10
, GLint v01
, GLint v11
)
86 /* fixed point interpolants in [0, ILERP_SCALE] */
87 const GLint temp0
= ILERP(ia
, v00
, v10
);
88 const GLint temp1
= ILERP(ia
, v01
, v11
);
89 return ILERP(ib
, temp0
, temp1
);
94 * Do 3D/trilinear interpolation of float values.
98 lerp_3d(GLfloat a
, GLfloat b
, GLfloat c
,
99 GLfloat v000
, GLfloat v100
, GLfloat v010
, GLfloat v110
,
100 GLfloat v001
, GLfloat v101
, GLfloat v011
, GLfloat v111
)
102 const GLfloat temp00
= LERP(a
, v000
, v100
);
103 const GLfloat temp10
= LERP(a
, v010
, v110
);
104 const GLfloat temp01
= LERP(a
, v001
, v101
);
105 const GLfloat temp11
= LERP(a
, v011
, v111
);
106 const GLfloat temp0
= LERP(b
, temp00
, temp10
);
107 const GLfloat temp1
= LERP(b
, temp01
, temp11
);
108 return LERP(c
, temp0
, temp1
);
113 * Do 3D/trilinear interpolation of integer values.
117 ilerp_3d(GLint ia
, GLint ib
, GLint ic
,
118 GLint v000
, GLint v100
, GLint v010
, GLint v110
,
119 GLint v001
, GLint v101
, GLint v011
, GLint v111
)
121 /* fixed point interpolants in [0, ILERP_SCALE] */
122 const GLint temp00
= ILERP(ia
, v000
, v100
);
123 const GLint temp10
= ILERP(ia
, v010
, v110
);
124 const GLint temp01
= ILERP(ia
, v001
, v101
);
125 const GLint temp11
= ILERP(ia
, v011
, v111
);
126 const GLint temp0
= ILERP(ib
, temp00
, temp10
);
127 const GLint temp1
= ILERP(ib
, temp01
, temp11
);
128 return ILERP(ic
, temp0
, temp1
);
133 * Do linear interpolation of colors.
136 lerp_rgba(GLfloat result
[4], GLfloat t
, const GLfloat a
[4], const GLfloat b
[4])
138 result
[0] = LERP(t
, a
[0], b
[0]);
139 result
[1] = LERP(t
, a
[1], b
[1]);
140 result
[2] = LERP(t
, a
[2], b
[2]);
141 result
[3] = LERP(t
, a
[3], b
[3]);
146 * Do bilinear interpolation of colors.
149 lerp_rgba_2d(GLfloat result
[4], GLfloat a
, GLfloat b
,
150 const GLfloat t00
[4], const GLfloat t10
[4],
151 const GLfloat t01
[4], const GLfloat t11
[4])
153 result
[0] = lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]);
154 result
[1] = lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]);
155 result
[2] = lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]);
156 result
[3] = lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]);
161 * Do trilinear interpolation of colors.
164 lerp_rgba_3d(GLfloat result
[4], GLfloat a
, GLfloat b
, GLfloat c
,
165 const GLfloat t000
[4], const GLfloat t100
[4],
166 const GLfloat t010
[4], const GLfloat t110
[4],
167 const GLfloat t001
[4], const GLfloat t101
[4],
168 const GLfloat t011
[4], const GLfloat t111
[4])
171 /* compiler should unroll these short loops */
172 for (k
= 0; k
< 4; k
++) {
173 result
[k
] = lerp_3d(a
, b
, c
, t000
[k
], t100
[k
], t010
[k
], t110
[k
],
174 t001
[k
], t101
[k
], t011
[k
], t111
[k
]);
180 * If A is a signed integer, A % B doesn't give the right value for A < 0
181 * (in terms of texture repeat). Just casting to unsigned fixes that.
183 #define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
187 * Used to compute texel locations for linear sampling.
189 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
190 * s = texcoord in [0,1]
191 * size = width (or height or depth) of texture
193 * i0, i1 = returns two nearest texel indexes
194 * weight = returns blend factor between texels
197 linear_texel_locations(GLenum wrapMode
,
198 const struct gl_texture_image
*img
,
199 GLint size
, GLfloat s
,
200 GLint
*i0
, GLint
*i1
, GLfloat
*weight
)
206 if (img
->_IsPowerOfTwo
) {
207 *i0
= IFLOOR(u
) & (size
- 1);
208 *i1
= (*i0
+ 1) & (size
- 1);
211 *i0
= REMAINDER(IFLOOR(u
), size
);
212 *i1
= REMAINDER(*i0
+ 1, size
);
215 case GL_CLAMP_TO_EDGE
:
227 if (*i1
>= (GLint
) size
)
230 case GL_CLAMP_TO_BORDER
:
232 const GLfloat min
= -1.0F
/ (2.0F
* size
);
233 const GLfloat max
= 1.0F
- min
;
245 case GL_MIRRORED_REPEAT
:
247 const GLint flr
= IFLOOR(s
);
249 u
= 1.0F
- (s
- (GLfloat
) flr
);
251 u
= s
- (GLfloat
) flr
;
252 u
= (u
* size
) - 0.5F
;
257 if (*i1
>= (GLint
) size
)
261 case GL_MIRROR_CLAMP_EXT
:
271 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
282 if (*i1
>= (GLint
) size
)
285 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
287 const GLfloat min
= -1.0F
/ (2.0F
* size
);
288 const GLfloat max
= 1.0F
- min
;
313 _mesa_problem(NULL
, "Bad wrap mode");
321 * Used to compute texel location for nearest sampling.
324 nearest_texel_location(GLenum wrapMode
,
325 const struct gl_texture_image
*img
,
326 GLint size
, GLfloat s
)
332 /* s limited to [0,1) */
333 /* i limited to [0,size-1] */
334 i
= IFLOOR(s
* size
);
335 if (img
->_IsPowerOfTwo
)
338 i
= REMAINDER(i
, size
);
340 case GL_CLAMP_TO_EDGE
:
342 /* s limited to [min,max] */
343 /* i limited to [0, size-1] */
344 const GLfloat min
= 1.0F
/ (2.0F
* size
);
345 const GLfloat max
= 1.0F
- min
;
351 i
= IFLOOR(s
* size
);
354 case GL_CLAMP_TO_BORDER
:
356 /* s limited to [min,max] */
357 /* i limited to [-1, size] */
358 const GLfloat min
= -1.0F
/ (2.0F
* size
);
359 const GLfloat max
= 1.0F
- min
;
365 i
= IFLOOR(s
* size
);
368 case GL_MIRRORED_REPEAT
:
370 const GLfloat min
= 1.0F
/ (2.0F
* size
);
371 const GLfloat max
= 1.0F
- min
;
372 const GLint flr
= IFLOOR(s
);
375 u
= 1.0F
- (s
- (GLfloat
) flr
);
377 u
= s
- (GLfloat
) flr
;
383 i
= IFLOOR(u
* size
);
386 case GL_MIRROR_CLAMP_EXT
:
388 /* s limited to [0,1] */
389 /* i limited to [0,size-1] */
390 const GLfloat u
= FABSF(s
);
396 i
= IFLOOR(u
* size
);
399 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
401 /* s limited to [min,max] */
402 /* i limited to [0, size-1] */
403 const GLfloat min
= 1.0F
/ (2.0F
* size
);
404 const GLfloat max
= 1.0F
- min
;
405 const GLfloat u
= FABSF(s
);
411 i
= IFLOOR(u
* size
);
414 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
416 /* s limited to [min,max] */
417 /* i limited to [0, size-1] */
418 const GLfloat min
= -1.0F
/ (2.0F
* size
);
419 const GLfloat max
= 1.0F
- min
;
420 const GLfloat u
= FABSF(s
);
426 i
= IFLOOR(u
* size
);
430 /* s limited to [0,1] */
431 /* i limited to [0,size-1] */
437 i
= IFLOOR(s
* size
);
440 _mesa_problem(NULL
, "Bad wrap mode");
446 /* Power of two image sizes only */
448 linear_repeat_texel_location(GLuint size
, GLfloat s
,
449 GLint
*i0
, GLint
*i1
, GLfloat
*weight
)
451 GLfloat u
= s
* size
- 0.5F
;
452 *i0
= IFLOOR(u
) & (size
- 1);
453 *i1
= (*i0
+ 1) & (size
- 1);
459 * For linear interpolation between mipmap levels N and N+1, this function
463 linear_mipmap_level(const struct gl_texture_object
*tObj
, GLfloat lambda
)
466 return tObj
->BaseLevel
;
467 else if (lambda
> tObj
->_MaxLambda
)
468 return (GLint
) (tObj
->BaseLevel
+ tObj
->_MaxLambda
);
470 return (GLint
) (tObj
->BaseLevel
+ lambda
);
475 * Compute the nearest mipmap level to take texels from.
478 nearest_mipmap_level(const struct gl_texture_object
*tObj
, GLfloat lambda
)
484 else if (lambda
> tObj
->_MaxLambda
+ 0.4999F
)
485 l
= tObj
->_MaxLambda
+ 0.4999F
;
488 level
= (GLint
) (tObj
->BaseLevel
+ l
+ 0.5F
);
489 if (level
> tObj
->_MaxLevel
)
490 level
= tObj
->_MaxLevel
;
497 * Bitflags for texture border color sampling.
509 * The lambda[] array values are always monotonic. Either the whole span
510 * will be minified, magnified, or split between the two. This function
511 * determines the subranges in [0, n-1] that are to be minified or magnified.
514 compute_min_mag_ranges(const struct gl_texture_object
*tObj
,
515 GLuint n
, const GLfloat lambda
[],
516 GLuint
*minStart
, GLuint
*minEnd
,
517 GLuint
*magStart
, GLuint
*magEnd
)
519 GLfloat minMagThresh
;
521 /* we shouldn't be here if minfilter == magfilter */
522 ASSERT(tObj
->MinFilter
!= tObj
->MagFilter
);
524 /* This bit comes from the OpenGL spec: */
525 if (tObj
->MagFilter
== GL_LINEAR
526 && (tObj
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
527 tObj
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
535 /* DEBUG CODE: Verify that lambda[] is monotonic.
536 * We can't really use this because the inaccuracy in the LOG2 function
537 * causes this test to fail, yet the resulting texturing is correct.
541 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
542 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
543 for (i
= 0; i
< n
- 1; i
++) {
544 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
547 else { /* increasing */
548 for (i
= 0; i
< n
- 1; i
++) {
549 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
555 if (lambda
[0] <= minMagThresh
&& (n
<= 1 || lambda
[n
-1] <= minMagThresh
)) {
556 /* magnification for whole span */
559 *minStart
= *minEnd
= 0;
561 else if (lambda
[0] > minMagThresh
&& (n
<=1 || lambda
[n
-1] > minMagThresh
)) {
562 /* minification for whole span */
565 *magStart
= *magEnd
= 0;
568 /* a mix of minification and magnification */
570 if (lambda
[0] > minMagThresh
) {
571 /* start with minification */
572 for (i
= 1; i
< n
; i
++) {
573 if (lambda
[i
] <= minMagThresh
)
582 /* start with magnification */
583 for (i
= 1; i
< n
; i
++) {
584 if (lambda
[i
] > minMagThresh
)
595 /* Verify the min/mag Start/End values
596 * We don't use this either (see above)
600 for (i
= 0; i
< n
; i
++) {
601 if (lambda
[i
] > minMagThresh
) {
603 ASSERT(i
>= *minStart
);
608 ASSERT(i
>= *magStart
);
617 /**********************************************************************/
618 /* 1-D Texture Sampling Functions */
619 /**********************************************************************/
622 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
625 sample_1d_nearest(GLcontext
*ctx
,
626 const struct gl_texture_object
*tObj
,
627 const struct gl_texture_image
*img
,
628 const GLfloat texcoord
[4], GLfloat rgba
[4])
630 const GLint width
= img
->Width2
; /* without border, power of two */
632 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
633 /* skip over the border, if any */
635 if (i
< 0 || i
>= (GLint
) img
->Width
) {
636 /* Need this test for GL_CLAMP_TO_BORDER mode */
637 COPY_4V(rgba
, tObj
->BorderColor
);
640 img
->FetchTexelf(img
, i
, 0, 0, rgba
);
646 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
649 sample_1d_linear(GLcontext
*ctx
,
650 const struct gl_texture_object
*tObj
,
651 const struct gl_texture_image
*img
,
652 const GLfloat texcoord
[4], GLfloat rgba
[4])
654 const GLint width
= img
->Width2
;
656 GLbitfield useBorderColor
= 0x0;
658 GLfloat t0
[4], t1
[4]; /* texels */
660 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
667 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
668 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
671 /* fetch texel colors */
672 if (useBorderColor
& I0BIT
) {
673 COPY_4V(t0
, tObj
->BorderColor
);
676 img
->FetchTexelf(img
, i0
, 0, 0, t0
);
678 if (useBorderColor
& I1BIT
) {
679 COPY_4V(t1
, tObj
->BorderColor
);
682 img
->FetchTexelf(img
, i1
, 0, 0, t1
);
685 lerp_rgba(rgba
, a
, t0
, t1
);
690 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
691 const struct gl_texture_object
*tObj
,
692 GLuint n
, const GLfloat texcoord
[][4],
693 const GLfloat lambda
[], GLfloat rgba
[][4])
696 ASSERT(lambda
!= NULL
);
697 for (i
= 0; i
< n
; i
++) {
698 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
699 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
705 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
706 const struct gl_texture_object
*tObj
,
707 GLuint n
, const GLfloat texcoord
[][4],
708 const GLfloat lambda
[], GLfloat rgba
[][4])
711 ASSERT(lambda
!= NULL
);
712 for (i
= 0; i
< n
; i
++) {
713 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
714 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
720 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
721 const struct gl_texture_object
*tObj
,
722 GLuint n
, const GLfloat texcoord
[][4],
723 const GLfloat lambda
[], GLfloat rgba
[][4])
726 ASSERT(lambda
!= NULL
);
727 for (i
= 0; i
< n
; i
++) {
728 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
729 if (level
>= tObj
->_MaxLevel
) {
730 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
731 texcoord
[i
], rgba
[i
]);
734 GLfloat t0
[4], t1
[4];
735 const GLfloat f
= FRAC(lambda
[i
]);
736 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
737 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
738 lerp_rgba(rgba
[i
], f
, t0
, t1
);
745 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
746 const struct gl_texture_object
*tObj
,
747 GLuint n
, const GLfloat texcoord
[][4],
748 const GLfloat lambda
[], GLfloat rgba
[][4])
751 ASSERT(lambda
!= NULL
);
752 for (i
= 0; i
< n
; i
++) {
753 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
754 if (level
>= tObj
->_MaxLevel
) {
755 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
756 texcoord
[i
], rgba
[i
]);
759 GLfloat t0
[4], t1
[4];
760 const GLfloat f
= FRAC(lambda
[i
]);
761 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
762 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
763 lerp_rgba(rgba
[i
], f
, t0
, t1
);
769 /** Sample 1D texture, nearest filtering for both min/magnification */
771 sample_nearest_1d( GLcontext
*ctx
,
772 const struct gl_texture_object
*tObj
, GLuint n
,
773 const GLfloat texcoords
[][4], const GLfloat lambda
[],
777 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
779 for (i
= 0; i
< n
; i
++) {
780 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
785 /** Sample 1D texture, linear filtering for both min/magnification */
787 sample_linear_1d( GLcontext
*ctx
,
788 const struct gl_texture_object
*tObj
, GLuint n
,
789 const GLfloat texcoords
[][4], const GLfloat lambda
[],
793 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
795 for (i
= 0; i
< n
; i
++) {
796 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
801 /** Sample 1D texture, using lambda to choose between min/magnification */
803 sample_lambda_1d( GLcontext
*ctx
,
804 const struct gl_texture_object
*tObj
, GLuint n
,
805 const GLfloat texcoords
[][4],
806 const GLfloat lambda
[], GLfloat rgba
[][4] )
808 GLuint minStart
, minEnd
; /* texels with minification */
809 GLuint magStart
, magEnd
; /* texels with magnification */
812 ASSERT(lambda
!= NULL
);
813 compute_min_mag_ranges(tObj
, n
, lambda
,
814 &minStart
, &minEnd
, &magStart
, &magEnd
);
816 if (minStart
< minEnd
) {
817 /* do the minified texels */
818 const GLuint m
= minEnd
- minStart
;
819 switch (tObj
->MinFilter
) {
821 for (i
= minStart
; i
< minEnd
; i
++)
822 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
823 texcoords
[i
], rgba
[i
]);
826 for (i
= minStart
; i
< minEnd
; i
++)
827 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
828 texcoords
[i
], rgba
[i
]);
830 case GL_NEAREST_MIPMAP_NEAREST
:
831 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
832 lambda
+ minStart
, rgba
+ minStart
);
834 case GL_LINEAR_MIPMAP_NEAREST
:
835 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
836 lambda
+ minStart
, rgba
+ minStart
);
838 case GL_NEAREST_MIPMAP_LINEAR
:
839 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
840 lambda
+ minStart
, rgba
+ minStart
);
842 case GL_LINEAR_MIPMAP_LINEAR
:
843 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
844 lambda
+ minStart
, rgba
+ minStart
);
847 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
852 if (magStart
< magEnd
) {
853 /* do the magnified texels */
854 switch (tObj
->MagFilter
) {
856 for (i
= magStart
; i
< magEnd
; i
++)
857 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
858 texcoords
[i
], rgba
[i
]);
861 for (i
= magStart
; i
< magEnd
; i
++)
862 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
863 texcoords
[i
], rgba
[i
]);
866 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
873 /**********************************************************************/
874 /* 2-D Texture Sampling Functions */
875 /**********************************************************************/
879 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
882 sample_2d_nearest(GLcontext
*ctx
,
883 const struct gl_texture_object
*tObj
,
884 const struct gl_texture_image
*img
,
885 const GLfloat texcoord
[4],
888 const GLint width
= img
->Width2
; /* without border, power of two */
889 const GLint height
= img
->Height2
; /* without border, power of two */
893 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
894 j
= nearest_texel_location(tObj
->WrapT
, img
, height
, texcoord
[1]);
896 /* skip over the border, if any */
900 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
901 /* Need this test for GL_CLAMP_TO_BORDER mode */
902 COPY_4V(rgba
, tObj
->BorderColor
);
905 img
->FetchTexelf(img
, i
, j
, 0, rgba
);
911 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
912 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
915 sample_2d_linear(GLcontext
*ctx
,
916 const struct gl_texture_object
*tObj
,
917 const struct gl_texture_image
*img
,
918 const GLfloat texcoord
[4],
921 const GLint width
= img
->Width2
;
922 const GLint height
= img
->Height2
;
923 GLint i0
, j0
, i1
, j1
;
924 GLbitfield useBorderColor
= 0x0;
926 GLfloat t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
928 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
929 linear_texel_locations(tObj
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
938 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
939 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
940 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
941 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
944 /* fetch four texel colors */
945 if (useBorderColor
& (I0BIT
| J0BIT
)) {
946 COPY_4V(t00
, tObj
->BorderColor
);
949 img
->FetchTexelf(img
, i0
, j0
, 0, t00
);
951 if (useBorderColor
& (I1BIT
| J0BIT
)) {
952 COPY_4V(t10
, tObj
->BorderColor
);
955 img
->FetchTexelf(img
, i1
, j0
, 0, t10
);
957 if (useBorderColor
& (I0BIT
| J1BIT
)) {
958 COPY_4V(t01
, tObj
->BorderColor
);
961 img
->FetchTexelf(img
, i0
, j1
, 0, t01
);
963 if (useBorderColor
& (I1BIT
| J1BIT
)) {
964 COPY_4V(t11
, tObj
->BorderColor
);
967 img
->FetchTexelf(img
, i1
, j1
, 0, t11
);
970 lerp_rgba_2d(rgba
, a
, b
, t00
, t10
, t01
, t11
);
975 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
976 * We don't have to worry about the texture border.
979 sample_2d_linear_repeat(GLcontext
*ctx
,
980 const struct gl_texture_object
*tObj
,
981 const struct gl_texture_image
*img
,
982 const GLfloat texcoord
[4],
985 const GLint width
= img
->Width2
;
986 const GLint height
= img
->Height2
;
987 GLint i0
, j0
, i1
, j1
;
989 GLfloat t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
993 ASSERT(tObj
->WrapS
== GL_REPEAT
);
994 ASSERT(tObj
->WrapT
== GL_REPEAT
);
995 ASSERT(img
->Border
== 0);
996 ASSERT(img
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
);
997 ASSERT(img
->_IsPowerOfTwo
);
999 linear_repeat_texel_location(width
, texcoord
[0], &i0
, &i1
, &wi
);
1000 linear_repeat_texel_location(height
, texcoord
[1], &j0
, &j1
, &wj
);
1002 img
->FetchTexelf(img
, i0
, j0
, 0, t00
);
1003 img
->FetchTexelf(img
, i1
, j0
, 0, t10
);
1004 img
->FetchTexelf(img
, i0
, j1
, 0, t01
);
1005 img
->FetchTexelf(img
, i1
, j1
, 0, t11
);
1007 lerp_rgba_2d(rgba
, wi
, wj
, t00
, t10
, t01
, t11
);
1012 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1013 const struct gl_texture_object
*tObj
,
1014 GLuint n
, const GLfloat texcoord
[][4],
1015 const GLfloat lambda
[], GLfloat rgba
[][4])
1018 for (i
= 0; i
< n
; i
++) {
1019 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1020 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1026 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1027 const struct gl_texture_object
*tObj
,
1028 GLuint n
, const GLfloat texcoord
[][4],
1029 const GLfloat lambda
[], GLfloat rgba
[][4])
1032 ASSERT(lambda
!= NULL
);
1033 for (i
= 0; i
< n
; i
++) {
1034 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1035 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1041 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1042 const struct gl_texture_object
*tObj
,
1043 GLuint n
, const GLfloat texcoord
[][4],
1044 const GLfloat lambda
[], GLfloat rgba
[][4])
1047 ASSERT(lambda
!= NULL
);
1048 for (i
= 0; i
< n
; i
++) {
1049 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1050 if (level
>= tObj
->_MaxLevel
) {
1051 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1052 texcoord
[i
], rgba
[i
]);
1055 GLfloat t0
[4], t1
[4]; /* texels */
1056 const GLfloat f
= FRAC(lambda
[i
]);
1057 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1058 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1059 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1066 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1067 const struct gl_texture_object
*tObj
,
1068 GLuint n
, const GLfloat texcoord
[][4],
1069 const GLfloat lambda
[], GLfloat rgba
[][4] )
1072 ASSERT(lambda
!= NULL
);
1073 for (i
= 0; i
< n
; i
++) {
1074 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1075 if (level
>= tObj
->_MaxLevel
) {
1076 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1077 texcoord
[i
], rgba
[i
]);
1080 GLfloat t0
[4], t1
[4]; /* texels */
1081 const GLfloat f
= FRAC(lambda
[i
]);
1082 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1083 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1084 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1091 sample_2d_linear_mipmap_linear_repeat(GLcontext
*ctx
,
1092 const struct gl_texture_object
*tObj
,
1093 GLuint n
, const GLfloat texcoord
[][4],
1094 const GLfloat lambda
[], GLfloat rgba
[][4])
1097 ASSERT(lambda
!= NULL
);
1098 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1099 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1100 for (i
= 0; i
< n
; i
++) {
1101 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1102 if (level
>= tObj
->_MaxLevel
) {
1103 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1104 texcoord
[i
], rgba
[i
]);
1107 GLfloat t0
[4], t1
[4]; /* texels */
1108 const GLfloat f
= FRAC(lambda
[i
]);
1109 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
],
1111 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
+1],
1113 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1119 /** Sample 2D texture, nearest filtering for both min/magnification */
1121 sample_nearest_2d(GLcontext
*ctx
,
1122 const struct gl_texture_object
*tObj
, GLuint n
,
1123 const GLfloat texcoords
[][4],
1124 const GLfloat lambda
[], GLfloat rgba
[][4])
1127 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1129 for (i
= 0; i
< n
; i
++) {
1130 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1135 /** Sample 2D texture, linear filtering for both min/magnification */
1137 sample_linear_2d(GLcontext
*ctx
,
1138 const struct gl_texture_object
*tObj
, GLuint n
,
1139 const GLfloat texcoords
[][4],
1140 const GLfloat lambda
[], GLfloat rgba
[][4])
1143 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1145 if (tObj
->WrapS
== GL_REPEAT
&&
1146 tObj
->WrapT
== GL_REPEAT
&&
1147 image
->_IsPowerOfTwo
&&
1148 image
->Border
== 0) {
1149 for (i
= 0; i
< n
; i
++) {
1150 sample_2d_linear_repeat(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1154 for (i
= 0; i
< n
; i
++) {
1155 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1162 * Optimized 2-D texture sampling:
1163 * S and T wrap mode == GL_REPEAT
1164 * GL_NEAREST min/mag filter
1166 * RowStride == Width,
1170 opt_sample_rgb_2d(GLcontext
*ctx
,
1171 const struct gl_texture_object
*tObj
,
1172 GLuint n
, const GLfloat texcoords
[][4],
1173 const GLfloat lambda
[], GLchan rgba
[][4])
1175 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1176 const GLfloat width
= (GLfloat
) img
->Width
;
1177 const GLfloat height
= (GLfloat
) img
->Height
;
1178 const GLint colMask
= img
->Width
- 1;
1179 const GLint rowMask
= img
->Height
- 1;
1180 const GLint shift
= img
->WidthLog2
;
1184 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1185 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1186 ASSERT(img
->Border
==0);
1187 ASSERT(img
->TexFormat
->MesaFormat
==MESA_FORMAT_RGB
);
1188 ASSERT(img
->_IsPowerOfTwo
);
1190 for (k
=0; k
<n
; k
++) {
1191 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1192 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1193 GLint pos
= (j
<< shift
) | i
;
1194 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1195 rgba
[k
][RCOMP
] = texel
[0];
1196 rgba
[k
][GCOMP
] = texel
[1];
1197 rgba
[k
][BCOMP
] = texel
[2];
1203 * Optimized 2-D texture sampling:
1204 * S and T wrap mode == GL_REPEAT
1205 * GL_NEAREST min/mag filter
1207 * RowStride == Width,
1211 opt_sample_rgba_2d(GLcontext
*ctx
,
1212 const struct gl_texture_object
*tObj
,
1213 GLuint n
, const GLfloat texcoords
[][4],
1214 const GLfloat lambda
[], GLchan rgba
[][4])
1216 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1217 const GLfloat width
= (GLfloat
) img
->Width
;
1218 const GLfloat height
= (GLfloat
) img
->Height
;
1219 const GLint colMask
= img
->Width
- 1;
1220 const GLint rowMask
= img
->Height
- 1;
1221 const GLint shift
= img
->WidthLog2
;
1225 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1226 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1227 ASSERT(img
->Border
==0);
1228 ASSERT(img
->TexFormat
->MesaFormat
==MESA_FORMAT_RGBA
);
1229 ASSERT(img
->_IsPowerOfTwo
);
1231 for (i
= 0; i
< n
; i
++) {
1232 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1233 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1234 const GLint pos
= (row
<< shift
) | col
;
1235 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1236 COPY_4V(rgba
[i
], texel
);
1241 /** Sample 2D texture, using lambda to choose between min/magnification */
1243 sample_lambda_2d(GLcontext
*ctx
,
1244 const struct gl_texture_object
*tObj
,
1245 GLuint n
, const GLfloat texcoords
[][4],
1246 const GLfloat lambda
[], GLfloat rgba
[][4])
1248 const struct gl_texture_image
*tImg
= tObj
->Image
[0][tObj
->BaseLevel
];
1249 GLuint minStart
, minEnd
; /* texels with minification */
1250 GLuint magStart
, magEnd
; /* texels with magnification */
1252 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1253 && (tObj
->WrapT
== GL_REPEAT
)
1254 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1255 && (tImg
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
)
1256 && tImg
->_IsPowerOfTwo
;
1258 ASSERT(lambda
!= NULL
);
1259 compute_min_mag_ranges(tObj
, n
, lambda
,
1260 &minStart
, &minEnd
, &magStart
, &magEnd
);
1262 if (minStart
< minEnd
) {
1263 /* do the minified texels */
1264 const GLuint m
= minEnd
- minStart
;
1265 switch (tObj
->MinFilter
) {
1267 if (repeatNoBorderPOT
) {
1268 switch (tImg
->TexFormat
->MesaFormat
) {
1270 case MESA_FORMAT_RGB
:
1271 opt_sample_rgb_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1272 NULL
, rgba
+ minStart
);
1274 case MESA_FORMAT_RGBA
:
1275 opt_sample_rgba_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1276 NULL
, rgba
+ minStart
);
1280 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1281 NULL
, rgba
+ minStart
);
1285 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1286 NULL
, rgba
+ minStart
);
1290 sample_linear_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1291 NULL
, rgba
+ minStart
);
1293 case GL_NEAREST_MIPMAP_NEAREST
:
1294 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1295 texcoords
+ minStart
,
1296 lambda
+ minStart
, rgba
+ minStart
);
1298 case GL_LINEAR_MIPMAP_NEAREST
:
1299 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1300 lambda
+ minStart
, rgba
+ minStart
);
1302 case GL_NEAREST_MIPMAP_LINEAR
:
1303 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1304 lambda
+ minStart
, rgba
+ minStart
);
1306 case GL_LINEAR_MIPMAP_LINEAR
:
1307 if (repeatNoBorderPOT
)
1308 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1309 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1311 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1312 lambda
+ minStart
, rgba
+ minStart
);
1315 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1320 if (magStart
< magEnd
) {
1321 /* do the magnified texels */
1322 const GLuint m
= magEnd
- magStart
;
1324 switch (tObj
->MagFilter
) {
1326 if (repeatNoBorderPOT
) {
1327 switch (tImg
->TexFormat
->MesaFormat
) {
1329 case MESA_FORMAT_RGB
:
1330 opt_sample_rgb_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1331 NULL
, rgba
+ magStart
);
1333 case MESA_FORMAT_RGBA
:
1334 opt_sample_rgba_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1335 NULL
, rgba
+ magStart
);
1339 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1340 NULL
, rgba
+ magStart
);
1344 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1345 NULL
, rgba
+ magStart
);
1349 sample_linear_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1350 NULL
, rgba
+ magStart
);
1353 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1360 /**********************************************************************/
1361 /* 3-D Texture Sampling Functions */
1362 /**********************************************************************/
1365 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1368 sample_3d_nearest(GLcontext
*ctx
,
1369 const struct gl_texture_object
*tObj
,
1370 const struct gl_texture_image
*img
,
1371 const GLfloat texcoord
[4],
1374 const GLint width
= img
->Width2
; /* without border, power of two */
1375 const GLint height
= img
->Height2
; /* without border, power of two */
1376 const GLint depth
= img
->Depth2
; /* without border, power of two */
1380 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
1381 j
= nearest_texel_location(tObj
->WrapT
, img
, height
, texcoord
[1]);
1382 k
= nearest_texel_location(tObj
->WrapR
, img
, depth
, texcoord
[2]);
1384 if (i
< 0 || i
>= (GLint
) img
->Width
||
1385 j
< 0 || j
>= (GLint
) img
->Height
||
1386 k
< 0 || k
>= (GLint
) img
->Depth
) {
1387 /* Need this test for GL_CLAMP_TO_BORDER mode */
1388 COPY_4V(rgba
, tObj
->BorderColor
);
1391 img
->FetchTexelf(img
, i
, j
, k
, rgba
);
1397 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1400 sample_3d_linear(GLcontext
*ctx
,
1401 const struct gl_texture_object
*tObj
,
1402 const struct gl_texture_image
*img
,
1403 const GLfloat texcoord
[4],
1406 const GLint width
= img
->Width2
;
1407 const GLint height
= img
->Height2
;
1408 const GLint depth
= img
->Depth2
;
1409 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1410 GLbitfield useBorderColor
= 0x0;
1412 GLfloat t000
[4], t010
[4], t001
[4], t011
[4];
1413 GLfloat t100
[4], t110
[4], t101
[4], t111
[4];
1415 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
1416 linear_texel_locations(tObj
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
1417 linear_texel_locations(tObj
->WrapR
, img
, depth
, texcoord
[2], &k0
, &k1
, &c
);
1428 /* check if sampling texture border color */
1429 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1430 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1431 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1432 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1433 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1434 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1438 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1439 COPY_4V(t000
, tObj
->BorderColor
);
1442 img
->FetchTexelf(img
, i0
, j0
, k0
, t000
);
1444 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1445 COPY_4V(t100
, tObj
->BorderColor
);
1448 img
->FetchTexelf(img
, i1
, j0
, k0
, t100
);
1450 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1451 COPY_4V(t010
, tObj
->BorderColor
);
1454 img
->FetchTexelf(img
, i0
, j1
, k0
, t010
);
1456 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1457 COPY_4V(t110
, tObj
->BorderColor
);
1460 img
->FetchTexelf(img
, i1
, j1
, k0
, t110
);
1463 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1464 COPY_4V(t001
, tObj
->BorderColor
);
1467 img
->FetchTexelf(img
, i0
, j0
, k1
, t001
);
1469 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1470 COPY_4V(t101
, tObj
->BorderColor
);
1473 img
->FetchTexelf(img
, i1
, j0
, k1
, t101
);
1475 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1476 COPY_4V(t011
, tObj
->BorderColor
);
1479 img
->FetchTexelf(img
, i0
, j1
, k1
, t011
);
1481 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1482 COPY_4V(t111
, tObj
->BorderColor
);
1485 img
->FetchTexelf(img
, i1
, j1
, k1
, t111
);
1488 /* trilinear interpolation of samples */
1489 lerp_rgba_3d(rgba
, a
, b
, c
, t000
, t100
, t010
, t110
, t001
, t101
, t011
, t111
);
1494 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1495 const struct gl_texture_object
*tObj
,
1496 GLuint n
, const GLfloat texcoord
[][4],
1497 const GLfloat lambda
[], GLfloat rgba
[][4] )
1500 for (i
= 0; i
< n
; i
++) {
1501 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1502 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1508 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1509 const struct gl_texture_object
*tObj
,
1510 GLuint n
, const GLfloat texcoord
[][4],
1511 const GLfloat lambda
[], GLfloat rgba
[][4])
1514 ASSERT(lambda
!= NULL
);
1515 for (i
= 0; i
< n
; i
++) {
1516 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1517 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1523 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1524 const struct gl_texture_object
*tObj
,
1525 GLuint n
, const GLfloat texcoord
[][4],
1526 const GLfloat lambda
[], GLfloat rgba
[][4])
1529 ASSERT(lambda
!= NULL
);
1530 for (i
= 0; i
< n
; i
++) {
1531 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1532 if (level
>= tObj
->_MaxLevel
) {
1533 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1534 texcoord
[i
], rgba
[i
]);
1537 GLfloat t0
[4], t1
[4]; /* texels */
1538 const GLfloat f
= FRAC(lambda
[i
]);
1539 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1540 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1541 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1548 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1549 const struct gl_texture_object
*tObj
,
1550 GLuint n
, const GLfloat texcoord
[][4],
1551 const GLfloat lambda
[], GLfloat rgba
[][4])
1554 ASSERT(lambda
!= NULL
);
1555 for (i
= 0; i
< n
; i
++) {
1556 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1557 if (level
>= tObj
->_MaxLevel
) {
1558 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1559 texcoord
[i
], rgba
[i
]);
1562 GLfloat t0
[4], t1
[4]; /* texels */
1563 const GLfloat f
= FRAC(lambda
[i
]);
1564 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1565 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1566 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1572 /** Sample 3D texture, nearest filtering for both min/magnification */
1574 sample_nearest_3d(GLcontext
*ctx
,
1575 const struct gl_texture_object
*tObj
, GLuint n
,
1576 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1580 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1582 for (i
= 0; i
< n
; i
++) {
1583 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1588 /** Sample 3D texture, linear filtering for both min/magnification */
1590 sample_linear_3d(GLcontext
*ctx
,
1591 const struct gl_texture_object
*tObj
, GLuint n
,
1592 const GLfloat texcoords
[][4],
1593 const GLfloat lambda
[], GLfloat rgba
[][4])
1596 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1598 for (i
= 0; i
< n
; i
++) {
1599 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1604 /** Sample 3D texture, using lambda to choose between min/magnification */
1606 sample_lambda_3d(GLcontext
*ctx
,
1607 const struct gl_texture_object
*tObj
, GLuint n
,
1608 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1611 GLuint minStart
, minEnd
; /* texels with minification */
1612 GLuint magStart
, magEnd
; /* texels with magnification */
1615 ASSERT(lambda
!= NULL
);
1616 compute_min_mag_ranges(tObj
, n
, lambda
,
1617 &minStart
, &minEnd
, &magStart
, &magEnd
);
1619 if (minStart
< minEnd
) {
1620 /* do the minified texels */
1621 GLuint m
= minEnd
- minStart
;
1622 switch (tObj
->MinFilter
) {
1624 for (i
= minStart
; i
< minEnd
; i
++)
1625 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1626 texcoords
[i
], rgba
[i
]);
1629 for (i
= minStart
; i
< minEnd
; i
++)
1630 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1631 texcoords
[i
], rgba
[i
]);
1633 case GL_NEAREST_MIPMAP_NEAREST
:
1634 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1635 lambda
+ minStart
, rgba
+ minStart
);
1637 case GL_LINEAR_MIPMAP_NEAREST
:
1638 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1639 lambda
+ minStart
, rgba
+ minStart
);
1641 case GL_NEAREST_MIPMAP_LINEAR
:
1642 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1643 lambda
+ minStart
, rgba
+ minStart
);
1645 case GL_LINEAR_MIPMAP_LINEAR
:
1646 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1647 lambda
+ minStart
, rgba
+ minStart
);
1650 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1655 if (magStart
< magEnd
) {
1656 /* do the magnified texels */
1657 switch (tObj
->MagFilter
) {
1659 for (i
= magStart
; i
< magEnd
; i
++)
1660 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1661 texcoords
[i
], rgba
[i
]);
1664 for (i
= magStart
; i
< magEnd
; i
++)
1665 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1666 texcoords
[i
], rgba
[i
]);
1669 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1676 /**********************************************************************/
1677 /* Texture Cube Map Sampling Functions */
1678 /**********************************************************************/
1681 * Choose one of six sides of a texture cube map given the texture
1682 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1685 static const struct gl_texture_image
**
1686 choose_cube_face(const struct gl_texture_object
*texObj
,
1687 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1691 direction target sc tc ma
1692 ---------- ------------------------------- --- --- ---
1693 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1694 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1695 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1696 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1697 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1698 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1700 const GLfloat rx
= texcoord
[0];
1701 const GLfloat ry
= texcoord
[1];
1702 const GLfloat rz
= texcoord
[2];
1703 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
1707 if (arx
> ary
&& arx
> arz
) {
1721 else if (ary
> arx
&& ary
> arz
) {
1750 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1751 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1752 return (const struct gl_texture_image
**) texObj
->Image
[face
];
1757 sample_nearest_cube(GLcontext
*ctx
,
1758 const struct gl_texture_object
*tObj
, GLuint n
,
1759 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1764 for (i
= 0; i
< n
; i
++) {
1765 const struct gl_texture_image
**images
;
1766 GLfloat newCoord
[4];
1767 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1768 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1775 sample_linear_cube(GLcontext
*ctx
,
1776 const struct gl_texture_object
*tObj
, GLuint n
,
1777 const GLfloat texcoords
[][4],
1778 const GLfloat lambda
[], GLfloat rgba
[][4])
1782 for (i
= 0; i
< n
; i
++) {
1783 const struct gl_texture_image
**images
;
1784 GLfloat newCoord
[4];
1785 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1786 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1793 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1794 const struct gl_texture_object
*tObj
,
1795 GLuint n
, const GLfloat texcoord
[][4],
1796 const GLfloat lambda
[], GLfloat rgba
[][4])
1799 ASSERT(lambda
!= NULL
);
1800 for (i
= 0; i
< n
; i
++) {
1801 const struct gl_texture_image
**images
;
1802 GLfloat newCoord
[4];
1804 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1806 /* XXX we actually need to recompute lambda here based on the newCoords.
1807 * But we would need the texcoords of adjacent fragments to compute that
1808 * properly, and we don't have those here.
1809 * For now, do an approximation: subtracting 1 from the chosen mipmap
1810 * level seems to work in some test cases.
1811 * The same adjustment is done in the next few functions.
1813 level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1814 level
= MAX2(level
- 1, 0);
1816 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1822 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1823 const struct gl_texture_object
*tObj
,
1824 GLuint n
, const GLfloat texcoord
[][4],
1825 const GLfloat lambda
[], GLfloat rgba
[][4])
1828 ASSERT(lambda
!= NULL
);
1829 for (i
= 0; i
< n
; i
++) {
1830 const struct gl_texture_image
**images
;
1831 GLfloat newCoord
[4];
1832 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1833 level
= MAX2(level
- 1, 0); /* see comment above */
1834 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1835 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1841 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1842 const struct gl_texture_object
*tObj
,
1843 GLuint n
, const GLfloat texcoord
[][4],
1844 const GLfloat lambda
[], GLfloat rgba
[][4])
1847 ASSERT(lambda
!= NULL
);
1848 for (i
= 0; i
< n
; i
++) {
1849 const struct gl_texture_image
**images
;
1850 GLfloat newCoord
[4];
1851 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1852 level
= MAX2(level
- 1, 0); /* see comment above */
1853 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1854 if (level
>= tObj
->_MaxLevel
) {
1855 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1859 GLfloat t0
[4], t1
[4]; /* texels */
1860 const GLfloat f
= FRAC(lambda
[i
]);
1861 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1862 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1863 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1870 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1871 const struct gl_texture_object
*tObj
,
1872 GLuint n
, const GLfloat texcoord
[][4],
1873 const GLfloat lambda
[], GLfloat rgba
[][4])
1876 ASSERT(lambda
!= NULL
);
1877 for (i
= 0; i
< n
; i
++) {
1878 const struct gl_texture_image
**images
;
1879 GLfloat newCoord
[4];
1880 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1881 level
= MAX2(level
- 1, 0); /* see comment above */
1882 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1883 if (level
>= tObj
->_MaxLevel
) {
1884 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1888 GLfloat t0
[4], t1
[4];
1889 const GLfloat f
= FRAC(lambda
[i
]);
1890 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
1891 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1892 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1898 /** Sample cube texture, using lambda to choose between min/magnification */
1900 sample_lambda_cube(GLcontext
*ctx
,
1901 const struct gl_texture_object
*tObj
, GLuint n
,
1902 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1905 GLuint minStart
, minEnd
; /* texels with minification */
1906 GLuint magStart
, magEnd
; /* texels with magnification */
1908 ASSERT(lambda
!= NULL
);
1909 compute_min_mag_ranges(tObj
, n
, lambda
,
1910 &minStart
, &minEnd
, &magStart
, &magEnd
);
1912 if (minStart
< minEnd
) {
1913 /* do the minified texels */
1914 const GLuint m
= minEnd
- minStart
;
1915 switch (tObj
->MinFilter
) {
1917 sample_nearest_cube(ctx
, tObj
, m
, texcoords
+ minStart
,
1918 lambda
+ minStart
, rgba
+ minStart
);
1921 sample_linear_cube(ctx
, tObj
, m
, texcoords
+ minStart
,
1922 lambda
+ minStart
, rgba
+ minStart
);
1924 case GL_NEAREST_MIPMAP_NEAREST
:
1925 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, m
,
1926 texcoords
+ minStart
,
1927 lambda
+ minStart
, rgba
+ minStart
);
1929 case GL_LINEAR_MIPMAP_NEAREST
:
1930 sample_cube_linear_mipmap_nearest(ctx
, tObj
, m
,
1931 texcoords
+ minStart
,
1932 lambda
+ minStart
, rgba
+ minStart
);
1934 case GL_NEAREST_MIPMAP_LINEAR
:
1935 sample_cube_nearest_mipmap_linear(ctx
, tObj
, m
,
1936 texcoords
+ minStart
,
1937 lambda
+ minStart
, rgba
+ minStart
);
1939 case GL_LINEAR_MIPMAP_LINEAR
:
1940 sample_cube_linear_mipmap_linear(ctx
, tObj
, m
,
1941 texcoords
+ minStart
,
1942 lambda
+ minStart
, rgba
+ minStart
);
1945 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
1949 if (magStart
< magEnd
) {
1950 /* do the magnified texels */
1951 const GLuint m
= magEnd
- magStart
;
1952 switch (tObj
->MagFilter
) {
1954 sample_nearest_cube(ctx
, tObj
, m
, texcoords
+ magStart
,
1955 lambda
+ magStart
, rgba
+ magStart
);
1958 sample_linear_cube(ctx
, tObj
, m
, texcoords
+ magStart
,
1959 lambda
+ magStart
, rgba
+ magStart
);
1962 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
1968 /**********************************************************************/
1969 /* Texture Rectangle Sampling Functions */
1970 /**********************************************************************/
1974 * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
1977 clamp_rect_coord_nearest(GLenum wrapMode
, GLfloat coord
, GLint max
)
1981 return IFLOOR( CLAMP(coord
, 0.0F
, max
- 1) );
1982 case GL_CLAMP_TO_EDGE
:
1983 return IFLOOR( CLAMP(coord
, 0.5F
, max
- 0.5F
) );
1984 case GL_CLAMP_TO_BORDER
:
1985 return IFLOOR( CLAMP(coord
, -0.5F
, max
+ 0.5F
) );
1987 _mesa_problem(NULL
, "bad wrapMode in clamp_rect_coord_nearest");
1994 * As above, but GL_LINEAR filtering.
1997 clamp_rect_coord_linear(GLenum wrapMode
, GLfloat coord
, GLint max
,
1998 GLint
*i0out
, GLint
*i1out
, GLfloat
*weight
)
2004 /* Not exactly what the spec says, but it matches NVIDIA output */
2005 fcol
= CLAMP(coord
- 0.5F
, 0.0, max
-1);
2009 case GL_CLAMP_TO_EDGE
:
2010 fcol
= CLAMP(coord
, 0.5F
, max
- 0.5F
);
2017 case GL_CLAMP_TO_BORDER
:
2018 fcol
= CLAMP(coord
, -0.5F
, max
+ 0.5F
);
2023 _mesa_problem(NULL
, "bad wrapMode in clamp_rect_coord_linear");
2029 *weight
= FRAC(fcol
);
2034 sample_nearest_rect(GLcontext
*ctx
,
2035 const struct gl_texture_object
*tObj
, GLuint n
,
2036 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2039 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2040 const GLint width
= img
->Width
;
2041 const GLint height
= img
->Height
;
2047 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2048 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2049 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2050 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2051 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2052 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2053 ASSERT(img
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
);
2055 for (i
= 0; i
< n
; i
++) {
2057 col
= clamp_rect_coord_nearest(tObj
->WrapS
, texcoords
[i
][0], width
);
2058 row
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoords
[i
][1], height
);
2059 if (col
< 0 || col
>= width
|| row
< 0 || row
>= height
)
2060 COPY_4V(rgba
[i
], tObj
->BorderColor
);
2062 img
->FetchTexelf(img
, col
, row
, 0, rgba
[i
]);
2068 sample_linear_rect(GLcontext
*ctx
,
2069 const struct gl_texture_object
*tObj
, GLuint n
,
2070 const GLfloat texcoords
[][4],
2071 const GLfloat lambda
[], GLfloat rgba
[][4])
2073 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2074 const GLint width
= img
->Width
;
2075 const GLint height
= img
->Height
;
2081 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2082 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2083 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2084 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2085 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2086 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2087 ASSERT(img
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
);
2089 for (i
= 0; i
< n
; i
++) {
2090 GLint i0
, j0
, i1
, j1
;
2091 GLfloat t00
[4], t01
[4], t10
[4], t11
[4];
2093 GLbitfield useBorderColor
= 0x0;
2095 clamp_rect_coord_linear(tObj
->WrapS
, texcoords
[i
][0], width
,
2097 clamp_rect_coord_linear(tObj
->WrapT
, texcoords
[i
][1], height
,
2100 /* compute integer rows/columns */
2101 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2102 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2103 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
2104 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
2106 /* get four texel samples */
2107 if (useBorderColor
& (I0BIT
| J0BIT
))
2108 COPY_4V(t00
, tObj
->BorderColor
);
2110 img
->FetchTexelf(img
, i0
, j0
, 0, t00
);
2112 if (useBorderColor
& (I1BIT
| J0BIT
))
2113 COPY_4V(t10
, tObj
->BorderColor
);
2115 img
->FetchTexelf(img
, i1
, j0
, 0, t10
);
2117 if (useBorderColor
& (I0BIT
| J1BIT
))
2118 COPY_4V(t01
, tObj
->BorderColor
);
2120 img
->FetchTexelf(img
, i0
, j1
, 0, t01
);
2122 if (useBorderColor
& (I1BIT
| J1BIT
))
2123 COPY_4V(t11
, tObj
->BorderColor
);
2125 img
->FetchTexelf(img
, i1
, j1
, 0, t11
);
2127 lerp_rgba_2d(rgba
[i
], a
, b
, t00
, t10
, t01
, t11
);
2132 /** Sample Rect texture, using lambda to choose between min/magnification */
2134 sample_lambda_rect(GLcontext
*ctx
,
2135 const struct gl_texture_object
*tObj
, GLuint n
,
2136 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2139 GLuint minStart
, minEnd
, magStart
, magEnd
;
2141 /* We only need lambda to decide between minification and magnification.
2142 * There is no mipmapping with rectangular textures.
2144 compute_min_mag_ranges(tObj
, n
, lambda
,
2145 &minStart
, &minEnd
, &magStart
, &magEnd
);
2147 if (minStart
< minEnd
) {
2148 if (tObj
->MinFilter
== GL_NEAREST
) {
2149 sample_nearest_rect(ctx
, tObj
, minEnd
- minStart
,
2150 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2153 sample_linear_rect(ctx
, tObj
, minEnd
- minStart
,
2154 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2157 if (magStart
< magEnd
) {
2158 if (tObj
->MagFilter
== GL_NEAREST
) {
2159 sample_nearest_rect(ctx
, tObj
, magEnd
- magStart
,
2160 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2163 sample_linear_rect(ctx
, tObj
, magEnd
- magStart
,
2164 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2171 /**********************************************************************/
2172 /* 2D Texture Array Sampling Functions */
2173 /**********************************************************************/
2176 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
2179 sample_2d_array_nearest(GLcontext
*ctx
,
2180 const struct gl_texture_object
*tObj
,
2181 const struct gl_texture_image
*img
,
2182 const GLfloat texcoord
[4],
2185 const GLint width
= img
->Width2
; /* without border, power of two */
2186 const GLint height
= img
->Height2
; /* without border, power of two */
2187 const GLint depth
= img
->Depth
;
2192 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
2193 j
= nearest_texel_location(tObj
->WrapT
, img
, height
, texcoord
[1]);
2194 array
= clamp_rect_coord_nearest(tObj
->WrapR
, texcoord
[2], depth
);
2196 if (i
< 0 || i
>= (GLint
) img
->Width
||
2197 j
< 0 || j
>= (GLint
) img
->Height
||
2198 array
< 0 || array
>= (GLint
) img
->Depth
) {
2199 /* Need this test for GL_CLAMP_TO_BORDER mode */
2200 COPY_4V(rgba
, tObj
->BorderColor
);
2203 img
->FetchTexelf(img
, i
, j
, array
, rgba
);
2209 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
2212 sample_2d_array_linear(GLcontext
*ctx
,
2213 const struct gl_texture_object
*tObj
,
2214 const struct gl_texture_image
*img
,
2215 const GLfloat texcoord
[4],
2218 const GLint width
= img
->Width2
;
2219 const GLint height
= img
->Height2
;
2220 const GLint depth
= img
->Depth
;
2221 GLint i0
, j0
, i1
, j1
;
2223 GLbitfield useBorderColor
= 0x0;
2225 GLfloat t00
[4], t01
[4], t10
[4], t11
[4];
2227 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
2228 linear_texel_locations(tObj
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
2229 array
= clamp_rect_coord_nearest(tObj
->WrapR
, texcoord
[2], depth
);
2231 if (array
< 0 || array
>= depth
) {
2232 COPY_4V(rgba
, tObj
->BorderColor
);
2242 /* check if sampling texture border color */
2243 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2244 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2245 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
2246 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
2250 if (useBorderColor
& (I0BIT
| J0BIT
)) {
2251 COPY_4V(t00
, tObj
->BorderColor
);
2254 img
->FetchTexelf(img
, i0
, j0
, array
, t00
);
2256 if (useBorderColor
& (I1BIT
| J0BIT
)) {
2257 COPY_4V(t10
, tObj
->BorderColor
);
2260 img
->FetchTexelf(img
, i1
, j0
, array
, t10
);
2262 if (useBorderColor
& (I0BIT
| J1BIT
)) {
2263 COPY_4V(t01
, tObj
->BorderColor
);
2266 img
->FetchTexelf(img
, i0
, j1
, array
, t01
);
2268 if (useBorderColor
& (I1BIT
| J1BIT
)) {
2269 COPY_4V(t11
, tObj
->BorderColor
);
2272 img
->FetchTexelf(img
, i1
, j1
, array
, t11
);
2275 /* trilinear interpolation of samples */
2276 lerp_rgba_2d(rgba
, a
, b
, t00
, t10
, t01
, t11
);
2282 sample_2d_array_nearest_mipmap_nearest(GLcontext
*ctx
,
2283 const struct gl_texture_object
*tObj
,
2284 GLuint n
, const GLfloat texcoord
[][4],
2285 const GLfloat lambda
[], GLfloat rgba
[][4])
2288 for (i
= 0; i
< n
; i
++) {
2289 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2290 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
],
2297 sample_2d_array_linear_mipmap_nearest(GLcontext
*ctx
,
2298 const struct gl_texture_object
*tObj
,
2299 GLuint n
, const GLfloat texcoord
[][4],
2300 const GLfloat lambda
[], GLfloat rgba
[][4])
2303 ASSERT(lambda
!= NULL
);
2304 for (i
= 0; i
< n
; i
++) {
2305 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2306 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
],
2307 texcoord
[i
], rgba
[i
]);
2313 sample_2d_array_nearest_mipmap_linear(GLcontext
*ctx
,
2314 const struct gl_texture_object
*tObj
,
2315 GLuint n
, const GLfloat texcoord
[][4],
2316 const GLfloat lambda
[], GLfloat rgba
[][4])
2319 ASSERT(lambda
!= NULL
);
2320 for (i
= 0; i
< n
; i
++) {
2321 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2322 if (level
>= tObj
->_MaxLevel
) {
2323 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2324 texcoord
[i
], rgba
[i
]);
2327 GLfloat t0
[4], t1
[4]; /* texels */
2328 const GLfloat f
= FRAC(lambda
[i
]);
2329 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
],
2331 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1],
2333 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2340 sample_2d_array_linear_mipmap_linear(GLcontext
*ctx
,
2341 const struct gl_texture_object
*tObj
,
2342 GLuint n
, const GLfloat texcoord
[][4],
2343 const GLfloat lambda
[], GLfloat rgba
[][4])
2346 ASSERT(lambda
!= NULL
);
2347 for (i
= 0; i
< n
; i
++) {
2348 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2349 if (level
>= tObj
->_MaxLevel
) {
2350 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2351 texcoord
[i
], rgba
[i
]);
2354 GLfloat t0
[4], t1
[4]; /* texels */
2355 const GLfloat f
= FRAC(lambda
[i
]);
2356 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
],
2358 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
+1],
2360 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2366 /** Sample 2D Array texture, nearest filtering for both min/magnification */
2368 sample_nearest_2d_array(GLcontext
*ctx
,
2369 const struct gl_texture_object
*tObj
, GLuint n
,
2370 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2374 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2376 for (i
= 0; i
< n
; i
++) {
2377 sample_2d_array_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2383 /** Sample 2D Array texture, linear filtering for both min/magnification */
2385 sample_linear_2d_array(GLcontext
*ctx
,
2386 const struct gl_texture_object
*tObj
, GLuint n
,
2387 const GLfloat texcoords
[][4],
2388 const GLfloat lambda
[], GLfloat rgba
[][4])
2391 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2393 for (i
= 0; i
< n
; i
++) {
2394 sample_2d_array_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2399 /** Sample 2D Array texture, using lambda to choose between min/magnification */
2401 sample_lambda_2d_array(GLcontext
*ctx
,
2402 const struct gl_texture_object
*tObj
, GLuint n
,
2403 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2406 GLuint minStart
, minEnd
; /* texels with minification */
2407 GLuint magStart
, magEnd
; /* texels with magnification */
2410 ASSERT(lambda
!= NULL
);
2411 compute_min_mag_ranges(tObj
, n
, lambda
,
2412 &minStart
, &minEnd
, &magStart
, &magEnd
);
2414 if (minStart
< minEnd
) {
2415 /* do the minified texels */
2416 GLuint m
= minEnd
- minStart
;
2417 switch (tObj
->MinFilter
) {
2419 for (i
= minStart
; i
< minEnd
; i
++)
2420 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2421 texcoords
[i
], rgba
[i
]);
2424 for (i
= minStart
; i
< minEnd
; i
++)
2425 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2426 texcoords
[i
], rgba
[i
]);
2428 case GL_NEAREST_MIPMAP_NEAREST
:
2429 sample_2d_array_nearest_mipmap_nearest(ctx
, tObj
, m
,
2430 texcoords
+ minStart
,
2434 case GL_LINEAR_MIPMAP_NEAREST
:
2435 sample_2d_array_linear_mipmap_nearest(ctx
, tObj
, m
,
2436 texcoords
+ minStart
,
2440 case GL_NEAREST_MIPMAP_LINEAR
:
2441 sample_2d_array_nearest_mipmap_linear(ctx
, tObj
, m
,
2442 texcoords
+ minStart
,
2446 case GL_LINEAR_MIPMAP_LINEAR
:
2447 sample_2d_array_linear_mipmap_linear(ctx
, tObj
, m
,
2448 texcoords
+ minStart
,
2453 _mesa_problem(ctx
, "Bad min filter in sample_2d_array_texture");
2458 if (magStart
< magEnd
) {
2459 /* do the magnified texels */
2460 switch (tObj
->MagFilter
) {
2462 for (i
= magStart
; i
< magEnd
; i
++)
2463 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2464 texcoords
[i
], rgba
[i
]);
2467 for (i
= magStart
; i
< magEnd
; i
++)
2468 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2469 texcoords
[i
], rgba
[i
]);
2472 _mesa_problem(ctx
, "Bad mag filter in sample_2d_array_texture");
2481 /**********************************************************************/
2482 /* 1D Texture Array Sampling Functions */
2483 /**********************************************************************/
2486 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
2489 sample_1d_array_nearest(GLcontext
*ctx
,
2490 const struct gl_texture_object
*tObj
,
2491 const struct gl_texture_image
*img
,
2492 const GLfloat texcoord
[4],
2495 const GLint width
= img
->Width2
; /* without border, power of two */
2496 const GLint height
= img
->Height
;
2501 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
2502 array
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoord
[1], height
);
2504 if (i
< 0 || i
>= (GLint
) img
->Width
||
2505 array
< 0 || array
>= (GLint
) img
->Height
) {
2506 /* Need this test for GL_CLAMP_TO_BORDER mode */
2507 COPY_4V(rgba
, tObj
->BorderColor
);
2510 img
->FetchTexelf(img
, i
, array
, 0, rgba
);
2516 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
2519 sample_1d_array_linear(GLcontext
*ctx
,
2520 const struct gl_texture_object
*tObj
,
2521 const struct gl_texture_image
*img
,
2522 const GLfloat texcoord
[4],
2525 const GLint width
= img
->Width2
;
2526 const GLint height
= img
->Height
;
2529 GLbitfield useBorderColor
= 0x0;
2531 GLfloat t0
[4], t1
[4];
2533 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
2534 array
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoord
[1], height
);
2541 /* check if sampling texture border color */
2542 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2543 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2546 if (array
< 0 || array
>= height
) useBorderColor
|= K0BIT
;
2549 if (useBorderColor
& (I0BIT
| K0BIT
)) {
2550 COPY_4V(t0
, tObj
->BorderColor
);
2553 img
->FetchTexelf(img
, i0
, array
, 0, t0
);
2555 if (useBorderColor
& (I1BIT
| K0BIT
)) {
2556 COPY_4V(t1
, tObj
->BorderColor
);
2559 img
->FetchTexelf(img
, i1
, array
, 0, t1
);
2562 /* bilinear interpolation of samples */
2563 lerp_rgba(rgba
, a
, t0
, t1
);
2568 sample_1d_array_nearest_mipmap_nearest(GLcontext
*ctx
,
2569 const struct gl_texture_object
*tObj
,
2570 GLuint n
, const GLfloat texcoord
[][4],
2571 const GLfloat lambda
[], GLfloat rgba
[][4])
2574 for (i
= 0; i
< n
; i
++) {
2575 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2576 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
],
2583 sample_1d_array_linear_mipmap_nearest(GLcontext
*ctx
,
2584 const struct gl_texture_object
*tObj
,
2585 GLuint n
, const GLfloat texcoord
[][4],
2586 const GLfloat lambda
[], GLfloat rgba
[][4])
2589 ASSERT(lambda
!= NULL
);
2590 for (i
= 0; i
< n
; i
++) {
2591 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2592 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
],
2593 texcoord
[i
], rgba
[i
]);
2599 sample_1d_array_nearest_mipmap_linear(GLcontext
*ctx
,
2600 const struct gl_texture_object
*tObj
,
2601 GLuint n
, const GLfloat texcoord
[][4],
2602 const GLfloat lambda
[], GLfloat rgba
[][4])
2605 ASSERT(lambda
!= NULL
);
2606 for (i
= 0; i
< n
; i
++) {
2607 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2608 if (level
>= tObj
->_MaxLevel
) {
2609 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2610 texcoord
[i
], rgba
[i
]);
2613 GLfloat t0
[4], t1
[4]; /* texels */
2614 const GLfloat f
= FRAC(lambda
[i
]);
2615 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
2616 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
2617 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2624 sample_1d_array_linear_mipmap_linear(GLcontext
*ctx
,
2625 const struct gl_texture_object
*tObj
,
2626 GLuint n
, const GLfloat texcoord
[][4],
2627 const GLfloat lambda
[], GLfloat rgba
[][4])
2630 ASSERT(lambda
!= NULL
);
2631 for (i
= 0; i
< n
; i
++) {
2632 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2633 if (level
>= tObj
->_MaxLevel
) {
2634 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2635 texcoord
[i
], rgba
[i
]);
2638 GLfloat t0
[4], t1
[4]; /* texels */
2639 const GLfloat f
= FRAC(lambda
[i
]);
2640 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
2641 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
2642 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2648 /** Sample 1D Array texture, nearest filtering for both min/magnification */
2650 sample_nearest_1d_array(GLcontext
*ctx
,
2651 const struct gl_texture_object
*tObj
, GLuint n
,
2652 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2656 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2658 for (i
= 0; i
< n
; i
++) {
2659 sample_1d_array_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2664 /** Sample 1D Array texture, linear filtering for both min/magnification */
2666 sample_linear_1d_array(GLcontext
*ctx
,
2667 const struct gl_texture_object
*tObj
, GLuint n
,
2668 const GLfloat texcoords
[][4],
2669 const GLfloat lambda
[], GLfloat rgba
[][4])
2672 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2674 for (i
= 0; i
< n
; i
++) {
2675 sample_1d_array_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2680 /** Sample 1D Array texture, using lambda to choose between min/magnification */
2682 sample_lambda_1d_array(GLcontext
*ctx
,
2683 const struct gl_texture_object
*tObj
, GLuint n
,
2684 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2687 GLuint minStart
, minEnd
; /* texels with minification */
2688 GLuint magStart
, magEnd
; /* texels with magnification */
2691 ASSERT(lambda
!= NULL
);
2692 compute_min_mag_ranges(tObj
, n
, lambda
,
2693 &minStart
, &minEnd
, &magStart
, &magEnd
);
2695 if (minStart
< minEnd
) {
2696 /* do the minified texels */
2697 GLuint m
= minEnd
- minStart
;
2698 switch (tObj
->MinFilter
) {
2700 for (i
= minStart
; i
< minEnd
; i
++)
2701 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2702 texcoords
[i
], rgba
[i
]);
2705 for (i
= minStart
; i
< minEnd
; i
++)
2706 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2707 texcoords
[i
], rgba
[i
]);
2709 case GL_NEAREST_MIPMAP_NEAREST
:
2710 sample_1d_array_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2711 lambda
+ minStart
, rgba
+ minStart
);
2713 case GL_LINEAR_MIPMAP_NEAREST
:
2714 sample_1d_array_linear_mipmap_nearest(ctx
, tObj
, m
,
2715 texcoords
+ minStart
,
2719 case GL_NEAREST_MIPMAP_LINEAR
:
2720 sample_1d_array_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2721 lambda
+ minStart
, rgba
+ minStart
);
2723 case GL_LINEAR_MIPMAP_LINEAR
:
2724 sample_1d_array_linear_mipmap_linear(ctx
, tObj
, m
,
2725 texcoords
+ minStart
,
2730 _mesa_problem(ctx
, "Bad min filter in sample_1d_array_texture");
2735 if (magStart
< magEnd
) {
2736 /* do the magnified texels */
2737 switch (tObj
->MagFilter
) {
2739 for (i
= magStart
; i
< magEnd
; i
++)
2740 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2741 texcoords
[i
], rgba
[i
]);
2744 for (i
= magStart
; i
< magEnd
; i
++)
2745 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2746 texcoords
[i
], rgba
[i
]);
2749 _mesa_problem(ctx
, "Bad mag filter in sample_1d_array_texture");
2757 * Sample a shadow/depth texture.
2760 sample_depth_texture( GLcontext
*ctx
,
2761 const struct gl_texture_object
*tObj
, GLuint n
,
2762 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2763 GLfloat texel
[][4] )
2765 const GLint baseLevel
= tObj
->BaseLevel
;
2766 const struct gl_texture_image
*img
= tObj
->Image
[0][baseLevel
];
2767 const GLint width
= img
->Width
;
2768 const GLint height
= img
->Height
;
2769 const GLint depth
= img
->Depth
;
2770 const GLuint compare_coord
= (tObj
->Target
== GL_TEXTURE_2D_ARRAY_EXT
)
2778 ASSERT(img
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2779 img
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
);
2781 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2782 tObj
->Target
== GL_TEXTURE_2D
||
2783 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
||
2784 tObj
->Target
== GL_TEXTURE_1D_ARRAY_EXT
||
2785 tObj
->Target
== GL_TEXTURE_2D_ARRAY_EXT
);
2787 ambient
= tObj
->CompareFailValue
;
2789 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2791 function
= (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) ?
2792 tObj
->CompareFunc
: GL_NONE
;
2794 if (tObj
->MagFilter
== GL_NEAREST
) {
2796 for (i
= 0; i
< n
; i
++) {
2797 GLfloat depthSample
;
2798 GLint col
, row
, slice
;
2800 switch (tObj
->Target
) {
2801 case GL_TEXTURE_RECTANGLE_ARB
:
2802 col
= clamp_rect_coord_nearest(tObj
->WrapS
, texcoords
[i
][0], width
);
2803 row
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoords
[i
][1], height
);
2808 col
= nearest_texel_location(tObj
->WrapS
, img
, width
,
2815 col
= nearest_texel_location(tObj
->WrapS
, img
, width
,
2817 row
= nearest_texel_location(tObj
->WrapT
, img
, height
,
2822 case GL_TEXTURE_1D_ARRAY_EXT
:
2823 col
= nearest_texel_location(tObj
->WrapS
, img
, width
,
2825 row
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoords
[i
][1], height
);
2829 case GL_TEXTURE_2D_ARRAY_EXT
:
2830 col
= nearest_texel_location(tObj
->WrapS
, img
, width
,
2832 row
= nearest_texel_location(tObj
->WrapT
, img
, height
,
2834 slice
= clamp_rect_coord_nearest(tObj
->WrapR
, texcoords
[i
][2], depth
);
2837 col
= row
= slice
= 0;
2840 if (col
>= 0 && row
>= 0 && col
< width
&& row
< height
&&
2841 slice
>= 0 && slice
< depth
) {
2842 img
->FetchTexelf(img
, col
, row
, slice
, &depthSample
);
2845 depthSample
= tObj
->BorderColor
[0];
2850 result
= (texcoords
[i
][compare_coord
] <= depthSample
) ? 1.0F
: ambient
;
2853 result
= (texcoords
[i
][compare_coord
] >= depthSample
) ? 1.0F
: ambient
;
2856 result
= (texcoords
[i
][compare_coord
] < depthSample
) ? 1.0F
: ambient
;
2859 result
= (texcoords
[i
][compare_coord
] > depthSample
) ? 1.0F
: ambient
;
2862 result
= (texcoords
[i
][compare_coord
] == depthSample
) ? 1.0F
: ambient
;
2865 result
= (texcoords
[i
][compare_coord
] != depthSample
) ? 1.0F
: ambient
;
2874 result
= depthSample
;
2877 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2881 switch (tObj
->DepthMode
) {
2883 ASSIGN_4V(texel
[i
], result
, result
, result
, 1.0F
);
2886 ASSIGN_4V(texel
[i
], result
, result
, result
, result
);
2889 ASSIGN_4V(texel
[i
], 0.0F
, 0.0F
, 0.0F
, result
);
2892 _mesa_problem(ctx
, "Bad depth texture mode");
2898 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2899 for (i
= 0; i
< n
; i
++) {
2900 GLfloat depth00
, depth01
, depth10
, depth11
;
2901 GLint i0
, i1
, j0
, j1
;
2904 GLuint useBorderTexel
;
2906 switch (tObj
->Target
) {
2907 case GL_TEXTURE_RECTANGLE_ARB
:
2908 clamp_rect_coord_linear(tObj
->WrapS
, texcoords
[i
][0],
2909 width
, &i0
, &i1
, &a
);
2910 clamp_rect_coord_linear(tObj
->WrapT
, texcoords
[i
][1],
2911 height
, &j0
, &j1
, &b
);
2917 linear_texel_locations(tObj
->WrapS
, img
, width
,
2918 texcoords
[i
][0], &i0
, &i1
, &a
);
2919 linear_texel_locations(tObj
->WrapT
, img
, height
,
2920 texcoords
[i
][1], &j0
, &j1
, &b
);
2924 case GL_TEXTURE_1D_ARRAY_EXT
:
2925 linear_texel_locations(tObj
->WrapS
, img
, width
,
2926 texcoords
[i
][0], &i0
, &i1
, &a
);
2927 j0
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoords
[i
][1], height
);
2932 case GL_TEXTURE_2D_ARRAY_EXT
:
2933 linear_texel_locations(tObj
->WrapS
, img
, width
,
2934 texcoords
[i
][0], &i0
, &i1
, &a
);
2935 linear_texel_locations(tObj
->WrapT
, img
, height
,
2936 texcoords
[i
][1], &j0
, &j1
, &b
);
2937 slice
= clamp_rect_coord_nearest(tObj
->WrapR
, texcoords
[i
][2], depth
);
2947 if (tObj
->Target
!= GL_TEXTURE_1D_ARRAY_EXT
) {
2953 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2954 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2955 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2956 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2959 if (slice
< 0 || slice
>= (GLint
) depth
) {
2960 depth00
= tObj
->BorderColor
[0];
2961 depth01
= tObj
->BorderColor
[0];
2962 depth10
= tObj
->BorderColor
[0];
2963 depth11
= tObj
->BorderColor
[0];
2966 /* get four depth samples from the texture */
2967 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2968 depth00
= tObj
->BorderColor
[0];
2971 img
->FetchTexelf(img
, i0
, j0
, slice
, &depth00
);
2973 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2974 depth10
= tObj
->BorderColor
[0];
2977 img
->FetchTexelf(img
, i1
, j0
, slice
, &depth10
);
2980 if (tObj
->Target
!= GL_TEXTURE_1D_ARRAY_EXT
) {
2981 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2982 depth01
= tObj
->BorderColor
[0];
2985 img
->FetchTexelf(img
, i0
, j1
, slice
, &depth01
);
2987 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2988 depth11
= tObj
->BorderColor
[0];
2991 img
->FetchTexelf(img
, i1
, j1
, slice
, &depth11
);
3001 /* compute a single weighted depth sample and do one comparison */
3002 const GLfloat depthSample
3003 = lerp_2d(a
, b
, depth00
, depth10
, depth01
, depth11
);
3004 if ((depthSample
<= texcoords
[i
][compare_coord
] && function
== GL_LEQUAL
) ||
3005 (depthSample
>= texcoords
[i
][compare_coord
] && function
== GL_GEQUAL
)) {
3013 /* Do four depth/R comparisons and compute a weighted result.
3014 * If this touches on somebody's I.P., I'll remove this code
3017 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
3018 GLfloat luminance
= CHAN_MAXF
;
3022 if (depth00
<= texcoords
[i
][compare_coord
]) luminance
-= d
;
3023 if (depth01
<= texcoords
[i
][compare_coord
]) luminance
-= d
;
3024 if (depth10
<= texcoords
[i
][compare_coord
]) luminance
-= d
;
3025 if (depth11
<= texcoords
[i
][compare_coord
]) luminance
-= d
;
3026 result
= (GLfloat
) luminance
;
3029 if (depth00
>= texcoords
[i
][compare_coord
]) luminance
-= d
;
3030 if (depth01
>= texcoords
[i
][compare_coord
]) luminance
-= d
;
3031 if (depth10
>= texcoords
[i
][compare_coord
]) luminance
-= d
;
3032 if (depth11
>= texcoords
[i
][compare_coord
]) luminance
-= d
;
3033 result
= (GLfloat
) luminance
;
3036 if (depth00
< texcoords
[i
][compare_coord
]) luminance
-= d
;
3037 if (depth01
< texcoords
[i
][compare_coord
]) luminance
-= d
;
3038 if (depth10
< texcoords
[i
][compare_coord
]) luminance
-= d
;
3039 if (depth11
< texcoords
[i
][compare_coord
]) luminance
-= d
;
3040 result
= (GLfloat
) luminance
;
3043 if (depth00
> texcoords
[i
][compare_coord
]) luminance
-= d
;
3044 if (depth01
> texcoords
[i
][compare_coord
]) luminance
-= d
;
3045 if (depth10
> texcoords
[i
][compare_coord
]) luminance
-= d
;
3046 if (depth11
> texcoords
[i
][compare_coord
]) luminance
-= d
;
3047 result
= (GLfloat
) luminance
;
3050 if (depth00
== texcoords
[i
][compare_coord
]) luminance
-= d
;
3051 if (depth01
== texcoords
[i
][compare_coord
]) luminance
-= d
;
3052 if (depth10
== texcoords
[i
][compare_coord
]) luminance
-= d
;
3053 if (depth11
== texcoords
[i
][compare_coord
]) luminance
-= d
;
3054 result
= (GLfloat
) luminance
;
3057 if (depth00
!= texcoords
[i
][compare_coord
]) luminance
-= d
;
3058 if (depth01
!= texcoords
[i
][compare_coord
]) luminance
-= d
;
3059 if (depth10
!= texcoords
[i
][compare_coord
]) luminance
-= d
;
3060 if (depth11
!= texcoords
[i
][compare_coord
]) luminance
-= d
;
3061 result
= (GLfloat
) luminance
;
3070 /* ordinary bilinear filtering */
3072 const GLfloat depthSample
3073 = lerp_2d(a
, b
, depth00
, depth10
, depth01
, depth11
);
3074 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
3078 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
3083 switch (tObj
->DepthMode
) {
3085 texel
[i
][RCOMP
] = result
;
3086 texel
[i
][GCOMP
] = result
;
3087 texel
[i
][BCOMP
] = result
;
3088 texel
[i
][ACOMP
] = CHAN_MAX
;
3091 texel
[i
][RCOMP
] = result
;
3092 texel
[i
][GCOMP
] = result
;
3093 texel
[i
][BCOMP
] = result
;
3094 texel
[i
][ACOMP
] = result
;
3097 texel
[i
][RCOMP
] = 0;
3098 texel
[i
][GCOMP
] = 0;
3099 texel
[i
][BCOMP
] = 0;
3100 texel
[i
][ACOMP
] = result
;
3103 _mesa_problem(ctx
, "Bad depth texture mode");
3111 * We use this function when a texture object is in an "incomplete" state.
3112 * When a fragment program attempts to sample an incomplete texture we
3113 * return black (see issue 23 in GL_ARB_fragment_program spec).
3114 * Note: fragment programs don't observe the texture enable/disable flags.
3117 null_sample_func( GLcontext
*ctx
,
3118 const struct gl_texture_object
*tObj
, GLuint n
,
3119 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3127 for (i
= 0; i
< n
; i
++) {
3131 rgba
[i
][ACOMP
] = CHAN_MAX
;
3137 * Choose the texture sampling function for the given texture object.
3140 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
3141 const struct gl_texture_object
*t
)
3143 if (!t
|| !t
->_Complete
) {
3144 return &null_sample_func
;
3147 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
3148 const GLenum format
= t
->Image
[0][t
->BaseLevel
]->TexFormat
->BaseFormat
;
3150 switch (t
->Target
) {
3152 if (format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
) {
3153 return &sample_depth_texture
;
3155 else if (needLambda
) {
3156 return &sample_lambda_1d
;
3158 else if (t
->MinFilter
== GL_LINEAR
) {
3159 return &sample_linear_1d
;
3162 ASSERT(t
->MinFilter
== GL_NEAREST
);
3163 return &sample_nearest_1d
;
3166 if (format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
) {
3167 return &sample_depth_texture
;
3169 else if (needLambda
) {
3170 return &sample_lambda_2d
;
3172 else if (t
->MinFilter
== GL_LINEAR
) {
3173 return &sample_linear_2d
;
3176 /* check for a few optimized cases */
3178 const struct gl_texture_image
*img
= t
->Image
[0][t
->BaseLevel
];
3179 ASSERT(t
->MinFilter
== GL_NEAREST
);
3180 if (t
->WrapS
== GL_REPEAT
&&
3181 t
->WrapT
== GL_REPEAT
&&
3182 img
->_IsPowerOfTwo
&&
3184 img
->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
3185 return &opt_sample_rgb_2d
;
3187 else if (t
->WrapS
== GL_REPEAT
&&
3188 t
->WrapT
== GL_REPEAT
&&
3189 img
->_IsPowerOfTwo
&&
3191 img
->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
3192 return &opt_sample_rgba_2d
;
3199 return &sample_nearest_2d
;
3204 return &sample_lambda_3d
;
3206 else if (t
->MinFilter
== GL_LINEAR
) {
3207 return &sample_linear_3d
;
3210 ASSERT(t
->MinFilter
== GL_NEAREST
);
3211 return &sample_nearest_3d
;
3213 case GL_TEXTURE_CUBE_MAP
:
3215 return &sample_lambda_cube
;
3217 else if (t
->MinFilter
== GL_LINEAR
) {
3218 return &sample_linear_cube
;
3221 ASSERT(t
->MinFilter
== GL_NEAREST
);
3222 return &sample_nearest_cube
;
3224 case GL_TEXTURE_RECTANGLE_NV
:
3225 if (format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
) {
3226 return &sample_depth_texture
;
3228 else if (needLambda
) {
3229 return &sample_lambda_rect
;
3231 else if (t
->MinFilter
== GL_LINEAR
) {
3232 return &sample_linear_rect
;
3235 ASSERT(t
->MinFilter
== GL_NEAREST
);
3236 return &sample_nearest_rect
;
3238 case GL_TEXTURE_1D_ARRAY_EXT
:
3240 return &sample_lambda_1d_array
;
3242 else if (t
->MinFilter
== GL_LINEAR
) {
3243 return &sample_linear_1d_array
;
3246 ASSERT(t
->MinFilter
== GL_NEAREST
);
3247 return &sample_nearest_1d_array
;
3249 case GL_TEXTURE_2D_ARRAY_EXT
:
3251 return &sample_lambda_2d_array
;
3253 else if (t
->MinFilter
== GL_LINEAR
) {
3254 return &sample_linear_2d_array
;
3257 ASSERT(t
->MinFilter
== GL_NEAREST
);
3258 return &sample_nearest_2d_array
;
3262 "invalid target in _swrast_choose_texture_sample_func");
3263 return &null_sample_func
;