📄 s_texfilter.c
字号:
{ \ /* s limited to [0,1] */ \ /* i limited to [0,size-1] */ \ const GLfloat u = FABSF(S); \ if (u <= 0.0F) \ I = 0; \ else if (u >= 1.0F) \ I = SIZE - 1; \ else \ I = IFLOOR(u * SIZE); \ } \ break; \ case GL_MIRROR_CLAMP_TO_EDGE_EXT: \ { \ /* s limited to [min,max] */ \ /* i limited to [0, size-1] */ \ const GLfloat min = 1.0F / (2.0F * SIZE); \ const GLfloat max = 1.0F - min; \ const GLfloat u = FABSF(S); \ if (u < min) \ I = 0; \ else if (u > max) \ I = SIZE - 1; \ else \ I = IFLOOR(u * SIZE); \ } \ break; \ case GL_MIRROR_CLAMP_TO_BORDER_EXT: \ { \ /* s limited to [min,max] */ \ /* i limited to [0, size-1] */ \ const GLfloat min = -1.0F / (2.0F * SIZE); \ const GLfloat max = 1.0F - min; \ const GLfloat u = FABSF(S); \ if (u < min) \ I = -1; \ else if (u > max) \ I = SIZE; \ else \ I = IFLOOR(u * SIZE); \ } \ break; \ case GL_CLAMP: \ /* s limited to [0,1] */ \ /* i limited to [0,size-1] */ \ if (S <= 0.0F) \ I = 0; \ else if (S >= 1.0F) \ I = SIZE - 1; \ else \ I = IFLOOR(S * SIZE); \ break; \ default: \ _mesa_problem(ctx, "Bad wrap mode"); \ return; \ } \}/* Power of two image sizes only */#define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \{ \ U = S * SIZE - 0.5F; \ I0 = IFLOOR(U) & (SIZE - 1); \ I1 = (I0 + 1) & (SIZE - 1); \}/** * For linear interpolation between mipmap levels N and N+1, this function * computes N. */static INLINE GLintlinear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda){ if (lambda < 0.0F) return tObj->BaseLevel; else if (lambda > tObj->_MaxLambda) return (GLint) (tObj->BaseLevel + tObj->_MaxLambda); else return (GLint) (tObj->BaseLevel + lambda);}/** * Compute the nearest mipmap level to take texels from. */static INLINE GLintnearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda){ GLfloat l; GLint level; if (lambda <= 0.5F) l = 0.0F; else if (lambda > tObj->_MaxLambda + 0.4999F) l = tObj->_MaxLambda + 0.4999F; else l = lambda; level = (GLint) (tObj->BaseLevel + l + 0.5F); if (level > tObj->_MaxLevel) level = tObj->_MaxLevel; return level;}/* * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes * see 1-pixel bands of improperly weighted linear-filtered textures. * The tests/texwrap.c demo is a good test. * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0. * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x). */#define FRAC(f) ((f) - IFLOOR(f))/* * Bitflags for texture border color sampling. */#define I0BIT 1#define I1BIT 2#define J0BIT 4#define J1BIT 8#define K0BIT 16#define K1BIT 32/* * The lambda[] array values are always monotonic. Either the whole span * will be minified, magnified, or split between the two. This function * determines the subranges in [0, n-1] that are to be minified or magnified. */static INLINE voidcompute_min_mag_ranges(const struct gl_texture_object *tObj, GLuint n, const GLfloat lambda[], GLuint *minStart, GLuint *minEnd, GLuint *magStart, GLuint *magEnd){ GLfloat minMagThresh; /* we shouldn't be here if minfilter == magfilter */ ASSERT(tObj->MinFilter != tObj->MagFilter); /* This bit comes from the OpenGL spec: */ if (tObj->MagFilter == GL_LINEAR && (tObj->MinFilter == GL_NEAREST_MIPMAP_NEAREST || tObj->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) { minMagThresh = 0.5F; } else { minMagThresh = 0.0F; }#if 0 /* DEBUG CODE: Verify that lambda[] is monotonic. * We can't really use this because the inaccuracy in the LOG2 function * causes this test to fail, yet the resulting texturing is correct. */ if (n > 1) { GLuint i; printf("lambda delta = %g\n", lambda[0] - lambda[n-1]); if (lambda[0] >= lambda[n-1]) { /* decreasing */ for (i = 0; i < n - 1; i++) { ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10)); } } else { /* increasing */ for (i = 0; i < n - 1; i++) { ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10)); } } }#endif /* DEBUG */ if (lambda[0] <= minMagThresh && (n <= 1 || lambda[n-1] <= minMagThresh)) { /* magnification for whole span */ *magStart = 0; *magEnd = n; *minStart = *minEnd = 0; } else if (lambda[0] > minMagThresh && (n <=1 || lambda[n-1] > minMagThresh)) { /* minification for whole span */ *minStart = 0; *minEnd = n; *magStart = *magEnd = 0; } else { /* a mix of minification and magnification */ GLuint i; if (lambda[0] > minMagThresh) { /* start with minification */ for (i = 1; i < n; i++) { if (lambda[i] <= minMagThresh) break; } *minStart = 0; *minEnd = i; *magStart = i; *magEnd = n; } else { /* start with magnification */ for (i = 1; i < n; i++) { if (lambda[i] > minMagThresh) break; } *magStart = 0; *magEnd = i; *minStart = i; *minEnd = n; } }#if 0 /* Verify the min/mag Start/End values * We don't use this either (see above) */ { GLint i; for (i = 0; i < n; i++) { if (lambda[i] > minMagThresh) { /* minification */ ASSERT(i >= *minStart); ASSERT(i < *minEnd); } else { /* magnification */ ASSERT(i >= *magStart); ASSERT(i < *magEnd); } } }#endif}/**********************************************************************//* 1-D Texture Sampling Functions *//**********************************************************************//* * Return the texture sample for coordinate (s) using GL_NEAREST filter. */static voidsample_1d_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, const GLfloat texcoord[4], GLchan rgba[4]){ const GLint width = img->Width2; /* without border, power of two */ GLint i; COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i); /* skip over the border, if any */ i += img->Border; if (i < 0 || i >= (GLint) img->Width) { /* Need this test for GL_CLAMP_TO_BORDER mode */ COPY_CHAN4(rgba, tObj->_BorderChan); } else { img->FetchTexelc(img, i, 0, 0, rgba); }}/* * Return the texture sample for coordinate (s) using GL_LINEAR filter. */static voidsample_1d_linear(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, const GLfloat texcoord[4], GLchan rgba[4]){ const GLint width = img->Width2; GLint i0, i1; GLfloat u; GLbitfield useBorderColor = 0x0; GLfloat a; GLchan t0[4], t1[4]; /* texels */ COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1); if (img->Border) { i0 += img->Border; i1 += img->Border; } else { if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; } /* fetch texel colors */ if (useBorderColor & I0BIT) { COPY_CHAN4(t0, tObj->_BorderChan); } else { img->FetchTexelc(img, i0, 0, 0, t0); } if (useBorderColor & I1BIT) { COPY_CHAN4(t1, tObj->_BorderChan); } else { img->FetchTexelc(img, i1, 0, 0, t1); } a = FRAC(u); lerp_rgba(rgba, a, t0, t1);}static voidsample_1d_nearest_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { GLint level = nearest_mipmap_level(tObj, lambda[i]); sample_1d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); }}static voidsample_1d_linear_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { GLint level = nearest_mipmap_level(tObj, lambda[i]); sample_1d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); }}static voidsample_1d_nearest_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { GLint level = linear_mipmap_level(tObj, lambda[i]); if (level >= tObj->_MaxLevel) { sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], texcoord[i], rgba[i]); } else { GLchan t0[4], t1[4]; const GLfloat f = FRAC(lambda[i]); sample_1d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); lerp_rgba(rgba[i], f, t0, t1); } }}static voidsample_1d_linear_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoord[][4], const GLfloat lambda[], GLchan rgba[][4]){ GLuint i; ASSERT(lambda != NULL); for (i = 0; i < n; i++) { GLint level = linear_mipmap_level(tObj, lambda[i]); if (level >= tObj->_MaxLevel) { sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], texcoord[i], rgba[i]); } else { GLchan t0[4], t1[4]; const GLfloat f = FRAC(lambda[i]); sample_1d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); lerp_rgba(rgba[i], f, t0, t1); } }}static voidsample_nearest_1d( GLcontext *ctx, const struct gl_texture_object *tObj, GLuint n, const GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4] ){ GLuint i; struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; (void) lambda; for (i=0;i<n;i++) { sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); }}static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -