2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * 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/samplerobj.h"
31 #include "main/teximage.h"
32 #include "main/texobj.h"
34 #include "s_context.h"
35 #include "s_texfilter.h"
39 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
40 * see 1-pixel bands of improperly weighted linear-filtered textures.
41 * The tests/texwrap.c demo is a good test.
42 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
43 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
45 #define FRAC(f) ((f) - IFLOOR(f))
50 * Linear interpolation macro
52 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
56 * Do 2D/biliner interpolation of float values.
57 * v00, v10, v01 and v11 are typically four texture samples in a square/box.
58 * a and b are the horizontal and vertical interpolants.
59 * It's important that this function is inlined when compiled with
60 * optimization! If we find that's not true on some systems, convert
64 lerp_2d(GLfloat a
, GLfloat b
,
65 GLfloat v00
, GLfloat v10
, GLfloat v01
, GLfloat v11
)
67 const GLfloat temp0
= LERP(a
, v00
, v10
);
68 const GLfloat temp1
= LERP(a
, v01
, v11
);
69 return LERP(b
, temp0
, temp1
);
74 * Do 3D/trilinear interpolation of float values.
78 lerp_3d(GLfloat a
, GLfloat b
, GLfloat c
,
79 GLfloat v000
, GLfloat v100
, GLfloat v010
, GLfloat v110
,
80 GLfloat v001
, GLfloat v101
, GLfloat v011
, GLfloat v111
)
82 const GLfloat temp00
= LERP(a
, v000
, v100
);
83 const GLfloat temp10
= LERP(a
, v010
, v110
);
84 const GLfloat temp01
= LERP(a
, v001
, v101
);
85 const GLfloat temp11
= LERP(a
, v011
, v111
);
86 const GLfloat temp0
= LERP(b
, temp00
, temp10
);
87 const GLfloat temp1
= LERP(b
, temp01
, temp11
);
88 return LERP(c
, temp0
, temp1
);
93 * Do linear interpolation of colors.
96 lerp_rgba(GLfloat result
[4], GLfloat t
, const GLfloat a
[4], const GLfloat b
[4])
98 result
[0] = LERP(t
, a
[0], b
[0]);
99 result
[1] = LERP(t
, a
[1], b
[1]);
100 result
[2] = LERP(t
, a
[2], b
[2]);
101 result
[3] = LERP(t
, a
[3], b
[3]);
106 * Do bilinear interpolation of colors.
109 lerp_rgba_2d(GLfloat result
[4], GLfloat a
, GLfloat b
,
110 const GLfloat t00
[4], const GLfloat t10
[4],
111 const GLfloat t01
[4], const GLfloat t11
[4])
113 result
[0] = lerp_2d(a
, b
, t00
[0], t10
[0], t01
[0], t11
[0]);
114 result
[1] = lerp_2d(a
, b
, t00
[1], t10
[1], t01
[1], t11
[1]);
115 result
[2] = lerp_2d(a
, b
, t00
[2], t10
[2], t01
[2], t11
[2]);
116 result
[3] = lerp_2d(a
, b
, t00
[3], t10
[3], t01
[3], t11
[3]);
121 * Do trilinear interpolation of colors.
124 lerp_rgba_3d(GLfloat result
[4], GLfloat a
, GLfloat b
, GLfloat c
,
125 const GLfloat t000
[4], const GLfloat t100
[4],
126 const GLfloat t010
[4], const GLfloat t110
[4],
127 const GLfloat t001
[4], const GLfloat t101
[4],
128 const GLfloat t011
[4], const GLfloat t111
[4])
131 /* compiler should unroll these short loops */
132 for (k
= 0; k
< 4; k
++) {
133 result
[k
] = lerp_3d(a
, b
, c
, t000
[k
], t100
[k
], t010
[k
], t110
[k
],
134 t001
[k
], t101
[k
], t011
[k
], t111
[k
]);
140 * Used for GL_REPEAT wrap mode. Using A % B doesn't produce the
141 * right results for A<0. Casting to A to be unsigned only works if B
142 * is a power of two. Adding a bias to A (which is a multiple of B)
143 * avoids the problems with A < 0 (for reasonable A) without using a
146 #define REMAINDER(A, B) (((A) + (B) * 1024) % (B))
150 * Used to compute texel locations for linear sampling.
152 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
153 * s = texcoord in [0,1]
154 * size = width (or height or depth) of texture
156 * i0, i1 = returns two nearest texel indexes
157 * weight = returns blend factor between texels
160 linear_texel_locations(GLenum wrapMode
,
161 const struct gl_texture_image
*img
,
162 GLint size
, GLfloat s
,
163 GLint
*i0
, GLint
*i1
, GLfloat
*weight
)
165 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
170 if (swImg
->_IsPowerOfTwo
) {
171 *i0
= IFLOOR(u
) & (size
- 1);
172 *i1
= (*i0
+ 1) & (size
- 1);
175 *i0
= REMAINDER(IFLOOR(u
), size
);
176 *i1
= REMAINDER(*i0
+ 1, size
);
179 case GL_CLAMP_TO_EDGE
:
191 if (*i1
>= (GLint
) size
)
194 case GL_CLAMP_TO_BORDER
:
196 const GLfloat min
= -1.0F
/ (2.0F
* size
);
197 const GLfloat max
= 1.0F
- min
;
209 case GL_MIRRORED_REPEAT
:
211 const GLint flr
= IFLOOR(s
);
213 u
= 1.0F
- (s
- (GLfloat
) flr
);
215 u
= s
- (GLfloat
) flr
;
216 u
= (u
* size
) - 0.5F
;
221 if (*i1
>= (GLint
) size
)
225 case GL_MIRROR_CLAMP_EXT
:
235 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
246 if (*i1
>= (GLint
) size
)
249 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
251 const GLfloat min
= -1.0F
/ (2.0F
* size
);
252 const GLfloat max
= 1.0F
- min
;
277 _mesa_problem(NULL
, "Bad wrap mode");
287 * Used to compute texel location for nearest sampling.
290 nearest_texel_location(GLenum wrapMode
,
291 const struct gl_texture_image
*img
,
292 GLint size
, GLfloat s
)
294 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
299 /* s limited to [0,1) */
300 /* i limited to [0,size-1] */
301 i
= IFLOOR(s
* size
);
302 if (swImg
->_IsPowerOfTwo
)
305 i
= REMAINDER(i
, size
);
307 case GL_CLAMP_TO_EDGE
:
309 /* s limited to [min,max] */
310 /* i limited to [0, size-1] */
311 const GLfloat min
= 1.0F
/ (2.0F
* size
);
312 const GLfloat max
= 1.0F
- min
;
318 i
= IFLOOR(s
* size
);
321 case GL_CLAMP_TO_BORDER
:
323 /* s limited to [min,max] */
324 /* i limited to [-1, size] */
325 const GLfloat min
= -1.0F
/ (2.0F
* size
);
326 const GLfloat max
= 1.0F
- min
;
332 i
= IFLOOR(s
* size
);
335 case GL_MIRRORED_REPEAT
:
337 const GLfloat min
= 1.0F
/ (2.0F
* size
);
338 const GLfloat max
= 1.0F
- min
;
339 const GLint flr
= IFLOOR(s
);
342 u
= 1.0F
- (s
- (GLfloat
) flr
);
344 u
= s
- (GLfloat
) flr
;
350 i
= IFLOOR(u
* size
);
353 case GL_MIRROR_CLAMP_EXT
:
355 /* s limited to [0,1] */
356 /* i limited to [0,size-1] */
357 const GLfloat u
= FABSF(s
);
363 i
= IFLOOR(u
* size
);
366 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
368 /* s limited to [min,max] */
369 /* i limited to [0, size-1] */
370 const GLfloat min
= 1.0F
/ (2.0F
* size
);
371 const GLfloat max
= 1.0F
- min
;
372 const GLfloat u
= FABSF(s
);
378 i
= IFLOOR(u
* size
);
381 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
383 /* s limited to [min,max] */
384 /* i limited to [0, size-1] */
385 const GLfloat min
= -1.0F
/ (2.0F
* size
);
386 const GLfloat max
= 1.0F
- min
;
387 const GLfloat u
= FABSF(s
);
393 i
= IFLOOR(u
* size
);
397 /* s limited to [0,1] */
398 /* i limited to [0,size-1] */
404 i
= IFLOOR(s
* size
);
407 _mesa_problem(NULL
, "Bad wrap mode");
413 /* Power of two image sizes only */
415 linear_repeat_texel_location(GLuint size
, GLfloat s
,
416 GLint
*i0
, GLint
*i1
, GLfloat
*weight
)
418 GLfloat u
= s
* size
- 0.5F
;
419 *i0
= IFLOOR(u
) & (size
- 1);
420 *i1
= (*i0
+ 1) & (size
- 1);
426 * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
429 clamp_rect_coord_nearest(GLenum wrapMode
, GLfloat coord
, GLint max
)
433 return IFLOOR( CLAMP(coord
, 0.0F
, max
- 1) );
434 case GL_CLAMP_TO_EDGE
:
435 return IFLOOR( CLAMP(coord
, 0.5F
, max
- 0.5F
) );
436 case GL_CLAMP_TO_BORDER
:
437 return IFLOOR( CLAMP(coord
, -0.5F
, max
+ 0.5F
) );
439 _mesa_problem(NULL
, "bad wrapMode in clamp_rect_coord_nearest");
446 * As above, but GL_LINEAR filtering.
449 clamp_rect_coord_linear(GLenum wrapMode
, GLfloat coord
, GLint max
,
450 GLint
*i0out
, GLint
*i1out
, GLfloat
*weight
)
456 /* Not exactly what the spec says, but it matches NVIDIA output */
457 fcol
= CLAMP(coord
- 0.5F
, 0.0F
, max
- 1);
461 case GL_CLAMP_TO_EDGE
:
462 fcol
= CLAMP(coord
, 0.5F
, max
- 0.5F
);
469 case GL_CLAMP_TO_BORDER
:
470 fcol
= CLAMP(coord
, -0.5F
, max
+ 0.5F
);
476 _mesa_problem(NULL
, "bad wrapMode in clamp_rect_coord_linear");
483 *weight
= FRAC(fcol
);
488 * Compute slice/image to use for 1D or 2D array texture.
491 tex_array_slice(GLfloat coord
, GLsizei size
)
493 GLint slice
= IFLOOR(coord
+ 0.5f
);
494 slice
= CLAMP(slice
, 0, size
- 1);
500 * Compute nearest integer texcoords for given texobj and coordinate.
501 * NOTE: only used for depth texture sampling.
504 nearest_texcoord(const struct gl_sampler_object
*samp
,
505 const struct gl_texture_object
*texObj
,
507 const GLfloat texcoord
[4],
508 GLint
*i
, GLint
*j
, GLint
*k
)
510 const struct gl_texture_image
*img
= texObj
->Image
[0][level
];
511 const GLint width
= img
->Width
;
512 const GLint height
= img
->Height
;
513 const GLint depth
= img
->Depth
;
515 switch (texObj
->Target
) {
516 case GL_TEXTURE_RECTANGLE_ARB
:
517 *i
= clamp_rect_coord_nearest(samp
->WrapS
, texcoord
[0], width
);
518 *j
= clamp_rect_coord_nearest(samp
->WrapT
, texcoord
[1], height
);
522 *i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
527 *i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
528 *j
= nearest_texel_location(samp
->WrapT
, img
, height
, texcoord
[1]);
531 case GL_TEXTURE_1D_ARRAY_EXT
:
532 *i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
533 *j
= tex_array_slice(texcoord
[1], height
);
536 case GL_TEXTURE_2D_ARRAY_EXT
:
537 *i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
538 *j
= nearest_texel_location(samp
->WrapT
, img
, height
, texcoord
[1]);
539 *k
= tex_array_slice(texcoord
[2], depth
);
549 * Compute linear integer texcoords for given texobj and coordinate.
550 * NOTE: only used for depth texture sampling.
553 linear_texcoord(const struct gl_sampler_object
*samp
,
554 const struct gl_texture_object
*texObj
,
556 const GLfloat texcoord
[4],
557 GLint
*i0
, GLint
*i1
, GLint
*j0
, GLint
*j1
, GLint
*slice
,
558 GLfloat
*wi
, GLfloat
*wj
)
560 const struct gl_texture_image
*img
= texObj
->Image
[0][level
];
561 const GLint width
= img
->Width
;
562 const GLint height
= img
->Height
;
563 const GLint depth
= img
->Depth
;
565 switch (texObj
->Target
) {
566 case GL_TEXTURE_RECTANGLE_ARB
:
567 clamp_rect_coord_linear(samp
->WrapS
, texcoord
[0],
569 clamp_rect_coord_linear(samp
->WrapT
, texcoord
[1],
576 linear_texel_locations(samp
->WrapS
, img
, width
,
577 texcoord
[0], i0
, i1
, wi
);
578 linear_texel_locations(samp
->WrapT
, img
, height
,
579 texcoord
[1], j0
, j1
, wj
);
583 case GL_TEXTURE_1D_ARRAY_EXT
:
584 linear_texel_locations(samp
->WrapS
, img
, width
,
585 texcoord
[0], i0
, i1
, wi
);
586 *j0
= tex_array_slice(texcoord
[1], height
);
591 case GL_TEXTURE_2D_ARRAY_EXT
:
592 linear_texel_locations(samp
->WrapS
, img
, width
,
593 texcoord
[0], i0
, i1
, wi
);
594 linear_texel_locations(samp
->WrapT
, img
, height
,
595 texcoord
[1], j0
, j1
, wj
);
596 *slice
= tex_array_slice(texcoord
[2], depth
);
608 * For linear interpolation between mipmap levels N and N+1, this function
612 linear_mipmap_level(const struct gl_texture_object
*tObj
, GLfloat lambda
)
615 return tObj
->BaseLevel
;
616 else if (lambda
> tObj
->_MaxLambda
)
617 return (GLint
) (tObj
->BaseLevel
+ tObj
->_MaxLambda
);
619 return (GLint
) (tObj
->BaseLevel
+ lambda
);
624 * Compute the nearest mipmap level to take texels from.
627 nearest_mipmap_level(const struct gl_texture_object
*tObj
, GLfloat lambda
)
633 else if (lambda
> tObj
->_MaxLambda
+ 0.4999F
)
634 l
= tObj
->_MaxLambda
+ 0.4999F
;
637 level
= (GLint
) (tObj
->BaseLevel
+ l
+ 0.5F
);
638 if (level
> tObj
->_MaxLevel
)
639 level
= tObj
->_MaxLevel
;
646 * Bitflags for texture border color sampling.
658 * The lambda[] array values are always monotonic. Either the whole span
659 * will be minified, magnified, or split between the two. This function
660 * determines the subranges in [0, n-1] that are to be minified or magnified.
663 compute_min_mag_ranges(const struct gl_sampler_object
*samp
,
664 GLuint n
, const GLfloat lambda
[],
665 GLuint
*minStart
, GLuint
*minEnd
,
666 GLuint
*magStart
, GLuint
*magEnd
)
668 GLfloat minMagThresh
;
670 /* we shouldn't be here if minfilter == magfilter */
671 assert(samp
->MinFilter
!= samp
->MagFilter
);
673 /* This bit comes from the OpenGL spec: */
674 if (samp
->MagFilter
== GL_LINEAR
675 && (samp
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
676 samp
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
684 /* DEBUG CODE: Verify that lambda[] is monotonic.
685 * We can't really use this because the inaccuracy in the LOG2 function
686 * causes this test to fail, yet the resulting texturing is correct.
690 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
691 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
692 for (i
= 0; i
< n
- 1; i
++) {
693 assert((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
696 else { /* increasing */
697 for (i
= 0; i
< n
- 1; i
++) {
698 assert((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
704 if (lambda
[0] <= minMagThresh
&& (n
<= 1 || lambda
[n
-1] <= minMagThresh
)) {
705 /* magnification for whole span */
708 *minStart
= *minEnd
= 0;
710 else if (lambda
[0] > minMagThresh
&& (n
<=1 || lambda
[n
-1] > minMagThresh
)) {
711 /* minification for whole span */
714 *magStart
= *magEnd
= 0;
717 /* a mix of minification and magnification */
719 if (lambda
[0] > minMagThresh
) {
720 /* start with minification */
721 for (i
= 1; i
< n
; i
++) {
722 if (lambda
[i
] <= minMagThresh
)
731 /* start with magnification */
732 for (i
= 1; i
< n
; i
++) {
733 if (lambda
[i
] > minMagThresh
)
744 /* Verify the min/mag Start/End values
745 * We don't use this either (see above)
749 for (i
= 0; i
< n
; i
++) {
750 if (lambda
[i
] > minMagThresh
) {
752 assert(i
>= *minStart
);
757 assert(i
>= *magStart
);
767 * When we sample the border color, it must be interpreted according to
768 * the base texture format. Ex: if the texture base format it GL_ALPHA,
769 * we return (0,0,0,BorderAlpha).
772 get_border_color(const struct gl_sampler_object
*samp
,
773 const struct gl_texture_image
*img
,
776 switch (img
->_BaseFormat
) {
778 rgba
[0] = samp
->BorderColor
.f
[0];
779 rgba
[1] = samp
->BorderColor
.f
[1];
780 rgba
[2] = samp
->BorderColor
.f
[2];
784 rgba
[0] = rgba
[1] = rgba
[2] = 0.0;
785 rgba
[3] = samp
->BorderColor
.f
[3];
788 rgba
[0] = rgba
[1] = rgba
[2] = samp
->BorderColor
.f
[0];
791 case GL_LUMINANCE_ALPHA
:
792 rgba
[0] = rgba
[1] = rgba
[2] = samp
->BorderColor
.f
[0];
793 rgba
[3] = samp
->BorderColor
.f
[3];
796 rgba
[0] = rgba
[1] = rgba
[2] = rgba
[3] = samp
->BorderColor
.f
[0];
799 COPY_4V(rgba
, samp
->BorderColor
.f
);
806 * Put z into texel according to GL_DEPTH_MODE.
809 apply_depth_mode(GLenum depthMode
, GLfloat z
, GLfloat texel
[4])
813 ASSIGN_4V(texel
, z
, z
, z
, 1.0F
);
816 ASSIGN_4V(texel
, z
, z
, z
, z
);
819 ASSIGN_4V(texel
, 0.0F
, 0.0F
, 0.0F
, z
);
822 ASSIGN_4V(texel
, z
, 0.0F
, 0.0F
, 1.0F
);
825 _mesa_problem(NULL
, "Bad depth texture mode");
831 * Is the given texture a depth (or depth/stencil) texture?
834 is_depth_texture(const struct gl_texture_object
*tObj
)
836 GLenum format
= _mesa_texture_base_format(tObj
);
837 return format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
;
841 /**********************************************************************/
842 /* 1-D Texture Sampling Functions */
843 /**********************************************************************/
846 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
849 sample_1d_nearest(struct gl_context
*ctx
,
850 const struct gl_sampler_object
*samp
,
851 const struct gl_texture_image
*img
,
852 const GLfloat texcoord
[4], GLfloat rgba
[4])
854 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
855 const GLint width
= img
->Width2
; /* without border, power of two */
857 i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
858 /* skip over the border, if any */
860 if (i
< 0 || i
>= (GLint
) img
->Width
) {
861 /* Need this test for GL_CLAMP_TO_BORDER mode */
862 get_border_color(samp
, img
, rgba
);
865 swImg
->FetchTexel(swImg
, i
, 0, 0, rgba
);
871 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
874 sample_1d_linear(struct gl_context
*ctx
,
875 const struct gl_sampler_object
*samp
,
876 const struct gl_texture_image
*img
,
877 const GLfloat texcoord
[4], GLfloat rgba
[4])
879 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
880 const GLint width
= img
->Width2
;
882 GLbitfield useBorderColor
= 0x0;
884 GLfloat t0
[4], t1
[4]; /* texels */
886 linear_texel_locations(samp
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
893 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
894 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
897 /* fetch texel colors */
898 if (useBorderColor
& I0BIT
) {
899 get_border_color(samp
, img
, t0
);
902 swImg
->FetchTexel(swImg
, i0
, 0, 0, t0
);
904 if (useBorderColor
& I1BIT
) {
905 get_border_color(samp
, img
, t1
);
908 swImg
->FetchTexel(swImg
, i1
, 0, 0, t1
);
911 lerp_rgba(rgba
, a
, t0
, t1
);
916 sample_1d_nearest_mipmap_nearest(struct gl_context
*ctx
,
917 const struct gl_sampler_object
*samp
,
918 const struct gl_texture_object
*tObj
,
919 GLuint n
, const GLfloat texcoord
[][4],
920 const GLfloat lambda
[], GLfloat rgba
[][4])
923 assert(lambda
!= NULL
);
924 for (i
= 0; i
< n
; i
++) {
925 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
926 sample_1d_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
932 sample_1d_linear_mipmap_nearest(struct gl_context
*ctx
,
933 const struct gl_sampler_object
*samp
,
934 const struct gl_texture_object
*tObj
,
935 GLuint n
, const GLfloat texcoord
[][4],
936 const GLfloat lambda
[], GLfloat rgba
[][4])
939 assert(lambda
!= NULL
);
940 for (i
= 0; i
< n
; i
++) {
941 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
942 sample_1d_linear(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
948 sample_1d_nearest_mipmap_linear(struct gl_context
*ctx
,
949 const struct gl_sampler_object
*samp
,
950 const struct gl_texture_object
*tObj
,
951 GLuint n
, const GLfloat texcoord
[][4],
952 const GLfloat lambda
[], GLfloat rgba
[][4])
955 assert(lambda
!= NULL
);
956 for (i
= 0; i
< n
; i
++) {
957 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
958 if (level
>= tObj
->_MaxLevel
) {
959 sample_1d_nearest(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
960 texcoord
[i
], rgba
[i
]);
963 GLfloat t0
[4], t1
[4];
964 const GLfloat f
= FRAC(lambda
[i
]);
965 sample_1d_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
966 sample_1d_nearest(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
967 lerp_rgba(rgba
[i
], f
, t0
, t1
);
974 sample_1d_linear_mipmap_linear(struct gl_context
*ctx
,
975 const struct gl_sampler_object
*samp
,
976 const struct gl_texture_object
*tObj
,
977 GLuint n
, const GLfloat texcoord
[][4],
978 const GLfloat lambda
[], GLfloat rgba
[][4])
981 assert(lambda
!= NULL
);
982 for (i
= 0; i
< n
; i
++) {
983 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
984 if (level
>= tObj
->_MaxLevel
) {
985 sample_1d_linear(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
986 texcoord
[i
], rgba
[i
]);
989 GLfloat t0
[4], t1
[4];
990 const GLfloat f
= FRAC(lambda
[i
]);
991 sample_1d_linear(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
992 sample_1d_linear(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
993 lerp_rgba(rgba
[i
], f
, t0
, t1
);
999 /** Sample 1D texture, nearest filtering for both min/magnification */
1001 sample_nearest_1d( struct gl_context
*ctx
,
1002 const struct gl_sampler_object
*samp
,
1003 const struct gl_texture_object
*tObj
, GLuint n
,
1004 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1008 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
1010 for (i
= 0; i
< n
; i
++) {
1011 sample_1d_nearest(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
1016 /** Sample 1D texture, linear filtering for both min/magnification */
1018 sample_linear_1d( struct gl_context
*ctx
,
1019 const struct gl_sampler_object
*samp
,
1020 const struct gl_texture_object
*tObj
, GLuint n
,
1021 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1025 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
1027 for (i
= 0; i
< n
; i
++) {
1028 sample_1d_linear(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
1033 /** Sample 1D texture, using lambda to choose between min/magnification */
1035 sample_lambda_1d( struct gl_context
*ctx
,
1036 const struct gl_sampler_object
*samp
,
1037 const struct gl_texture_object
*tObj
, GLuint n
,
1038 const GLfloat texcoords
[][4],
1039 const GLfloat lambda
[], GLfloat rgba
[][4] )
1041 GLuint minStart
, minEnd
; /* texels with minification */
1042 GLuint magStart
, magEnd
; /* texels with magnification */
1045 assert(lambda
!= NULL
);
1046 compute_min_mag_ranges(samp
, n
, lambda
,
1047 &minStart
, &minEnd
, &magStart
, &magEnd
);
1049 if (minStart
< minEnd
) {
1050 /* do the minified texels */
1051 const GLuint m
= minEnd
- minStart
;
1052 switch (samp
->MinFilter
) {
1054 for (i
= minStart
; i
< minEnd
; i
++)
1055 sample_1d_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
1056 texcoords
[i
], rgba
[i
]);
1059 for (i
= minStart
; i
< minEnd
; i
++)
1060 sample_1d_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
1061 texcoords
[i
], rgba
[i
]);
1063 case GL_NEAREST_MIPMAP_NEAREST
:
1064 sample_1d_nearest_mipmap_nearest(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1065 lambda
+ minStart
, rgba
+ minStart
);
1067 case GL_LINEAR_MIPMAP_NEAREST
:
1068 sample_1d_linear_mipmap_nearest(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1069 lambda
+ minStart
, rgba
+ minStart
);
1071 case GL_NEAREST_MIPMAP_LINEAR
:
1072 sample_1d_nearest_mipmap_linear(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1073 lambda
+ minStart
, rgba
+ minStart
);
1075 case GL_LINEAR_MIPMAP_LINEAR
:
1076 sample_1d_linear_mipmap_linear(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1077 lambda
+ minStart
, rgba
+ minStart
);
1080 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
1085 if (magStart
< magEnd
) {
1086 /* do the magnified texels */
1087 switch (samp
->MagFilter
) {
1089 for (i
= magStart
; i
< magEnd
; i
++)
1090 sample_1d_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
1091 texcoords
[i
], rgba
[i
]);
1094 for (i
= magStart
; i
< magEnd
; i
++)
1095 sample_1d_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
1096 texcoords
[i
], rgba
[i
]);
1099 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
1106 /**********************************************************************/
1107 /* 2-D Texture Sampling Functions */
1108 /**********************************************************************/
1112 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1115 sample_2d_nearest(struct gl_context
*ctx
,
1116 const struct gl_sampler_object
*samp
,
1117 const struct gl_texture_image
*img
,
1118 const GLfloat texcoord
[4],
1121 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
1122 const GLint width
= img
->Width2
; /* without border, power of two */
1123 const GLint height
= img
->Height2
; /* without border, power of two */
1127 i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
1128 j
= nearest_texel_location(samp
->WrapT
, img
, height
, texcoord
[1]);
1130 /* skip over the border, if any */
1134 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
1135 /* Need this test for GL_CLAMP_TO_BORDER mode */
1136 get_border_color(samp
, img
, rgba
);
1139 swImg
->FetchTexel(swImg
, i
, j
, 0, rgba
);
1145 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1146 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1149 sample_2d_linear(struct gl_context
*ctx
,
1150 const struct gl_sampler_object
*samp
,
1151 const struct gl_texture_image
*img
,
1152 const GLfloat texcoord
[4],
1155 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
1156 const GLint width
= img
->Width2
;
1157 const GLint height
= img
->Height2
;
1158 GLint i0
, j0
, i1
, j1
;
1159 GLbitfield useBorderColor
= 0x0;
1161 GLfloat t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
1163 linear_texel_locations(samp
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
1164 linear_texel_locations(samp
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
1173 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1174 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1175 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1176 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1179 /* fetch four texel colors */
1180 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1181 get_border_color(samp
, img
, t00
);
1184 swImg
->FetchTexel(swImg
, i0
, j0
, 0, t00
);
1186 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1187 get_border_color(samp
, img
, t10
);
1190 swImg
->FetchTexel(swImg
, i1
, j0
, 0, t10
);
1192 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1193 get_border_color(samp
, img
, t01
);
1196 swImg
->FetchTexel(swImg
, i0
, j1
, 0, t01
);
1198 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1199 get_border_color(samp
, img
, t11
);
1202 swImg
->FetchTexel(swImg
, i1
, j1
, 0, t11
);
1205 lerp_rgba_2d(rgba
, a
, b
, t00
, t10
, t01
, t11
);
1210 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
1211 * We don't have to worry about the texture border.
1214 sample_2d_linear_repeat(struct gl_context
*ctx
,
1215 const struct gl_sampler_object
*samp
,
1216 const struct gl_texture_image
*img
,
1217 const GLfloat texcoord
[4],
1220 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
1221 const GLint width
= img
->Width2
;
1222 const GLint height
= img
->Height2
;
1223 GLint i0
, j0
, i1
, j1
;
1225 GLfloat t00
[4], t10
[4], t01
[4], t11
[4]; /* sampled texel colors */
1229 assert(samp
->WrapS
== GL_REPEAT
);
1230 assert(samp
->WrapT
== GL_REPEAT
);
1231 assert(img
->Border
== 0);
1232 assert(swImg
->_IsPowerOfTwo
);
1234 linear_repeat_texel_location(width
, texcoord
[0], &i0
, &i1
, &wi
);
1235 linear_repeat_texel_location(height
, texcoord
[1], &j0
, &j1
, &wj
);
1237 swImg
->FetchTexel(swImg
, i0
, j0
, 0, t00
);
1238 swImg
->FetchTexel(swImg
, i1
, j0
, 0, t10
);
1239 swImg
->FetchTexel(swImg
, i0
, j1
, 0, t01
);
1240 swImg
->FetchTexel(swImg
, i1
, j1
, 0, t11
);
1242 lerp_rgba_2d(rgba
, wi
, wj
, t00
, t10
, t01
, t11
);
1247 sample_2d_nearest_mipmap_nearest(struct gl_context
*ctx
,
1248 const struct gl_sampler_object
*samp
,
1249 const struct gl_texture_object
*tObj
,
1250 GLuint n
, const GLfloat texcoord
[][4],
1251 const GLfloat lambda
[], GLfloat rgba
[][4])
1254 for (i
= 0; i
< n
; i
++) {
1255 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1256 sample_2d_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1262 sample_2d_linear_mipmap_nearest(struct gl_context
*ctx
,
1263 const struct gl_sampler_object
*samp
,
1264 const struct gl_texture_object
*tObj
,
1265 GLuint n
, const GLfloat texcoord
[][4],
1266 const GLfloat lambda
[], GLfloat rgba
[][4])
1269 assert(lambda
!= NULL
);
1270 for (i
= 0; i
< n
; i
++) {
1271 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
1272 sample_2d_linear(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1278 sample_2d_nearest_mipmap_linear(struct gl_context
*ctx
,
1279 const struct gl_sampler_object
*samp
,
1280 const struct gl_texture_object
*tObj
,
1281 GLuint n
, const GLfloat texcoord
[][4],
1282 const GLfloat lambda
[], GLfloat rgba
[][4])
1285 assert(lambda
!= NULL
);
1286 for (i
= 0; i
< n
; i
++) {
1287 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1288 if (level
>= tObj
->_MaxLevel
) {
1289 sample_2d_nearest(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
1290 texcoord
[i
], rgba
[i
]);
1293 GLfloat t0
[4], t1
[4]; /* texels */
1294 const GLfloat f
= FRAC(lambda
[i
]);
1295 sample_2d_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1296 sample_2d_nearest(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1297 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1304 sample_2d_linear_mipmap_linear( struct gl_context
*ctx
,
1305 const struct gl_sampler_object
*samp
,
1306 const struct gl_texture_object
*tObj
,
1307 GLuint n
, const GLfloat texcoord
[][4],
1308 const GLfloat lambda
[], GLfloat rgba
[][4] )
1311 assert(lambda
!= NULL
);
1312 for (i
= 0; i
< n
; i
++) {
1313 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1314 if (level
>= tObj
->_MaxLevel
) {
1315 sample_2d_linear(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
1316 texcoord
[i
], rgba
[i
]);
1319 GLfloat t0
[4], t1
[4]; /* texels */
1320 const GLfloat f
= FRAC(lambda
[i
]);
1321 sample_2d_linear(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1322 sample_2d_linear(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1323 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1330 sample_2d_linear_mipmap_linear_repeat(struct gl_context
*ctx
,
1331 const struct gl_sampler_object
*samp
,
1332 const struct gl_texture_object
*tObj
,
1333 GLuint n
, const GLfloat texcoord
[][4],
1334 const GLfloat lambda
[], GLfloat rgba
[][4])
1337 assert(lambda
!= NULL
);
1338 assert(samp
->WrapS
== GL_REPEAT
);
1339 assert(samp
->WrapT
== GL_REPEAT
);
1340 for (i
= 0; i
< n
; i
++) {
1341 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
1342 if (level
>= tObj
->_MaxLevel
) {
1343 sample_2d_linear_repeat(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
1344 texcoord
[i
], rgba
[i
]);
1347 GLfloat t0
[4], t1
[4]; /* texels */
1348 const GLfloat f
= FRAC(lambda
[i
]);
1349 sample_2d_linear_repeat(ctx
, samp
, tObj
->Image
[0][level
],
1351 sample_2d_linear_repeat(ctx
, samp
, tObj
->Image
[0][level
+1],
1353 lerp_rgba(rgba
[i
], f
, t0
, t1
);
1359 /** Sample 2D texture, nearest filtering for both min/magnification */
1361 sample_nearest_2d(struct gl_context
*ctx
,
1362 const struct gl_sampler_object
*samp
,
1363 const struct gl_texture_object
*tObj
, GLuint n
,
1364 const GLfloat texcoords
[][4],
1365 const GLfloat lambda
[], GLfloat rgba
[][4])
1368 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
1370 for (i
= 0; i
< n
; i
++) {
1371 sample_2d_nearest(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
1376 /** Sample 2D texture, linear filtering for both min/magnification */
1378 sample_linear_2d(struct gl_context
*ctx
,
1379 const struct gl_sampler_object
*samp
,
1380 const struct gl_texture_object
*tObj
, GLuint n
,
1381 const GLfloat texcoords
[][4],
1382 const GLfloat lambda
[], GLfloat rgba
[][4])
1385 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
1386 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(image
);
1388 if (samp
->WrapS
== GL_REPEAT
&&
1389 samp
->WrapT
== GL_REPEAT
&&
1390 swImg
->_IsPowerOfTwo
&&
1391 image
->Border
== 0) {
1392 for (i
= 0; i
< n
; i
++) {
1393 sample_2d_linear_repeat(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
1397 for (i
= 0; i
< n
; i
++) {
1398 sample_2d_linear(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
1405 * Optimized 2-D texture sampling:
1406 * S and T wrap mode == GL_REPEAT
1407 * GL_NEAREST min/mag filter
1409 * RowStride == Width,
1413 opt_sample_rgb_2d(struct gl_context
*ctx
,
1414 const struct gl_sampler_object
*samp
,
1415 const struct gl_texture_object
*tObj
,
1416 GLuint n
, const GLfloat texcoords
[][4],
1417 const GLfloat lambda
[], GLfloat rgba
[][4])
1419 const struct gl_texture_image
*img
= _mesa_base_tex_image(tObj
);
1420 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
1421 const GLfloat width
= (GLfloat
) img
->Width
;
1422 const GLfloat height
= (GLfloat
) img
->Height
;
1423 const GLint colMask
= img
->Width
- 1;
1424 const GLint rowMask
= img
->Height
- 1;
1425 const GLint shift
= img
->WidthLog2
;
1429 assert(samp
->WrapS
==GL_REPEAT
);
1430 assert(samp
->WrapT
==GL_REPEAT
);
1431 assert(img
->Border
==0);
1432 assert(img
->TexFormat
== MESA_FORMAT_BGR_UNORM8
);
1433 assert(swImg
->_IsPowerOfTwo
);
1436 for (k
=0; k
<n
; k
++) {
1437 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1438 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1439 GLint pos
= (j
<< shift
) | i
;
1440 GLubyte
*texel
= (GLubyte
*) swImg
->ImageSlices
[0] + 3 * pos
;
1441 rgba
[k
][RCOMP
] = UBYTE_TO_FLOAT(texel
[2]);
1442 rgba
[k
][GCOMP
] = UBYTE_TO_FLOAT(texel
[1]);
1443 rgba
[k
][BCOMP
] = UBYTE_TO_FLOAT(texel
[0]);
1444 rgba
[k
][ACOMP
] = 1.0F
;
1450 * Optimized 2-D texture sampling:
1451 * S and T wrap mode == GL_REPEAT
1452 * GL_NEAREST min/mag filter
1454 * RowStride == Width,
1458 opt_sample_rgba_2d(struct gl_context
*ctx
,
1459 const struct gl_sampler_object
*samp
,
1460 const struct gl_texture_object
*tObj
,
1461 GLuint n
, const GLfloat texcoords
[][4],
1462 const GLfloat lambda
[], GLfloat rgba
[][4])
1464 const struct gl_texture_image
*img
= _mesa_base_tex_image(tObj
);
1465 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
1466 const GLfloat width
= (GLfloat
) img
->Width
;
1467 const GLfloat height
= (GLfloat
) img
->Height
;
1468 const GLint colMask
= img
->Width
- 1;
1469 const GLint rowMask
= img
->Height
- 1;
1470 const GLint shift
= img
->WidthLog2
;
1474 assert(samp
->WrapS
==GL_REPEAT
);
1475 assert(samp
->WrapT
==GL_REPEAT
);
1476 assert(img
->Border
==0);
1477 assert(img
->TexFormat
== MESA_FORMAT_A8B8G8R8_UNORM
);
1478 assert(swImg
->_IsPowerOfTwo
);
1481 for (i
= 0; i
< n
; i
++) {
1482 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1483 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1484 const GLint pos
= (row
<< shift
) | col
;
1485 const GLuint texel
= *((GLuint
*) swImg
->ImageSlices
[0] + pos
);
1486 rgba
[i
][RCOMP
] = UBYTE_TO_FLOAT( (texel
>> 24) );
1487 rgba
[i
][GCOMP
] = UBYTE_TO_FLOAT( (texel
>> 16) & 0xff );
1488 rgba
[i
][BCOMP
] = UBYTE_TO_FLOAT( (texel
>> 8) & 0xff );
1489 rgba
[i
][ACOMP
] = UBYTE_TO_FLOAT( (texel
) & 0xff );
1494 /** Sample 2D texture, using lambda to choose between min/magnification */
1496 sample_lambda_2d(struct gl_context
*ctx
,
1497 const struct gl_sampler_object
*samp
,
1498 const struct gl_texture_object
*tObj
,
1499 GLuint n
, const GLfloat texcoords
[][4],
1500 const GLfloat lambda
[], GLfloat rgba
[][4])
1502 const struct gl_texture_image
*tImg
= _mesa_base_tex_image(tObj
);
1503 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(tImg
);
1504 GLuint minStart
, minEnd
; /* texels with minification */
1505 GLuint magStart
, magEnd
; /* texels with magnification */
1507 const GLboolean repeatNoBorderPOT
= (samp
->WrapS
== GL_REPEAT
)
1508 && (samp
->WrapT
== GL_REPEAT
)
1509 && (tImg
->Border
== 0)
1510 && (_mesa_format_row_stride(tImg
->TexFormat
, tImg
->Width
) ==
1512 && swImg
->_IsPowerOfTwo
;
1514 assert(lambda
!= NULL
);
1515 compute_min_mag_ranges(samp
, n
, lambda
,
1516 &minStart
, &minEnd
, &magStart
, &magEnd
);
1518 if (minStart
< minEnd
) {
1519 /* do the minified texels */
1520 const GLuint m
= minEnd
- minStart
;
1521 switch (samp
->MinFilter
) {
1523 if (repeatNoBorderPOT
) {
1524 switch (tImg
->TexFormat
) {
1525 case MESA_FORMAT_BGR_UNORM8
:
1526 opt_sample_rgb_2d(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1527 NULL
, rgba
+ minStart
);
1529 case MESA_FORMAT_A8B8G8R8_UNORM
:
1530 opt_sample_rgba_2d(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1531 NULL
, rgba
+ minStart
);
1534 sample_nearest_2d(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1535 NULL
, rgba
+ minStart
);
1539 sample_nearest_2d(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1540 NULL
, rgba
+ minStart
);
1544 sample_linear_2d(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1545 NULL
, rgba
+ minStart
);
1547 case GL_NEAREST_MIPMAP_NEAREST
:
1548 sample_2d_nearest_mipmap_nearest(ctx
, samp
, tObj
, m
,
1549 texcoords
+ minStart
,
1550 lambda
+ minStart
, rgba
+ minStart
);
1552 case GL_LINEAR_MIPMAP_NEAREST
:
1553 sample_2d_linear_mipmap_nearest(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1554 lambda
+ minStart
, rgba
+ minStart
);
1556 case GL_NEAREST_MIPMAP_LINEAR
:
1557 sample_2d_nearest_mipmap_linear(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1558 lambda
+ minStart
, rgba
+ minStart
);
1560 case GL_LINEAR_MIPMAP_LINEAR
:
1561 if (repeatNoBorderPOT
)
1562 sample_2d_linear_mipmap_linear_repeat(ctx
, samp
, tObj
, m
,
1563 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1565 sample_2d_linear_mipmap_linear(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
1566 lambda
+ minStart
, rgba
+ minStart
);
1569 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1574 if (magStart
< magEnd
) {
1575 /* do the magnified texels */
1576 const GLuint m
= magEnd
- magStart
;
1578 switch (samp
->MagFilter
) {
1580 if (repeatNoBorderPOT
) {
1581 switch (tImg
->TexFormat
) {
1582 case MESA_FORMAT_BGR_UNORM8
:
1583 opt_sample_rgb_2d(ctx
, samp
, tObj
, m
, texcoords
+ magStart
,
1584 NULL
, rgba
+ magStart
);
1586 case MESA_FORMAT_A8B8G8R8_UNORM
:
1587 opt_sample_rgba_2d(ctx
, samp
, tObj
, m
, texcoords
+ magStart
,
1588 NULL
, rgba
+ magStart
);
1591 sample_nearest_2d(ctx
, samp
, tObj
, m
, texcoords
+ magStart
,
1592 NULL
, rgba
+ magStart
);
1596 sample_nearest_2d(ctx
, samp
, tObj
, m
, texcoords
+ magStart
,
1597 NULL
, rgba
+ magStart
);
1601 sample_linear_2d(ctx
, samp
, tObj
, m
, texcoords
+ magStart
,
1602 NULL
, rgba
+ magStart
);
1605 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1612 /* For anisotropic filtering */
1613 #define WEIGHT_LUT_SIZE 1024
1615 static GLfloat
*weightLut
= NULL
;
1618 * Creates the look-up table used to speed-up EWA sampling
1621 create_filter_table(void)
1625 weightLut
= malloc(WEIGHT_LUT_SIZE
* sizeof(GLfloat
));
1627 for (i
= 0; i
< WEIGHT_LUT_SIZE
; ++i
) {
1629 GLfloat r2
= (GLfloat
) i
/ (GLfloat
) (WEIGHT_LUT_SIZE
- 1);
1630 GLfloat weight
= (GLfloat
) exp(-alpha
* r2
);
1631 weightLut
[i
] = weight
;
1638 * Elliptical weighted average (EWA) filter for producing high quality
1639 * anisotropic filtered results.
1640 * Based on the Higher Quality Elliptical Weighted Avarage Filter
1641 * published by Paul S. Heckbert in his Master's Thesis
1642 * "Fundamentals of Texture Mapping and Image Warping" (1989)
1645 sample_2d_ewa(struct gl_context
*ctx
,
1646 const struct gl_sampler_object
*samp
,
1647 const struct gl_texture_object
*tObj
,
1648 const GLfloat texcoord
[4],
1649 const GLfloat dudx
, const GLfloat dvdx
,
1650 const GLfloat dudy
, const GLfloat dvdy
, const GLint lod
,
1653 GLint level
= lod
> 0 ? lod
: 0;
1654 GLfloat scaling
= 1.0f
/ (1 << level
);
1655 const struct gl_texture_image
*img
= tObj
->Image
[0][level
];
1656 const struct gl_texture_image
*mostDetailedImage
=
1657 _mesa_base_tex_image(tObj
);
1658 const struct swrast_texture_image
*swImg
=
1659 swrast_texture_image_const(mostDetailedImage
);
1660 GLfloat tex_u
= -0.5f
+ texcoord
[0] * swImg
->WidthScale
* scaling
;
1661 GLfloat tex_v
= -0.5f
+ texcoord
[1] * swImg
->HeightScale
* scaling
;
1663 GLfloat ux
= dudx
* scaling
;
1664 GLfloat vx
= dvdx
* scaling
;
1665 GLfloat uy
= dudy
* scaling
;
1666 GLfloat vy
= dvdy
* scaling
;
1668 /* compute ellipse coefficients to bound the region:
1669 * A*x*x + B*x*y + C*y*y = F.
1671 GLfloat A
= vx
*vx
+vy
*vy
+1;
1672 GLfloat B
= -2*(ux
*vx
+uy
*vy
);
1673 GLfloat C
= ux
*ux
+uy
*uy
+1;
1674 GLfloat F
= A
*C
-B
*B
/4.0f
;
1676 /* check if it is an ellipse */
1677 /* assert(F > 0.0); */
1679 /* Compute the ellipse's (u,v) bounding box in texture space */
1680 GLfloat d
= -B
*B
+4.0f
*C
*A
;
1681 GLfloat box_u
= 2.0f
/ d
* sqrtf(d
*C
*F
); /* box_u -> half of bbox with */
1682 GLfloat box_v
= 2.0f
/ d
* sqrtf(A
*d
*F
); /* box_v -> half of bbox height */
1684 GLint u0
= (GLint
) floorf(tex_u
- box_u
);
1685 GLint u1
= (GLint
) ceilf (tex_u
+ box_u
);
1686 GLint v0
= (GLint
) floorf(tex_v
- box_v
);
1687 GLint v1
= (GLint
) ceilf (tex_v
+ box_v
);
1689 GLfloat num
[4] = {0.0F
, 0.0F
, 0.0F
, 0.0F
};
1690 GLfloat newCoord
[2];
1693 GLfloat U
= u0
- tex_u
;
1696 /* Scale ellipse formula to directly index the Filter Lookup Table.
1697 * i.e. scale so that F = WEIGHT_LUT_SIZE-1
1699 GLfloat formScale
= (GLfloat
) (WEIGHT_LUT_SIZE
- 1) / F
;
1703 /* F *= formScale; */ /* no need to scale F as we don't use it below here */
1705 /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
1706 * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
1707 * value, q, is less than F, we're inside the ellipse
1710 for (v
= v0
; v
<= v1
; ++v
) {
1711 GLfloat V
= v
- tex_v
;
1712 GLfloat dq
= A
* (2 * U
+ 1) + B
* V
;
1713 GLfloat q
= (C
* V
+ B
* U
) * V
+ A
* U
* U
;
1716 for (u
= u0
; u
<= u1
; ++u
) {
1717 /* Note that the ellipse has been pre-scaled so F = WEIGHT_LUT_SIZE - 1 */
1718 if (q
< WEIGHT_LUT_SIZE
) {
1719 /* as a LUT is used, q must never be negative;
1720 * should not happen, though
1722 const GLint qClamped
= q
>= 0.0F
? (GLint
) q
: 0;
1723 GLfloat weight
= weightLut
[qClamped
];
1725 newCoord
[0] = u
/ ((GLfloat
) img
->Width2
);
1726 newCoord
[1] = v
/ ((GLfloat
) img
->Height2
);
1728 sample_2d_nearest(ctx
, samp
, img
, newCoord
, rgba
);
1729 num
[0] += weight
* rgba
[0];
1730 num
[1] += weight
* rgba
[1];
1731 num
[2] += weight
* rgba
[2];
1732 num
[3] += weight
* rgba
[3];
1742 /* Reaching this place would mean
1743 * that no pixels intersected the ellipse.
1744 * This should never happen because
1745 * the filter we use always
1746 * intersects at least one pixel.
1753 /* not enough pixels in resampling, resort to direct interpolation */
1754 sample_2d_linear(ctx
, samp
, img
, texcoord
, rgba
);
1758 rgba
[0] = num
[0] / den
;
1759 rgba
[1] = num
[1] / den
;
1760 rgba
[2] = num
[2] / den
;
1761 rgba
[3] = num
[3] / den
;
1766 * Anisotropic filtering using footprint assembly as outlined in the
1767 * EXT_texture_filter_anisotropic spec:
1768 * http://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
1769 * Faster than EWA but has less quality (more aliasing effects)
1772 sample_2d_footprint(struct gl_context
*ctx
,
1773 const struct gl_sampler_object
*samp
,
1774 const struct gl_texture_object
*tObj
,
1775 const GLfloat texcoord
[4],
1776 const GLfloat dudx
, const GLfloat dvdx
,
1777 const GLfloat dudy
, const GLfloat dvdy
, const GLint lod
,
1780 GLint level
= lod
> 0 ? lod
: 0;
1781 GLfloat scaling
= 1.0F
/ (1 << level
);
1782 const struct gl_texture_image
*img
= tObj
->Image
[0][level
];
1784 GLfloat ux
= dudx
* scaling
;
1785 GLfloat vx
= dvdx
* scaling
;
1786 GLfloat uy
= dudy
* scaling
;
1787 GLfloat vy
= dvdy
* scaling
;
1789 GLfloat Px2
= ux
* ux
+ vx
* vx
; /* squared length of dx */
1790 GLfloat Py2
= uy
* uy
+ vy
* vy
; /* squared length of dy */
1796 GLfloat num
[4] = {0.0F
, 0.0F
, 0.0F
, 0.0F
};
1797 GLfloat newCoord
[2];
1800 /* Calculate the per anisotropic sample offsets in s,t space. */
1802 numSamples
= (GLint
) ceilf(sqrtf(Px2
));
1803 ds
= ux
/ ((GLfloat
) img
->Width2
);
1804 dt
= vx
/ ((GLfloat
) img
->Height2
);
1807 numSamples
= (GLint
) ceilf(sqrtf(Py2
));
1808 ds
= uy
/ ((GLfloat
) img
->Width2
);
1809 dt
= vy
/ ((GLfloat
) img
->Height2
);
1812 for (s
= 0; s
<numSamples
; s
++) {
1813 newCoord
[0] = texcoord
[0] + ds
* ((GLfloat
)(s
+1) / (numSamples
+1) -0.5f
);
1814 newCoord
[1] = texcoord
[1] + dt
* ((GLfloat
)(s
+1) / (numSamples
+1) -0.5f
);
1816 sample_2d_linear(ctx
, samp
, img
, newCoord
, rgba
);
1823 rgba
[0] = num
[0] / numSamples
;
1824 rgba
[1] = num
[1] / numSamples
;
1825 rgba
[2] = num
[2] / numSamples
;
1826 rgba
[3] = num
[3] / numSamples
;
1831 * Returns the index of the specified texture object in the
1832 * gl_context texture unit array.
1835 texture_unit_index(const struct gl_context
*ctx
,
1836 const struct gl_texture_object
*tObj
)
1838 const GLuint maxUnit
1839 = (ctx
->Texture
._EnabledCoordUnits
> 1) ? ctx
->Const
.MaxTextureUnits
: 1;
1842 /* XXX CoordUnits vs. ImageUnits */
1843 for (u
= 0; u
< maxUnit
; u
++) {
1844 if (ctx
->Texture
.Unit
[u
]._Current
== tObj
)
1848 u
= 0; /* not found, use 1st one; should never happen */
1855 * Sample 2D texture using an anisotropic filter.
1856 * NOTE: the const GLfloat lambda_iso[] parameter does *NOT* contain
1857 * the lambda float array but a "hidden" SWspan struct which is required
1858 * by this function but is not available in the texture_sample_func signature.
1859 * See _swrast_texture_span( struct gl_context *ctx, SWspan *span ) on how
1860 * this function is called.
1863 sample_lambda_2d_aniso(struct gl_context
*ctx
,
1864 const struct gl_sampler_object
*samp
,
1865 const struct gl_texture_object
*tObj
,
1866 GLuint n
, const GLfloat texcoords
[][4],
1867 const GLfloat lambda_iso
[], GLfloat rgba
[][4])
1869 const struct gl_texture_image
*tImg
= _mesa_base_tex_image(tObj
);
1870 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(tImg
);
1871 const GLfloat maxEccentricity
=
1872 samp
->MaxAnisotropy
* samp
->MaxAnisotropy
;
1874 /* re-calculate the lambda values so that they are usable with anisotropic
1877 SWspan
*span
= (SWspan
*)lambda_iso
; /* access the "hidden" SWspan struct */
1879 /* based on interpolate_texcoords(struct gl_context *ctx, SWspan *span)
1880 * in swrast/s_span.c
1883 /* find the texture unit index by looking up the current texture object
1884 * from the context list of available texture objects.
1886 const GLuint u
= texture_unit_index(ctx
, tObj
);
1887 const GLuint attr
= VARYING_SLOT_TEX0
+ u
;
1890 const GLfloat dsdx
= span
->attrStepX
[attr
][0];
1891 const GLfloat dsdy
= span
->attrStepY
[attr
][0];
1892 const GLfloat dtdx
= span
->attrStepX
[attr
][1];
1893 const GLfloat dtdy
= span
->attrStepY
[attr
][1];
1894 const GLfloat dqdx
= span
->attrStepX
[attr
][3];
1895 const GLfloat dqdy
= span
->attrStepY
[attr
][3];
1896 GLfloat s
= span
->attrStart
[attr
][0] + span
->leftClip
* dsdx
;
1897 GLfloat t
= span
->attrStart
[attr
][1] + span
->leftClip
* dtdx
;
1898 GLfloat q
= span
->attrStart
[attr
][3] + span
->leftClip
* dqdx
;
1900 /* from swrast/s_texcombine.c _swrast_texture_span */
1901 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[u
];
1902 const GLboolean adjustLOD
=
1903 (texUnit
->LodBias
+ samp
->LodBias
!= 0.0F
)
1904 || (samp
->MinLod
!= -1000.0 || samp
->MaxLod
!= 1000.0);
1908 /* on first access create the lookup table containing the filter weights. */
1910 create_filter_table();
1913 texW
= swImg
->WidthScale
;
1914 texH
= swImg
->HeightScale
;
1916 for (i
= 0; i
< n
; i
++) {
1917 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
1919 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
1920 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
1921 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
1922 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
1924 /* note: instead of working with Px and Py, we will use the
1925 * squared length instead, to avoid sqrt.
1927 GLfloat Px2
= dudx
* dudx
+ dvdx
* dvdx
;
1928 GLfloat Py2
= dudy
* dudy
+ dvdy
* dvdy
;
1948 /* if the eccentricity of the ellipse is too big, scale up the shorter
1949 * of the two vectors to limit the maximum amount of work per pixel
1952 if (e
> maxEccentricity
) {
1953 /* GLfloat s=e / maxEccentricity;
1957 Pmin2
= Pmax2
/ maxEccentricity
;
1960 /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
1961 * this since 0.5*log(x) = log(sqrt(x))
1963 lod
= 0.5f
* LOG2(Pmin2
);
1966 /* from swrast/s_texcombine.c _swrast_texture_span */
1967 if (texUnit
->LodBias
+ samp
->LodBias
!= 0.0F
) {
1968 /* apply LOD bias, but don't clamp yet */
1969 const GLfloat bias
=
1970 CLAMP(texUnit
->LodBias
+ samp
->LodBias
,
1971 -ctx
->Const
.MaxTextureLodBias
,
1972 ctx
->Const
.MaxTextureLodBias
);
1975 if (samp
->MinLod
!= -1000.0 ||
1976 samp
->MaxLod
!= 1000.0) {
1977 /* apply LOD clamping to lambda */
1978 lod
= CLAMP(lod
, samp
->MinLod
, samp
->MaxLod
);
1983 /* If the ellipse covers the whole image, we can
1984 * simply return the average of the whole image.
1986 if (lod
>= tObj
->_MaxLevel
) {
1987 sample_2d_linear(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
1988 texcoords
[i
], rgba
[i
]);
1991 /* don't bother interpolating between multiple LODs; it doesn't
1992 * seem to be worth the extra running time.
1994 sample_2d_ewa(ctx
, samp
, tObj
, texcoords
[i
],
1995 dudx
, dvdx
, dudy
, dvdy
, (GLint
) floorf(lod
), rgba
[i
]);
1998 (void) sample_2d_footprint
;
2000 sample_2d_footprint(ctx, tObj, texcoords[i],
2001 dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]);
2009 /**********************************************************************/
2010 /* 3-D Texture Sampling Functions */
2011 /**********************************************************************/
2014 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
2017 sample_3d_nearest(struct gl_context
*ctx
,
2018 const struct gl_sampler_object
*samp
,
2019 const struct gl_texture_image
*img
,
2020 const GLfloat texcoord
[4],
2023 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
2024 const GLint width
= img
->Width2
; /* without border, power of two */
2025 const GLint height
= img
->Height2
; /* without border, power of two */
2026 const GLint depth
= img
->Depth2
; /* without border, power of two */
2030 i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
2031 j
= nearest_texel_location(samp
->WrapT
, img
, height
, texcoord
[1]);
2032 k
= nearest_texel_location(samp
->WrapR
, img
, depth
, texcoord
[2]);
2034 if (i
< 0 || i
>= (GLint
) img
->Width
||
2035 j
< 0 || j
>= (GLint
) img
->Height
||
2036 k
< 0 || k
>= (GLint
) img
->Depth
) {
2037 /* Need this test for GL_CLAMP_TO_BORDER mode */
2038 get_border_color(samp
, img
, rgba
);
2041 swImg
->FetchTexel(swImg
, i
, j
, k
, rgba
);
2047 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
2050 sample_3d_linear(struct gl_context
*ctx
,
2051 const struct gl_sampler_object
*samp
,
2052 const struct gl_texture_image
*img
,
2053 const GLfloat texcoord
[4],
2056 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
2057 const GLint width
= img
->Width2
;
2058 const GLint height
= img
->Height2
;
2059 const GLint depth
= img
->Depth2
;
2060 GLint i0
, j0
, k0
, i1
, j1
, k1
;
2061 GLbitfield useBorderColor
= 0x0;
2063 GLfloat t000
[4], t010
[4], t001
[4], t011
[4];
2064 GLfloat t100
[4], t110
[4], t101
[4], t111
[4];
2066 linear_texel_locations(samp
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
2067 linear_texel_locations(samp
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
2068 linear_texel_locations(samp
->WrapR
, img
, depth
, texcoord
[2], &k0
, &k1
, &c
);
2079 /* check if sampling texture border color */
2080 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2081 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2082 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
2083 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
2084 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
2085 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
2089 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
2090 get_border_color(samp
, img
, t000
);
2093 swImg
->FetchTexel(swImg
, i0
, j0
, k0
, t000
);
2095 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
2096 get_border_color(samp
, img
, t100
);
2099 swImg
->FetchTexel(swImg
, i1
, j0
, k0
, t100
);
2101 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
2102 get_border_color(samp
, img
, t010
);
2105 swImg
->FetchTexel(swImg
, i0
, j1
, k0
, t010
);
2107 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
2108 get_border_color(samp
, img
, t110
);
2111 swImg
->FetchTexel(swImg
, i1
, j1
, k0
, t110
);
2114 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
2115 get_border_color(samp
, img
, t001
);
2118 swImg
->FetchTexel(swImg
, i0
, j0
, k1
, t001
);
2120 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
2121 get_border_color(samp
, img
, t101
);
2124 swImg
->FetchTexel(swImg
, i1
, j0
, k1
, t101
);
2126 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
2127 get_border_color(samp
, img
, t011
);
2130 swImg
->FetchTexel(swImg
, i0
, j1
, k1
, t011
);
2132 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
2133 get_border_color(samp
, img
, t111
);
2136 swImg
->FetchTexel(swImg
, i1
, j1
, k1
, t111
);
2139 /* trilinear interpolation of samples */
2140 lerp_rgba_3d(rgba
, a
, b
, c
, t000
, t100
, t010
, t110
, t001
, t101
, t011
, t111
);
2145 sample_3d_nearest_mipmap_nearest(struct gl_context
*ctx
,
2146 const struct gl_sampler_object
*samp
,
2147 const struct gl_texture_object
*tObj
,
2148 GLuint n
, const GLfloat texcoord
[][4],
2149 const GLfloat lambda
[], GLfloat rgba
[][4] )
2152 for (i
= 0; i
< n
; i
++) {
2153 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2154 sample_3d_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
2160 sample_3d_linear_mipmap_nearest(struct gl_context
*ctx
,
2161 const struct gl_sampler_object
*samp
,
2162 const struct gl_texture_object
*tObj
,
2163 GLuint n
, const GLfloat texcoord
[][4],
2164 const GLfloat lambda
[], GLfloat rgba
[][4])
2167 assert(lambda
!= NULL
);
2168 for (i
= 0; i
< n
; i
++) {
2169 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2170 sample_3d_linear(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
2176 sample_3d_nearest_mipmap_linear(struct gl_context
*ctx
,
2177 const struct gl_sampler_object
*samp
,
2178 const struct gl_texture_object
*tObj
,
2179 GLuint n
, const GLfloat texcoord
[][4],
2180 const GLfloat lambda
[], GLfloat rgba
[][4])
2183 assert(lambda
!= NULL
);
2184 for (i
= 0; i
< n
; i
++) {
2185 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2186 if (level
>= tObj
->_MaxLevel
) {
2187 sample_3d_nearest(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
2188 texcoord
[i
], rgba
[i
]);
2191 GLfloat t0
[4], t1
[4]; /* texels */
2192 const GLfloat f
= FRAC(lambda
[i
]);
2193 sample_3d_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
2194 sample_3d_nearest(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
2195 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2202 sample_3d_linear_mipmap_linear(struct gl_context
*ctx
,
2203 const struct gl_sampler_object
*samp
,
2204 const struct gl_texture_object
*tObj
,
2205 GLuint n
, const GLfloat texcoord
[][4],
2206 const GLfloat lambda
[], GLfloat rgba
[][4])
2209 assert(lambda
!= NULL
);
2210 for (i
= 0; i
< n
; i
++) {
2211 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2212 if (level
>= tObj
->_MaxLevel
) {
2213 sample_3d_linear(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
2214 texcoord
[i
], rgba
[i
]);
2217 GLfloat t0
[4], t1
[4]; /* texels */
2218 const GLfloat f
= FRAC(lambda
[i
]);
2219 sample_3d_linear(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
2220 sample_3d_linear(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
2221 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2227 /** Sample 3D texture, nearest filtering for both min/magnification */
2229 sample_nearest_3d(struct gl_context
*ctx
,
2230 const struct gl_sampler_object
*samp
,
2231 const struct gl_texture_object
*tObj
, GLuint n
,
2232 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2236 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
2238 for (i
= 0; i
< n
; i
++) {
2239 sample_3d_nearest(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
2244 /** Sample 3D texture, linear filtering for both min/magnification */
2246 sample_linear_3d(struct gl_context
*ctx
,
2247 const struct gl_sampler_object
*samp
,
2248 const struct gl_texture_object
*tObj
, GLuint n
,
2249 const GLfloat texcoords
[][4],
2250 const GLfloat lambda
[], GLfloat rgba
[][4])
2253 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
2255 for (i
= 0; i
< n
; i
++) {
2256 sample_3d_linear(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
2261 /** Sample 3D texture, using lambda to choose between min/magnification */
2263 sample_lambda_3d(struct gl_context
*ctx
,
2264 const struct gl_sampler_object
*samp
,
2265 const struct gl_texture_object
*tObj
, GLuint n
,
2266 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2269 GLuint minStart
, minEnd
; /* texels with minification */
2270 GLuint magStart
, magEnd
; /* texels with magnification */
2273 assert(lambda
!= NULL
);
2274 compute_min_mag_ranges(samp
, n
, lambda
,
2275 &minStart
, &minEnd
, &magStart
, &magEnd
);
2277 if (minStart
< minEnd
) {
2278 /* do the minified texels */
2279 GLuint m
= minEnd
- minStart
;
2280 switch (samp
->MinFilter
) {
2282 for (i
= minStart
; i
< minEnd
; i
++)
2283 sample_3d_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
2284 texcoords
[i
], rgba
[i
]);
2287 for (i
= minStart
; i
< minEnd
; i
++)
2288 sample_3d_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
2289 texcoords
[i
], rgba
[i
]);
2291 case GL_NEAREST_MIPMAP_NEAREST
:
2292 sample_3d_nearest_mipmap_nearest(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
2293 lambda
+ minStart
, rgba
+ minStart
);
2295 case GL_LINEAR_MIPMAP_NEAREST
:
2296 sample_3d_linear_mipmap_nearest(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
2297 lambda
+ minStart
, rgba
+ minStart
);
2299 case GL_NEAREST_MIPMAP_LINEAR
:
2300 sample_3d_nearest_mipmap_linear(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
2301 lambda
+ minStart
, rgba
+ minStart
);
2303 case GL_LINEAR_MIPMAP_LINEAR
:
2304 sample_3d_linear_mipmap_linear(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
2305 lambda
+ minStart
, rgba
+ minStart
);
2308 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
2313 if (magStart
< magEnd
) {
2314 /* do the magnified texels */
2315 switch (samp
->MagFilter
) {
2317 for (i
= magStart
; i
< magEnd
; i
++)
2318 sample_3d_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
2319 texcoords
[i
], rgba
[i
]);
2322 for (i
= magStart
; i
< magEnd
; i
++)
2323 sample_3d_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
2324 texcoords
[i
], rgba
[i
]);
2327 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2334 /**********************************************************************/
2335 /* Texture Cube Map Sampling Functions */
2336 /**********************************************************************/
2339 * Choose one of six sides of a texture cube map given the texture
2340 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2343 static const struct gl_texture_image
**
2344 choose_cube_face(const struct gl_texture_object
*texObj
,
2345 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2349 direction target sc tc ma
2350 ---------- ------------------------------- --- --- ---
2351 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2352 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2353 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2354 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2355 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2356 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2358 const GLfloat rx
= texcoord
[0];
2359 const GLfloat ry
= texcoord
[1];
2360 const GLfloat rz
= texcoord
[2];
2361 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
2365 if (arx
>= ary
&& arx
>= arz
) {
2379 else if (ary
>= arx
&& ary
>= arz
) {
2409 const float ima
= 1.0F
/ ma
;
2410 newCoord
[0] = ( sc
* ima
+ 1.0F
) * 0.5F
;
2411 newCoord
[1] = ( tc
* ima
+ 1.0F
) * 0.5F
;
2414 return (const struct gl_texture_image
**) texObj
->Image
[face
];
2419 sample_nearest_cube(struct gl_context
*ctx
,
2420 const struct gl_sampler_object
*samp
,
2421 const struct gl_texture_object
*tObj
, GLuint n
,
2422 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2427 for (i
= 0; i
< n
; i
++) {
2428 const struct gl_texture_image
**images
;
2429 GLfloat newCoord
[4];
2430 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2431 sample_2d_nearest(ctx
, samp
, images
[tObj
->BaseLevel
],
2434 if (is_depth_texture(tObj
)) {
2435 for (i
= 0; i
< n
; i
++) {
2436 apply_depth_mode(tObj
->DepthMode
, rgba
[i
][0], rgba
[i
]);
2443 sample_linear_cube(struct gl_context
*ctx
,
2444 const struct gl_sampler_object
*samp
,
2445 const struct gl_texture_object
*tObj
, GLuint n
,
2446 const GLfloat texcoords
[][4],
2447 const GLfloat lambda
[], GLfloat rgba
[][4])
2451 for (i
= 0; i
< n
; i
++) {
2452 const struct gl_texture_image
**images
;
2453 GLfloat newCoord
[4];
2454 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2455 sample_2d_linear(ctx
, samp
, images
[tObj
->BaseLevel
],
2458 if (is_depth_texture(tObj
)) {
2459 for (i
= 0; i
< n
; i
++) {
2460 apply_depth_mode(tObj
->DepthMode
, rgba
[i
][0], rgba
[i
]);
2467 sample_cube_nearest_mipmap_nearest(struct gl_context
*ctx
,
2468 const struct gl_sampler_object
*samp
,
2469 const struct gl_texture_object
*tObj
,
2470 GLuint n
, const GLfloat texcoord
[][4],
2471 const GLfloat lambda
[], GLfloat rgba
[][4])
2474 assert(lambda
!= NULL
);
2475 for (i
= 0; i
< n
; i
++) {
2476 const struct gl_texture_image
**images
;
2477 GLfloat newCoord
[4];
2479 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2481 /* XXX we actually need to recompute lambda here based on the newCoords.
2482 * But we would need the texcoords of adjacent fragments to compute that
2483 * properly, and we don't have those here.
2484 * For now, do an approximation: subtracting 1 from the chosen mipmap
2485 * level seems to work in some test cases.
2486 * The same adjustment is done in the next few functions.
2488 level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2489 level
= MAX2(level
- 1, 0);
2491 sample_2d_nearest(ctx
, samp
, images
[level
], newCoord
, rgba
[i
]);
2493 if (is_depth_texture(tObj
)) {
2494 for (i
= 0; i
< n
; i
++) {
2495 apply_depth_mode(tObj
->DepthMode
, rgba
[i
][0], rgba
[i
]);
2502 sample_cube_linear_mipmap_nearest(struct gl_context
*ctx
,
2503 const struct gl_sampler_object
*samp
,
2504 const struct gl_texture_object
*tObj
,
2505 GLuint n
, const GLfloat texcoord
[][4],
2506 const GLfloat lambda
[], GLfloat rgba
[][4])
2509 assert(lambda
!= NULL
);
2510 for (i
= 0; i
< n
; i
++) {
2511 const struct gl_texture_image
**images
;
2512 GLfloat newCoord
[4];
2513 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2514 level
= MAX2(level
- 1, 0); /* see comment above */
2515 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2516 sample_2d_linear(ctx
, samp
, images
[level
], newCoord
, rgba
[i
]);
2518 if (is_depth_texture(tObj
)) {
2519 for (i
= 0; i
< n
; i
++) {
2520 apply_depth_mode(tObj
->DepthMode
, rgba
[i
][0], rgba
[i
]);
2527 sample_cube_nearest_mipmap_linear(struct gl_context
*ctx
,
2528 const struct gl_sampler_object
*samp
,
2529 const struct gl_texture_object
*tObj
,
2530 GLuint n
, const GLfloat texcoord
[][4],
2531 const GLfloat lambda
[], GLfloat rgba
[][4])
2534 assert(lambda
!= NULL
);
2535 for (i
= 0; i
< n
; i
++) {
2536 const struct gl_texture_image
**images
;
2537 GLfloat newCoord
[4];
2538 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2539 level
= MAX2(level
- 1, 0); /* see comment above */
2540 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2541 if (level
>= tObj
->_MaxLevel
) {
2542 sample_2d_nearest(ctx
, samp
, images
[tObj
->_MaxLevel
],
2546 GLfloat t0
[4], t1
[4]; /* texels */
2547 const GLfloat f
= FRAC(lambda
[i
]);
2548 sample_2d_nearest(ctx
, samp
, images
[level
], newCoord
, t0
);
2549 sample_2d_nearest(ctx
, samp
, images
[level
+1], newCoord
, t1
);
2550 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2553 if (is_depth_texture(tObj
)) {
2554 for (i
= 0; i
< n
; i
++) {
2555 apply_depth_mode(tObj
->DepthMode
, rgba
[i
][0], rgba
[i
]);
2562 sample_cube_linear_mipmap_linear(struct gl_context
*ctx
,
2563 const struct gl_sampler_object
*samp
,
2564 const struct gl_texture_object
*tObj
,
2565 GLuint n
, const GLfloat texcoord
[][4],
2566 const GLfloat lambda
[], GLfloat rgba
[][4])
2569 assert(lambda
!= NULL
);
2570 for (i
= 0; i
< n
; i
++) {
2571 const struct gl_texture_image
**images
;
2572 GLfloat newCoord
[4];
2573 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2574 level
= MAX2(level
- 1, 0); /* see comment above */
2575 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2576 if (level
>= tObj
->_MaxLevel
) {
2577 sample_2d_linear(ctx
, samp
, images
[tObj
->_MaxLevel
],
2581 GLfloat t0
[4], t1
[4];
2582 const GLfloat f
= FRAC(lambda
[i
]);
2583 sample_2d_linear(ctx
, samp
, images
[level
], newCoord
, t0
);
2584 sample_2d_linear(ctx
, samp
, images
[level
+1], newCoord
, t1
);
2585 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2588 if (is_depth_texture(tObj
)) {
2589 for (i
= 0; i
< n
; i
++) {
2590 apply_depth_mode(tObj
->DepthMode
, rgba
[i
][0], rgba
[i
]);
2596 /** Sample cube texture, using lambda to choose between min/magnification */
2598 sample_lambda_cube(struct gl_context
*ctx
,
2599 const struct gl_sampler_object
*samp
,
2600 const struct gl_texture_object
*tObj
, GLuint n
,
2601 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2604 GLuint minStart
, minEnd
; /* texels with minification */
2605 GLuint magStart
, magEnd
; /* texels with magnification */
2607 assert(lambda
!= NULL
);
2608 compute_min_mag_ranges(samp
, n
, lambda
,
2609 &minStart
, &minEnd
, &magStart
, &magEnd
);
2611 if (minStart
< minEnd
) {
2612 /* do the minified texels */
2613 const GLuint m
= minEnd
- minStart
;
2614 switch (samp
->MinFilter
) {
2616 sample_nearest_cube(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
2617 lambda
+ minStart
, rgba
+ minStart
);
2620 sample_linear_cube(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
2621 lambda
+ minStart
, rgba
+ minStart
);
2623 case GL_NEAREST_MIPMAP_NEAREST
:
2624 sample_cube_nearest_mipmap_nearest(ctx
, samp
, tObj
, m
,
2625 texcoords
+ minStart
,
2626 lambda
+ minStart
, rgba
+ minStart
);
2628 case GL_LINEAR_MIPMAP_NEAREST
:
2629 sample_cube_linear_mipmap_nearest(ctx
, samp
, tObj
, m
,
2630 texcoords
+ minStart
,
2631 lambda
+ minStart
, rgba
+ minStart
);
2633 case GL_NEAREST_MIPMAP_LINEAR
:
2634 sample_cube_nearest_mipmap_linear(ctx
, samp
, tObj
, m
,
2635 texcoords
+ minStart
,
2636 lambda
+ minStart
, rgba
+ minStart
);
2638 case GL_LINEAR_MIPMAP_LINEAR
:
2639 sample_cube_linear_mipmap_linear(ctx
, samp
, tObj
, m
,
2640 texcoords
+ minStart
,
2641 lambda
+ minStart
, rgba
+ minStart
);
2644 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2649 if (magStart
< magEnd
) {
2650 /* do the magnified texels */
2651 const GLuint m
= magEnd
- magStart
;
2652 switch (samp
->MagFilter
) {
2654 sample_nearest_cube(ctx
, samp
, tObj
, m
, texcoords
+ magStart
,
2655 lambda
+ magStart
, rgba
+ magStart
);
2658 sample_linear_cube(ctx
, samp
, tObj
, m
, texcoords
+ magStart
,
2659 lambda
+ magStart
, rgba
+ magStart
);
2662 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2669 /**********************************************************************/
2670 /* Texture Rectangle Sampling Functions */
2671 /**********************************************************************/
2675 sample_nearest_rect(struct gl_context
*ctx
,
2676 const struct gl_sampler_object
*samp
,
2677 const struct gl_texture_object
*tObj
, GLuint n
,
2678 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2681 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2682 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
2683 const GLint width
= img
->Width
;
2684 const GLint height
= img
->Height
;
2690 assert(samp
->WrapS
== GL_CLAMP
||
2691 samp
->WrapS
== GL_CLAMP_TO_EDGE
||
2692 samp
->WrapS
== GL_CLAMP_TO_BORDER
);
2693 assert(samp
->WrapT
== GL_CLAMP
||
2694 samp
->WrapT
== GL_CLAMP_TO_EDGE
||
2695 samp
->WrapT
== GL_CLAMP_TO_BORDER
);
2697 for (i
= 0; i
< n
; i
++) {
2699 col
= clamp_rect_coord_nearest(samp
->WrapS
, texcoords
[i
][0], width
);
2700 row
= clamp_rect_coord_nearest(samp
->WrapT
, texcoords
[i
][1], height
);
2701 if (col
< 0 || col
>= width
|| row
< 0 || row
>= height
)
2702 get_border_color(samp
, img
, rgba
[i
]);
2704 swImg
->FetchTexel(swImg
, col
, row
, 0, rgba
[i
]);
2710 sample_linear_rect(struct gl_context
*ctx
,
2711 const struct gl_sampler_object
*samp
,
2712 const struct gl_texture_object
*tObj
, GLuint n
,
2713 const GLfloat texcoords
[][4],
2714 const GLfloat lambda
[], GLfloat rgba
[][4])
2716 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2717 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
2718 const GLint width
= img
->Width
;
2719 const GLint height
= img
->Height
;
2725 assert(samp
->WrapS
== GL_CLAMP
||
2726 samp
->WrapS
== GL_CLAMP_TO_EDGE
||
2727 samp
->WrapS
== GL_CLAMP_TO_BORDER
);
2728 assert(samp
->WrapT
== GL_CLAMP
||
2729 samp
->WrapT
== GL_CLAMP_TO_EDGE
||
2730 samp
->WrapT
== GL_CLAMP_TO_BORDER
);
2732 for (i
= 0; i
< n
; i
++) {
2733 GLint i0
, j0
, i1
, j1
;
2734 GLfloat t00
[4], t01
[4], t10
[4], t11
[4];
2736 GLbitfield useBorderColor
= 0x0;
2738 clamp_rect_coord_linear(samp
->WrapS
, texcoords
[i
][0], width
,
2740 clamp_rect_coord_linear(samp
->WrapT
, texcoords
[i
][1], height
,
2743 /* compute integer rows/columns */
2744 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2745 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2746 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
2747 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
2749 /* get four texel samples */
2750 if (useBorderColor
& (I0BIT
| J0BIT
))
2751 get_border_color(samp
, img
, t00
);
2753 swImg
->FetchTexel(swImg
, i0
, j0
, 0, t00
);
2755 if (useBorderColor
& (I1BIT
| J0BIT
))
2756 get_border_color(samp
, img
, t10
);
2758 swImg
->FetchTexel(swImg
, i1
, j0
, 0, t10
);
2760 if (useBorderColor
& (I0BIT
| J1BIT
))
2761 get_border_color(samp
, img
, t01
);
2763 swImg
->FetchTexel(swImg
, i0
, j1
, 0, t01
);
2765 if (useBorderColor
& (I1BIT
| J1BIT
))
2766 get_border_color(samp
, img
, t11
);
2768 swImg
->FetchTexel(swImg
, i1
, j1
, 0, t11
);
2770 lerp_rgba_2d(rgba
[i
], a
, b
, t00
, t10
, t01
, t11
);
2775 /** Sample Rect texture, using lambda to choose between min/magnification */
2777 sample_lambda_rect(struct gl_context
*ctx
,
2778 const struct gl_sampler_object
*samp
,
2779 const struct gl_texture_object
*tObj
, GLuint n
,
2780 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2783 GLuint minStart
, minEnd
, magStart
, magEnd
;
2785 /* We only need lambda to decide between minification and magnification.
2786 * There is no mipmapping with rectangular textures.
2788 compute_min_mag_ranges(samp
, n
, lambda
,
2789 &minStart
, &minEnd
, &magStart
, &magEnd
);
2791 if (minStart
< minEnd
) {
2792 if (samp
->MinFilter
== GL_NEAREST
) {
2793 sample_nearest_rect(ctx
, samp
, tObj
, minEnd
- minStart
,
2794 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2797 sample_linear_rect(ctx
, samp
, tObj
, minEnd
- minStart
,
2798 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2801 if (magStart
< magEnd
) {
2802 if (samp
->MagFilter
== GL_NEAREST
) {
2803 sample_nearest_rect(ctx
, samp
, tObj
, magEnd
- magStart
,
2804 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2807 sample_linear_rect(ctx
, samp
, tObj
, magEnd
- magStart
,
2808 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2814 /**********************************************************************/
2815 /* 2D Texture Array Sampling Functions */
2816 /**********************************************************************/
2819 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
2822 sample_2d_array_nearest(struct gl_context
*ctx
,
2823 const struct gl_sampler_object
*samp
,
2824 const struct gl_texture_image
*img
,
2825 const GLfloat texcoord
[4],
2828 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
2829 const GLint width
= img
->Width2
; /* without border, power of two */
2830 const GLint height
= img
->Height2
; /* without border, power of two */
2831 const GLint depth
= img
->Depth
;
2836 i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
2837 j
= nearest_texel_location(samp
->WrapT
, img
, height
, texcoord
[1]);
2838 array
= tex_array_slice(texcoord
[2], depth
);
2840 if (i
< 0 || i
>= (GLint
) img
->Width
||
2841 j
< 0 || j
>= (GLint
) img
->Height
||
2842 array
< 0 || array
>= (GLint
) img
->Depth
) {
2843 /* Need this test for GL_CLAMP_TO_BORDER mode */
2844 get_border_color(samp
, img
, rgba
);
2847 swImg
->FetchTexel(swImg
, i
, j
, array
, rgba
);
2853 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
2856 sample_2d_array_linear(struct gl_context
*ctx
,
2857 const struct gl_sampler_object
*samp
,
2858 const struct gl_texture_image
*img
,
2859 const GLfloat texcoord
[4],
2862 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
2863 const GLint width
= img
->Width2
;
2864 const GLint height
= img
->Height2
;
2865 const GLint depth
= img
->Depth
;
2866 GLint i0
, j0
, i1
, j1
;
2868 GLbitfield useBorderColor
= 0x0;
2870 GLfloat t00
[4], t01
[4], t10
[4], t11
[4];
2872 linear_texel_locations(samp
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
2873 linear_texel_locations(samp
->WrapT
, img
, height
, texcoord
[1], &j0
, &j1
, &b
);
2874 array
= tex_array_slice(texcoord
[2], depth
);
2876 if (array
< 0 || array
>= depth
) {
2877 COPY_4V(rgba
, samp
->BorderColor
.f
);
2887 /* check if sampling texture border color */
2888 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
2889 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
2890 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
2891 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
2895 if (useBorderColor
& (I0BIT
| J0BIT
)) {
2896 get_border_color(samp
, img
, t00
);
2899 swImg
->FetchTexel(swImg
, i0
, j0
, array
, t00
);
2901 if (useBorderColor
& (I1BIT
| J0BIT
)) {
2902 get_border_color(samp
, img
, t10
);
2905 swImg
->FetchTexel(swImg
, i1
, j0
, array
, t10
);
2907 if (useBorderColor
& (I0BIT
| J1BIT
)) {
2908 get_border_color(samp
, img
, t01
);
2911 swImg
->FetchTexel(swImg
, i0
, j1
, array
, t01
);
2913 if (useBorderColor
& (I1BIT
| J1BIT
)) {
2914 get_border_color(samp
, img
, t11
);
2917 swImg
->FetchTexel(swImg
, i1
, j1
, array
, t11
);
2920 /* trilinear interpolation of samples */
2921 lerp_rgba_2d(rgba
, a
, b
, t00
, t10
, t01
, t11
);
2927 sample_2d_array_nearest_mipmap_nearest(struct gl_context
*ctx
,
2928 const struct gl_sampler_object
*samp
,
2929 const struct gl_texture_object
*tObj
,
2930 GLuint n
, const GLfloat texcoord
[][4],
2931 const GLfloat lambda
[], GLfloat rgba
[][4])
2934 for (i
= 0; i
< n
; i
++) {
2935 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2936 sample_2d_array_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
],
2943 sample_2d_array_linear_mipmap_nearest(struct gl_context
*ctx
,
2944 const struct gl_sampler_object
*samp
,
2945 const struct gl_texture_object
*tObj
,
2946 GLuint n
, const GLfloat texcoord
[][4],
2947 const GLfloat lambda
[], GLfloat rgba
[][4])
2950 assert(lambda
!= NULL
);
2951 for (i
= 0; i
< n
; i
++) {
2952 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
2953 sample_2d_array_linear(ctx
, samp
, tObj
->Image
[0][level
],
2954 texcoord
[i
], rgba
[i
]);
2960 sample_2d_array_nearest_mipmap_linear(struct gl_context
*ctx
,
2961 const struct gl_sampler_object
*samp
,
2962 const struct gl_texture_object
*tObj
,
2963 GLuint n
, const GLfloat texcoord
[][4],
2964 const GLfloat lambda
[], GLfloat rgba
[][4])
2967 assert(lambda
!= NULL
);
2968 for (i
= 0; i
< n
; i
++) {
2969 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2970 if (level
>= tObj
->_MaxLevel
) {
2971 sample_2d_array_nearest(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
2972 texcoord
[i
], rgba
[i
]);
2975 GLfloat t0
[4], t1
[4]; /* texels */
2976 const GLfloat f
= FRAC(lambda
[i
]);
2977 sample_2d_array_nearest(ctx
, samp
, tObj
->Image
[0][level
],
2979 sample_2d_array_nearest(ctx
, samp
, tObj
->Image
[0][level
+1],
2981 lerp_rgba(rgba
[i
], f
, t0
, t1
);
2988 sample_2d_array_linear_mipmap_linear(struct gl_context
*ctx
,
2989 const struct gl_sampler_object
*samp
,
2990 const struct gl_texture_object
*tObj
,
2991 GLuint n
, const GLfloat texcoord
[][4],
2992 const GLfloat lambda
[], GLfloat rgba
[][4])
2995 assert(lambda
!= NULL
);
2996 for (i
= 0; i
< n
; i
++) {
2997 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
2998 if (level
>= tObj
->_MaxLevel
) {
2999 sample_2d_array_linear(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
3000 texcoord
[i
], rgba
[i
]);
3003 GLfloat t0
[4], t1
[4]; /* texels */
3004 const GLfloat f
= FRAC(lambda
[i
]);
3005 sample_2d_array_linear(ctx
, samp
, tObj
->Image
[0][level
],
3007 sample_2d_array_linear(ctx
, samp
, tObj
->Image
[0][level
+1],
3009 lerp_rgba(rgba
[i
], f
, t0
, t1
);
3015 /** Sample 2D Array texture, nearest filtering for both min/magnification */
3017 sample_nearest_2d_array(struct gl_context
*ctx
,
3018 const struct gl_sampler_object
*samp
,
3019 const struct gl_texture_object
*tObj
, GLuint n
,
3020 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3024 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
3026 for (i
= 0; i
< n
; i
++) {
3027 sample_2d_array_nearest(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
3033 /** Sample 2D Array texture, linear filtering for both min/magnification */
3035 sample_linear_2d_array(struct gl_context
*ctx
,
3036 const struct gl_sampler_object
*samp
,
3037 const struct gl_texture_object
*tObj
, GLuint n
,
3038 const GLfloat texcoords
[][4],
3039 const GLfloat lambda
[], GLfloat rgba
[][4])
3042 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
3044 for (i
= 0; i
< n
; i
++) {
3045 sample_2d_array_linear(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
3050 /** Sample 2D Array texture, using lambda to choose between min/magnification */
3052 sample_lambda_2d_array(struct gl_context
*ctx
,
3053 const struct gl_sampler_object
*samp
,
3054 const struct gl_texture_object
*tObj
, GLuint n
,
3055 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3058 GLuint minStart
, minEnd
; /* texels with minification */
3059 GLuint magStart
, magEnd
; /* texels with magnification */
3062 assert(lambda
!= NULL
);
3063 compute_min_mag_ranges(samp
, n
, lambda
,
3064 &minStart
, &minEnd
, &magStart
, &magEnd
);
3066 if (minStart
< minEnd
) {
3067 /* do the minified texels */
3068 GLuint m
= minEnd
- minStart
;
3069 switch (samp
->MinFilter
) {
3071 for (i
= minStart
; i
< minEnd
; i
++)
3072 sample_2d_array_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
3073 texcoords
[i
], rgba
[i
]);
3076 for (i
= minStart
; i
< minEnd
; i
++)
3077 sample_2d_array_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
3078 texcoords
[i
], rgba
[i
]);
3080 case GL_NEAREST_MIPMAP_NEAREST
:
3081 sample_2d_array_nearest_mipmap_nearest(ctx
, samp
, tObj
, m
,
3082 texcoords
+ minStart
,
3086 case GL_LINEAR_MIPMAP_NEAREST
:
3087 sample_2d_array_linear_mipmap_nearest(ctx
, samp
, tObj
, m
,
3088 texcoords
+ minStart
,
3092 case GL_NEAREST_MIPMAP_LINEAR
:
3093 sample_2d_array_nearest_mipmap_linear(ctx
, samp
, tObj
, m
,
3094 texcoords
+ minStart
,
3098 case GL_LINEAR_MIPMAP_LINEAR
:
3099 sample_2d_array_linear_mipmap_linear(ctx
, samp
, tObj
, m
,
3100 texcoords
+ minStart
,
3105 _mesa_problem(ctx
, "Bad min filter in sample_2d_array_texture");
3110 if (magStart
< magEnd
) {
3111 /* do the magnified texels */
3112 switch (samp
->MagFilter
) {
3114 for (i
= magStart
; i
< magEnd
; i
++)
3115 sample_2d_array_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
3116 texcoords
[i
], rgba
[i
]);
3119 for (i
= magStart
; i
< magEnd
; i
++)
3120 sample_2d_array_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
3121 texcoords
[i
], rgba
[i
]);
3124 _mesa_problem(ctx
, "Bad mag filter in sample_2d_array_texture");
3133 /**********************************************************************/
3134 /* 1D Texture Array Sampling Functions */
3135 /**********************************************************************/
3138 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
3141 sample_1d_array_nearest(struct gl_context
*ctx
,
3142 const struct gl_sampler_object
*samp
,
3143 const struct gl_texture_image
*img
,
3144 const GLfloat texcoord
[4],
3147 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
3148 const GLint width
= img
->Width2
; /* without border, power of two */
3149 const GLint height
= img
->Height
;
3154 i
= nearest_texel_location(samp
->WrapS
, img
, width
, texcoord
[0]);
3155 array
= tex_array_slice(texcoord
[1], height
);
3157 if (i
< 0 || i
>= (GLint
) img
->Width
||
3158 array
< 0 || array
>= (GLint
) img
->Height
) {
3159 /* Need this test for GL_CLAMP_TO_BORDER mode */
3160 get_border_color(samp
, img
, rgba
);
3163 swImg
->FetchTexel(swImg
, i
, array
, 0, rgba
);
3169 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
3172 sample_1d_array_linear(struct gl_context
*ctx
,
3173 const struct gl_sampler_object
*samp
,
3174 const struct gl_texture_image
*img
,
3175 const GLfloat texcoord
[4],
3178 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
3179 const GLint width
= img
->Width2
;
3180 const GLint height
= img
->Height
;
3183 GLbitfield useBorderColor
= 0x0;
3185 GLfloat t0
[4], t1
[4];
3187 linear_texel_locations(samp
->WrapS
, img
, width
, texcoord
[0], &i0
, &i1
, &a
);
3188 array
= tex_array_slice(texcoord
[1], height
);
3195 /* check if sampling texture border color */
3196 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
3197 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
3200 if (array
< 0 || array
>= height
) useBorderColor
|= K0BIT
;
3203 if (useBorderColor
& (I0BIT
| K0BIT
)) {
3204 get_border_color(samp
, img
, t0
);
3207 swImg
->FetchTexel(swImg
, i0
, array
, 0, t0
);
3209 if (useBorderColor
& (I1BIT
| K0BIT
)) {
3210 get_border_color(samp
, img
, t1
);
3213 swImg
->FetchTexel(swImg
, i1
, array
, 0, t1
);
3216 /* bilinear interpolation of samples */
3217 lerp_rgba(rgba
, a
, t0
, t1
);
3222 sample_1d_array_nearest_mipmap_nearest(struct gl_context
*ctx
,
3223 const struct gl_sampler_object
*samp
,
3224 const struct gl_texture_object
*tObj
,
3225 GLuint n
, const GLfloat texcoord
[][4],
3226 const GLfloat lambda
[], GLfloat rgba
[][4])
3229 for (i
= 0; i
< n
; i
++) {
3230 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
3231 sample_1d_array_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
],
3238 sample_1d_array_linear_mipmap_nearest(struct gl_context
*ctx
,
3239 const struct gl_sampler_object
*samp
,
3240 const struct gl_texture_object
*tObj
,
3241 GLuint n
, const GLfloat texcoord
[][4],
3242 const GLfloat lambda
[], GLfloat rgba
[][4])
3245 assert(lambda
!= NULL
);
3246 for (i
= 0; i
< n
; i
++) {
3247 GLint level
= nearest_mipmap_level(tObj
, lambda
[i
]);
3248 sample_1d_array_linear(ctx
, samp
, tObj
->Image
[0][level
],
3249 texcoord
[i
], rgba
[i
]);
3255 sample_1d_array_nearest_mipmap_linear(struct gl_context
*ctx
,
3256 const struct gl_sampler_object
*samp
,
3257 const struct gl_texture_object
*tObj
,
3258 GLuint n
, const GLfloat texcoord
[][4],
3259 const GLfloat lambda
[], GLfloat rgba
[][4])
3262 assert(lambda
!= NULL
);
3263 for (i
= 0; i
< n
; i
++) {
3264 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
3265 if (level
>= tObj
->_MaxLevel
) {
3266 sample_1d_array_nearest(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
3267 texcoord
[i
], rgba
[i
]);
3270 GLfloat t0
[4], t1
[4]; /* texels */
3271 const GLfloat f
= FRAC(lambda
[i
]);
3272 sample_1d_array_nearest(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
3273 sample_1d_array_nearest(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
3274 lerp_rgba(rgba
[i
], f
, t0
, t1
);
3281 sample_1d_array_linear_mipmap_linear(struct gl_context
*ctx
,
3282 const struct gl_sampler_object
*samp
,
3283 const struct gl_texture_object
*tObj
,
3284 GLuint n
, const GLfloat texcoord
[][4],
3285 const GLfloat lambda
[], GLfloat rgba
[][4])
3288 assert(lambda
!= NULL
);
3289 for (i
= 0; i
< n
; i
++) {
3290 GLint level
= linear_mipmap_level(tObj
, lambda
[i
]);
3291 if (level
>= tObj
->_MaxLevel
) {
3292 sample_1d_array_linear(ctx
, samp
, tObj
->Image
[0][tObj
->_MaxLevel
],
3293 texcoord
[i
], rgba
[i
]);
3296 GLfloat t0
[4], t1
[4]; /* texels */
3297 const GLfloat f
= FRAC(lambda
[i
]);
3298 sample_1d_array_linear(ctx
, samp
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
3299 sample_1d_array_linear(ctx
, samp
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
3300 lerp_rgba(rgba
[i
], f
, t0
, t1
);
3306 /** Sample 1D Array texture, nearest filtering for both min/magnification */
3308 sample_nearest_1d_array(struct gl_context
*ctx
,
3309 const struct gl_sampler_object
*samp
,
3310 const struct gl_texture_object
*tObj
, GLuint n
,
3311 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3315 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
3317 for (i
= 0; i
< n
; i
++) {
3318 sample_1d_array_nearest(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
3323 /** Sample 1D Array texture, linear filtering for both min/magnification */
3325 sample_linear_1d_array(struct gl_context
*ctx
,
3326 const struct gl_sampler_object
*samp
,
3327 const struct gl_texture_object
*tObj
, GLuint n
,
3328 const GLfloat texcoords
[][4],
3329 const GLfloat lambda
[], GLfloat rgba
[][4])
3332 const struct gl_texture_image
*image
= _mesa_base_tex_image(tObj
);
3334 for (i
= 0; i
< n
; i
++) {
3335 sample_1d_array_linear(ctx
, samp
, image
, texcoords
[i
], rgba
[i
]);
3340 /** Sample 1D Array texture, using lambda to choose between min/magnification */
3342 sample_lambda_1d_array(struct gl_context
*ctx
,
3343 const struct gl_sampler_object
*samp
,
3344 const struct gl_texture_object
*tObj
, GLuint n
,
3345 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3348 GLuint minStart
, minEnd
; /* texels with minification */
3349 GLuint magStart
, magEnd
; /* texels with magnification */
3352 assert(lambda
!= NULL
);
3353 compute_min_mag_ranges(samp
, n
, lambda
,
3354 &minStart
, &minEnd
, &magStart
, &magEnd
);
3356 if (minStart
< minEnd
) {
3357 /* do the minified texels */
3358 GLuint m
= minEnd
- minStart
;
3359 switch (samp
->MinFilter
) {
3361 for (i
= minStart
; i
< minEnd
; i
++)
3362 sample_1d_array_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
3363 texcoords
[i
], rgba
[i
]);
3366 for (i
= minStart
; i
< minEnd
; i
++)
3367 sample_1d_array_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
3368 texcoords
[i
], rgba
[i
]);
3370 case GL_NEAREST_MIPMAP_NEAREST
:
3371 sample_1d_array_nearest_mipmap_nearest(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
3372 lambda
+ minStart
, rgba
+ minStart
);
3374 case GL_LINEAR_MIPMAP_NEAREST
:
3375 sample_1d_array_linear_mipmap_nearest(ctx
, samp
, tObj
, m
,
3376 texcoords
+ minStart
,
3380 case GL_NEAREST_MIPMAP_LINEAR
:
3381 sample_1d_array_nearest_mipmap_linear(ctx
, samp
, tObj
, m
, texcoords
+ minStart
,
3382 lambda
+ minStart
, rgba
+ minStart
);
3384 case GL_LINEAR_MIPMAP_LINEAR
:
3385 sample_1d_array_linear_mipmap_linear(ctx
, samp
, tObj
, m
,
3386 texcoords
+ minStart
,
3391 _mesa_problem(ctx
, "Bad min filter in sample_1d_array_texture");
3396 if (magStart
< magEnd
) {
3397 /* do the magnified texels */
3398 switch (samp
->MagFilter
) {
3400 for (i
= magStart
; i
< magEnd
; i
++)
3401 sample_1d_array_nearest(ctx
, samp
, _mesa_base_tex_image(tObj
),
3402 texcoords
[i
], rgba
[i
]);
3405 for (i
= magStart
; i
< magEnd
; i
++)
3406 sample_1d_array_linear(ctx
, samp
, _mesa_base_tex_image(tObj
),
3407 texcoords
[i
], rgba
[i
]);
3410 _mesa_problem(ctx
, "Bad mag filter in sample_1d_array_texture");
3418 * Compare texcoord against depth sample. Return 1.0 or 0.0 value.
3421 shadow_compare(GLenum function
, GLfloat coord
, GLfloat depthSample
)
3425 return (coord
<= depthSample
) ? 1.0F
: 0.0F
;
3427 return (coord
>= depthSample
) ? 1.0F
: 0.0F
;
3429 return (coord
< depthSample
) ? 1.0F
: 0.0F
;
3431 return (coord
> depthSample
) ? 1.0F
: 0.0F
;
3433 return (coord
== depthSample
) ? 1.0F
: 0.0F
;
3435 return (coord
!= depthSample
) ? 1.0F
: 0.0F
;
3443 _mesa_problem(NULL
, "Bad compare func in shadow_compare");
3450 * Compare texcoord against four depth samples.
3453 shadow_compare4(GLenum function
, GLfloat coord
,
3454 GLfloat depth00
, GLfloat depth01
,
3455 GLfloat depth10
, GLfloat depth11
,
3456 GLfloat wi
, GLfloat wj
)
3458 const GLfloat d
= 0.25F
;
3459 GLfloat luminance
= 1.0F
;
3463 if (coord
> depth00
) luminance
-= d
;
3464 if (coord
> depth01
) luminance
-= d
;
3465 if (coord
> depth10
) luminance
-= d
;
3466 if (coord
> depth11
) luminance
-= d
;
3469 if (coord
< depth00
) luminance
-= d
;
3470 if (coord
< depth01
) luminance
-= d
;
3471 if (coord
< depth10
) luminance
-= d
;
3472 if (coord
< depth11
) luminance
-= d
;
3475 if (coord
>= depth00
) luminance
-= d
;
3476 if (coord
>= depth01
) luminance
-= d
;
3477 if (coord
>= depth10
) luminance
-= d
;
3478 if (coord
>= depth11
) luminance
-= d
;
3481 if (coord
<= depth00
) luminance
-= d
;
3482 if (coord
<= depth01
) luminance
-= d
;
3483 if (coord
<= depth10
) luminance
-= d
;
3484 if (coord
<= depth11
) luminance
-= d
;
3487 if (coord
!= depth00
) luminance
-= d
;
3488 if (coord
!= depth01
) luminance
-= d
;
3489 if (coord
!= depth10
) luminance
-= d
;
3490 if (coord
!= depth11
) luminance
-= d
;
3493 if (coord
== depth00
) luminance
-= d
;
3494 if (coord
== depth01
) luminance
-= d
;
3495 if (coord
== depth10
) luminance
-= d
;
3496 if (coord
== depth11
) luminance
-= d
;
3503 /* ordinary bilinear filtering */
3504 return lerp_2d(wi
, wj
, depth00
, depth10
, depth01
, depth11
);
3506 _mesa_problem(NULL
, "Bad compare func in sample_compare4");
3513 * Choose the mipmap level to use when sampling from a depth texture.
3516 choose_depth_texture_level(const struct gl_sampler_object
*samp
,
3517 const struct gl_texture_object
*tObj
, GLfloat lambda
)
3521 if (samp
->MinFilter
== GL_NEAREST
|| samp
->MinFilter
== GL_LINEAR
) {
3522 /* no mipmapping - use base level */
3523 level
= tObj
->BaseLevel
;
3526 /* choose mipmap level */
3527 lambda
= CLAMP(lambda
, samp
->MinLod
, samp
->MaxLod
);
3528 level
= (GLint
) lambda
;
3529 level
= CLAMP(level
, tObj
->BaseLevel
, tObj
->_MaxLevel
);
3537 * Sample a shadow/depth texture. This function is incomplete. It doesn't
3538 * check for minification vs. magnification, etc.
3541 sample_depth_texture( struct gl_context
*ctx
,
3542 const struct gl_sampler_object
*samp
,
3543 const struct gl_texture_object
*tObj
, GLuint n
,
3544 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3545 GLfloat texel
[][4] )
3547 const GLint level
= choose_depth_texture_level(samp
, tObj
, lambda
[0]);
3548 const struct gl_texture_image
*img
= tObj
->Image
[0][level
];
3549 const struct swrast_texture_image
*swImg
= swrast_texture_image_const(img
);
3550 const GLint width
= img
->Width
;
3551 const GLint height
= img
->Height
;
3552 const GLint depth
= img
->Depth
;
3553 const GLuint compare_coord
= (tObj
->Target
== GL_TEXTURE_2D_ARRAY_EXT
)
3558 assert(img
->_BaseFormat
== GL_DEPTH_COMPONENT
||
3559 img
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
);
3561 assert(tObj
->Target
== GL_TEXTURE_1D
||
3562 tObj
->Target
== GL_TEXTURE_2D
||
3563 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
||
3564 tObj
->Target
== GL_TEXTURE_1D_ARRAY_EXT
||
3565 tObj
->Target
== GL_TEXTURE_2D_ARRAY_EXT
||
3566 tObj
->Target
== GL_TEXTURE_CUBE_MAP
);
3568 /* XXXX if samp->MinFilter != samp->MagFilter, we're ignoring lambda */
3570 function
= (samp
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) ?
3571 samp
->CompareFunc
: GL_NONE
;
3573 if (samp
->MagFilter
== GL_NEAREST
) {
3575 for (i
= 0; i
< n
; i
++) {
3576 GLfloat depthSample
, depthRef
;
3577 GLint col
, row
, slice
;
3579 nearest_texcoord(samp
, tObj
, level
, texcoords
[i
], &col
, &row
, &slice
);
3581 if (col
>= 0 && row
>= 0 && col
< width
&& row
< height
&&
3582 slice
>= 0 && slice
< depth
) {
3583 swImg
->FetchTexel(swImg
, col
, row
, slice
, &depthSample
);
3586 depthSample
= samp
->BorderColor
.f
[0];
3589 depthRef
= CLAMP(texcoords
[i
][compare_coord
], 0.0F
, 1.0F
);
3591 result
= shadow_compare(function
, depthRef
, depthSample
);
3593 apply_depth_mode(tObj
->DepthMode
, result
, texel
[i
]);
3598 assert(samp
->MagFilter
== GL_LINEAR
);
3599 for (i
= 0; i
< n
; i
++) {
3600 GLfloat depth00
, depth01
, depth10
, depth11
, depthRef
;
3601 GLint i0
, i1
, j0
, j1
;
3604 GLuint useBorderTexel
;
3606 linear_texcoord(samp
, tObj
, level
, texcoords
[i
], &i0
, &i1
, &j0
, &j1
, &slice
,
3613 if (tObj
->Target
!= GL_TEXTURE_1D_ARRAY_EXT
) {
3619 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
3620 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
3621 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
3622 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
3625 if (slice
< 0 || slice
>= (GLint
) depth
) {
3626 depth00
= samp
->BorderColor
.f
[0];
3627 depth01
= samp
->BorderColor
.f
[0];
3628 depth10
= samp
->BorderColor
.f
[0];
3629 depth11
= samp
->BorderColor
.f
[0];
3632 /* get four depth samples from the texture */
3633 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
3634 depth00
= samp
->BorderColor
.f
[0];
3637 swImg
->FetchTexel(swImg
, i0
, j0
, slice
, &depth00
);
3639 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
3640 depth10
= samp
->BorderColor
.f
[0];
3643 swImg
->FetchTexel(swImg
, i1
, j0
, slice
, &depth10
);
3646 if (tObj
->Target
!= GL_TEXTURE_1D_ARRAY_EXT
) {
3647 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
3648 depth01
= samp
->BorderColor
.f
[0];
3651 swImg
->FetchTexel(swImg
, i0
, j1
, slice
, &depth01
);
3653 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
3654 depth11
= samp
->BorderColor
.f
[0];
3657 swImg
->FetchTexel(swImg
, i1
, j1
, slice
, &depth11
);
3666 depthRef
= CLAMP(texcoords
[i
][compare_coord
], 0.0F
, 1.0F
);
3668 result
= shadow_compare4(function
, depthRef
,
3669 depth00
, depth01
, depth10
, depth11
,
3672 apply_depth_mode(tObj
->DepthMode
, result
, texel
[i
]);
3679 * We use this function when a texture object is in an "incomplete" state.
3680 * When a fragment program attempts to sample an incomplete texture we
3681 * return black (see issue 23 in GL_ARB_fragment_program spec).
3682 * Note: fragment programs don't observe the texture enable/disable flags.
3685 null_sample_func( struct gl_context
*ctx
,
3686 const struct gl_sampler_object
*samp
,
3687 const struct gl_texture_object
*tObj
, GLuint n
,
3688 const GLfloat texcoords
[][4], const GLfloat lambda
[],
3697 for (i
= 0; i
< n
; i
++) {
3701 rgba
[i
][ACOMP
] = 1.0;
3707 * Choose the texture sampling function for the given texture object.
3710 _swrast_choose_texture_sample_func( struct gl_context
*ctx
,
3711 const struct gl_texture_object
*t
,
3712 const struct gl_sampler_object
*sampler
)
3714 if (!t
|| !_mesa_is_texture_complete(t
, sampler
)) {
3715 return &null_sample_func
;
3718 const GLboolean needLambda
=
3719 (GLboolean
) (sampler
->MinFilter
!= sampler
->MagFilter
);
3721 switch (t
->Target
) {
3723 if (is_depth_texture(t
)) {
3724 return &sample_depth_texture
;
3726 else if (needLambda
) {
3727 return &sample_lambda_1d
;
3729 else if (sampler
->MinFilter
== GL_LINEAR
) {
3730 return &sample_linear_1d
;
3733 assert(sampler
->MinFilter
== GL_NEAREST
);
3734 return &sample_nearest_1d
;
3737 if (is_depth_texture(t
)) {
3738 return &sample_depth_texture
;
3740 else if (needLambda
) {
3741 /* Anisotropic filtering extension. Activated only if mipmaps are used */
3742 if (sampler
->MaxAnisotropy
> 1.0 &&
3743 sampler
->MinFilter
== GL_LINEAR_MIPMAP_LINEAR
) {
3744 return &sample_lambda_2d_aniso
;
3746 return &sample_lambda_2d
;
3748 else if (sampler
->MinFilter
== GL_LINEAR
) {
3749 return &sample_linear_2d
;
3752 /* check for a few optimized cases */
3753 const struct gl_texture_image
*img
= _mesa_base_tex_image(t
);
3754 const struct swrast_texture_image
*swImg
=
3755 swrast_texture_image_const(img
);
3756 texture_sample_func func
;
3758 assert(sampler
->MinFilter
== GL_NEAREST
);
3759 func
= &sample_nearest_2d
;
3760 if (sampler
->WrapS
== GL_REPEAT
&&
3761 sampler
->WrapT
== GL_REPEAT
&&
3762 swImg
->_IsPowerOfTwo
&&
3764 if (img
->TexFormat
== MESA_FORMAT_BGR_UNORM8
)
3765 func
= &opt_sample_rgb_2d
;
3766 else if (img
->TexFormat
== MESA_FORMAT_A8B8G8R8_UNORM
)
3767 func
= &opt_sample_rgba_2d
;
3774 return &sample_lambda_3d
;
3776 else if (sampler
->MinFilter
== GL_LINEAR
) {
3777 return &sample_linear_3d
;
3780 assert(sampler
->MinFilter
== GL_NEAREST
);
3781 return &sample_nearest_3d
;
3783 case GL_TEXTURE_CUBE_MAP
:
3785 return &sample_lambda_cube
;
3787 else if (sampler
->MinFilter
== GL_LINEAR
) {
3788 return &sample_linear_cube
;
3791 assert(sampler
->MinFilter
== GL_NEAREST
);
3792 return &sample_nearest_cube
;
3794 case GL_TEXTURE_RECTANGLE_NV
:
3795 if (is_depth_texture(t
)) {
3796 return &sample_depth_texture
;
3798 else if (needLambda
) {
3799 return &sample_lambda_rect
;
3801 else if (sampler
->MinFilter
== GL_LINEAR
) {
3802 return &sample_linear_rect
;
3805 assert(sampler
->MinFilter
== GL_NEAREST
);
3806 return &sample_nearest_rect
;
3808 case GL_TEXTURE_1D_ARRAY_EXT
:
3809 if (is_depth_texture(t
)) {
3810 return &sample_depth_texture
;
3812 else if (needLambda
) {
3813 return &sample_lambda_1d_array
;
3815 else if (sampler
->MinFilter
== GL_LINEAR
) {
3816 return &sample_linear_1d_array
;
3819 assert(sampler
->MinFilter
== GL_NEAREST
);
3820 return &sample_nearest_1d_array
;
3822 case GL_TEXTURE_2D_ARRAY_EXT
:
3823 if (is_depth_texture(t
)) {
3824 return &sample_depth_texture
;
3826 else if (needLambda
) {
3827 return &sample_lambda_2d_array
;
3829 else if (sampler
->MinFilter
== GL_LINEAR
) {
3830 return &sample_linear_2d_array
;
3833 assert(sampler
->MinFilter
== GL_NEAREST
);
3834 return &sample_nearest_2d_array
;
3838 "invalid target in _swrast_choose_texture_sample_func");
3839 return &null_sample_func
;