Lots of improvements in the 2D texture sampling code. Fewer function calls
authorBrian Paul <brian.paul@tungstengraphics.com>
Sun, 17 Feb 2002 01:58:59 +0000 (01:58 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sun, 17 Feb 2002 01:58:59 +0000 (01:58 +0000)
and no more switches inside loops.  To do: give the 1D/3D/cube routines the
same treatment.

src/mesa/swrast/s_texture.c

index 07e005b..1e881a3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_texture.c,v 1.52 2002/02/16 23:44:46 brianp Exp $ */
+/* $Id: s_texture.c,v 1.53 2002/02/17 01:58:59 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
 }
 
 
+#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)                                          \
-      lambda = 0.0F;                                           \
+      level = tObj->BaseLevel;                                 \
    else if (lambda > tObj->_MaxLambda)                         \
-      lambda = tObj->_MaxLambda;                               \
-   level = (GLint) (tObj->BaseLevel + lambda);                 \
+      level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda);    \
+   else                                                                \
+      level = (GLint) (tObj->BaseLevel + lambda);              \
 }
 
 
  */
 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level)      \
 {                                                              \
+   GLfloat l;                                                  \
    if (lambda <= 0.5F)                                         \
-      lambda = 0.0F;                                           \
+      l = 0.0F;                                                        \
    else if (lambda > tObj->_MaxLambda + 0.4999F)               \
-      lambda = tObj->_MaxLambda + 0.4999F;                     \
-   level = (GLint) (tObj->BaseLevel + lambda + 0.5F);          \
+      l = tObj->_MaxLambda + 0.4999F;                          \
+   else                                                                \
+      l = lambda;                                              \
+   level = (GLint) (tObj->BaseLevel + l + 0.5F);               \
    if (level > tObj->_MaxLevel)                                        \
       level = tObj->_MaxLevel;                                 \
 }
@@ -752,16 +764,98 @@ sample_2d_linear(GLcontext *ctx,
 }
 
 
+/*
+ * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
+ * and we're not using a paletted texture.
+ */
+static void
+sample_2d_linear_repeat(GLcontext *ctx,
+                        const struct gl_texture_object *tObj,
+                        const struct gl_texture_image *img,
+                        const GLfloat texcoord[4],
+                        GLchan rgba[])
+{
+   const GLint width = img->Width2;
+   const GLint height = img->Height2;
+   GLint i0, j0, i1, j1;
+   GLfloat u, v;
+
+   ASSERT(tObj->WrapS == GL_REPEAT);
+   ASSERT(tObj->WrapT == GL_REPEAT);
+   ASSERT(img->Format != GL_COLOR_INDEX);
+
+   COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[0], u, width,  i0, i1);
+   COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[1], v, height, j0, j1);
+
+   {
+      const GLfloat a = FRAC(u);
+      const GLfloat b = FRAC(v);
+
+#if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
+      const GLfloat w00 = (1.0F-a) * (1.0F-b);
+      const GLfloat w10 =       a  * (1.0F-b);
+      const GLfloat w01 = (1.0F-a) *       b ;
+      const GLfloat w11 =       a  *       b ;
+#else /* CHAN_BITS == 8 */
+      /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
+      const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
+      const GLint w10 = IROUND_POS(      a  * (1.0F-b) * WEIGHT_SCALE);
+      const GLint w01 = IROUND_POS((1.0F-a) *       b  * WEIGHT_SCALE);
+      const GLint w11 = IROUND_POS(      a  *       b  * WEIGHT_SCALE);
+#endif
+      GLchan t00[4];
+      GLchan t10[4];
+      GLchan t01[4];
+      GLchan t11[4];
+
+      (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
+      (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
+      (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
+      (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
+
+#if CHAN_TYPE == GL_FLOAT
+      rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0];
+      rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1];
+      rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2];
+      rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3];
+#elif CHAN_TYPE == GL_UNSIGNED_SHORT
+      rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] +
+                          w01 * t01[0] + w11 * t11[0] + 0.5);
+      rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] +
+                          w01 * t01[1] + w11 * t11[1] + 0.5);
+      rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] +
+                          w01 * t01[2] + w11 * t11[2] + 0.5);
+      rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] +
+                          w01 * t01[3] + w11 * t11[3] + 0.5);
+#else /* CHAN_BITS == 8 */
+      rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] +
+                           w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
+      rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] +
+                           w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
+      rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] +
+                           w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
+      rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] +
+                           w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
+#endif
+
+   }
+
+}
+
+
 
 static void
 sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
                                  const struct gl_texture_object *tObj,
