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

📄 s_texture.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Mesa 3-D graphics library
 * Version:  6.4
 *
 * Copyright (C) 1999-2005  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 "macros.h"
#include "imports.h"
#include "pixel.h"
#include "texformat.h"
#include "teximage.h"

#include "s_context.h"
#include "s_texture.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 GLfloat
lerp_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 GLint
ilerp_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 GLfloat
lerp_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 GLint
ilerp_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);
}



/**
 * Compute the remainder of a divided by b, but be careful with
 * negative values so that GL_REPEAT mode works right.
 */
static INLINE GLint
repeat_remainder(GLint a, GLint b)
{
   if (a >= 0)
      return a % b;
   else
      return (a + 1) % b + b - 1;
}


/**
 * 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)	\
{									\
   if (wrapMode == GL_REPEAT) {						\
      U = S * SIZE - 0.5F;						\
      if (tObj->_IsPowerOfTwo) {					\
         I0 = IFLOOR(U) & (SIZE - 1);					\
         I1 = (I0 + 1) & (SIZE - 1);					\
      }									\
      else {								\
         I0 = repeat_remainder(IFLOOR(U), SIZE);			\
         I1 = repeat_remainder(I0 + 1, SIZE);				\
      }									\
   }									\
   else if (wrapMode == 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;							\
   }									\
   else if (wrapMode == 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;							\
   }									\
   else if (wrapMode == 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;							\
   }									\
   else if (wrapMode == GL_MIRROR_CLAMP_EXT) {				\
      U = (GLfloat) fabs(S);						\
      if (U >= 1.0F)							\
         U = (GLfloat) SIZE;						\
      else								\
         U *= SIZE;							\
      U -= 0.5F;							\
      I0 = IFLOOR(U);							\
      I1 = I0 + 1;							\
   }									\
   else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) {			\
      U = (GLfloat) fabs(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;							\
   }									\
   else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) {		\
      const GLfloat min = -1.0F / (2.0F * SIZE);			\
      const GLfloat max = 1.0F - min;					\
      U = (GLfloat) fabs(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;							\
   }									\
   else {								\
      ASSERT(wrapMode == 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;							\
   }									\
}


/**
 * Used to compute texel location for nearest sampling.
 */
#define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I)		\
{									\
   if (wrapMode == GL_REPEAT) {						\
      /* s limited to [0,1) */						\
      /* i limited to [0,size-1] */					\
      I = IFLOOR(S * SIZE);						\
      if (tObj->_IsPowerOfTwo)						\
         I &= (SIZE - 1);						\
      else								\
         I = repeat_remainder(I, SIZE);					\
   }									\
   else if (wrapMode == 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);						\
   }									\
   else if (wrapMode == 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);						\
   }									\
   else if (wrapMode == 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);						\
   }									\
   else if (wrapMode == GL_MIRROR_CLAMP_EXT) {				\
      /* s limited to [0,1] */						\
      /* i limited to [0,size-1] */					\
      const GLfloat u = (GLfloat) fabs(S);				\
      if (u <= 0.0F)							\
         I = 0;								\
      else if (u >= 1.0F)						\
         I = SIZE - 1;							\
      else								\
         I = IFLOOR(u * SIZE);						\
   }									\
   else if (wrapMode == 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 = (GLfloat) fabs(S);				\
      if (u < min)							\
         I = 0;								\
      else if (u > max)							\
         I = SIZE - 1;							\
      else								\
         I = IFLOOR(u * SIZE);						\
   }									\
   else if (wrapMode == 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 = (GLfloat) fabs(S);				\
      if (u < min)							\
         I = -1;							\
      else if (u > max)							\
         I = SIZE;							\
      else								\
         I = IFLOOR(u * SIZE);						\
   }									\
   else {								\
      ASSERT(wrapMode == 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);						\
   }									\
}


/* 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);						\
}


/*
 * Compute linear mipmap levels for given lambda.
 */
#define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level)	\
{								\
   if (lambda < 0.0F)						\
      level = tObj->BaseLevel;					\
   else if (lambda > tObj->_MaxLambda)				\
      level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda);	\
   else								\
      level = (GLint) (tObj->BaseLevel + lambda);		\
}


⌨️ 快捷键说明

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