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))
48 * Linear interpolation macro
50 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
54 * Do 2D/biliner interpolation of float values.
55 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
56 * a and b are the horizontal and vertical interpolants.
57 * It's important that this function is inlined when compiled with
58 * optimization! If we find that's not true on some systems, convert
62 lerp_2d(GLfloat a
, GLfloat b
,
63 GLfloat v00
, GLfloat v10
, GLfloat v01
, GLfloat v11
)
65 const GLfloat temp0
= LERP(a
, v00
, v10
);
66 const GLfloat temp1
= LERP(a
, v01
, v11
);
67 return LERP(b
, temp0
, temp1
);
72 * Do 3D/trilinear interpolation of float values.
76 lerp_3d(GLfloat a
, GLfloat b
, GLfloat c
,
77 GLfloat v000
, GLfloat v100
, GLfloat v010
, GLfloat v110
,
78 GLfloat v001
, GLfloat v101
, GLfloat v011
, GLfloat v111
)
80 const GLfloat temp00
= LERP(a
, v000
, v100
);
81 const GLfloat temp10
= LERP(a
, v010
, v110
);
82 const GLfloat temp01
= LERP(a
, v001
, v101
);
83 const GLfloat temp11
= LERP(a
, v011
, v111
);
84 const GLfloat temp0
= LERP(b
, temp00
, temp10
);
85 const GLfloat temp1
= LERP(b
, temp01
, temp11
);
86 return LERP(c
, temp0
, temp1
);
91 * Do linear interpolation of colors.
94 lerp_rgba(GLfloat result
[4], GLfloat t
, const GLfloat a
[4], const GLfloat b
[4])
96 result
[0] = LERP(t
, a
[0], b
[0]);
97 result
[1] = LERP(t
, a
[1], b
[1]);
98 result
[2] = LERP(t
, a
[2], b
[2]);
99 result
[3] = LERP(t
, a
[3], b
[3]);
104 * Do bilinear interpolation of colors.
107 lerp_rgba_2d(GLfloat result
[4], GLfloat a
, GLfloat b
,
108 const GLfloat t00
[4], const GLfloat t10
[4],
109 const GLfloat t01
[4], const GLfloat t11
[4])
111 result
[0] = lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]);
112 result
[1] = lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]);
113 result
[2] = lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]);
114 result
[3] = lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]);
119 * Do trilinear interpolation of colors.
122 lerp_rgba_3d(GLfloat result
[4], GLfloat a
, GLfloat b
, GLfloat c
,
123 const GLfloat t000
[4], const GLfloat t100
[4],
124 const GLfloat t010
[4], const GLfloat t110
[4],
125 const GLfloat t001
[4], const GLfloat t101
[4],
126 const GLfloat t011
[4], const GLfloat t111
[4])
129 /* compiler should unroll these short loops */
130 for (k
= 0; k
< 4; k
++) {
131 result
[k
] = lerp_3d(a
, b
, c
, t000
[k
], t100
[k
], t010
[k
], t110
[k
],
132 t001
[k
], t101
[k
], t011
[k
], t111
[k
]);
138 * If A is a signed integer, A % B doesn't give the right value for A < 0
139 * (in terms of texture repeat). Just casting to unsigned fixes that.
141 #define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
145 * Used to compute texel locations for linear sampling.
147 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
148 * s = texcoord in [0,1]
149 * size = width (or height or depth) of texture
151 * i0, i1 = returns two nearest texel indexes
152 * weight = returns blend factor between texels
155 linear_texel_locations(GLenum wrapMode
,
156 const struct gl_texture_image
*img
,
157 GLint size
, GLfloat s
,
158 GLint
*i0
, GLint
*i1
, GLfloat
*weight
)
164 if (img
->_IsPowerOfTwo
) {
165 *i0
= IFLOOR(u
) & (size
- 1);
166 *i1
= (*i0
+ 1) & (size
- 1);
169 *i0
= REMAINDER(IFLOOR(u
), size
);
170 *i1
= REMAINDER(*i0
+ 1, size
);
173 case GL_CLAMP_TO_EDGE
:
185 if (*i1
>= (GLint
) size
)
188 case GL_CLAMP_TO_BORDER
:
190 const GLfloat min
= -1.0F
/ (2.0F
* size
);
191 const GLfloat max
= 1.0F
- min
;
203 case GL_MIRRORED_REPEAT
:
205 const GLint flr
= IFLOOR(s
);
207 u
= 1.0F
- (s
- (GLfloat
) flr
);
209 u
= s
- (GLfloat
) flr
;
210 u
= (u
* size
) - 0.5F
;
215 if (*i1
>= (GLint
) size
)
219 case GL_MIRROR_CLAMP_EXT
:
229 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
240 if (*i1
>= (GLint
) size
)
243 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
245 const GLfloat min
= -1.0F
/ (2.0F
* size
);
246 const GLfloat max
= 1.0F
- min
;
271 _mesa_problem(NULL
, "Bad wrap mode");
279 * Used to compute texel location for nearest sampling.
282 nearest_texel_location(GLenum wrapMode
,
283 const struct gl_texture_image
*img
,
284 GLint size
, GLfloat s
)
290 /* s limited to [0,1) */
291 /* i limited to [0,size-1] */
292 i
= IFLOOR(s
* size
);
293 if (img
->_IsPowerOfTwo
)
296 i
= REMAINDER(i
, size
);
298 case GL_CLAMP_TO_EDGE
:
300 /* s limited to [min,max] */
301 /* i limited to [0, size-1] */
302 const GLfloat min
= 1.0F
/ (2.0F
* size
);
303 const GLfloat max
= 1.0F
- min
;
309 i
= IFLOOR(s
* size
);
312 case GL_CLAMP_TO_BORDER
:
314 /* s limited to [min,max] */
315 /* i limited to [-1, size] */
316 const GLfloat min
= -1.0F
/ (2.0F
* size
);
317 const GLfloat max
= 1.0F
- min
;
323 i
= IFLOOR(s
* size
);
326 case GL_MIRRORED_REPEAT
:
328 const GLfloat min
= 1.0F
/ (2.0F
* size
);
329 const GLfloat max
= 1.0F
- min
;
330 const GLint flr
= IFLOOR(s
);
333 u
= 1.0F
- (s
- (GLfloat
) flr
);
335 u
= s
- (GLfloat
) flr
;
341 i
= IFLOOR(u
* size
);
344 case GL_MIRROR_CLAMP_EXT
:
346 /* s limited to [0,1] */
347 /* i limited to [0,size-1] */
348 const GLfloat u
= FABSF(s
);
354 i
= IFLOOR(u
* size
);
357 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
359 /* s limited to [min,max] */
360 /* i limited to [0, size-1] */
361 const GLfloat min
= 1.0F
/ (2.0F
* size
);
362 const GLfloat max
= 1.0F
- min
;
363 const GLfloat u
= FABSF(s
);
369 i
= IFLOOR(u
* size
);
372 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
374 /* s limited to [min,max] */
375 /* i limited to [0, size-1] */
376 const GLfloat min
= -1.0F
/ (2.0F
* size
);
377 const GLfloat max
= 1.0F
- min
;
378 const GLfloat u
= FABSF(s
);
384 i
= IFLOOR(u
* size
);
388 /* s limited to [0,1] */
389 /* i limited to [0,size-1] */
395 i
= IFLOOR(s
* size
);
398 _mesa_problem(NULL
, "Bad wrap mode");
404 /* Power of two image sizes only */
406 linear_repeat_texel_location(GLuint size
, GLfloat s
,
407 GLint
*i0
, GLint
*i1
, GLfloat
*weight
)
409 GLfloat u
= s
* size
- 0.5F
;
410 *i0
= IFLOOR(u
) & (size
- 1);
411 *i1
= (*i0
+ 1) & (size
- 1);
417 * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
420 clamp_rect_coord_nearest(GLenum wrapMode
, GLfloat coord
, GLint max
)
424 return IFLOOR( CLAMP(coord
, 0.0F
, max
- 1) );
425 case GL_CLAMP_TO_EDGE
:
426 return IFLOOR( CLAMP(coord
, 0.5F
, max
- 0.5F
) );
427 case GL_CLAMP_TO_BORDER
:
428 return IFLOOR( CLAMP(coord
, -0.5F
, max
+ 0.5F
) );
430 _mesa_problem(NULL
, "bad wrapMode in clamp_rect_coord_nearest");
437 * As above, but GL_LINEAR filtering.
440 clamp_rect_coord_linear(GLenum wrapMode
, GLfloat coord
, GLint max
,
441 GLint
*i0out
, GLint
*i1out
, GLfloat
*weight
)
447 /* Not exactly what the spec says, but it matches NVIDIA output */
448 fcol
= CLAMP(coord
- 0.5F
, 0.0, max
-1);
452 case GL_CLAMP_TO_EDGE
:
453 fcol
= CLAMP(coord
, 0.5F
, max
- 0.5F
);
460 case GL_CLAMP_TO_BORDER
:
461 fcol
= CLAMP(coord
, -0.5F
, max
+ 0.5F
);
466 _mesa_problem(NULL
, "bad wrapMode in clamp_rect_coord_linear");
472 *weight
= FRAC(fcol
);
477 * Compute nearest integer texcoords for given texobj and coordinate.
480 nearest_texcoord(const struct gl_texture_object
*texObj
,
481 const GLfloat texcoord
[4],
482 GLint
*i
, GLint
*j
, GLint
*k
)
484 const GLint baseLevel
= texObj
->BaseLevel
;
485 const struct gl_texture_image
*img
= texObj
->Image
[0][baseLevel
];
486 const GLint width
= img
->Width
;
487 const GLint height
= img
->Height
;
488 const GLint depth
= img
->Depth
;
490 switch (texObj
->Target
) {
491 case GL_TEXTURE_RECTANGLE_ARB
:
492 *i
= clamp_rect_coord_nearest(texObj
->WrapS
, texcoord
[0], width
);
493 *j
= clamp_rect_coord_nearest(texObj
->WrapT
, texcoord
[1], height
);
497 *i
= nearest_texel_location(texObj
->WrapS
, img
, width
, texcoord
[0]);
502 *i
= nearest_texel_location(texObj
->WrapS
, img
, width
, texcoord
[0]);
503 *j
= nearest_texel_location(texObj
->WrapT
, img
, height
, texcoord
[1]);
506 case GL_TEXTURE_1D_ARRAY_EXT
:
507 *i
= nearest_texel_location(texObj
->WrapS
, img
, width
, texcoord
[0]);
508 *j
= clamp_rect_coord_nearest(texObj
->WrapT
, texcoord
[1], height
);
511 case GL_TEXTURE_2D_ARRAY_EXT
:
512 *i
= nearest_texel_location(texObj
->WrapS
, img
, width
, texcoord
[0]);
513 *j
= nearest_texel_location(texObj
->WrapT
, img
, height
, texcoord
[1]);
514 *k
= clamp_rect_coord_nearest(texObj
->WrapR
, texcoord
[2], depth
);
523 * Compute linear integer texcoords for given texobj and coordinate.
526 linear_texcoord(const struct gl_texture_object
*texObj
,
527 const GLfloat texcoord
[4],
528 GLint
*i0
, GLint
*i1
, GLint
*j0
, GLint
*j1
, GLint
*slice
,
529 GLfloat
*wi
, GLfloat
*wj
)
531 const GLint baseLevel
= texObj
->BaseLevel
;
532 const struct gl_texture_image
*img
= texObj
->Image
[0][baseLevel
];
533 const GLint width
= img
->Width
;
534 const GLint height
= img
->Height
;
535 const GLint depth
= img
->Depth
;
537 switch (texObj
->Target
) {
538 case GL_TEXTURE_RECTANGLE_ARB
:
539 clamp_rect_coord_linear(texObj
->WrapS
, texcoord
[0],
541 clamp_rect_coord_linear(texObj
->WrapT
, texcoord
[1],
548 linear_texel_locations(texObj
->WrapS
, img
, width
,
549 texcoord
[0], i0
, i1
, wi
);
550 linear_texel_locations(texObj
->WrapT
, img
, height
,
551 texcoord
[1], j0
, j1
, wj
);
555 case GL_TEXTURE_1D_ARRAY_EXT
:
556 linear_texel_locations(texObj
->WrapS
, img
, width
,
557 texcoord
[0], i0
, i1
, wi
);
558 *j0
= clamp_rect_coord_nearest(texObj
->WrapT
, texcoord
[1], height
);
563 case GL_TEXTURE_2D_ARRAY_EXT
:
564 linear_texel_locations(texObj
->WrapS
, img
, width
,
565 texcoord
[0], i0
, i1
, wi
);
566 linear_texel_locations(texObj
->WrapT
, img
, height
,
567 texcoord
[1], j0
, j1
, wj
);
568 *slice
= clamp_rect_coord_nearest(texObj
->WrapR
, texcoord
[2], depth
);
579 * For linear interpolation between mipmap levels N and N+1, this function
583 linear_mipmap_level(const struct gl_texture_object
*tObj
, GLfloat lambda
)
586 return tObj
->BaseLevel
;
587 else if (lambda
> tObj
->_MaxLambda
)
588 return (GLint
) (tObj
->BaseLevel
+ tObj
->_MaxLambda
);
590 return (GLint
) (tObj
->BaseLevel
+ lambda
);
595 * Compute the nearest mipmap level to take texels from.
598 nearest_mipmap_level(const struct gl_texture_object
*tObj
, GLfloat lambda
)
604 else if (lambda
> tObj
->_MaxLambda
+ 0.4999F
)
605 l
= tObj
->_MaxLambda
+ 0.4999F
;
608 level
= (GLint
) (tObj
->BaseLevel
+ l
+ 0.5F
);
609 if (level
> tObj
->_MaxLevel
)
610 level
= tObj
->_MaxLevel
;
617 * Bitflags for texture border color sampling.
629 * The lambda[] array values are always monotonic. Either the whole span
630 * will be minified, magnified, or split between the two. This function
631 * determines the subranges in [0, n-1] that are to be minified or magnified.
634 compute_min_mag_ranges(const struct gl_texture_object
*tObj
,
635 GLuint n
, const GLfloat lambda
[],
636 GLuint
*minStart
, GLuint
*minEnd
,
637 GLuint
*magStart
, GLuint
*magEnd
)
639 GLfloat minMagThresh
;
641 /* we shouldn't be here if minfilter == magfilter */
642 ASSERT(tObj
->MinFilter
!= tObj
->MagFilter
);
644 /* This bit comes from the OpenGL spec: */
645 if (tObj
->MagFilter
== GL_LINEAR
646 && (tObj
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
647 tObj
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
655 /* DEBUG CODE: Verify that lambda[] is monotonic.
656 * We can't really use this because the inaccuracy in the LOG2 function
657 * causes this test to fail, yet the resulting texturing is correct.
661 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
662 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
663 for (i
= 0; i
< n
- 1; i
++) {
664 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
667 else { /* increasing */
668 for (i
= 0; i
< n
- 1; i
++) {
669 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
675 if (lambda
[0] <= minMagThresh
&& (n
<= 1 || lambda
[n
-1] <= minMagThresh
)) {
676 /* magnification for whole span */
679 *minStart
= *minEnd
= 0;
681 else if (lambda
[0] > minMagThresh
&& (n
<=1 || lambda
[n
-1] > minMagThresh
)) {
682 /* minification for whole span */
685 *magStart
= *magEnd
= 0;
688 /* a mix of minification and magnification */
690 if (lambda
[0] > minMagThresh
) {
691 /* start with minification */
692 for (i
= 1; i
< n
; i
++) {
693 if (lambda
[i
] <= minMagThresh
)
702 /* start with magnification */
703 for (i
= 1; i
< n
; i
++) {
704 if (lambda
[i
] > minMagThresh
)
715 /* Verify the min/mag Start/End values
716 * We don't use this either (see above)
720 for (i
= 0; i
< n
; i
++) {
721 if (lambda
[i
] > minMagThresh
) {
723 ASSERT(i
>= *minStart
);
728 ASSERT(i
>= *magStart
);
737 /**********************************************************************/
738 /* 1-D Texture Sampling Functions */
739 /**********************************************************************/
742 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
745 sample_1d_nearest(GLcontext
*ctx
,
746 const struct gl_texture_object
*tObj
,
747 const struct gl_texture_image
*img
,
748 const GLfloat texcoord
[4], GLfloat rgba
[4])
750 const GLint width
= img
->Width2
; /* without border, power of two */
752 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
753 /* skip over the border, if any */
755 if (i
< 0 || i
>= (GLint
) img
->Width
) {
756 /* Need this test for GL_CLAMP_TO_BORDER mode */
757 COPY_4V(rgba
, tObj
->BorderColor
);
760 img
->FetchTexelf(img
, i
, 0, 0, rgba
);
766 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
769 sample_1d_linear(GLcontext
*ctx
,
770 const struct gl_texture_object
*tObj
,
771 const struct gl_texture_image
*img
,
772 const GLfloat texcoord
[4], GLfloat rgba
[4])
774 const GLint width
= img
->Width2
;
776 GLbitfield useBorderColor
= 0x0;
778 GLfloat t0
[4], t1
[4]; /* texels */
780 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
787 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
788 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
791 /* fetch texel colors */
792 if (useBorderColor
& I0BIT
) {
793 COPY_4V(t0
, tObj
->BorderColor
);
796 img
->FetchTexelf(img
, i0
, 0, 0, t0
);
798 if (useBorderColor
& I1BIT
) {
799 COPY_4V(t1
, tObj
->BorderColor
);
802 img
->FetchTexelf(img
, i1
, 0, 0, t1
);
805 lerp_rgba(rgba
, a
, t0
, t1
);
810 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
811 const struct gl_texture_object
*tObj
,
812 GLuint n
, const GLfloat texcoord
[][4],
813 const GLfloat lambda
[], GLfloat rgba
[][4])
816 ASSERT(lambda
!= NULL
);
817 for (i
= 0; i
< n
; i
++) {
818 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
819 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
825 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
826 const struct gl_texture_object
*tObj
,
827 GLuint n
, const GLfloat texcoord
[][4],
828 const GLfloat lambda
[], GLfloat rgba
[][4])
831 ASSERT(lambda
!= NULL
);
832 for (i
= 0; i
< n
; i
++) {
833 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
834 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
840 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
841 const struct gl_texture_object
*tObj
,
842 GLuint n
, const GLfloat texcoord
[][4],
843 const GLfloat lambda
[], GLfloat rgba
[][4])
846 ASSERT(lambda
!= NULL
);
847 for (i
= 0; i
< n
; i
++) {
848 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
849 if (level
>= tObj
->_MaxLevel
) {
850 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
851 texcoord
[i
], rgba
[i
]);
854 GLfloat t0
[4], t1
[4];
855 const GLfloat f
= FRAC(lambda
[i
]);
856 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
857 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
858 lerp_rgba(rgba
[i
], f
, t0
, t1
);
865 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
866 const struct gl_texture_object
*tObj
,
867 GLuint n
, const GLfloat texcoord
[][4],
868 const GLfloat lambda
[], GLfloat rgba
[][4])
871 ASSERT(lambda
!= NULL
);
872 for (i
= 0; i
< n
; i
++) {
873 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
874 if (level
>= tObj
->_MaxLevel
) {
875 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
876 texcoord
[i
], rgba
[i
]);
879 GLfloat t0
[4], t1
[4];
880 const GLfloat f
= FRAC(lambda
[i
]);
881 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
882 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
883 lerp_rgba(rgba
[i
], f
, t0
, t1
);
889 /** Sample 1D texture, nearest filtering for both min/magnification */
891 sample_nearest_1d( GLcontext
*ctx
,
892 const struct gl_texture_object
*tObj
, GLuint n
,
893 const GLfloat texcoords
[][4], const GLfloat lambda
[],
897 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
899 for (i
= 0; i
< n
; i
++) {
900 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
905 /** Sample 1D texture, linear filtering for both min/magnification */
907 sample_linear_1d( GLcontext
*ctx
,
908 const struct gl_texture_object
*tObj
, GLuint n
,
909 const GLfloat texcoords
[][4], const GLfloat lambda
[],
913 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
915 for (i
= 0; i
< n
; i
++) {
916 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
921 /** Sample 1D texture, using lambda to choose between min/magnification */
923 sample_lambda_1d( GLcontext
*ctx
,
924 const struct gl_texture_object
*tObj
, GLuint n
,
925 const GLfloat texcoords
[][4],
926 const GLfloat lambda
[], GLfloat rgba
[][4] )
928 GLuint minStart
, minEnd
; /* texels with minification */
929 GLuint magStart
, magEnd
; /* texels with magnification */
932 ASSERT(lambda
!= NULL
);
933 compute_min_mag_ranges(tObj
, n
, lambda
,
934 &minStart
, &minEnd
, &magStart
, &magEnd
);
936 if (minStart
< minEnd
) {
937 /* do the minified texels */
938 const GLuint m
= minEnd
- minStart
;
939 switch (tObj
->MinFilter
) {
941 for (i
= minStart
; i
< minEnd
; i
++)
942 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
943 texcoords
[i
], rgba
[i
]);
946 for (i
= minStart
; i
< minEnd
; i
++)
947 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
948 texcoords
[i
], rgba
[i
]);
950 case GL_NEAREST_MIPMAP_NEAREST
:
951 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
952 lambda
+ minStart
, rgba
+ minStart
);
954 case GL_LINEAR_MIPMAP_NEAREST
:
955 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
956 lambda
+ minStart
, rgba
+ minStart
);
958 case GL_NEAREST_MIPMAP_LINEAR
:
959 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
960 lambda
+ minStart
, rgba
+ minStart
);
962 case GL_LINEAR_MIPMAP_LINEAR
:
963 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
964 lambda
+ minStart
, rgba
+ minStart
);
967 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
972 if (magStart
< magEnd
) {
973 /* do the magnified texels */
974 switch (tObj
->MagFilter
) {
976 for (i
= magStart
; i
< magEnd
; i
++)
977 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
978 texcoords
[i
], rgba
[i
]);
981 for (i
= magStart
; i
< magEnd
; i
++)
982 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
983 texcoords
[i
], rgba
[i
]);
986 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
993 /**********************************************************************/
994 /* 2-D Texture Sampling Functions */
995 /**********************************************************************/
999 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1002 sample_2d_nearest(GLcontext
*ctx
,
1003 const struct gl_texture_object
*tObj
,
1004 const struct gl_texture_image
*img
,
1005 const GLfloat texcoord
[4],
1008 const GLint width
= img
->Width2
; /* without border, power of two */
1009 const GLint height
= img
->Height2
; /* without border, power of two */
1013 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
1014 j
= nearest_texel_location(tObj
->WrapT
, img
, height
, texcoord
[1]);
1016 /* skip over the border, if any */
1020 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
1021 /* Need this test for GL_CLAMP_TO_BORDER mode */
1022 COPY_4V(rgba
, tObj
->BorderColor
);
1025 img
->FetchTexelf(img
, i
, j
, 0, rgba
);
1031 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1032 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1035 sample_2d_linear(GLcontext
*ctx
,
1036 const struct gl_texture_object
*tObj
,
1037 const struct gl_texture_image
*img
,
1038 const GLfloat texcoord
[4],
1041 const GLint width
= img
->Width2
;
1042 const GLint height
= img
->Height2
;
1043 GLint i0
, j0
, i1
, j1
;
1044 GLbitfield useBorderColor
= 0x0;
1046 GLfloat t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
1048 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
1049 linear_texel_locations(tObj
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
1058 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1059 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1060 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1061 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1064 /* fetch four texel colors */
1065 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1066 COPY_4V(t00
, tObj
->BorderColor
);
1069 img
->FetchTexelf(img
, i0
, j0
, 0, t00
);
1071 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1072 COPY_4V(t10
, tObj
->BorderColor
);
1075 img
->FetchTexelf(img
, i1
, j0
, 0, t10
);
1077 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1078 COPY_4V(t01
, tObj
->BorderColor
);
1081 img
->FetchTexelf(img
, i0
, j1
, 0, t01
);
1083 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1084 COPY_4V(t11
, tObj
->BorderColor
);
1087 img
->FetchTexelf(img
, i1
, j1
, 0, t11
);
1090 lerp_rgba_2d(rgba
, a
, b
, t00
, t10
, t01
, t11
);
1095 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
1096 * We don't have to worry about the texture border.
1099 sample_2d_linear_repeat(GLcontext
*ctx
,
1100 const struct gl_texture_object
*tObj
,
1101 const struct gl_texture_image
*img
,
1102 const GLfloat texcoord
[4],
1105 const GLint width
= img
->Width2
;
1106 const GLint height
= img
->Height2
;
1107 GLint i0
, j0
, i1
, j1
;
1109 GLfloat t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
1113 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1114 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1115 ASSERT(img
->Border
== 0);
1116 ASSERT(img
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
);
1117 ASSERT(img
->_IsPowerOfTwo
);
1119 linear_repeat_texel_location(width
, texcoord
[0], &i0
, &i1
, &wi
);
1120 linear_repeat_texel_location(height
, texcoord
[1], &j0
, &j1
, &wj
);
1122 img
->FetchTexelf(img
, i0
, j0
, 0, t00
);
1123 img
->FetchTexelf(img
, i1
, j0
, 0, t10
);
1124 img
->FetchTexelf(img
, i0
, j1
, 0, t01
);
1125 img
->FetchTexelf(img
, i1
, j1
, 0, t11
);
1127 lerp_rgba_2d(rgba
, wi
, wj
, t00
, t10
, t01
, t11
);
1132 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1133 const struct gl_texture_object
*tObj
,
1134 GLuint n
, const GLfloat texcoord
[][4],
1135 const GLfloat lambda
[], GLfloat rgba
[][4])
1138 for (i
= 0; i
< n
; i
++) {
1139 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1140 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1146 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1147 const struct gl_texture_object
*tObj
,
1148 GLuint n
, const GLfloat texcoord
[][4],
1149 const GLfloat lambda
[], GLfloat rgba
[][4])
1152 ASSERT(lambda
!= NULL
);
1153 for (i
= 0; i
< n
; i
++) {
1154 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1155 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1161 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1162 const struct gl_texture_object
*tObj
,
1163 GLuint n
, const GLfloat texcoord
[][4],
1164 const GLfloat lambda
[], GLfloat rgba
[][4])
1167 ASSERT(lambda
!= NULL
);
1168 for (i
= 0; i
< n
; i
++) {
1169 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1170 if (level
>= tObj
->_MaxLevel
) {
1171 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1172 texcoord
[i
], rgba
[i
]);
1175 GLfloat t0
[4], t1
[4]; /* texels */
1176 const GLfloat f
= FRAC(lambda
[i
]);
1177 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1178 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1179 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1186 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1187 const struct gl_texture_object
*tObj
,
1188 GLuint n
, const GLfloat texcoord
[][4],
1189 const GLfloat lambda
[], GLfloat rgba
[][4] )
1192 ASSERT(lambda
!= NULL
);
1193 for (i
= 0; i
< n
; i
++) {
1194 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1195 if (level
>= tObj
->_MaxLevel
) {
1196 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1197 texcoord
[i
], rgba
[i
]);
1200 GLfloat t0
[4], t1
[4]; /* texels */
1201 const GLfloat f
= FRAC(lambda
[i
]);
1202 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1203 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1204 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1211 sample_2d_linear_mipmap_linear_repeat(GLcontext
*ctx
,
1212 const struct gl_texture_object
*tObj
,
1213 GLuint n
, const GLfloat texcoord
[][4],
1214 const GLfloat lambda
[], GLfloat rgba
[][4])
1217 ASSERT(lambda
!= NULL
);
1218 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1219 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1220 for (i
= 0; i
< n
; i
++) {
1221 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1222 if (level
>= tObj
->_MaxLevel
) {
1223 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1224 texcoord
[i
], rgba
[i
]);
1227 GLfloat t0
[4], t1
[4]; /* texels */
1228 const GLfloat f
= FRAC(lambda
[i
]);
1229 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
],
1231 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
+1],
1233 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1239 /** Sample 2D texture, nearest filtering for both min/magnification */
1241 sample_nearest_2d(GLcontext
*ctx
,
1242 const struct gl_texture_object
*tObj
, GLuint n
,
1243 const GLfloat texcoords
[][4],
1244 const GLfloat lambda
[], GLfloat rgba
[][4])
1247 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1249 for (i
= 0; i
< n
; i
++) {
1250 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1255 /** Sample 2D texture, linear filtering for both min/magnification */
1257 sample_linear_2d(GLcontext
*ctx
,
1258 const struct gl_texture_object
*tObj
, GLuint n
,
1259 const GLfloat texcoords
[][4],
1260 const GLfloat lambda
[], GLfloat rgba
[][4])
1263 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1265 if (tObj
->WrapS
== GL_REPEAT
&&
1266 tObj
->WrapT
== GL_REPEAT
&&
1267 image
->_IsPowerOfTwo
&&
1268 image
->Border
== 0) {
1269 for (i
= 0; i
< n
; i
++) {
1270 sample_2d_linear_repeat(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1274 for (i
= 0; i
< n
; i
++) {
1275 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1282 * Optimized 2-D texture sampling:
1283 * S and T wrap mode == GL_REPEAT
1284 * GL_NEAREST min/mag filter
1286 * RowStride == Width,
1290 opt_sample_rgb_2d(GLcontext
*ctx
,
1291 const struct gl_texture_object
*tObj
,
1292 GLuint n
, const GLfloat texcoords
[][4],
1293 const GLfloat lambda
[], GLchan rgba
[][4])
1295 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1296 const GLfloat width
= (GLfloat
) img
->Width
;
1297 const GLfloat height
= (GLfloat
) img
->Height
;
1298 const GLint colMask
= img
->Width
- 1;
1299 const GLint rowMask
= img
->Height
- 1;
1300 const GLint shift
= img
->WidthLog2
;
1304 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1305 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1306 ASSERT(img
->Border
==0);
1307 ASSERT(img
->TexFormat
->MesaFormat
==MESA_FORMAT_RGB
);
1308 ASSERT(img
->_IsPowerOfTwo
);
1310 for (k
=0; k
<n
; k
++) {
1311 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1312 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1313 GLint pos
= (j
<< shift
) | i
;
1314 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1315 rgba
[k
][RCOMP
] = texel
[0];
1316 rgba
[k
][GCOMP
] = texel
[1];
1317 rgba
[k
][BCOMP
] = texel
[2];
1323 * Optimized 2-D texture sampling:
1324 * S and T wrap mode == GL_REPEAT
1325 * GL_NEAREST min/mag filter
1327 * RowStride == Width,
1331 opt_sample_rgba_2d(GLcontext
*ctx
,
1332 const struct gl_texture_object
*tObj
,
1333 GLuint n
, const GLfloat texcoords
[][4],
1334 const GLfloat lambda
[], GLchan rgba
[][4])
1336 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1337 const GLfloat width
= (GLfloat
) img
->Width
;
1338 const GLfloat height
= (GLfloat
) img
->Height
;
1339 const GLint colMask
= img
->Width
- 1;
1340 const GLint rowMask
= img
->Height
- 1;
1341 const GLint shift
= img
->WidthLog2
;
1345 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1346 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1347 ASSERT(img
->Border
==0);
1348 ASSERT(img
->TexFormat
->MesaFormat
==MESA_FORMAT_RGBA
);
1349 ASSERT(img
->_IsPowerOfTwo
);
1351 for (i
= 0; i
< n
; i
++) {
1352 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1353 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1354 const GLint pos
= (row
<< shift
) | col
;
1355 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1356 COPY_4V(rgba
[i
], texel
);
1361 /** Sample 2D texture, using lambda to choose between min/magnification */
1363 sample_lambda_2d(GLcontext
*ctx
,
1364 const struct gl_texture_object
*tObj
,
1365 GLuint n
, const GLfloat texcoords
[][4],
1366 const GLfloat lambda
[], GLfloat rgba
[][4])
1368 const struct gl_texture_image
*tImg
= tObj
->Image
[0][tObj
->BaseLevel
];
1369 GLuint minStart
, minEnd
; /* texels with minification */
1370 GLuint magStart
, magEnd
; /* texels with magnification */
1372 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1373 && (tObj
->WrapT
== GL_REPEAT
)
1374 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1375 && (tImg
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
)
1376 && tImg
->_IsPowerOfTwo
;
1378 ASSERT(lambda
!= NULL
);
1379 compute_min_mag_ranges(tObj
, n
, lambda
,
1380 &minStart
, &minEnd
, &magStart
, &magEnd
);
1382 if (minStart
< minEnd
) {
1383 /* do the minified texels */
1384 const GLuint m
= minEnd
- minStart
;
1385 switch (tObj
->MinFilter
) {
1387 if (repeatNoBorderPOT
) {
1388 switch (tImg
->TexFormat
->MesaFormat
) {
1390 case MESA_FORMAT_RGB
:
1391 opt_sample_rgb_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1392 NULL
, rgba
+ minStart
);
1394 case MESA_FORMAT_RGBA
:
1395 opt_sample_rgba_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1396 NULL
, rgba
+ minStart
);
1400 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1401 NULL
, rgba
+ minStart
);
1405 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1406 NULL
, rgba
+ minStart
);
1410 sample_linear_2d(ctx
, tObj
, m
, texcoords
+ minStart
,
1411 NULL
, rgba
+ minStart
);
1413 case GL_NEAREST_MIPMAP_NEAREST
:
1414 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1415 texcoords
+ minStart
,
1416 lambda
+ minStart
, rgba
+ minStart
);
1418 case GL_LINEAR_MIPMAP_NEAREST
:
1419 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1420 lambda
+ minStart
, rgba
+ minStart
);
1422 case GL_NEAREST_MIPMAP_LINEAR
:
1423 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1424 lambda
+ minStart
, rgba
+ minStart
);
1426 case GL_LINEAR_MIPMAP_LINEAR
:
1427 if (repeatNoBorderPOT
)
1428 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1429 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1431 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1432 lambda
+ minStart
, rgba
+ minStart
);
1435 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1440 if (magStart
< magEnd
) {
1441 /* do the magnified texels */
1442 const GLuint m
= magEnd
- magStart
;
1444 switch (tObj
->MagFilter
) {
1446 if (repeatNoBorderPOT
) {
1447 switch (tImg
->TexFormat
->MesaFormat
) {
1449 case MESA_FORMAT_RGB
:
1450 opt_sample_rgb_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1451 NULL
, rgba
+ magStart
);
1453 case MESA_FORMAT_RGBA
:
1454 opt_sample_rgba_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1455 NULL
, rgba
+ magStart
);
1459 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1460 NULL
, rgba
+ magStart
);
1464 sample_nearest_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1465 NULL
, rgba
+ magStart
);
1469 sample_linear_2d(ctx
, tObj
, m
, texcoords
+ magStart
,
1470 NULL
, rgba
+ magStart
);
1473 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1480 /**********************************************************************/
1481 /* 3-D Texture Sampling Functions */
1482 /**********************************************************************/
1485 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1488 sample_3d_nearest(GLcontext
*ctx
,
1489 const struct gl_texture_object
*tObj
,
1490 const struct gl_texture_image
*img
,
1491 const GLfloat texcoord
[4],
1494 const GLint width
= img
->Width2
; /* without border, power of two */
1495 const GLint height
= img
->Height2
; /* without border, power of two */
1496 const GLint depth
= img
->Depth2
; /* without border, power of two */
1500 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
1501 j
= nearest_texel_location(tObj
->WrapT
, img
, height
, texcoord
[1]);
1502 k
= nearest_texel_location(tObj
->WrapR
, img
, depth
, texcoord
[2]);
1504 if (i
< 0 || i
>= (GLint
) img
->Width
||
1505 j
< 0 || j
>= (GLint
) img
->Height
||
1506 k
< 0 || k
>= (GLint
) img
->Depth
) {
1507 /* Need this test for GL_CLAMP_TO_BORDER mode */
1508 COPY_4V(rgba
, tObj
->BorderColor
);
1511 img
->FetchTexelf(img
, i
, j
, k
, rgba
);
1517 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1520 sample_3d_linear(GLcontext
*ctx
,
1521 const struct gl_texture_object
*tObj
,
1522 const struct gl_texture_image
*img
,
1523 const GLfloat texcoord
[4],
1526 const GLint width
= img
->Width2
;
1527 const GLint height
= img
->Height2
;
1528 const GLint depth
= img
->Depth2
;
1529 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1530 GLbitfield useBorderColor
= 0x0;
1532 GLfloat t000
[4], t010
[4], t001
[4], t011
[4];
1533 GLfloat t100
[4], t110
[4], t101
[4], t111
[4];
1535 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
1536 linear_texel_locations(tObj
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
1537 linear_texel_locations(tObj
->WrapR
, img
, depth
, texcoord
[2], &k0
, &k1
, &c
);
1548 /* check if sampling texture border color */
1549 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1550 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1551 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1552 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1553 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1554 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1558 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1559 COPY_4V(t000
, tObj
->BorderColor
);
1562 img
->FetchTexelf(img
, i0
, j0
, k0
, t000
);
1564 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1565 COPY_4V(t100
, tObj
->BorderColor
);
1568 img
->FetchTexelf(img
, i1
, j0
, k0
, t100
);
1570 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1571 COPY_4V(t010
, tObj
->BorderColor
);
1574 img
->FetchTexelf(img
, i0
, j1
, k0
, t010
);
1576 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1577 COPY_4V(t110
, tObj
->BorderColor
);
1580 img
->FetchTexelf(img
, i1
, j1
, k0
, t110
);
1583 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1584 COPY_4V(t001
, tObj
->BorderColor
);
1587 img
->FetchTexelf(img
, i0
, j0
, k1
, t001
);
1589 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1590 COPY_4V(t101
, tObj
->BorderColor
);
1593 img
->FetchTexelf(img
, i1
, j0
, k1
, t101
);
1595 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1596 COPY_4V(t011
, tObj
->BorderColor
);
1599 img
->FetchTexelf(img
, i0
, j1
, k1
, t011
);
1601 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1602 COPY_4V(t111
, tObj
->BorderColor
);
1605 img
->FetchTexelf(img
, i1
, j1
, k1
, t111
);
1608 /* trilinear interpolation of samples */
1609 lerp_rgba_3d(rgba
, a
, b
, c
, t000
, t100
, t010
, t110
, t001
, t101
, t011
, t111
);
1614 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1615 const struct gl_texture_object
*tObj
,
1616 GLuint n
, const GLfloat texcoord
[][4],
1617 const GLfloat lambda
[], GLfloat rgba
[][4] )
1620 for (i
= 0; i
< n
; i
++) {
1621 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1622 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1628 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1629 const struct gl_texture_object
*tObj
,
1630 GLuint n
, const GLfloat texcoord
[][4],
1631 const GLfloat lambda
[], GLfloat rgba
[][4])
1634 ASSERT(lambda
!= NULL
);
1635 for (i
= 0; i
< n
; i
++) {
1636 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1637 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1643 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1644 const struct gl_texture_object
*tObj
,
1645 GLuint n
, const GLfloat texcoord
[][4],
1646 const GLfloat lambda
[], GLfloat rgba
[][4])
1649 ASSERT(lambda
!= NULL
);
1650 for (i
= 0; i
< n
; i
++) {
1651 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1652 if (level
>= tObj
->_MaxLevel
) {
1653 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1654 texcoord
[i
], rgba
[i
]);
1657 GLfloat t0
[4], t1
[4]; /* texels */
1658 const GLfloat f
= FRAC(lambda
[i
]);
1659 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1660 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1661 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1668 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1669 const struct gl_texture_object
*tObj
,
1670 GLuint n
, const GLfloat texcoord
[][4],
1671 const GLfloat lambda
[], GLfloat rgba
[][4])
1674 ASSERT(lambda
!= NULL
);
1675 for (i
= 0; i
< n
; i
++) {
1676 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1677 if (level
>= tObj
->_MaxLevel
) {
1678 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1679 texcoord
[i
], rgba
[i
]);
1682 GLfloat t0
[4], t1
[4]; /* texels */
1683 const GLfloat f
= FRAC(lambda
[i
]);
1684 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1685 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1686 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1692 /** Sample 3D texture, nearest filtering for both min/magnification */
1694 sample_nearest_3d(GLcontext
*ctx
,
1695 const struct gl_texture_object
*tObj
, GLuint n
,
1696 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1700 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1702 for (i
= 0; i
< n
; i
++) {
1703 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1708 /** Sample 3D texture, linear filtering for both min/magnification */
1710 sample_linear_3d(GLcontext
*ctx
,
1711 const struct gl_texture_object
*tObj
, GLuint n
,
1712 const GLfloat texcoords
[][4],
1713 const GLfloat lambda
[], GLfloat rgba
[][4])
1716 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1718 for (i
= 0; i
< n
; i
++) {
1719 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1724 /** Sample 3D texture, using lambda to choose between min/magnification */
1726 sample_lambda_3d(GLcontext
*ctx
,
1727 const struct gl_texture_object
*tObj
, GLuint n
,
1728 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1731 GLuint minStart
, minEnd
; /* texels with minification */
1732 GLuint magStart
, magEnd
; /* texels with magnification */
1735 ASSERT(lambda
!= NULL
);
1736 compute_min_mag_ranges(tObj
, n
, lambda
,
1737 &minStart
, &minEnd
, &magStart
, &magEnd
);
1739 if (minStart
< minEnd
) {
1740 /* do the minified texels */
1741 GLuint m
= minEnd
- minStart
;
1742 switch (tObj
->MinFilter
) {
1744 for (i
= minStart
; i
< minEnd
; i
++)
1745 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1746 texcoords
[i
], rgba
[i
]);
1749 for (i
= minStart
; i
< minEnd
; i
++)
1750 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1751 texcoords
[i
], rgba
[i
]);
1753 case GL_NEAREST_MIPMAP_NEAREST
:
1754 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1755 lambda
+ minStart
, rgba
+ minStart
);
1757 case GL_LINEAR_MIPMAP_NEAREST
:
1758 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1759 lambda
+ minStart
, rgba
+ minStart
);
1761 case GL_NEAREST_MIPMAP_LINEAR
:
1762 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1763 lambda
+ minStart
, rgba
+ minStart
);
1765 case GL_LINEAR_MIPMAP_LINEAR
:
1766 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1767 lambda
+ minStart
, rgba
+ minStart
);
1770 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1775 if (magStart
< magEnd
) {
1776 /* do the magnified texels */
1777 switch (tObj
->MagFilter
) {
1779 for (i
= magStart
; i
< magEnd
; i
++)
1780 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1781 texcoords
[i
], rgba
[i
]);
1784 for (i
= magStart
; i
< magEnd
; i
++)
1785 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1786 texcoords
[i
], rgba
[i
]);
1789 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
1796 /**********************************************************************/
1797 /* Texture Cube Map Sampling Functions */
1798 /**********************************************************************/
1801 * Choose one of six sides of a texture cube map given the texture
1802 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1805 static const struct gl_texture_image
**
1806 choose_cube_face(const struct gl_texture_object
*texObj
,
1807 const GLfloat texcoord
[4], GLfloat newCoord
[4])
1811 direction target sc tc ma
1812 ---------- ------------------------------- --- --- ---
1813 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1814 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1815 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1816 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1817 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1818 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1820 const GLfloat rx
= texcoord
[0];
1821 const GLfloat ry
= texcoord
[1];
1822 const GLfloat rz
= texcoord
[2];
1823 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
1827 if (arx
> ary
&& arx
> arz
) {
1841 else if (ary
> arx
&& ary
> arz
) {
1870 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
1871 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
1872 return (const struct gl_texture_image
**) texObj
->Image
[face
];
1877 sample_nearest_cube(GLcontext
*ctx
,
1878 const struct gl_texture_object
*tObj
, GLuint n
,
1879 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1884 for (i
= 0; i
< n
; i
++) {
1885 const struct gl_texture_image
**images
;
1886 GLfloat newCoord
[4];
1887 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1888 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
1895 sample_linear_cube(GLcontext
*ctx
,
1896 const struct gl_texture_object
*tObj
, GLuint n
,
1897 const GLfloat texcoords
[][4],
1898 const GLfloat lambda
[], GLfloat rgba
[][4])
1902 for (i
= 0; i
< n
; i
++) {
1903 const struct gl_texture_image
**images
;
1904 GLfloat newCoord
[4];
1905 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
1906 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
1913 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
1914 const struct gl_texture_object
*tObj
,
1915 GLuint n
, const GLfloat texcoord
[][4],
1916 const GLfloat lambda
[], GLfloat rgba
[][4])
1919 ASSERT(lambda
!= NULL
);
1920 for (i
= 0; i
< n
; i
++) {
1921 const struct gl_texture_image
**images
;
1922 GLfloat newCoord
[4];
1924 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1926 /* XXX we actually need to recompute lambda here based on the newCoords.
1927 * But we would need the texcoords of adjacent fragments to compute that
1928 * properly, and we don't have those here.
1929 * For now, do an approximation: subtracting 1 from the chosen mipmap
1930 * level seems to work in some test cases.
1931 * The same adjustment is done in the next few functions.
1933 level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1934 level
= MAX2(level
- 1, 0);
1936 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1942 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
1943 const struct gl_texture_object
*tObj
,
1944 GLuint n
, const GLfloat texcoord
[][4],
1945 const GLfloat lambda
[], GLfloat rgba
[][4])
1948 ASSERT(lambda
!= NULL
);
1949 for (i
= 0; i
< n
; i
++) {
1950 const struct gl_texture_image
**images
;
1951 GLfloat newCoord
[4];
1952 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1953 level
= MAX2(level
- 1, 0); /* see comment above */
1954 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1955 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
1961 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
1962 const struct gl_texture_object
*tObj
,
1963 GLuint n
, const GLfloat texcoord
[][4],
1964 const GLfloat lambda
[], GLfloat rgba
[][4])
1967 ASSERT(lambda
!= NULL
);
1968 for (i
= 0; i
< n
; i
++) {
1969 const struct gl_texture_image
**images
;
1970 GLfloat newCoord
[4];
1971 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1972 level
= MAX2(level
- 1, 0); /* see comment above */
1973 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
1974 if (level
>= tObj
->_MaxLevel
) {
1975 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
1979 GLfloat t0
[4], t1
[4]; /* texels */
1980 const GLfloat f
= FRAC(lambda
[i
]);
1981 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
1982 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
1983 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1990 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
1991 const struct gl_texture_object
*tObj
,
1992 GLuint n
, const GLfloat texcoord
[][4],
1993 const GLfloat lambda
[], GLfloat rgba
[][4])
1996 ASSERT(lambda
!= NULL
);
1997 for (i
= 0; i
< n
; i
++) {
1998 const struct gl_texture_image
**images
;
1999 GLfloat newCoord
[4];
2000 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2001 level
= MAX2(level
- 1, 0); /* see comment above */
2002 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2003 if (level
>= tObj
->_MaxLevel
) {
2004 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2008 GLfloat t0
[4], t1
[4];
2009 const GLfloat f
= FRAC(lambda
[i
]);
2010 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2011 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2012 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2018 /** Sample cube texture, using lambda to choose between min/magnification */
2020 sample_lambda_cube(GLcontext
*ctx
,
2021 const struct gl_texture_object
*tObj
, GLuint n
,
2022 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2025 GLuint minStart
, minEnd
; /* texels with minification */
2026 GLuint magStart
, magEnd
; /* texels with magnification */
2028 ASSERT(lambda
!= NULL
);
2029 compute_min_mag_ranges(tObj
, n
, lambda
,
2030 &minStart
, &minEnd
, &magStart
, &magEnd
);
2032 if (minStart
< minEnd
) {
2033 /* do the minified texels */
2034 const GLuint m
= minEnd
- minStart
;
2035 switch (tObj
->MinFilter
) {
2037 sample_nearest_cube(ctx
, tObj
, m
, texcoords
+ minStart
,
2038 lambda
+ minStart
, rgba
+ minStart
);
2041 sample_linear_cube(ctx
, tObj
, m
, texcoords
+ minStart
,
2042 lambda
+ minStart
, rgba
+ minStart
);
2044 case GL_NEAREST_MIPMAP_NEAREST
:
2045 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, m
,
2046 texcoords
+ minStart
,
2047 lambda
+ minStart
, rgba
+ minStart
);
2049 case GL_LINEAR_MIPMAP_NEAREST
:
2050 sample_cube_linear_mipmap_nearest(ctx
, tObj
, m
,
2051 texcoords
+ minStart
,
2052 lambda
+ minStart
, rgba
+ minStart
);
2054 case GL_NEAREST_MIPMAP_LINEAR
:
2055 sample_cube_nearest_mipmap_linear(ctx
, tObj
, m
,
2056 texcoords
+ minStart
,
2057 lambda
+ minStart
, rgba
+ minStart
);
2059 case GL_LINEAR_MIPMAP_LINEAR
:
2060 sample_cube_linear_mipmap_linear(ctx
, tObj
, m
,
2061 texcoords
+ minStart
,
2062 lambda
+ minStart
, rgba
+ minStart
);
2065 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2069 if (magStart
< magEnd
) {
2070 /* do the magnified texels */
2071 const GLuint m
= magEnd
- magStart
;
2072 switch (tObj
->MagFilter
) {
2074 sample_nearest_cube(ctx
, tObj
, m
, texcoords
+ magStart
,
2075 lambda
+ magStart
, rgba
+ magStart
);
2078 sample_linear_cube(ctx
, tObj
, m
, texcoords
+ magStart
,
2079 lambda
+ magStart
, rgba
+ magStart
);
2082 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2088 /**********************************************************************/
2089 /* Texture Rectangle Sampling Functions */
2090 /**********************************************************************/
2094 sample_nearest_rect(GLcontext
*ctx
,
2095 const struct gl_texture_object
*tObj
, GLuint n
,
2096 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2099 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2100 const GLint width
= img
->Width
;
2101 const GLint height
= img
->Height
;
2107 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2108 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2109 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2110 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2111 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2112 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2113 ASSERT(img
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
);
2115 for (i
= 0; i
< n
; i
++) {
2117 col
= clamp_rect_coord_nearest(tObj
->WrapS
, texcoords
[i
][0], width
);
2118 row
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoords
[i
][1], height
);
2119 if (col
< 0 || col
>= width
|| row
< 0 || row
>= height
)
2120 COPY_4V(rgba
[i
], tObj
->BorderColor
);
2122 img
->FetchTexelf(img
, col
, row
, 0, rgba
[i
]);
2128 sample_linear_rect(GLcontext
*ctx
,
2129 const struct gl_texture_object
*tObj
, GLuint n
,
2130 const GLfloat texcoords
[][4],
2131 const GLfloat lambda
[], GLfloat rgba
[][4])
2133 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2134 const GLint width
= img
->Width
;
2135 const GLint height
= img
->Height
;
2141 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2142 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2143 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2144 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2145 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2146 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2147 ASSERT(img
->TexFormat
->BaseFormat
!= GL_COLOR_INDEX
);
2149 for (i
= 0; i
< n
; i
++) {
2150 GLint i0
, j0
, i1
, j1
;
2151 GLfloat t00
[4], t01
[4], t10
[4], t11
[4];
2153 GLbitfield useBorderColor
= 0x0;
2155 clamp_rect_coord_linear(tObj
->WrapS
, texcoords
[i
][0], width
,
2157 clamp_rect_coord_linear(tObj
->WrapT
, texcoords
[i
][1], height
,
2160 /* compute integer rows/columns */
2161 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2162 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2163 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
2164 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
2166 /* get four texel samples */
2167 if (useBorderColor
& (I0BIT
| J0BIT
))
2168 COPY_4V(t00
, tObj
->BorderColor
);
2170 img
->FetchTexelf(img
, i0
, j0
, 0, t00
);
2172 if (useBorderColor
& (I1BIT
| J0BIT
))
2173 COPY_4V(t10
, tObj
->BorderColor
);
2175 img
->FetchTexelf(img
, i1
, j0
, 0, t10
);
2177 if (useBorderColor
& (I0BIT
| J1BIT
))
2178 COPY_4V(t01
, tObj
->BorderColor
);
2180 img
->FetchTexelf(img
, i0
, j1
, 0, t01
);
2182 if (useBorderColor
& (I1BIT
| J1BIT
))
2183 COPY_4V(t11
, tObj
->BorderColor
);
2185 img
->FetchTexelf(img
, i1
, j1
, 0, t11
);
2187 lerp_rgba_2d(rgba
[i
], a
, b
, t00
, t10
, t01
, t11
);
2192 /** Sample Rect texture, using lambda to choose between min/magnification */
2194 sample_lambda_rect(GLcontext
*ctx
,
2195 const struct gl_texture_object
*tObj
, GLuint n
,
2196 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2199 GLuint minStart
, minEnd
, magStart
, magEnd
;
2201 /* We only need lambda to decide between minification and magnification.
2202 * There is no mipmapping with rectangular textures.
2204 compute_min_mag_ranges(tObj
, n
, lambda
,
2205 &minStart
, &minEnd
, &magStart
, &magEnd
);
2207 if (minStart
< minEnd
) {
2208 if (tObj
->MinFilter
== GL_NEAREST
) {
2209 sample_nearest_rect(ctx
, tObj
, minEnd
- minStart
,
2210 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2213 sample_linear_rect(ctx
, tObj
, minEnd
- minStart
,
2214 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2217 if (magStart
< magEnd
) {
2218 if (tObj
->MagFilter
== GL_NEAREST
) {
2219 sample_nearest_rect(ctx
, tObj
, magEnd
- magStart
,
2220 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2223 sample_linear_rect(ctx
, tObj
, magEnd
- magStart
,
2224 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2231 /**********************************************************************/
2232 /* 2D Texture Array Sampling Functions */
2233 /**********************************************************************/
2236 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
2239 sample_2d_array_nearest(GLcontext
*ctx
,
2240 const struct gl_texture_object
*tObj
,
2241 const struct gl_texture_image
*img
,
2242 const GLfloat texcoord
[4],
2245 const GLint width
= img
->Width2
; /* without border, power of two */
2246 const GLint height
= img
->Height2
; /* without border, power of two */
2247 const GLint depth
= img
->Depth
;
2252 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
2253 j
= nearest_texel_location(tObj
->WrapT
, img
, height
, texcoord
[1]);
2254 array
= clamp_rect_coord_nearest(tObj
->WrapR
, texcoord
[2], depth
);
2256 if (i
< 0 || i
>= (GLint
) img
->Width
||
2257 j
< 0 || j
>= (GLint
) img
->Height
||
2258 array
< 0 || array
>= (GLint
) img
->Depth
) {
2259 /* Need this test for GL_CLAMP_TO_BORDER mode */
2260 COPY_4V(rgba
, tObj
->BorderColor
);
2263 img
->FetchTexelf(img
, i
, j
, array
, rgba
);
2269 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
2272 sample_2d_array_linear(GLcontext
*ctx
,
2273 const struct gl_texture_object
*tObj
,
2274 const struct gl_texture_image
*img
,
2275 const GLfloat texcoord
[4],
2278 const GLint width
= img
->Width2
;
2279 const GLint height
= img
->Height2
;
2280 const GLint depth
= img
->Depth
;
2281 GLint i0
, j0
, i1
, j1
;
2283 GLbitfield useBorderColor
= 0x0;
2285 GLfloat t00
[4], t01
[4], t10
[4], t11
[4];
2287 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
2288 linear_texel_locations(tObj
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
2289 array
= clamp_rect_coord_nearest(tObj
->WrapR
, texcoord
[2], depth
);
2291 if (array
< 0 || array
>= depth
) {
2292 COPY_4V(rgba
, tObj
->BorderColor
);
2302 /* check if sampling texture border color */
2303 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2304 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2305 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
2306 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
2310 if (useBorderColor
& (I0BIT
| J0BIT
)) {
2311 COPY_4V(t00
, tObj
->BorderColor
);
2314 img
->FetchTexelf(img
, i0
, j0
, array
, t00
);
2316 if (useBorderColor
& (I1BIT
| J0BIT
)) {
2317 COPY_4V(t10
, tObj
->BorderColor
);
2320 img
->FetchTexelf(img
, i1
, j0
, array
, t10
);
2322 if (useBorderColor
& (I0BIT
| J1BIT
)) {
2323 COPY_4V(t01
, tObj
->BorderColor
);
2326 img
->FetchTexelf(img
, i0
, j1
, array
, t01
);
2328 if (useBorderColor
& (I1BIT
| J1BIT
)) {
2329 COPY_4V(t11
, tObj
->BorderColor
);
2332 img
->FetchTexelf(img
, i1
, j1
, array
, t11
);
2335 /* trilinear interpolation of samples */
2336 lerp_rgba_2d(rgba
, a
, b
, t00
, t10
, t01
, t11
);
2342 sample_2d_array_nearest_mipmap_nearest(GLcontext
*ctx
,
2343 const struct gl_texture_object
*tObj
,
2344 GLuint n
, const GLfloat texcoord
[][4],
2345 const GLfloat lambda
[], GLfloat rgba
[][4])
2348 for (i
= 0; i
< n
; i
++) {
2349 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2350 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
],
2357 sample_2d_array_linear_mipmap_nearest(GLcontext
*ctx
,
2358 const struct gl_texture_object
*tObj
,
2359 GLuint n
, const GLfloat texcoord
[][4],
2360 const GLfloat lambda
[], GLfloat rgba
[][4])
2363 ASSERT(lambda
!= NULL
);
2364 for (i
= 0; i
< n
; i
++) {
2365 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2366 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
],
2367 texcoord
[i
], rgba
[i
]);
2373 sample_2d_array_nearest_mipmap_linear(GLcontext
*ctx
,
2374 const struct gl_texture_object
*tObj
,
2375 GLuint n
, const GLfloat texcoord
[][4],
2376 const GLfloat lambda
[], GLfloat rgba
[][4])
2379 ASSERT(lambda
!= NULL
);
2380 for (i
= 0; i
< n
; i
++) {
2381 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2382 if (level
>= tObj
->_MaxLevel
) {
2383 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2384 texcoord
[i
], rgba
[i
]);
2387 GLfloat t0
[4], t1
[4]; /* texels */
2388 const GLfloat f
= FRAC(lambda
[i
]);
2389 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
],
2391 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1],
2393 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2400 sample_2d_array_linear_mipmap_linear(GLcontext
*ctx
,
2401 const struct gl_texture_object
*tObj
,
2402 GLuint n
, const GLfloat texcoord
[][4],
2403 const GLfloat lambda
[], GLfloat rgba
[][4])
2406 ASSERT(lambda
!= NULL
);
2407 for (i
= 0; i
< n
; i
++) {
2408 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2409 if (level
>= tObj
->_MaxLevel
) {
2410 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2411 texcoord
[i
], rgba
[i
]);
2414 GLfloat t0
[4], t1
[4]; /* texels */
2415 const GLfloat f
= FRAC(lambda
[i
]);
2416 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
],
2418 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
+1],
2420 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2426 /** Sample 2D Array texture, nearest filtering for both min/magnification */
2428 sample_nearest_2d_array(GLcontext
*ctx
,
2429 const struct gl_texture_object
*tObj
, GLuint n
,
2430 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2434 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2436 for (i
= 0; i
< n
; i
++) {
2437 sample_2d_array_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2443 /** Sample 2D Array texture, linear filtering for both min/magnification */
2445 sample_linear_2d_array(GLcontext
*ctx
,
2446 const struct gl_texture_object
*tObj
, GLuint n
,
2447 const GLfloat texcoords
[][4],
2448 const GLfloat lambda
[], GLfloat rgba
[][4])
2451 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2453 for (i
= 0; i
< n
; i
++) {
2454 sample_2d_array_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2459 /** Sample 2D Array texture, using lambda to choose between min/magnification */
2461 sample_lambda_2d_array(GLcontext
*ctx
,
2462 const struct gl_texture_object
*tObj
, GLuint n
,
2463 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2466 GLuint minStart
, minEnd
; /* texels with minification */
2467 GLuint magStart
, magEnd
; /* texels with magnification */
2470 ASSERT(lambda
!= NULL
);
2471 compute_min_mag_ranges(tObj
, n
, lambda
,
2472 &minStart
, &minEnd
, &magStart
, &magEnd
);
2474 if (minStart
< minEnd
) {
2475 /* do the minified texels */
2476 GLuint m
= minEnd
- minStart
;
2477 switch (tObj
->MinFilter
) {
2479 for (i
= minStart
; i
< minEnd
; i
++)
2480 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2481 texcoords
[i
], rgba
[i
]);
2484 for (i
= minStart
; i
< minEnd
; i
++)
2485 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2486 texcoords
[i
], rgba
[i
]);
2488 case GL_NEAREST_MIPMAP_NEAREST
:
2489 sample_2d_array_nearest_mipmap_nearest(ctx
, tObj
, m
,
2490 texcoords
+ minStart
,
2494 case GL_LINEAR_MIPMAP_NEAREST
:
2495 sample_2d_array_linear_mipmap_nearest(ctx
, tObj
, m
,
2496 texcoords
+ minStart
,
2500 case GL_NEAREST_MIPMAP_LINEAR
:
2501 sample_2d_array_nearest_mipmap_linear(ctx
, tObj
, m
,
2502 texcoords
+ minStart
,
2506 case GL_LINEAR_MIPMAP_LINEAR
:
2507 sample_2d_array_linear_mipmap_linear(ctx
, tObj
, m
,
2508 texcoords
+ minStart
,
2513 _mesa_problem(ctx
, "Bad min filter in sample_2d_array_texture");
2518 if (magStart
< magEnd
) {
2519 /* do the magnified texels */
2520 switch (tObj
->MagFilter
) {
2522 for (i
= magStart
; i
< magEnd
; i
++)
2523 sample_2d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2524 texcoords
[i
], rgba
[i
]);
2527 for (i
= magStart
; i
< magEnd
; i
++)
2528 sample_2d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2529 texcoords
[i
], rgba
[i
]);
2532 _mesa_problem(ctx
, "Bad mag filter in sample_2d_array_texture");
2541 /**********************************************************************/
2542 /* 1D Texture Array Sampling Functions */
2543 /**********************************************************************/
2546 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
2549 sample_1d_array_nearest(GLcontext
*ctx
,
2550 const struct gl_texture_object
*tObj
,
2551 const struct gl_texture_image
*img
,
2552 const GLfloat texcoord
[4],
2555 const GLint width
= img
->Width2
; /* without border, power of two */
2556 const GLint height
= img
->Height
;
2561 i
= nearest_texel_location(tObj
->WrapS
, img
, width
, texcoord
[0]);
2562 array
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoord
[1], height
);
2564 if (i
< 0 || i
>= (GLint
) img
->Width
||
2565 array
< 0 || array
>= (GLint
) img
->Height
) {
2566 /* Need this test for GL_CLAMP_TO_BORDER mode */
2567 COPY_4V(rgba
, tObj
->BorderColor
);
2570 img
->FetchTexelf(img
, i
, array
, 0, rgba
);
2576 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
2579 sample_1d_array_linear(GLcontext
*ctx
,
2580 const struct gl_texture_object
*tObj
,
2581 const struct gl_texture_image
*img
,
2582 const GLfloat texcoord
[4],
2585 const GLint width
= img
->Width2
;
2586 const GLint height
= img
->Height
;
2589 GLbitfield useBorderColor
= 0x0;
2591 GLfloat t0
[4], t1
[4];
2593 linear_texel_locations(tObj
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
2594 array
= clamp_rect_coord_nearest(tObj
->WrapT
, texcoord
[1], height
);
2601 /* check if sampling texture border color */
2602 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2603 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2606 if (array
< 0 || array
>= height
) useBorderColor
|= K0BIT
;
2609 if (useBorderColor
& (I0BIT
| K0BIT
)) {
2610 COPY_4V(t0
, tObj
->BorderColor
);
2613 img
->FetchTexelf(img
, i0
, array
, 0, t0
);
2615 if (useBorderColor
& (I1BIT
| K0BIT
)) {
2616 COPY_4V(t1
, tObj
->BorderColor
);
2619 img
->FetchTexelf(img
, i1
, array
, 0, t1
);
2622 /* bilinear interpolation of samples */
2623 lerp_rgba(rgba
, a
, t0
, t1
);
2628 sample_1d_array_nearest_mipmap_nearest(GLcontext
*ctx
,
2629 const struct gl_texture_object
*tObj
,
2630 GLuint n
, const GLfloat texcoord
[][4],
2631 const GLfloat lambda
[], GLfloat rgba
[][4])
2634 for (i
= 0; i
< n
; i
++) {
2635 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2636 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
],
2643 sample_1d_array_linear_mipmap_nearest(GLcontext
*ctx
,
2644 const struct gl_texture_object
*tObj
,
2645 GLuint n
, const GLfloat texcoord
[][4],
2646 const GLfloat lambda
[], GLfloat rgba
[][4])
2649 ASSERT(lambda
!= NULL
);
2650 for (i
= 0; i
< n
; i
++) {
2651 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2652 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
],
2653 texcoord
[i
], rgba
[i
]);
2659 sample_1d_array_nearest_mipmap_linear(GLcontext
*ctx
,
2660 const struct gl_texture_object
*tObj
,
2661 GLuint n
, const GLfloat texcoord
[][4],
2662 const GLfloat lambda
[], GLfloat rgba
[][4])
2665 ASSERT(lambda
!= NULL
);
2666 for (i
= 0; i
< n
; i
++) {
2667 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2668 if (level
>= tObj
->_MaxLevel
) {
2669 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2670 texcoord
[i
], rgba
[i
]);
2673 GLfloat t0
[4], t1
[4]; /* texels */
2674 const GLfloat f
= FRAC(lambda
[i
]);
2675 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
2676 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
2677 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2684 sample_1d_array_linear_mipmap_linear(GLcontext
*ctx
,
2685 const struct gl_texture_object
*tObj
,
2686 GLuint n
, const GLfloat texcoord
[][4],
2687 const GLfloat lambda
[], GLfloat rgba
[][4])
2690 ASSERT(lambda
!= NULL
);
2691 for (i
= 0; i
< n
; i
++) {
2692 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2693 if (level
>= tObj
->_MaxLevel
) {
2694 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2695 texcoord
[i
], rgba
[i
]);
2698 GLfloat t0
[4], t1
[4]; /* texels */
2699 const GLfloat f
= FRAC(lambda
[i
]);
2700 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
2701 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
2702 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2708 /** Sample 1D Array texture, nearest filtering for both min/magnification */
2710 sample_nearest_1d_array(GLcontext
*ctx
,
2711 const struct gl_texture_object
*tObj
, GLuint n
,
2712 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2716 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2718 for (i
= 0; i
< n
; i
++) {
2719 sample_1d_array_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2724 /** Sample 1D Array texture, linear filtering for both min/magnification */
2726 sample_linear_1d_array(GLcontext
*ctx
,
2727 const struct gl_texture_object
*tObj
, GLuint n
,
2728 const GLfloat texcoords
[][4],
2729 const GLfloat lambda
[], GLfloat rgba
[][4])
2732 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2734 for (i
= 0; i
< n
; i
++) {
2735 sample_1d_array_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2740 /** Sample 1D Array texture, using lambda to choose between min/magnification */
2742 sample_lambda_1d_array(GLcontext
*ctx
,
2743 const struct gl_texture_object
*tObj
, GLuint n
,
2744 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2747 GLuint minStart
, minEnd
; /* texels with minification */
2748 GLuint magStart
, magEnd
; /* texels with magnification */
2751 ASSERT(lambda
!= NULL
);
2752 compute_min_mag_ranges(tObj
, n
, lambda
,
2753 &minStart
, &minEnd
, &magStart
, &magEnd
);
2755 if (minStart
< minEnd
) {
2756 /* do the minified texels */
2757 GLuint m
= minEnd
- minStart
;
2758 switch (tObj
->MinFilter
) {
2760 for (i
= minStart
; i
< minEnd
; i
++)
2761 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2762 texcoords
[i
], rgba
[i
]);
2765 for (i
= minStart
; i
< minEnd
; i
++)
2766 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2767 texcoords
[i
], rgba
[i
]);
2769 case GL_NEAREST_MIPMAP_NEAREST
:
2770 sample_1d_array_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2771 lambda
+ minStart
, rgba
+ minStart
);
2773 case GL_LINEAR_MIPMAP_NEAREST
:
2774 sample_1d_array_linear_mipmap_nearest(ctx
, tObj
, m
,
2775 texcoords
+ minStart
,
2779 case GL_NEAREST_MIPMAP_LINEAR
:
2780 sample_1d_array_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2781 lambda
+ minStart
, rgba
+ minStart
);
2783 case GL_LINEAR_MIPMAP_LINEAR
:
2784 sample_1d_array_linear_mipmap_linear(ctx
, tObj
, m
,
2785 texcoords
+ minStart
,
2790 _mesa_problem(ctx
, "Bad min filter in sample_1d_array_texture");
2795 if (magStart
< magEnd
) {
2796 /* do the magnified texels */
2797 switch (tObj
->MagFilter
) {
2799 for (i
= magStart
; i
< magEnd
; i
++)
2800 sample_1d_array_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2801 texcoords
[i
], rgba
[i
]);
2804 for (i
= magStart
; i
< magEnd
; i
++)
2805 sample_1d_array_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2806 texcoords
[i
], rgba
[i
]);
2809 _mesa_problem(ctx
, "Bad mag filter in sample_1d_array_texture");
2817 * Compare texcoord against depth sample. Return 1.0 or the ambient value.
2819 static INLINE GLfloat
2820 shadow_compare(GLenum function
, GLfloat coord
, GLfloat depthSample
,
2825 return (coord
<= depthSample
) ? 1.0F
: ambient
;
2827 return (coord
>= depthSample
) ? 1.0F
: ambient
;
2829 return (coord
< depthSample
) ? 1.0F
: ambient
;
2831 return (coord
> depthSample
) ? 1.0F
: ambient
;
2833 return (coord
== depthSample
) ? 1.0F
: ambient
;
2835 return (coord
!= depthSample
) ? 1.0F
: ambient
;
2843 _mesa_problem(NULL
, "Bad compare func in shadow_compare");
2850 * Compare texcoord against four depth samples.
2852 static INLINE GLfloat
2853 shadow_compare4(GLenum function
, GLfloat coord
,
2854 GLfloat depth00
, GLfloat depth01
,
2855 GLfloat depth10
, GLfloat depth11
,
2856 GLfloat ambient
, GLfloat wi
, GLfloat wj
)
2858 const GLfloat d
= (1.0F
- (GLfloat
) ambient
) * 0.25F
;
2859 GLfloat luminance
= 1.0F
;
2863 if (depth00
<= coord
) luminance
-= d
;
2864 if (depth01
<= coord
) luminance
-= d
;
2865 if (depth10
<= coord
) luminance
-= d
;
2866 if (depth11
<= coord
) luminance
-= d
;
2869 if (depth00
>= coord
) luminance
-= d
;
2870 if (depth01
>= coord
) luminance
-= d
;
2871 if (depth10
>= coord
) luminance
-= d
;
2872 if (depth11
>= coord
) luminance
-= d
;
2875 if (depth00
< coord
) luminance
-= d
;
2876 if (depth01
< coord
) luminance
-= d
;
2877 if (depth10
< coord
) luminance
-= d
;
2878 if (depth11
< coord
) luminance
-= d
;
2881 if (depth00
> coord
) luminance
-= d
;
2882 if (depth01
> coord
) luminance
-= d
;
2883 if (depth10
> coord
) luminance
-= d
;
2884 if (depth11
> coord
) luminance
-= d
;
2887 if (depth00
== coord
) luminance
-= d
;
2888 if (depth01
== coord
) luminance
-= d
;
2889 if (depth10
== coord
) luminance
-= d
;
2890 if (depth11
== coord
) luminance
-= d
;
2893 if (depth00
!= coord
) luminance
-= d
;
2894 if (depth01
!= coord
) luminance
-= d
;
2895 if (depth10
!= coord
) luminance
-= d
;
2896 if (depth11
!= coord
) luminance
-= d
;
2903 /* ordinary bilinear filtering */
2904 return lerp_2d(wi
, wj
, depth00
, depth10
, depth01
, depth11
);
2906 _mesa_problem(NULL
, "Bad compare func in sample_depth_texture");
2913 * Sample a shadow/depth texture.
2916 sample_depth_texture( GLcontext
*ctx
,
2917 const struct gl_texture_object
*tObj
, GLuint n
,
2918 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2919 GLfloat texel
[][4] )
2921 const GLint baseLevel
= tObj
->BaseLevel
;
2922 const struct gl_texture_image
*img
= tObj
->Image
[0][baseLevel
];
2923 const GLint width
= img
->Width
;
2924 const GLint height
= img
->Height
;
2925 const GLint depth
= img
->Depth
;
2926 const GLuint compare_coord
= (tObj
->Target
== GL_TEXTURE_2D_ARRAY_EXT
)
2934 ASSERT(img
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
||
2935 img
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
);
2937 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2938 tObj
->Target
== GL_TEXTURE_2D
||
2939 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
||
2940 tObj
->Target
== GL_TEXTURE_1D_ARRAY_EXT
||
2941 tObj
->Target
== GL_TEXTURE_2D_ARRAY_EXT
);
2943 ambient
= tObj
->CompareFailValue
;
2945 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2947 function
= (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) ?
2948 tObj
->CompareFunc
: GL_NONE
;
2950 if (tObj
->MagFilter
== GL_NEAREST
) {
2952 for (i
= 0; i
< n
; i
++) {
2953 GLfloat depthSample
;
2954 GLint col
, row
, slice
;
2956 nearest_texcoord(tObj
, texcoords
[i
], &col
, &row
, &slice
);
2958 if (col
>= 0 && row
>= 0 && col
< width
&& row
< height
&&
2959 slice
>= 0 && slice
< depth
) {
2960 img
->FetchTexelf(img
, col
, row
, slice
, &depthSample
);
2963 depthSample
= tObj
->BorderColor
[0];
2966 result
= shadow_compare(function
, texcoords
[i
][compare_coord
],
2967 depthSample
, ambient
);
2969 switch (tObj
->DepthMode
) {
2971 ASSIGN_4V(texel
[i
], result
, result
, result
, 1.0F
);
2974 ASSIGN_4V(texel
[i
], result
, result
, result
, result
);
2977 ASSIGN_4V(texel
[i
], 0.0F
, 0.0F
, 0.0F
, result
);
2980 _mesa_problem(ctx
, "Bad depth texture mode");
2986 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2987 for (i
= 0; i
< n
; i
++) {
2988 GLfloat depth00
, depth01
, depth10
, depth11
;
2989 GLint i0
, i1
, j0
, j1
;
2992 GLuint useBorderTexel
;
2994 linear_texcoord(tObj
, texcoords
[i
], &i0
, &i1
, &j0
, &j1
, &slice
,
3001 if (tObj
->Target
!= GL_TEXTURE_1D_ARRAY_EXT
) {
3007 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
3008 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
3009 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
3010 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
3013 if (slice
< 0 || slice
>= (GLint
) depth
) {
3014 depth00
= tObj
->BorderColor
[0];
3015 depth01
= tObj
->BorderColor
[0];
3016 depth10
= tObj
->BorderColor
[0];
3017 depth11
= tObj
->BorderColor
[0];
3020 /* get four depth samples from the texture */
3021 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
3022 depth00
= tObj
->BorderColor
[0];
3025 img
->FetchTexelf(img
, i0
, j0
, slice
, &depth00
);
3027 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
3028 depth10
= tObj
->BorderColor
[0];
3031 img
->FetchTexelf(img
, i1
, j0
, slice
, &depth10
);
3034 if (tObj
->Target
!= GL_TEXTURE_1D_ARRAY_EXT
) {
3035 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
3036 depth01
= tObj
->BorderColor
[0];
3039 img
->FetchTexelf(img
, i0
, j1
, slice
, &depth01
);
3041 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
3042 depth11
= tObj
->BorderColor
[0];
3045 img
->FetchTexelf(img
, i1
, j1
, slice
, &depth11
);
3054 result
= shadow_compare4(function
, texcoords
[i
][compare_coord
],
3055 depth00
, depth01
, depth10
, depth11
,
3058 switch (tObj
->DepthMode
) {
3060 ASSIGN_4V(texel
[i
], result
, result
, result
, 1.0F
);
3063 ASSIGN_4V(texel
[i
], result
, result
, result
, result
);
3066 ASSIGN_4V(texel
[i
], 0.0F
, 0.0F
, 0.0F
, result
);
3069 _mesa_problem(ctx
, "Bad depth texture mode");
3078 * We use this function when a texture object is in an "incomplete" state.
3079 * When a fragment program attempts to sample an incomplete texture we
3080 * return black (see issue 23 in GL_ARB_fragment_program spec).
3081 * Note: fragment programs don't observe the texture enable/disable flags.
3084 null_sample_func( GLcontext
*ctx
,
3085 const struct gl_texture_object
*tObj
, GLuint n
,
3086 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3094 for (i
= 0; i
< n
; i
++) {
3098 rgba
[i
][ACOMP
] = CHAN_MAX
;
3104 * Choose the texture sampling function for the given texture object.
3107 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
3108 const struct gl_texture_object
*t
)
3110 if (!t
|| !t
->_Complete
) {
3111 return &null_sample_func
;
3114 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
3115 const GLenum format
= t
->Image
[0][t
->BaseLevel
]->TexFormat
->BaseFormat
;
3117 switch (t
->Target
) {
3119 if (format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
) {
3120 return &sample_depth_texture
;
3122 else if (needLambda
) {
3123 return &sample_lambda_1d
;
3125 else if (t
->MinFilter
== GL_LINEAR
) {
3126 return &sample_linear_1d
;
3129 ASSERT(t
->MinFilter
== GL_NEAREST
);
3130 return &sample_nearest_1d
;
3133 if (format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
) {
3134 return &sample_depth_texture
;
3136 else if (needLambda
) {
3137 return &sample_lambda_2d
;
3139 else if (t
->MinFilter
== GL_LINEAR
) {
3140 return &sample_linear_2d
;
3143 /* check for a few optimized cases */
3145 const struct gl_texture_image
*img
= t
->Image
[0][t
->BaseLevel
];
3146 ASSERT(t
->MinFilter
== GL_NEAREST
);
3147 if (t
->WrapS
== GL_REPEAT
&&
3148 t
->WrapT
== GL_REPEAT
&&
3149 img
->_IsPowerOfTwo
&&
3151 img
->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
3152 return &opt_sample_rgb_2d
;
3154 else if (t
->WrapS
== GL_REPEAT
&&
3155 t
->WrapT
== GL_REPEAT
&&
3156 img
->_IsPowerOfTwo
&&
3158 img
->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
3159 return &opt_sample_rgba_2d
;
3166 return &sample_nearest_2d
;
3171 return &sample_lambda_3d
;
3173 else if (t
->MinFilter
== GL_LINEAR
) {
3174 return &sample_linear_3d
;
3177 ASSERT(t
->MinFilter
== GL_NEAREST
);
3178 return &sample_nearest_3d
;
3180 case GL_TEXTURE_CUBE_MAP
:
3182 return &sample_lambda_cube
;
3184 else if (t
->MinFilter
== GL_LINEAR
) {
3185 return &sample_linear_cube
;
3188 ASSERT(t
->MinFilter
== GL_NEAREST
);
3189 return &sample_nearest_cube
;
3191 case GL_TEXTURE_RECTANGLE_NV
:
3192 if (format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
) {
3193 return &sample_depth_texture
;
3195 else if (needLambda
) {
3196 return &sample_lambda_rect
;
3198 else if (t
->MinFilter
== GL_LINEAR
) {
3199 return &sample_linear_rect
;
3202 ASSERT(t
->MinFilter
== GL_NEAREST
);
3203 return &sample_nearest_rect
;
3205 case GL_TEXTURE_1D_ARRAY_EXT
:
3207 return &sample_lambda_1d_array
;
3209 else if (t
->MinFilter
== GL_LINEAR
) {
3210 return &sample_linear_1d_array
;
3213 ASSERT(t
->MinFilter
== GL_NEAREST
);
3214 return &sample_nearest_1d_array
;
3216 case GL_TEXTURE_2D_ARRAY_EXT
:
3218 return &sample_lambda_2d_array
;
3220 else if (t
->MinFilter
== GL_LINEAR
) {
3221 return &sample_linear_2d_array
;
3224 ASSERT(t
->MinFilter
== GL_NEAREST
);
3225 return &sample_nearest_2d_array
;
3229 "invalid target in _swrast_choose_texture_sample_func");
3230 return &null_sample_func
;