-                                 const GLfloat texcoord[4], GLfloat lambda,
-                                 GLchan rgba[4])
+                                 GLuint n, GLfloat texcoord[][4],
+                                 const GLfloat lambda[], GLchan rgba[][4])
 {
-   GLint level;
-   COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
-   sample_2d_nearest(ctx, tObj, tObj->Image[level], texcoord, rgba);
+   GLuint i;
+   for (i = 0; i < n; i++) {
+      GLint level;
+      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
+      sample_2d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
+   }
 }
 
 
@@ -769,12 +863,15 @@ sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
 static void
 sample_2d_linear_mipmap_nearest(GLcontext *ctx,
                                 const struct gl_texture_object *tObj,
-                                const GLfloat texcoord[4], GLfloat lambda,
-                                GLchan rgba[4])
+                                GLuint n, GLfloat texcoord[][4],
+                                const GLfloat lambda[], GLchan rgba[][4])
 {
-   GLint level;
-   COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
-   sample_2d_linear(ctx, tObj, tObj->Image[level], texcoord, rgba);
+   GLuint i;
+   for (i = 0; i < n; i++) {
+      GLint level;
+      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
+      sample_2d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
+   }
 }
 
 
@@ -782,57 +879,91 @@ sample_2d_linear_mipmap_nearest(GLcontext *ctx,
 static void
 sample_2d_nearest_mipmap_linear(GLcontext *ctx,
                                 const struct gl_texture_object *tObj,
-                                const GLfloat texcoord[4], GLfloat lambda,
-                                GLchan rgba[4])
+                                GLuint n, GLfloat texcoord[][4],
+                                const GLfloat lambda[], GLchan rgba[][4])
 {
-   GLint level;
-
-   COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
-
-   if (level >= tObj->_MaxLevel) {
-      sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], texcoord, rgba);
-   }
-   else {
-      GLchan t0[4], t1[4];  /* texels */
-      const GLfloat f = FRAC(lambda);
-      sample_2d_nearest(ctx, tObj, tObj->Image[level  ], texcoord, t0);
-      sample_2d_nearest(ctx, tObj, tObj->Image[level+1], texcoord, t1);
-      rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
-      rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
-      rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
-      rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
+   GLuint i;
+   for (i = 0; i < n; i++) {
+      GLint level;
+      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
+      if (level >= tObj->_MaxLevel) {
+         sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
+                           texcoord[i], rgba[i]);
+      }
+      else {
+         GLchan t0[4], t1[4];  /* texels */
+         const GLfloat f = FRAC(lambda[i]);
+         sample_2d_nearest(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
+         sample_2d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
+         rgba[i][RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
+         rgba[i][GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
+         rgba[i][BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
+         rgba[i][ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
+      }
    }
 }
 
 
 
+/* Trilinear filtering */
 static void
-sample_2d_linear_mipmap_linear(GLcontext *ctx,
-                               const struct gl_texture_object *tObj,
-                               const GLfloat texcoord[4], GLfloat lambda,
-                               GLchan rgba[4])
+sample_2d_linear_mipmap_linear( GLcontext *ctx,
+                                const struct gl_texture_object *tObj,
+                                GLuint n, GLfloat texcoord[][4],
+                                const GLfloat lambda[], GLchan rgba[][4] )
 {
-   GLint level;
+   GLuint i;
+   for (i = 0; i < n; i++) {
+      GLint level;
+      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
+      if (level >= tObj->_MaxLevel) {
+         sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
+                          texcoord[i], rgba[i]);
+      }
+      else {
+         GLchan t0[4], t1[4];  /* texels */
+         const GLfloat f = FRAC(lambda[i]);
+         sample_2d_linear(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
+         sample_2d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
+         rgba[i][RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
+         rgba[i][GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
+         rgba[i][BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
+         rgba[i][ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
+      }
+   }
+}
 
-   COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
 
-   if (level >= tObj->_MaxLevel) {
-      sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], texcoord, rgba);
-   }
-   else {
-      GLchan t0[4], t1[4];  /* texels */
-      const GLfloat f = FRAC(lambda);
-      sample_2d_linear(ctx, tObj, tObj->Image[level  ], texcoord, t0);
-      sample_2d_linear(ctx, tObj, tObj->Image[level+1], texcoord, t1);
-      rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
-      rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
-      rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
-      rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
+static void
+sample_2d_linear_mipmap_linear_repeat( GLcontext *ctx,
+                                       const struct gl_texture_object *tObj,
+                                       GLuint n, GLfloat texcoord[][4],
+                                       const GLfloat lambda[], GLchan rgba[][4] )
+{
+   GLuint i;
+   ASSERT(tObj->WrapS == GL_REPEAT);
+   ASSERT(tObj->WrapT == GL_REPEAT);
+   for (i = 0; i < n; i++) {
+      GLint level;
+      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
+      if (level >= tObj->_MaxLevel) {
+         sample_2d_linear_repeat(ctx, tObj, tObj->Image[tObj->_MaxLevel],
+                                 texcoord[i], rgba[i]);
+      }
+      else {
+         GLchan t0[4], t1[4];  /* texels */
+         const GLfloat f = FRAC(lambda[i]);
+         sample_2d_linear_repeat(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
+         sample_2d_linear_repeat(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
+         rgba[i][RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
+         rgba[i][GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
+         rgba[i][BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
+         rgba[i][ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
+      }
    }
 }
 
 
-
 static void
 sample_nearest_2d( GLcontext *ctx, GLuint texUnit,
                    const struct gl_texture_object *tObj, GLuint n,
@@ -970,8 +1101,16 @@ sample_lambda_2d( GLcontext *ctx, GLuint texUnit,
                   GLuint n, GLfloat texcoords[][4],
                   const GLfloat lambda[], GLchan rgba[][4] )
 {
+   const struct gl_texture_image *tImg = tObj->Image[tObj->BaseLevel];
    const GLfloat minMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
    GLuint i;
+   GLint minStart, minEnd;  /* texels with minification */
+   GLint magStart, magEnd;  /* texels with magnification */
+
+   const GLboolean repeatNoBorder = (tObj->WrapS == GL_REPEAT)
+      && (tObj->WrapT == GL_REPEAT)
+      && (tImg->Border == 0)
+      && (tImg->Format != GL_COLOR_INDEX);
 
 #ifdef DEBUG
    ASSERT (span_is_monotonous(n, lambda) == GL_TRUE);
@@ -980,84 +1119,148 @@ sample_lambda_2d( GLcontext *ctx, GLuint texUnit,
    /* since lambda is monotonous-array use this check first */
    if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
       /* magnification for whole span */
-      const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
-      switch (tObj->MagFilter) {
+      magStart = 0;
+      magEnd = n;
+      minStart = minEnd = 0;
+   }
+   else if (lambda[0] > minMagThresh && lambda[n-1] > minMagThresh) {
+      /* minification for whole span */
+      minStart = 0;
+      minEnd = n;
+      magStart = magEnd = 0;
+   }
+   else {
+      /* a mix of minification and magnification */
+      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;
+      }
+   }
+
+#ifdef DEBUG
+   /* Verify the min/mag Start/End values */
+   {
+      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
+
+   if (minStart < minEnd) {
+      /* do the minified texels */
+      const GLuint m = (GLuint) (minEnd - minStart);
+      switch (tObj->MinFilter) {
       case GL_NEAREST:
-         if (tObj->WrapS == GL_REPEAT && tObj->WrapT == GL_REPEAT &&
-             img->Border == 0) {
-            switch (img->Format) {
+         if (repeatNoBorder) {
+            switch (tImg->Format) {
             case GL_RGB:
-               opt_sample_rgb_2d(ctx, texUnit, tObj, n, texcoords,
-                                 NULL, rgba);
+               opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + minStart,
+                                 NULL, rgba + minStart);
                break;
             case GL_RGBA:
-              opt_sample_rgba_2d(ctx, texUnit, tObj, n, texcoords,
-                                  NULL, rgba);
+              opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + minStart,
+                                  NULL, rgba + minStart);
                break;
             default:
-               sample_nearest_2d(ctx, texUnit, tObj, n, texcoords,
-                                 NULL, rgba);
+               sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
+                                 NULL, rgba + minStart );
             }
          }
          else {
-            sample_nearest_2d(ctx, texUnit, tObj, n, texcoords,
-                              NULL, rgba);
+            sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
+                              NULL, rgba + minStart);
          }
          break;
       case GL_LINEAR:
-        sample_linear_2d(ctx, texUnit, tObj, n, texcoords,
-                         NULL, rgba);
+        sample_linear_2d(ctx, texUnit, tObj, m, texcoords + minStart,
+                         NULL, rgba + minStart);
+         break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+         sample_2d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+                                          lambda + minStart, rgba + minStart);
+         break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+         sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+                                         lambda + minStart, rgba + minStart);
+         break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+         sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+                                         lambda + minStart, rgba + minStart);
+         break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+         if (repeatNoBorder)
+            sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
+                  texcoords + minStart, lambda + minStart, rgba + minStart);
+         else
+            sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+                                        lambda + minStart, rgba + minStart);
          break;
       default:
-         _mesa_problem(NULL, "Bad mag filter in sample_lambda_2d");
+         _mesa_problem(NULL, "Bad min filter in sample_2d_texture");
+         return;
       }
    }
-   else {
-      const struct gl_texture_image *tImg = tObj->Image[tObj->BaseLevel];
-      for (i = 0; i < n; i++) {
-         if (lambda[i] > minMagThresh) {
-            /* minification */
-            switch (tObj->MinFilter) {
-               case GL_NEAREST:
-                  sample_2d_nearest(ctx, tObj, tImg, texcoords[i], rgba[i]);
-                  break;
-               case GL_LINEAR:
-                  sample_2d_linear(ctx, tObj, tImg, texcoords[i], rgba[i]);
-                  break;
-               case GL_NEAREST_MIPMAP_NEAREST:
-                  sample_2d_nearest_mipmap_nearest(ctx, tObj, texcoords[i],
-                                                   lambda[i], rgba[i]);
-                  break;
-               case GL_LINEAR_MIPMAP_NEAREST:
-                  sample_2d_linear_mipmap_nearest(ctx, tObj, texcoords[i],
-                                                  lambda[i], rgba[i]);
-                  break;
-               case GL_NEAREST_MIPMAP_LINEAR:
-                  sample_2d_nearest_mipmap_linear(ctx, tObj, texcoords[i],
-                                                  lambda[i], rgba[i]);
-                  break;
-               case GL_LINEAR_MIPMAP_LINEAR:
-                  sample_2d_linear_mipmap_linear(ctx, tObj, texcoords[i],
-                                                 lambda[i], rgba[i] );
-                  break;
-               default:
-                  _mesa_problem(NULL, "Bad min filter in sample_2d_texture");
-                  return;
+
+   if (magStart < magEnd) {
+      /* do the magnified texels */
+      const GLuint m = (GLuint) (magEnd - magStart);
+
+      switch (tObj->MagFilter) {
+      case GL_NEAREST:
+         if (repeatNoBorder) {
+            switch (tImg->Format) {
+            case GL_RGB:
+               opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + magStart,
+                                 NULL, rgba + magStart);
+               break;
+            case GL_RGBA:
+              opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + magStart,
+                                  NULL, rgba + magStart);
+               break;
+            default:
+               sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
+                                 NULL, rgba + magStart );
             }
          }
          else {
-            /* magnification */
-            switch (tObj->MagFilter) {
-               case GL_NEAREST:
-                  sample_2d_nearest(ctx, tObj, tImg, texcoords[i], rgba[i]);
-                  break;
-               case GL_LINEAR:
-                  sample_2d_linear(ctx, tObj, tImg, texcoords[i], rgba[i] );
-                  break;
-               default:
-                  _mesa_problem(NULL, "Bad mag filter in sample_2d_texture");
-            }
+            sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
+                              NULL, rgba + magStart);
          }
+         break;
+      case GL_LINEAR:
+        sample_linear_2d(ctx, texUnit, tObj, m, texcoords + magStart,
+                         NULL, rgba + magStart);
+         break;
+      default:
+         _mesa_problem(NULL, "Bad mag filter in sample_lambda_2d");
       }
    }
 }