⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s_texfilter.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Mesa 3-D graphics library * Version:  7.0.3 * * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "glheader.h"#include "context.h"#include "colormac.h"#include "imports.h"#include "texformat.h"#include "s_context.h"#include "s_texfilter.h"/** * Constants for integer linear interpolation. */#define ILERP_SCALE 65536.0F#define ILERP_SHIFT 16/** * Linear interpolation macros */#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )#define ILERP(IT, A, B)  ( (A) + (((IT) * ((B) - (A))) >> ILERP_SHIFT) )/** * Do 2D/biliner interpolation of float values. * v00, v10, v01 and v11 are typically four texture samples in a square/box. * a and b are the horizontal and vertical interpolants. * It's important that this function is inlined when compiled with * optimization!  If we find that's not true on some systems, convert * to a macro. */static INLINE GLfloatlerp_2d(GLfloat a, GLfloat b,        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11){   const GLfloat temp0 = LERP(a, v00, v10);   const GLfloat temp1 = LERP(a, v01, v11);   return LERP(b, temp0, temp1);}/** * Do 2D/biliner interpolation of integer values. * \sa lerp_2d */static INLINE GLintilerp_2d(GLint ia, GLint ib,         GLint v00, GLint v10, GLint v01, GLint v11){   /* fixed point interpolants in [0, ILERP_SCALE] */   const GLint temp0 = ILERP(ia, v00, v10);   const GLint temp1 = ILERP(ia, v01, v11);   return ILERP(ib, temp0, temp1);}/** * Do 3D/trilinear interpolation of float values. * \sa lerp_2d */static INLINE GLfloatlerp_3d(GLfloat a, GLfloat b, GLfloat c,        GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110,        GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111){   const GLfloat temp00 = LERP(a, v000, v100);   const GLfloat temp10 = LERP(a, v010, v110);   const GLfloat temp01 = LERP(a, v001, v101);   const GLfloat temp11 = LERP(a, v011, v111);   const GLfloat temp0 = LERP(b, temp00, temp10);   const GLfloat temp1 = LERP(b, temp01, temp11);   return LERP(c, temp0, temp1);}/** * Do 3D/trilinear interpolation of integer values. * \sa lerp_2d */static INLINE GLintilerp_3d(GLint ia, GLint ib, GLint ic,         GLint v000, GLint v100, GLint v010, GLint v110,         GLint v001, GLint v101, GLint v011, GLint v111){   /* fixed point interpolants in [0, ILERP_SCALE] */   const GLint temp00 = ILERP(ia, v000, v100);   const GLint temp10 = ILERP(ia, v010, v110);   const GLint temp01 = ILERP(ia, v001, v101);   const GLint temp11 = ILERP(ia, v011, v111);   const GLint temp0 = ILERP(ib, temp00, temp10);   const GLint temp1 = ILERP(ib, temp01, temp11);   return ILERP(ic, temp0, temp1);}/** * Do linear interpolation of colors. */static INLINE voidlerp_rgba(GLchan result[4], GLfloat t, const GLchan a[4], const GLchan b[4]){#if CHAN_TYPE == GL_FLOAT   result[0] = LERP(t, a[0], b[0]);   result[1] = LERP(t, a[1], b[1]);   result[2] = LERP(t, a[2], b[2]);   result[3] = LERP(t, a[3], b[3]);#elif CHAN_TYPE == GL_UNSIGNED_SHORT   result[0] = (GLchan) (LERP(t, a[0], b[0]) + 0.5);   result[1] = (GLchan) (LERP(t, a[1], b[1]) + 0.5);   result[2] = (GLchan) (LERP(t, a[2], b[2]) + 0.5);   result[3] = (GLchan) (LERP(t, a[3], b[3]) + 0.5);#else   /* fixed point interpolants in [0, ILERP_SCALE] */   const GLint it = IROUND_POS(t * ILERP_SCALE);   ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);   result[0] = ILERP(it, a[0], b[0]);   result[1] = ILERP(it, a[1], b[1]);   result[2] = ILERP(it, a[2], b[2]);   result[3] = ILERP(it, a[3], b[3]);#endif}/** * Do bilinear interpolation of colors. */static INLINE voidlerp_rgba_2d(GLchan result[4], GLfloat a, GLfloat b,             const GLchan t00[4], const GLchan t10[4],             const GLchan t01[4], const GLchan t11[4]){#if CHAN_TYPE == GL_FLOAT   result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);   result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);   result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);   result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);#elif CHAN_TYPE == GL_UNSIGNED_SHORT   result[0] = (GLchan) (lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]) + 0.5);   result[1] = (GLchan) (lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]) + 0.5);   result[2] = (GLchan) (lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]) + 0.5);   result[3] = (GLchan) (lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]) + 0.5);#else   const GLint ia = IROUND_POS(a * ILERP_SCALE);   const GLint ib = IROUND_POS(b * ILERP_SCALE);   ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);   result[0] = ilerp_2d(ia, ib, t00[0], t10[0], t01[0], t11[0]);   result[1] = ilerp_2d(ia, ib, t00[1], t10[1], t01[1], t11[1]);   result[2] = ilerp_2d(ia, ib, t00[2], t10[2], t01[2], t11[2]);   result[3] = ilerp_2d(ia, ib, t00[3], t10[3], t01[3], t11[3]);#endif}/** * Do trilinear interpolation of colors. */static INLINE voidlerp_rgba_3d(GLchan result[4], GLfloat a, GLfloat b, GLfloat c,             const GLchan t000[4], const GLchan t100[4],             const GLchan t010[4], const GLchan t110[4],             const GLchan t001[4], const GLchan t101[4],             const GLchan t011[4], const GLchan t111[4]){   GLuint k;   /* compiler should unroll these short loops */#if CHAN_TYPE == GL_FLOAT   for (k = 0; k < 4; k++) {      result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k],                                   t001[k], t101[k], t011[k], t111[k]);   }#elif CHAN_TYPE == GL_UNSIGNED_SHORT   for (k = 0; k < 4; k++) {      result[k] = (GLchan)(lerp_3d(a, b, c,                                   t000[k], t100[k], t010[k], t110[k],                                   t001[k], t101[k], t011[k], t111[k]) + 0.5F);   }#else   GLint ia = IROUND_POS(a * ILERP_SCALE);   GLint ib = IROUND_POS(b * ILERP_SCALE);   GLint ic = IROUND_POS(c * ILERP_SCALE);   for (k = 0; k < 4; k++) {      result[k] = ilerp_3d(ia, ib, ic, t000[k], t100[k], t010[k], t110[k],                                       t001[k], t101[k], t011[k], t111[k]);   }#endif}/** * If A is a signed integer, A % B doesn't give the right value for A < 0 * (in terms of texture repeat).  Just casting to unsigned fixes that. */#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))/** * Used to compute texel locations for linear sampling. * Input: *    wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER *    S = texcoord in [0,1] *    SIZE = width (or height or depth) of texture * Output: *    U = texcoord in [0, width] *    I0, I1 = two nearest texel indexes */#define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1)	\{									\   switch (wrapMode) {							\   case GL_REPEAT:							\      U = S * SIZE - 0.5F;						\      if (img->_IsPowerOfTwo) {						\         I0 = IFLOOR(U) & (SIZE - 1);					\         I1 = (I0 + 1) & (SIZE - 1);					\      }									\      else {								\         I0 = REMAINDER(IFLOOR(U), SIZE);				\         I1 = REMAINDER(I0 + 1, SIZE);					\      }									\      break;								\   case GL_CLAMP_TO_EDGE:						\      if (S <= 0.0F)							\         U = 0.0F;							\      else if (S >= 1.0F)						\         U = (GLfloat) SIZE;						\      else								\         U = S * SIZE;							\      U -= 0.5F;							\      I0 = IFLOOR(U);							\      I1 = I0 + 1;							\      if (I0 < 0)							\         I0 = 0;							\      if (I1 >= (GLint) SIZE)						\         I1 = SIZE - 1;							\      break;								\   case GL_CLAMP_TO_BORDER:						\      {									\         const GLfloat min = -1.0F / (2.0F * SIZE);			\         const GLfloat max = 1.0F - min;				\         if (S <= min)							\            U = min * SIZE;						\         else if (S >= max)						\            U = max * SIZE;						\         else								\            U = S * SIZE;						\         U -= 0.5F;							\         I0 = IFLOOR(U);						\         I1 = I0 + 1;							\      }									\      break;								\   case GL_MIRRORED_REPEAT:						\      {									\         const GLint flr = IFLOOR(S);					\         if (flr & 1)							\            U = 1.0F - (S - (GLfloat) flr);	/* flr is odd */	\         else								\            U = S - (GLfloat) flr;		/* flr is even */	\         U = (U * SIZE) - 0.5F;						\         I0 = IFLOOR(U);						\         I1 = I0 + 1;							\         if (I0 < 0)							\            I0 = 0;							\         if (I1 >= (GLint) SIZE)					\            I1 = SIZE - 1;						\      }									\      break;								\   case GL_MIRROR_CLAMP_EXT:						\      U = FABSF(S);							\      if (U >= 1.0F)							\         U = (GLfloat) SIZE;						\      else								\         U *= SIZE;							\      U -= 0.5F;							\      I0 = IFLOOR(U);							\      I1 = I0 + 1;							\      break;								\   case GL_MIRROR_CLAMP_TO_EDGE_EXT:					\      U = FABSF(S);							\      if (U >= 1.0F)							\         U = (GLfloat) SIZE;						\      else								\         U *= SIZE;							\      U -= 0.5F;							\      I0 = IFLOOR(U);							\      I1 = I0 + 1;							\      if (I0 < 0)							\         I0 = 0;							\      if (I1 >= (GLint) SIZE)						\         I1 = SIZE - 1;							\      break;								\   case GL_MIRROR_CLAMP_TO_BORDER_EXT:					\      {									\         const GLfloat min = -1.0F / (2.0F * SIZE);			\         const GLfloat max = 1.0F - min;				\         U = FABSF(S);							\         if (U <= min)							\            U = min * SIZE;						\         else if (U >= max)						\            U = max * SIZE;						\         else								\            U *= SIZE;							\         U -= 0.5F;							\         I0 = IFLOOR(U);						\         I1 = I0 + 1;							\      }									\      break;								\   case GL_CLAMP:							\      if (S <= 0.0F)							\         U = 0.0F;							\      else if (S >= 1.0F)						\         U = (GLfloat) SIZE;						\      else								\         U = S * SIZE;							\      U -= 0.5F;							\      I0 = IFLOOR(U);							\      I1 = I0 + 1;							\      break;								\   default:								\      _mesa_problem(ctx, "Bad wrap mode");				\      return;								\   }									\}/** * Used to compute texel location for nearest sampling. */#define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I)		\{									\   switch (wrapMode) {							\   case GL_REPEAT:							\      /* s limited to [0,1) */						\      /* i limited to [0,size-1] */					\      I = IFLOOR(S * SIZE);						\      if (img->_IsPowerOfTwo)						\         I &= (SIZE - 1);						\      else								\         I = REMAINDER(I, SIZE);					\      break;								\   case GL_CLAMP_TO_EDGE:						\      {									\         /* 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;				\         if (S < min)							\            I = 0;							\         else if (S > max)						\            I = SIZE - 1;						\         else								\            I = IFLOOR(S * SIZE);					\      }									\      break;								\   case GL_CLAMP_TO_BORDER:						\      {									\         /* s limited to [min,max] */					\         /* i limited to [-1, size] */					\         const GLfloat min = -1.0F / (2.0F * SIZE);			\         const GLfloat max = 1.0F - min;				\         if (S <= min)							\            I = -1;							\         else if (S >= max)						\            I = SIZE;							\         else								\            I = IFLOOR(S * SIZE);					\      }									\      break;								\   case GL_MIRRORED_REPEAT:						\      {									\         const GLfloat min = 1.0F / (2.0F * SIZE);			\         const GLfloat max = 1.0F - min;				\         const GLint flr = IFLOOR(S);					\         GLfloat u;							\         if (flr & 1)							\            u = 1.0F - (S - (GLfloat) flr);	/* flr is odd */	\         else								\            u = S - (GLfloat) flr;		/* flr is even */	\         if (u < min)							\            I = 0;							\         else if (u > max)						\            I = SIZE - 1;						\         else								\            I = IFLOOR(u * SIZE);					\      }									\      break;								\   case GL_MIRROR_CLAMP_EXT:						\

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -