[Mesa-dev] [PATCH 16/21] swrast: Support sampler object for texture fetching state

Pauli Nieminen pauli.nieminen at linux.intel.com
Sun Jun 10 23:59:37 PDT 2012


swrast needs to pass sampler object into all texture fetching functions
to use correct sampling state when sampler object is bound to the unit.
The changes were made using half manual regular expression replace.

With the patch llvmpipe didn't get any regressions.

Signed-off-by: Pauli Nieminen <pauli.nieminen at linux.intel.com>
---
 src/mesa/swrast/s_atifragshader.c |    6 +-
 src/mesa/swrast/s_context.c       |    4 +-
 src/mesa/swrast/s_context.h       |    1 +
 src/mesa/swrast/s_fragprog.c      |   17 +-
 src/mesa/swrast/s_span.c          |    8 +-
 src/mesa/swrast/s_texcombine.c    |   42 ++-
 src/mesa/swrast/s_texfetch.c      |   20 +-
 src/mesa/swrast/s_texfetch.h      |    2 +-
 src/mesa/swrast/s_texfilter.c     |  692 ++++++++++++++++++++-----------------
 src/mesa/tnl/t_vb_program.c       |    4 +-
 10 files changed, 438 insertions(+), 358 deletions(-)

diff --git a/src/mesa/swrast/s_atifragshader.c b/src/mesa/swrast/s_atifragshader.c
index 1eb026e..394fac5 100644
--- a/src/mesa/swrast/s_atifragshader.c
+++ b/src/mesa/swrast/s_atifragshader.c
@@ -23,6 +23,7 @@
 #include "main/colormac.h"
 #include "main/macros.h"
 #include "main/atifragshader.h"
+#include "main/samplerobj.h"
 #include "swrast/s_atifragshader.h"
 #include "swrast/s_context.h"
 
@@ -49,8 +50,9 @@ fetch_texel(struct gl_context * ctx, const GLfloat texcoord[4], GLfloat lambda,
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
    /* XXX use a float-valued TextureSample routine here!!! */
-   swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
-                               1, (const GLfloat(*)[4]) texcoord,
+   swrast->TextureSample[unit](ctx, _mesa_get_samplerobj(ctx, unit),
+                               ctx->Texture.Unit[unit]._Current,
+			       1, (const GLfloat(*)[4]) texcoord,
                                &lambda, (GLfloat (*)[4]) color);
 }
 
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index 432db71..4ed7b94 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -480,9 +480,7 @@ _swrast_update_texture_samplers(struct gl_context *ctx)
       /* Note: If tObj is NULL, the sample function will be a simple
        * function that just returns opaque black (0,0,0,1).
        */
-      if (tObj) {
-         _mesa_update_fetch_functions(tObj);
-      }
+      _mesa_update_fetch_functions(ctx, u);
       swrast->TextureSample[u] =
          _swrast_choose_texture_sample_func(ctx, tObj,
                                             _mesa_get_samplerobj(ctx, u));
diff --git a/src/mesa/swrast/s_context.h b/src/mesa/swrast/s_context.h
index 26b97f7..18353c4 100644
--- a/src/mesa/swrast/s_context.h
+++ b/src/mesa/swrast/s_context.h
@@ -52,6 +52,7 @@
 
 
 typedef void (*texture_sample_func)(struct gl_context *ctx,
+                                    const struct gl_sampler_object *samp,
                                     const struct gl_texture_object *tObj,
                                     GLuint n, const GLfloat texcoords[][4],
                                     const GLfloat lambda[], GLfloat rgba[][4]);
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index 8d59371..812189f 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -24,6 +24,7 @@
 
 #include "main/glheader.h"
 #include "main/colormac.h"
+#include "main/samplerobj.h"
 #include "program/prog_instruction.h"
 
 #include "s_context.h"
@@ -83,11 +84,12 @@ fetch_texel_lod( struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lamb
    if (texObj) {
       SWcontext *swrast = SWRAST_CONTEXT(ctx);
       GLfloat rgba[4];
+      const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
 
-      lambda = CLAMP(lambda, texObj->Sampler.MinLod, texObj->Sampler.MaxLod);
+      lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);
 
-      swrast->TextureSample[unit](ctx, texObj, 1,
-                                  (const GLfloat (*)[4]) texcoord,
+      swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
+                                  1, (const GLfloat (*)[4]) texcoord,
                                   &lambda, &rgba);
       swizzle_texel(rgba, color, texObj->_Swizzle);
    }
@@ -118,6 +120,7 @@ fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
          texObj->Image[0][texObj->BaseLevel];
       const struct swrast_texture_image *swImg =
          swrast_texture_image_const(texImg);
+      const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
       const GLfloat texW = (GLfloat) swImg->WidthScale;
       const GLfloat texH = (GLfloat) swImg->HeightScale;
       GLfloat lambda;
@@ -130,12 +133,12 @@ fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
                                       texcoord[0], texcoord[1], texcoord[3],
                                       1.0F / texcoord[3]);
 
-      lambda += lodBias + texUnit->LodBias + texObj->Sampler.LodBias;
+      lambda += lodBias + texUnit->LodBias + samp->LodBias;
 
-      lambda = CLAMP(lambda, texObj->Sampler.MinLod, texObj->Sampler.MaxLod);
+      lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);
 
-      swrast->TextureSample[unit](ctx, texObj, 1,
-                                  (const GLfloat (*)[4]) texcoord,
+      swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
+                                  1, (const GLfloat (*)[4]) texcoord,
                                   &lambda, &rgba);
       swizzle_texel(rgba, color, texObj->_Swizzle);
    }
diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c
index 627ef11..ef51479 100644
--- a/src/mesa/swrast/s_span.c
+++ b/src/mesa/swrast/s_span.c
@@ -38,6 +38,7 @@
 #include "main/macros.h"
 #include "main/imports.h"
 #include "main/image.h"
+#include "main/samplerobj.h"
 
 #include "s_atifragshader.h"
 #include "s_alpha.h"
@@ -497,14 +498,15 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span)
             const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
             const struct swrast_texture_image *swImg =
                swrast_texture_image_const(img);
+            const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, u);
 
-            needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter)
+            needLambda = (samp->MinFilter != samp->MagFilter)
                || _swrast_use_fragment_program(ctx);
             /* LOD is calculated directly in the ansiotropic filter, we can
              * skip the normal lambda function as the result is ignored.
              */
-            if (obj->Sampler.MaxAnisotropy > 1.0 &&
-                obj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
+            if (samp->MaxAnisotropy > 1.0 &&
+                samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
                needLambda = GL_FALSE;
             }
             texW = swImg->WidthScale;
diff --git a/src/mesa/swrast/s_texcombine.c b/src/mesa/swrast/s_texcombine.c
index 8fbf988..2a32361 100644
--- a/src/mesa/swrast/s_texcombine.c
+++ b/src/mesa/swrast/s_texcombine.c
@@ -29,6 +29,7 @@
 #include "main/colormac.h"
 #include "main/imports.h"
 #include "main/pixeltransfer.h"
+#include "main/samplerobj.h"
 #include "program/prog_instruction.h"
 
 #include "s_context.h"
@@ -652,7 +653,7 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
             span->array->attribs[FRAG_ATTRIB_TEX0 +
                ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
 
-         const struct gl_texture_object *curObj = texUnit->_Current;
+         const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
          GLfloat *lambda = span->array->lambda[unit];
          float4_array texels = get_texel_array(swrast, unit);
          GLuint i;
@@ -663,9 +664,9 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
 
          /* adjust texture lod (lambda) */
          if (span->arrayMask & SPAN_LAMBDA) {
-            if (texUnit->LodBias + curObj->Sampler.LodBias != 0.0F) {
+            if (texUnit->LodBias + samp->LodBias != 0.0F) {
                /* apply LOD bias, but don't clamp yet */
-               const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.LodBias,
+               const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
                                           -ctx->Const.MaxTextureLodBias,
                                           ctx->Const.MaxTextureLodBias);
                GLuint i;
@@ -674,11 +675,11 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
                }
             }
 
-            if (curObj->Sampler.MinLod != -1000.0 ||
-                curObj->Sampler.MaxLod != 1000.0) {
+            if (samp->MinLod != -1000.0 ||
+                samp->MaxLod != 1000.0) {
                /* apply LOD clamping to lambda */
-               const GLfloat min = curObj->Sampler.MinLod;
-               const GLfloat max = curObj->Sampler.MaxLod;
+               const GLfloat min = samp->MinLod;
+               const GLfloat max = samp->MaxLod;
                GLuint i;
                for (i = 0; i < span->end; i++) {
                   GLfloat l = lambda[i];
@@ -688,8 +689,9 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
          }
 
          /* Sample the texture (span->end = number of fragments) */
-         swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
-                                      texcoords, lambda, texels );
+         swrast->TextureSample[unit]( ctx, samp,
+                                      ctx->Texture.Unit[unit]._Current,
+                                      span->end, texcoords, lambda, texels );
 
          /* manipulate the span values of the bump target
             not sure this can work correctly even ignoring
@@ -714,14 +716,15 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
          const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
             span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
          const struct gl_texture_object *curObj = texUnit->_Current;
+         const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
          GLfloat *lambda = span->array->lambda[unit];
          float4_array texels = get_texel_array(swrast, unit);
 
          /* adjust texture lod (lambda) */
          if (span->arrayMask & SPAN_LAMBDA) {
-            if (texUnit->LodBias + curObj->Sampler.LodBias != 0.0F) {
+            if (texUnit->LodBias + samp->LodBias != 0.0F) {
                /* apply LOD bias, but don't clamp yet */
-               const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.LodBias,
+               const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
                                           -ctx->Const.MaxTextureLodBias,
                                           ctx->Const.MaxTextureLodBias);
                GLuint i;
@@ -730,11 +733,11 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
                }
             }
 
-            if (curObj->Sampler.MinLod != -1000.0 ||
-                curObj->Sampler.MaxLod != 1000.0) {
+            if (samp->MinLod != -1000.0 ||
+                samp->MaxLod != 1000.0) {
                /* apply LOD clamping to lambda */
-               const GLfloat min = curObj->Sampler.MinLod;
-               const GLfloat max = curObj->Sampler.MaxLod;
+               const GLfloat min = samp->MinLod;
+               const GLfloat max = samp->MaxLod;
                GLuint i;
                for (i = 0; i < span->end; i++) {
                   GLfloat l = lambda[i];
@@ -742,8 +745,8 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
                }
             }
          }
-         else if (curObj->Sampler.MaxAnisotropy > 1.0 &&
-                  curObj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
+         else if (samp->MaxAnisotropy > 1.0 &&
+                  samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
             /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
              * it requires the current SWspan *span as an additional parameter.
              * In order to keep the same function signature, the unused lambda
@@ -756,8 +759,9 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
          }
 
          /* Sample the texture (span->end = number of fragments) */
-         swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
-                                      texcoords, lambda, texels );
+         swrast->TextureSample[unit]( ctx, samp,
+                                      ctx->Texture.Unit[unit]._Current,
+                                      span->end, texcoords, lambda, texels );
 
          /* GL_EXT_texture_swizzle */
          if (curObj->_Swizzle != SWIZZLE_NOOP) {
diff --git a/src/mesa/swrast/s_texfetch.c b/src/mesa/swrast/s_texfetch.c
index 8529ff0..c2c5f09 100644
--- a/src/mesa/swrast/s_texfetch.c
+++ b/src/mesa/swrast/s_texfetch.c
@@ -41,6 +41,7 @@
 #include "main/texcompress_rgtc.h"
 #include "main/texcompress_etc.h"
 #include "main/teximage.h"
+#include "main/samplerobj.h"
 #include "s_context.h"
 #include "s_texfetch.h"
 #include "../../gallium/auxiliary/util/u_format_rgb9e5.h"
@@ -1104,7 +1105,7 @@ texfetch_funcs[MESA_FORMAT_COUNT] =
       NULL,
       NULL,
       NULL
-   }
+   },
 };
 
 
@@ -1141,13 +1142,14 @@ _mesa_get_texel_fetch_func(gl_format format, GLuint dims)
  * Initialize the texture image's FetchTexel methods.
  */
 static void
-set_fetch_functions(struct swrast_texture_image *texImage, GLuint dims)
+set_fetch_functions(struct gl_sampler_object *samp,
+                    struct swrast_texture_image *texImage, GLuint dims)
 {
    gl_format format = texImage->Base.TexFormat;
 
    ASSERT(dims == 1 || dims == 2 || dims == 3);
 
-   if (texImage->Base.TexObject->Sampler.sRGBDecode == GL_SKIP_DECODE_EXT &&
+   if (samp->sRGBDecode == GL_SKIP_DECODE_EXT &&
        _mesa_get_format_color_encoding(format) == GL_SRGB) {
       format = _mesa_get_srgb_format_linear(format);
    }
@@ -1157,17 +1159,25 @@ set_fetch_functions(struct swrast_texture_image *texImage, GLuint dims)
 }
 
 void
-_mesa_update_fetch_functions(struct gl_texture_object *texObj)
+_mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit)
 {
+   struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
+   struct gl_sampler_object *samp;
    GLuint face, i;
    GLuint dims;
 
+   if (!texObj)
+      return;
+
+   samp = _mesa_get_samplerobj(ctx, unit);
+
    dims = _mesa_get_texture_dimensions(texObj->Target);
 
    for (face = 0; face < 6; face++) {
       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
          if (texObj->Image[face][i]) {
-	    set_fetch_functions(swrast_texture_image(texObj->Image[face][i]),
+	    set_fetch_functions(samp,
+                                swrast_texture_image(texObj->Image[face][i]),
                                 dims);
          }
       }
diff --git a/src/mesa/swrast/s_texfetch.h b/src/mesa/swrast/s_texfetch.h
index 1aa7ce5..33950ce 100644
--- a/src/mesa/swrast/s_texfetch.h
+++ b/src/mesa/swrast/s_texfetch.h
@@ -33,6 +33,6 @@ extern FetchTexelFunc
 _mesa_get_texel_fetch_func(gl_format format, GLuint dims);
 
 void
-_mesa_update_fetch_functions(struct gl_texture_object *texObj);
+_mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit);
 
 #endif /* S_TEXFETCH_H */
diff --git a/src/mesa/swrast/s_texfilter.c b/src/mesa/swrast/s_texfilter.c
index 103b442..51c8992 100644
--- a/src/mesa/swrast/s_texfilter.c
+++ b/src/mesa/swrast/s_texfilter.c
@@ -28,6 +28,7 @@
 #include "main/colormac.h"
 #include "main/imports.h"
 #include "main/texobj.h"
+#include "main/samplerobj.h"
 
 #include "s_context.h"
 #include "s_texfilter.h"
@@ -498,7 +499,8 @@ tex_array_slice(GLfloat coord, GLsizei size)
  * NOTE: only used for depth texture sampling.
  */
 static inline void
-nearest_texcoord(const struct gl_texture_object *texObj,
+nearest_texcoord(const struct gl_sampler_object *samp,
+                 const struct gl_texture_object *texObj,
                  GLuint level,
                  const GLfloat texcoord[4],
                  GLint *i, GLint *j, GLint *k)
@@ -510,28 +512,28 @@ nearest_texcoord(const struct gl_texture_object *texObj,
 
    switch (texObj->Target) {
    case GL_TEXTURE_RECTANGLE_ARB:
-      *i = clamp_rect_coord_nearest(texObj->Sampler.WrapS, texcoord[0], width);
-      *j = clamp_rect_coord_nearest(texObj->Sampler.WrapT, texcoord[1], height);
+      *i = clamp_rect_coord_nearest(samp->WrapS, texcoord[0], width);
+      *j = clamp_rect_coord_nearest(samp->WrapT, texcoord[1], height);
       *k = 0;
       break;
    case GL_TEXTURE_1D:
-      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
+      *i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
       *j = 0;
       *k = 0;
       break;
    case GL_TEXTURE_2D:
-      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
-      *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]);
+      *i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
+      *j = nearest_texel_location(samp->WrapT, img, height, texcoord[1]);
       *k = 0;
       break;
    case GL_TEXTURE_1D_ARRAY_EXT:
-      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
+      *i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
       *j = tex_array_slice(texcoord[1], height);
       *k = 0;
       break;
    case GL_TEXTURE_2D_ARRAY_EXT:
-      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
-      *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]);
+      *i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
+      *j = nearest_texel_location(samp->WrapT, img, height, texcoord[1]);
       *k = tex_array_slice(texcoord[2], depth);
       break;
    default:
@@ -546,7 +548,8 @@ nearest_texcoord(const struct gl_texture_object *texObj,
  * NOTE: only used for depth texture sampling.
  */
 static inline void
-linear_texcoord(const struct gl_texture_object *texObj,
+linear_texcoord(const struct gl_sampler_object *samp,
+                const struct gl_texture_object *texObj,
                 GLuint level,
                 const GLfloat texcoord[4],
                 GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice,
@@ -559,24 +562,24 @@ linear_texcoord(const struct gl_texture_object *texObj,
 
    switch (texObj->Target) {
    case GL_TEXTURE_RECTANGLE_ARB:
-      clamp_rect_coord_linear(texObj->Sampler.WrapS, texcoord[0],
+      clamp_rect_coord_linear(samp->WrapS, texcoord[0],
                               width, i0, i1, wi);
-      clamp_rect_coord_linear(texObj->Sampler.WrapT, texcoord[1],
+      clamp_rect_coord_linear(samp->WrapT, texcoord[1],
                               height, j0, j1, wj);
       *slice = 0;
       break;
 
    case GL_TEXTURE_1D:
    case GL_TEXTURE_2D:
-      linear_texel_locations(texObj->Sampler.WrapS, img, width,
+      linear_texel_locations(samp->WrapS, img, width,
                              texcoord[0], i0, i1, wi);
-      linear_texel_locations(texObj->Sampler.WrapT, img, height,
+      linear_texel_locations(samp->WrapT, img, height,
                              texcoord[1], j0, j1, wj);
       *slice = 0;
       break;
 
    case GL_TEXTURE_1D_ARRAY_EXT:
-      linear_texel_locations(texObj->Sampler.WrapS, img, width,
+      linear_texel_locations(samp->WrapS, img, width,
                              texcoord[0], i0, i1, wi);
       *j0 = tex_array_slice(texcoord[1], height);
       *j1 = *j0;
@@ -584,9 +587,9 @@ linear_texcoord(const struct gl_texture_object *texObj,
       break;
 
    case GL_TEXTURE_2D_ARRAY_EXT:
-      linear_texel_locations(texObj->Sampler.WrapS, img, width,
+      linear_texel_locations(samp->WrapS, img, width,
                              texcoord[0], i0, i1, wi);
-      linear_texel_locations(texObj->Sampler.WrapT, img, height,
+      linear_texel_locations(samp->WrapT, img, height,
                              texcoord[1], j0, j1, wj);
       *slice = tex_array_slice(texcoord[2], depth);
       break;
@@ -655,7 +658,7 @@ nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
  * determines the subranges in [0, n-1] that are to be minified or magnified.
  */
 static inline void
-compute_min_mag_ranges(const struct gl_texture_object *tObj,
+compute_min_mag_ranges(const struct gl_sampler_object *samp,
                        GLuint n, const GLfloat lambda[],
                        GLuint *minStart, GLuint *minEnd,
                        GLuint *magStart, GLuint *magEnd)
@@ -663,12 +666,12 @@ compute_min_mag_ranges(const struct gl_texture_object *tObj,
    GLfloat minMagThresh;
 
    /* we shouldn't be here if minfilter == magfilter */
-   ASSERT(tObj->Sampler.MinFilter != tObj->Sampler.MagFilter);
+   ASSERT(samp->MinFilter != samp->MagFilter);
 
    /* This bit comes from the OpenGL spec: */
-   if (tObj->Sampler.MagFilter == GL_LINEAR
-       && (tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
-           tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
+   if (samp->MagFilter == GL_LINEAR
+       && (samp->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
+           samp->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
       minMagThresh = 0.5F;
    }
    else {
@@ -764,34 +767,34 @@ compute_min_mag_ranges(const struct gl_texture_object *tObj,
  * we return (0,0,0,BorderAlpha).
  */
 static inline void
-get_border_color(const struct gl_texture_object *tObj,
+get_border_color(const struct gl_sampler_object *samp,
                  const struct gl_texture_image *img,
                  GLfloat rgba[4])
 {
    switch (img->_BaseFormat) {
    case GL_RGB:
-      rgba[0] = tObj->Sampler.BorderColor.f[0];
-      rgba[1] = tObj->Sampler.BorderColor.f[1];
-      rgba[2] = tObj->Sampler.BorderColor.f[2];
+      rgba[0] = samp->BorderColor.f[0];
+      rgba[1] = samp->BorderColor.f[1];
+      rgba[2] = samp->BorderColor.f[2];
       rgba[3] = 1.0F;
       break;
    case GL_ALPHA:
       rgba[0] = rgba[1] = rgba[2] = 0.0;
-      rgba[3] = tObj->Sampler.BorderColor.f[3];
+      rgba[3] = samp->BorderColor.f[3];
       break;
    case GL_LUMINANCE:
-      rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0];
+      rgba[0] = rgba[1] = rgba[2] = samp->BorderColor.f[0];
       rgba[3] = 1.0;
       break;
    case GL_LUMINANCE_ALPHA:
-      rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0];
-      rgba[3] = tObj->Sampler.BorderColor.f[3];
+      rgba[0] = rgba[1] = rgba[2] = samp->BorderColor.f[0];
+      rgba[3] = samp->BorderColor.f[3];
       break;
    case GL_INTENSITY:
-      rgba[0] = rgba[1] = rgba[2] = rgba[3] = tObj->Sampler.BorderColor.f[0];
+      rgba[0] = rgba[1] = rgba[2] = rgba[3] = samp->BorderColor.f[0];
       break;
    default:
-      COPY_4V(rgba, tObj->Sampler.BorderColor.f);
+      COPY_4V(rgba, samp->BorderColor.f);
       break;
    }
 }
@@ -806,19 +809,19 @@ get_border_color(const struct gl_texture_object *tObj,
  */
 static inline void
 sample_1d_nearest(struct gl_context *ctx,
-                  const struct gl_texture_object *tObj,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_image *img,
                   const GLfloat texcoord[4], GLfloat rgba[4])
 {
    const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
    const GLint width = img->Width2;  /* without border, power of two */
    GLint i;
-   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
+   i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
    /* 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 */
-      get_border_color(tObj, img, rgba);
+      get_border_color(samp, img, rgba);
    }
    else {
       swImg->FetchTexel(swImg, i, 0, 0, rgba);
@@ -831,7 +834,7 @@ sample_1d_nearest(struct gl_context *ctx,
  */
 static inline void
 sample_1d_linear(struct gl_context *ctx,
-                 const struct gl_texture_object *tObj,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_image *img,
                  const GLfloat texcoord[4], GLfloat rgba[4])
 {
@@ -842,7 +845,7 @@ sample_1d_linear(struct gl_context *ctx,
    GLfloat a;
    GLfloat t0[4], t1[4];  /* texels */
 
-   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
+   linear_texel_locations(samp->WrapS, img, width, texcoord[0], &i0, &i1, &a);
 
    if (img->Border) {
       i0 += img->Border;
@@ -855,13 +858,13 @@ sample_1d_linear(struct gl_context *ctx,
 
    /* fetch texel colors */
    if (useBorderColor & I0BIT) {
-      get_border_color(tObj, img, t0);
+      get_border_color(samp, img, t0);
    }
    else {
       swImg->FetchTexel(swImg, i0, 0, 0, t0);
    }
    if (useBorderColor & I1BIT) {
-      get_border_color(tObj, img, t1);
+      get_border_color(samp, img, t1);
    }
    else {
       swImg->FetchTexel(swImg, i1, 0, 0, t1);
@@ -873,6 +876,7 @@ sample_1d_linear(struct gl_context *ctx,
 
 static void
 sample_1d_nearest_mipmap_nearest(struct gl_context *ctx,
+                                 const struct gl_sampler_object *samp,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -881,13 +885,14 @@ sample_1d_nearest_mipmap_nearest(struct gl_context *ctx,
    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]);
+      sample_1d_nearest(ctx, samp, tObj->Image[0][level], texcoord[i], rgba[i]);
    }
 }
 
 
 static void
 sample_1d_linear_mipmap_nearest(struct gl_context *ctx,
+                                const struct gl_sampler_object *samp,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -896,13 +901,14 @@ sample_1d_linear_mipmap_nearest(struct gl_context *ctx,
    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]);
+      sample_1d_linear(ctx, samp, tObj->Image[0][level], texcoord[i], rgba[i]);
    }
 }
 
 
 static void
 sample_1d_nearest_mipmap_linear(struct gl_context *ctx,
+                                const struct gl_sampler_object *samp,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -912,14 +918,14 @@ sample_1d_nearest_mipmap_linear(struct gl_context *ctx,
    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],
+         sample_1d_nearest(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                            texcoord[i], rgba[i]);
       }
       else {
          GLfloat 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);
+         sample_1d_nearest(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_1d_nearest(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -928,6 +934,7 @@ sample_1d_nearest_mipmap_linear(struct gl_context *ctx,
 
 static void
 sample_1d_linear_mipmap_linear(struct gl_context *ctx,
+                               const struct gl_sampler_object *samp,
                                const struct gl_texture_object *tObj,
                                GLuint n, const GLfloat texcoord[][4],
                                const GLfloat lambda[], GLfloat rgba[][4])
@@ -937,14 +944,14 @@ sample_1d_linear_mipmap_linear(struct gl_context *ctx,
    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],
+         sample_1d_linear(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                           texcoord[i], rgba[i]);
       }
       else {
          GLfloat 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);
+         sample_1d_linear(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_1d_linear(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -954,6 +961,7 @@ sample_1d_linear_mipmap_linear(struct gl_context *ctx,
 /** Sample 1D texture, nearest filtering for both min/magnification */
 static void
 sample_nearest_1d( struct gl_context *ctx,
+                   const struct gl_sampler_object *samp,
                    const struct gl_texture_object *tObj, GLuint n,
                    const GLfloat texcoords[][4], const GLfloat lambda[],
                    GLfloat rgba[][4] )
@@ -962,7 +970,7 @@ sample_nearest_1d( struct gl_context *ctx,
    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]);
+      sample_1d_nearest(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -970,6 +978,7 @@ sample_nearest_1d( struct gl_context *ctx,
 /** Sample 1D texture, linear filtering for both min/magnification */
 static void
 sample_linear_1d( struct gl_context *ctx,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4], const GLfloat lambda[],
                   GLfloat rgba[][4] )
@@ -978,7 +987,7 @@ sample_linear_1d( struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_1d_linear(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -986,6 +995,7 @@ sample_linear_1d( struct gl_context *ctx,
 /** Sample 1D texture, using lambda to choose between min/magnification */
 static void
 sample_lambda_1d( struct gl_context *ctx,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4] )
@@ -995,37 +1005,37 @@ sample_lambda_1d( struct gl_context *ctx,
    GLuint i;
 
    ASSERT(lambda != NULL);
-   compute_min_mag_ranges(tObj, n, lambda,
+   compute_min_mag_ranges(samp, n, lambda,
                           &minStart, &minEnd, &magStart, &magEnd);
 
    if (minStart < minEnd) {
       /* do the minified texels */
       const GLuint m = minEnd - minStart;
-      switch (tObj->Sampler.MinFilter) {
+      switch (samp->MinFilter) {
       case GL_NEAREST:
          for (i = minStart; i < minEnd; i++)
-            sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                               texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = minStart; i < minEnd; i++)
-            sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                              texcoords[i], rgba[i]);
          break;
       case GL_NEAREST_MIPMAP_NEAREST:
-         sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+         sample_1d_nearest_mipmap_nearest(ctx, samp, tObj, m, texcoords + minStart,
                                           lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_NEAREST:
-         sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+         sample_1d_linear_mipmap_nearest(ctx, samp, tObj, m, texcoords + minStart,
                                          lambda + minStart, rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_LINEAR:
-         sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+         sample_1d_nearest_mipmap_linear(ctx, samp, tObj, m, texcoords + minStart,
                                          lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_LINEAR:
-         sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+         sample_1d_linear_mipmap_linear(ctx, samp, tObj, m, texcoords + minStart,
                                         lambda + minStart, rgba + minStart);
          break;
       default:
@@ -1036,15 +1046,15 @@ sample_lambda_1d( struct gl_context *ctx,
 
    if (magStart < magEnd) {
       /* do the magnified texels */
-      switch (tObj->Sampler.MagFilter) {
+      switch (samp->MagFilter) {
       case GL_NEAREST:
          for (i = magStart; i < magEnd; i++)
-            sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                               texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = magStart; i < magEnd; i++)
-            sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                              texcoords[i], rgba[i]);
          break;
       default:
@@ -1065,7 +1075,7 @@ sample_lambda_1d( struct gl_context *ctx,
  */
 static inline void
 sample_2d_nearest(struct gl_context *ctx,
-                  const struct gl_texture_object *tObj,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_image *img,
                   const GLfloat texcoord[4],
                   GLfloat rgba[])
@@ -1076,8 +1086,8 @@ sample_2d_nearest(struct gl_context *ctx,
    GLint i, j;
    (void) ctx;
 
-   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
-   j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
+   i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
+   j = nearest_texel_location(samp->WrapT, img, height, texcoord[1]);
 
    /* skip over the border, if any */
    i += img->Border;
@@ -1085,7 +1095,7 @@ sample_2d_nearest(struct gl_context *ctx,
 
    if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
       /* Need this test for GL_CLAMP_TO_BORDER mode */
-      get_border_color(tObj, img, rgba);
+      get_border_color(samp, img, rgba);
    }
    else {
       swImg->FetchTexel(swImg, i, j, 0, rgba);
@@ -1099,7 +1109,7 @@ sample_2d_nearest(struct gl_context *ctx,
  */
 static inline void
 sample_2d_linear(struct gl_context *ctx,
-                 const struct gl_texture_object *tObj,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_image *img,
                  const GLfloat texcoord[4],
                  GLfloat rgba[])
@@ -1112,8 +1122,8 @@ sample_2d_linear(struct gl_context *ctx,
    GLfloat a, b;
    GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
 
-   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0],  &i0, &i1, &a);
-   linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
+   linear_texel_locations(samp->WrapS, img, width, texcoord[0],  &i0, &i1, &a);
+   linear_texel_locations(samp->WrapT, img, height, texcoord[1], &j0, &j1, &b);
 
    if (img->Border) {
       i0 += img->Border;
@@ -1130,25 +1140,25 @@ sample_2d_linear(struct gl_context *ctx,
 
    /* fetch four texel colors */
    if (useBorderColor & (I0BIT | J0BIT)) {
-      get_border_color(tObj, img, t00);
+      get_border_color(samp, img, t00);
    }
    else {
       swImg->FetchTexel(swImg, i0, j0, 0, t00);
    }
    if (useBorderColor & (I1BIT | J0BIT)) {
-      get_border_color(tObj, img, t10);
+      get_border_color(samp, img, t10);
    }
    else {
       swImg->FetchTexel(swImg, i1, j0, 0, t10);
    }
    if (useBorderColor & (I0BIT | J1BIT)) {
-      get_border_color(tObj, img, t01);
+      get_border_color(samp, img, t01);
    }
    else {
       swImg->FetchTexel(swImg, i0, j1, 0, t01);
    }
    if (useBorderColor & (I1BIT | J1BIT)) {
-      get_border_color(tObj, img, t11);
+      get_border_color(samp, img, t11);
    }
    else {
       swImg->FetchTexel(swImg, i1, j1, 0, t11);
@@ -1164,7 +1174,7 @@ sample_2d_linear(struct gl_context *ctx,
  */
 static inline void
 sample_2d_linear_repeat(struct gl_context *ctx,
-                        const struct gl_texture_object *tObj,
+                        const struct gl_sampler_object *samp,
                         const struct gl_texture_image *img,
                         const GLfloat texcoord[4],
                         GLfloat rgba[])
@@ -1178,8 +1188,8 @@ sample_2d_linear_repeat(struct gl_context *ctx,
 
    (void) ctx;
 
-   ASSERT(tObj->Sampler.WrapS == GL_REPEAT);
-   ASSERT(tObj->Sampler.WrapT == GL_REPEAT);
+   ASSERT(samp->WrapS == GL_REPEAT);
+   ASSERT(samp->WrapT == GL_REPEAT);
    ASSERT(img->Border == 0);
    ASSERT(swImg->_IsPowerOfTwo);
 
@@ -1197,6 +1207,7 @@ sample_2d_linear_repeat(struct gl_context *ctx,
 
 static void
 sample_2d_nearest_mipmap_nearest(struct gl_context *ctx,
+                                 const struct gl_sampler_object *samp,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -1204,13 +1215,14 @@ sample_2d_nearest_mipmap_nearest(struct gl_context *ctx,
    GLuint i;
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_2d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+      sample_2d_nearest(ctx, samp, tObj->Image[0][level], texcoord[i], rgba[i]);
    }
 }
 
 
 static void
 sample_2d_linear_mipmap_nearest(struct gl_context *ctx,
+                                const struct gl_sampler_object *samp,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -1219,13 +1231,14 @@ sample_2d_linear_mipmap_nearest(struct gl_context *ctx,
    ASSERT(lambda != NULL);
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_2d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+      sample_2d_linear(ctx, samp, tObj->Image[0][level], texcoord[i], rgba[i]);
    }
 }
 
 
 static void
 sample_2d_nearest_mipmap_linear(struct gl_context *ctx,
+                                const struct gl_sampler_object *samp,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -1235,14 +1248,14 @@ sample_2d_nearest_mipmap_linear(struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_2d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_2d_nearest(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                            texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_2d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
-         sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+         sample_2d_nearest(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_2d_nearest(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -1251,6 +1264,7 @@ sample_2d_nearest_mipmap_linear(struct gl_context *ctx,
 
 static void
 sample_2d_linear_mipmap_linear( struct gl_context *ctx,
+                                const struct gl_sampler_object *samp,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4] )
@@ -1260,14 +1274,14 @@ sample_2d_linear_mipmap_linear( struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_2d_linear(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                           texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_2d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
-         sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+         sample_2d_linear(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_2d_linear(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -1276,26 +1290,27 @@ sample_2d_linear_mipmap_linear( struct gl_context *ctx,
 
 static void
 sample_2d_linear_mipmap_linear_repeat(struct gl_context *ctx,
+                                      const struct gl_sampler_object *samp,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
 {
    GLuint i;
    ASSERT(lambda != NULL);
-   ASSERT(tObj->Sampler.WrapS == GL_REPEAT);
-   ASSERT(tObj->Sampler.WrapT == GL_REPEAT);
+   ASSERT(samp->WrapS == GL_REPEAT);
+   ASSERT(samp->WrapT == GL_REPEAT);
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_2d_linear_repeat(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                                  texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level  ],
+         sample_2d_linear_repeat(ctx, samp, tObj->Image[0][level  ],
                                  texcoord[i], t0);
-         sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level+1],
+         sample_2d_linear_repeat(ctx, samp, tObj->Image[0][level+1],
                                  texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
@@ -1306,6 +1321,7 @@ sample_2d_linear_mipmap_linear_repeat(struct gl_context *ctx,
 /** Sample 2D texture, nearest filtering for both min/magnification */
 static void
 sample_nearest_2d(struct gl_context *ctx,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -1314,7 +1330,7 @@ sample_nearest_2d(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_2d_nearest(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -1322,6 +1338,7 @@ sample_nearest_2d(struct gl_context *ctx,
 /** Sample 2D texture, linear filtering for both min/magnification */
 static void
 sample_linear_2d(struct gl_context *ctx,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_object *tObj, GLuint n,
                  const GLfloat texcoords[][4],
                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -1330,17 +1347,17 @@ sample_linear_2d(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    const struct swrast_texture_image *swImg = swrast_texture_image_const(image);
    (void) lambda;
-   if (tObj->Sampler.WrapS == GL_REPEAT &&
-       tObj->Sampler.WrapT == GL_REPEAT &&
+   if (samp->WrapS == GL_REPEAT &&
+       samp->WrapT == GL_REPEAT &&
        swImg->_IsPowerOfTwo &&
        image->Border == 0) {
       for (i = 0; i < n; i++) {
-         sample_2d_linear_repeat(ctx, tObj, image, texcoords[i], rgba[i]);
+         sample_2d_linear_repeat(ctx, samp, image, texcoords[i], rgba[i]);
       }
    }
    else {
       for (i = 0; i < n; i++) {
-         sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+         sample_2d_linear(ctx, samp, image, texcoords[i], rgba[i]);
       }
    }
 }
@@ -1356,6 +1373,7 @@ sample_linear_2d(struct gl_context *ctx,
  */
 static void
 opt_sample_rgb_2d(struct gl_context *ctx,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_object *tObj,
                   GLuint n, const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -1370,8 +1388,8 @@ opt_sample_rgb_2d(struct gl_context *ctx,
    GLuint k;
    (void) ctx;
    (void) lambda;
-   ASSERT(tObj->Sampler.WrapS==GL_REPEAT);
-   ASSERT(tObj->Sampler.WrapT==GL_REPEAT);
+   ASSERT(samp->WrapS==GL_REPEAT);
+   ASSERT(samp->WrapT==GL_REPEAT);
    ASSERT(img->Border==0);
    ASSERT(img->TexFormat == MESA_FORMAT_RGB888);
    ASSERT(swImg->_IsPowerOfTwo);
@@ -1400,6 +1418,7 @@ opt_sample_rgb_2d(struct gl_context *ctx,
  */
 static void
 opt_sample_rgba_2d(struct gl_context *ctx,
+                   const struct gl_sampler_object *samp,
                    const struct gl_texture_object *tObj,
                    GLuint n, const GLfloat texcoords[][4],
                    const GLfloat lambda[], GLfloat rgba[][4])
@@ -1414,8 +1433,8 @@ opt_sample_rgba_2d(struct gl_context *ctx,
    GLuint i;
    (void) ctx;
    (void) lambda;
-   ASSERT(tObj->Sampler.WrapS==GL_REPEAT);
-   ASSERT(tObj->Sampler.WrapT==GL_REPEAT);
+   ASSERT(samp->WrapS==GL_REPEAT);
+   ASSERT(samp->WrapT==GL_REPEAT);
    ASSERT(img->Border==0);
    ASSERT(img->TexFormat == MESA_FORMAT_RGBA8888);
    ASSERT(swImg->_IsPowerOfTwo);
@@ -1437,6 +1456,7 @@ opt_sample_rgba_2d(struct gl_context *ctx,
 /** Sample 2D texture, using lambda to choose between min/magnification */
 static void
 sample_lambda_2d(struct gl_context *ctx,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_object *tObj,
                  GLuint n, const GLfloat texcoords[][4],
                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -1446,63 +1466,63 @@ sample_lambda_2d(struct gl_context *ctx,
    GLuint minStart, minEnd;  /* texels with minification */
    GLuint magStart, magEnd;  /* texels with magnification */
 
-   const GLboolean repeatNoBorderPOT = (tObj->Sampler.WrapS == GL_REPEAT)
-      && (tObj->Sampler.WrapT == GL_REPEAT)
+   const GLboolean repeatNoBorderPOT = (samp->WrapS == GL_REPEAT)
+      && (samp->WrapT == GL_REPEAT)
       && (tImg->Border == 0 && (tImg->Width == swImg->RowStride))
       && swImg->_IsPowerOfTwo;
 
    ASSERT(lambda != NULL);
-   compute_min_mag_ranges(tObj, n, lambda,
+   compute_min_mag_ranges(samp, n, lambda,
                           &minStart, &minEnd, &magStart, &magEnd);
 
    if (minStart < minEnd) {
       /* do the minified texels */
       const GLuint m = minEnd - minStart;
-      switch (tObj->Sampler.MinFilter) {
+      switch (samp->MinFilter) {
       case GL_NEAREST:
          if (repeatNoBorderPOT) {
             switch (tImg->TexFormat) {
             case MESA_FORMAT_RGB888:
-               opt_sample_rgb_2d(ctx, tObj, m, texcoords + minStart,
+               opt_sample_rgb_2d(ctx, samp, tObj, m, texcoords + minStart,
                                  NULL, rgba + minStart);
                break;
             case MESA_FORMAT_RGBA8888:
-	       opt_sample_rgba_2d(ctx, tObj, m, texcoords + minStart,
+	       opt_sample_rgba_2d(ctx, samp, tObj, m, texcoords + minStart,
                                   NULL, rgba + minStart);
                break;
             default:
-               sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
+               sample_nearest_2d(ctx, samp, tObj, m, texcoords + minStart,
                                  NULL, rgba + minStart );
             }
          }
          else {
-            sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
+            sample_nearest_2d(ctx, samp, tObj, m, texcoords + minStart,
                               NULL, rgba + minStart);
          }
          break;
       case GL_LINEAR:
-	 sample_linear_2d(ctx, tObj, m, texcoords + minStart,
+	 sample_linear_2d(ctx, samp, tObj, m, texcoords + minStart,
 			  NULL, rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_NEAREST:
-         sample_2d_nearest_mipmap_nearest(ctx, tObj, m,
+         sample_2d_nearest_mipmap_nearest(ctx, samp, tObj, m,
                                           texcoords + minStart,
                                           lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_NEAREST:
-         sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+         sample_2d_linear_mipmap_nearest(ctx, samp, tObj, m, texcoords + minStart,
                                          lambda + minStart, rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_LINEAR:
-         sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+         sample_2d_nearest_mipmap_linear(ctx, samp, tObj, m, texcoords + minStart,
                                          lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_LINEAR:
          if (repeatNoBorderPOT)
-            sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
+            sample_2d_linear_mipmap_linear_repeat(ctx, samp, tObj, m,
                   texcoords + minStart, lambda + minStart, rgba + minStart);
          else
-            sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+            sample_2d_linear_mipmap_linear(ctx, samp, tObj, m, texcoords + minStart,
                                         lambda + minStart, rgba + minStart);
          break;
       default:
@@ -1515,30 +1535,30 @@ sample_lambda_2d(struct gl_context *ctx,
       /* do the magnified texels */
       const GLuint m = magEnd - magStart;
 
-      switch (tObj->Sampler.MagFilter) {
+      switch (samp->MagFilter) {
       case GL_NEAREST:
          if (repeatNoBorderPOT) {
             switch (tImg->TexFormat) {
             case MESA_FORMAT_RGB888:
-               opt_sample_rgb_2d(ctx, tObj, m, texcoords + magStart,
+               opt_sample_rgb_2d(ctx, samp, tObj, m, texcoords + magStart,
                                  NULL, rgba + magStart);
                break;
             case MESA_FORMAT_RGBA8888:
-	       opt_sample_rgba_2d(ctx, tObj, m, texcoords + magStart,
+	       opt_sample_rgba_2d(ctx, samp, tObj, m, texcoords + magStart,
                                   NULL, rgba + magStart);
                break;
             default:
-               sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
+               sample_nearest_2d(ctx, samp, tObj, m, texcoords + magStart,
                                  NULL, rgba + magStart );
             }
          }
          else {
-            sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
+            sample_nearest_2d(ctx, samp, tObj, m, texcoords + magStart,
                               NULL, rgba + magStart);
          }
          break;
       case GL_LINEAR:
-	 sample_linear_2d(ctx, tObj, m, texcoords + magStart,
+	 sample_linear_2d(ctx, samp, tObj, m, texcoords + magStart,
 			  NULL, rgba + magStart);
          break;
       default:
@@ -1583,6 +1603,7 @@ create_filter_table(void)
  */
 static void
 sample_2d_ewa(struct gl_context *ctx,
+              const struct gl_sampler_object *samp,
               const struct gl_texture_object *tObj,
               const GLfloat texcoord[4],
               const GLfloat dudx, const GLfloat dvdx,
@@ -1664,7 +1685,7 @@ sample_2d_ewa(struct gl_context *ctx,
             newCoord[0] = u / ((GLfloat) img->Width2);
             newCoord[1] = v / ((GLfloat) img->Height2);
 
-            sample_2d_nearest(ctx, tObj, img, newCoord, rgba);
+            sample_2d_nearest(ctx, samp, img, newCoord, rgba);
             num[0] += weight * rgba[0];
             num[1] += weight * rgba[1];
             num[2] += weight * rgba[2];
@@ -1690,7 +1711,7 @@ sample_2d_ewa(struct gl_context *ctx,
       rgba[2]=0;
       rgba[3]=0;*/
       /* not enough pixels in resampling, resort to direct interpolation */
-      sample_2d_linear(ctx, tObj, img, texcoord, rgba);
+      sample_2d_linear(ctx, samp, img, texcoord, rgba);
       return;
    }
 
@@ -1709,6 +1730,7 @@ sample_2d_ewa(struct gl_context *ctx,
  */
 static void
 sample_2d_footprint(struct gl_context *ctx,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_object *tObj,
                  const GLfloat texcoord[4],
                  const GLfloat dudx, const GLfloat dvdx,
@@ -1751,7 +1773,7 @@ sample_2d_footprint(struct gl_context *ctx,
       newCoord[0] = texcoord[0] + ds * ((GLfloat)(s+1) / (numSamples+1) -0.5);
       newCoord[1] = texcoord[1] + dt * ((GLfloat)(s+1) / (numSamples+1) -0.5);
 
-      sample_2d_linear(ctx, tObj, img, newCoord, rgba);
+      sample_2d_linear(ctx, samp, img, newCoord, rgba);
       num[0] += rgba[0];
       num[1] += rgba[1];
       num[2] += rgba[2];
@@ -1799,6 +1821,7 @@ texture_unit_index(const struct gl_context *ctx,
  */
 static void
 sample_lambda_2d_aniso(struct gl_context *ctx,
+                       const struct gl_sampler_object *samp,
                        const struct gl_texture_object *tObj,
                        GLuint n, const GLfloat texcoords[][4],
                        const GLfloat lambda_iso[], GLfloat rgba[][4])
@@ -1806,7 +1829,7 @@ sample_lambda_2d_aniso(struct gl_context *ctx,
    const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
    const struct swrast_texture_image *swImg = swrast_texture_image_const(tImg);
    const GLfloat maxEccentricity =
-      tObj->Sampler.MaxAnisotropy * tObj->Sampler.MaxAnisotropy;
+      samp->MaxAnisotropy * samp->MaxAnisotropy;
    
    /* re-calculate the lambda values so that they are usable with anisotropic
     * filtering
@@ -1837,8 +1860,8 @@ sample_lambda_2d_aniso(struct gl_context *ctx,
    /* from swrast/s_texcombine.c _swrast_texture_span */
    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
    const GLboolean adjustLOD =
-      (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F)
-      || (tObj->Sampler.MinLod != -1000.0 || tObj->Sampler.MaxLod != 1000.0);
+      (texUnit->LodBias + samp->LodBias != 0.0F)
+      || (samp->MinLod != -1000.0 || samp->MaxLod != 1000.0);
 
    GLuint i;
    
@@ -1901,18 +1924,18 @@ sample_lambda_2d_aniso(struct gl_context *ctx,
       
       if (adjustLOD) {
          /* from swrast/s_texcombine.c _swrast_texture_span */
-         if (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F) {
+         if (texUnit->LodBias + samp->LodBias != 0.0F) {
             /* apply LOD bias, but don't clamp yet */
             const GLfloat bias =
-               CLAMP(texUnit->LodBias + tObj->Sampler.LodBias,
+               CLAMP(texUnit->LodBias + samp->LodBias,
                      -ctx->Const.MaxTextureLodBias,
                      ctx->Const.MaxTextureLodBias);
             lod += bias;
 
-            if (tObj->Sampler.MinLod != -1000.0 ||
-                tObj->Sampler.MaxLod != 1000.0) {
+            if (samp->MinLod != -1000.0 ||
+                samp->MaxLod != 1000.0) {
                /* apply LOD clamping to lambda */
-               lod = CLAMP(lod, tObj->Sampler.MinLod, tObj->Sampler.MaxLod);
+               lod = CLAMP(lod, samp->MinLod, samp->MaxLod);
             }
          }
       }
@@ -1921,14 +1944,14 @@ sample_lambda_2d_aniso(struct gl_context *ctx,
        * simply return the average of the whole image.
        */
       if (lod >= tObj->_MaxLevel) {
-         sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_2d_linear(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                           texcoords[i], rgba[i]);
       }
       else {
          /* don't bother interpolating between multiple LODs; it doesn't
           * seem to be worth the extra running time.
           */
-         sample_2d_ewa(ctx, tObj, texcoords[i],
+         sample_2d_ewa(ctx, samp, tObj, texcoords[i],
                        dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]);
 
          /* unused: */
@@ -1952,7 +1975,7 @@ sample_lambda_2d_aniso(struct gl_context *ctx,
  */
 static inline void
 sample_3d_nearest(struct gl_context *ctx,
-                  const struct gl_texture_object *tObj,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_image *img,
                   const GLfloat texcoord[4],
                   GLfloat rgba[4])
@@ -1964,15 +1987,15 @@ sample_3d_nearest(struct gl_context *ctx,
    GLint i, j, k;
    (void) ctx;
 
-   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
-   j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
-   k = nearest_texel_location(tObj->Sampler.WrapR, img, depth, texcoord[2]);
+   i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
+   j = nearest_texel_location(samp->WrapT, img, height, texcoord[1]);
+   k = nearest_texel_location(samp->WrapR, img, depth, texcoord[2]);
 
    if (i < 0 || i >= (GLint) img->Width ||
        j < 0 || j >= (GLint) img->Height ||
        k < 0 || k >= (GLint) img->Depth) {
       /* Need this test for GL_CLAMP_TO_BORDER mode */
-      get_border_color(tObj, img, rgba);
+      get_border_color(samp, img, rgba);
    }
    else {
       swImg->FetchTexel(swImg, i, j, k, rgba);
@@ -1985,7 +2008,7 @@ sample_3d_nearest(struct gl_context *ctx,
  */
 static void
 sample_3d_linear(struct gl_context *ctx,
-                 const struct gl_texture_object *tObj,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_image *img,
                  const GLfloat texcoord[4],
                  GLfloat rgba[4])
@@ -2000,9 +2023,9 @@ sample_3d_linear(struct gl_context *ctx,
    GLfloat t000[4], t010[4], t001[4], t011[4];
    GLfloat t100[4], t110[4], t101[4], t111[4];
 
-   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0],  &i0, &i1, &a);
-   linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
-   linear_texel_locations(tObj->Sampler.WrapR, img, depth, texcoord[2],  &k0, &k1, &c);
+   linear_texel_locations(samp->WrapS, img, width, texcoord[0],  &i0, &i1, &a);
+   linear_texel_locations(samp->WrapT, img, height, texcoord[1], &j0, &j1, &b);
+   linear_texel_locations(samp->WrapR, img, depth, texcoord[2],  &k0, &k1, &c);
 
    if (img->Border) {
       i0 += img->Border;
@@ -2024,50 +2047,50 @@ sample_3d_linear(struct gl_context *ctx,
 
    /* Fetch texels */
    if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
-      get_border_color(tObj, img, t000);
+      get_border_color(samp, img, t000);
    }
    else {
       swImg->FetchTexel(swImg, i0, j0, k0, t000);
    }
    if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
-      get_border_color(tObj, img, t100);
+      get_border_color(samp, img, t100);
    }
    else {
       swImg->FetchTexel(swImg, i1, j0, k0, t100);
    }
    if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
-      get_border_color(tObj, img, t010);
+      get_border_color(samp, img, t010);
    }
    else {
       swImg->FetchTexel(swImg, i0, j1, k0, t010);
    }
    if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
-      get_border_color(tObj, img, t110);
+      get_border_color(samp, img, t110);
    }
    else {
       swImg->FetchTexel(swImg, i1, j1, k0, t110);
    }
 
    if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
-      get_border_color(tObj, img, t001);
+      get_border_color(samp, img, t001);
    }
    else {
       swImg->FetchTexel(swImg, i0, j0, k1, t001);
    }
    if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
-      get_border_color(tObj, img, t101);
+      get_border_color(samp, img, t101);
    }
    else {
       swImg->FetchTexel(swImg, i1, j0, k1, t101);
    }
    if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
-      get_border_color(tObj, img, t011);
+      get_border_color(samp, img, t011);
    }
    else {
       swImg->FetchTexel(swImg, i0, j1, k1, t011);
    }
    if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
-      get_border_color(tObj, img, t111);
+      get_border_color(samp, img, t111);
    }
    else {
       swImg->FetchTexel(swImg, i1, j1, k1, t111);
@@ -2080,6 +2103,7 @@ sample_3d_linear(struct gl_context *ctx,
 
 static void
 sample_3d_nearest_mipmap_nearest(struct gl_context *ctx,
+                                 const struct gl_sampler_object *samp,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4] )
@@ -2087,13 +2111,14 @@ sample_3d_nearest_mipmap_nearest(struct gl_context *ctx,
    GLuint i;
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_3d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+      sample_3d_nearest(ctx, samp, tObj->Image[0][level], texcoord[i], rgba[i]);
    }
 }
 
 
 static void
 sample_3d_linear_mipmap_nearest(struct gl_context *ctx,
+                                const struct gl_sampler_object *samp,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -2102,13 +2127,14 @@ sample_3d_linear_mipmap_nearest(struct gl_context *ctx,
    ASSERT(lambda != NULL);
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_3d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+      sample_3d_linear(ctx, samp, tObj->Image[0][level], texcoord[i], rgba[i]);
    }
 }
 
 
 static void
 sample_3d_nearest_mipmap_linear(struct gl_context *ctx,
+                                const struct gl_sampler_object *samp,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -2118,14 +2144,14 @@ sample_3d_nearest_mipmap_linear(struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_3d_nearest(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                            texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_3d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
-         sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+         sample_3d_nearest(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_3d_nearest(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -2134,6 +2160,7 @@ sample_3d_nearest_mipmap_linear(struct gl_context *ctx,
 
 static void
 sample_3d_linear_mipmap_linear(struct gl_context *ctx,
+                               const struct gl_sampler_object *samp,
                                const struct gl_texture_object *tObj,
                                GLuint n, const GLfloat texcoord[][4],
                                const GLfloat lambda[], GLfloat rgba[][4])
@@ -2143,14 +2170,14 @@ sample_3d_linear_mipmap_linear(struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_3d_linear(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                           texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_3d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
-         sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+         sample_3d_linear(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_3d_linear(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -2160,6 +2187,7 @@ sample_3d_linear_mipmap_linear(struct gl_context *ctx,
 /** Sample 3D texture, nearest filtering for both min/magnification */
 static void
 sample_nearest_3d(struct gl_context *ctx,
+                  const struct gl_sampler_object *samp,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4], const GLfloat lambda[],
                   GLfloat rgba[][4])
@@ -2168,7 +2196,7 @@ sample_nearest_3d(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_3d_nearest(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -2176,6 +2204,7 @@ sample_nearest_3d(struct gl_context *ctx,
 /** Sample 3D texture, linear filtering for both min/magnification */
 static void
 sample_linear_3d(struct gl_context *ctx,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_object *tObj, GLuint n,
                  const GLfloat texcoords[][4],
 		 const GLfloat lambda[], GLfloat rgba[][4])
@@ -2184,7 +2213,7 @@ sample_linear_3d(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_3d_linear(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -2192,6 +2221,7 @@ sample_linear_3d(struct gl_context *ctx,
 /** Sample 3D texture, using lambda to choose between min/magnification */
 static void
 sample_lambda_3d(struct gl_context *ctx,
+                 const struct gl_sampler_object *samp,
                  const struct gl_texture_object *tObj, GLuint n,
                  const GLfloat texcoords[][4], const GLfloat lambda[],
                  GLfloat rgba[][4])
@@ -2201,37 +2231,37 @@ sample_lambda_3d(struct gl_context *ctx,
    GLuint i;
 
    ASSERT(lambda != NULL);
-   compute_min_mag_ranges(tObj, n, lambda,
+   compute_min_mag_ranges(samp, n, lambda,
                           &minStart, &minEnd, &magStart, &magEnd);
 
    if (minStart < minEnd) {
       /* do the minified texels */
       GLuint m = minEnd - minStart;
-      switch (tObj->Sampler.MinFilter) {
+      switch (samp->MinFilter) {
       case GL_NEAREST:
          for (i = minStart; i < minEnd; i++)
-            sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_3d_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                               texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = minStart; i < minEnd; i++)
-            sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_3d_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                              texcoords[i], rgba[i]);
          break;
       case GL_NEAREST_MIPMAP_NEAREST:
-         sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+         sample_3d_nearest_mipmap_nearest(ctx, samp, tObj, m, texcoords + minStart,
                                           lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_NEAREST:
-         sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+         sample_3d_linear_mipmap_nearest(ctx, samp, tObj, m, texcoords + minStart,
                                          lambda + minStart, rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_LINEAR:
-         sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+         sample_3d_nearest_mipmap_linear(ctx, samp, tObj, m, texcoords + minStart,
                                          lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_LINEAR:
-         sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+         sample_3d_linear_mipmap_linear(ctx, samp, tObj, m, texcoords + minStart,
                                         lambda + minStart, rgba + minStart);
          break;
       default:
@@ -2242,15 +2272,15 @@ sample_lambda_3d(struct gl_context *ctx,
 
    if (magStart < magEnd) {
       /* do the magnified texels */
-      switch (tObj->Sampler.MagFilter) {
+      switch (samp->MagFilter) {
       case GL_NEAREST:
          for (i = magStart; i < magEnd; i++)
-            sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_3d_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                               texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = magStart; i < magEnd; i++)
-            sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_3d_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                              texcoords[i], rgba[i]);
          break;
       default:
@@ -2347,6 +2377,7 @@ choose_cube_face(const struct gl_texture_object *texObj,
 
 static void
 sample_nearest_cube(struct gl_context *ctx,
+                    const struct gl_sampler_object *samp,
 		    const struct gl_texture_object *tObj, GLuint n,
                     const GLfloat texcoords[][4], const GLfloat lambda[],
                     GLfloat rgba[][4])
@@ -2357,7 +2388,7 @@ sample_nearest_cube(struct gl_context *ctx,
       const struct gl_texture_image **images;
       GLfloat newCoord[4];
       images = choose_cube_face(tObj, texcoords[i], newCoord);
-      sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
+      sample_2d_nearest(ctx, samp, images[tObj->BaseLevel],
                         newCoord, rgba[i]);
    }
 }
@@ -2365,6 +2396,7 @@ sample_nearest_cube(struct gl_context *ctx,
 
 static void
 sample_linear_cube(struct gl_context *ctx,
+                   const struct gl_sampler_object *samp,
 		   const struct gl_texture_object *tObj, GLuint n,
                    const GLfloat texcoords[][4],
 		   const GLfloat lambda[], GLfloat rgba[][4])
@@ -2375,7 +2407,7 @@ sample_linear_cube(struct gl_context *ctx,
       const struct gl_texture_image **images;
       GLfloat newCoord[4];
       images = choose_cube_face(tObj, texcoords[i], newCoord);
-      sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
+      sample_2d_linear(ctx, samp, images[tObj->BaseLevel],
                        newCoord, rgba[i]);
    }
 }
@@ -2383,6 +2415,7 @@ sample_linear_cube(struct gl_context *ctx,
 
 static void
 sample_cube_nearest_mipmap_nearest(struct gl_context *ctx,
+                                   const struct gl_sampler_object *samp,
                                    const struct gl_texture_object *tObj,
                                    GLuint n, const GLfloat texcoord[][4],
                                    const GLfloat lambda[], GLfloat rgba[][4])
@@ -2405,13 +2438,14 @@ sample_cube_nearest_mipmap_nearest(struct gl_context *ctx,
       level = nearest_mipmap_level(tObj, lambda[i]);
       level = MAX2(level - 1, 0);
 
-      sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
+      sample_2d_nearest(ctx, samp, images[level], newCoord, rgba[i]);
    }
 }
 
 
 static void
 sample_cube_linear_mipmap_nearest(struct gl_context *ctx,
+                                  const struct gl_sampler_object *samp,
                                   const struct gl_texture_object *tObj,
                                   GLuint n, const GLfloat texcoord[][4],
                                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -2424,13 +2458,14 @@ sample_cube_linear_mipmap_nearest(struct gl_context *ctx,
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
       level = MAX2(level - 1, 0); /* see comment above */
       images = choose_cube_face(tObj, texcoord[i], newCoord);
-      sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
+      sample_2d_linear(ctx, samp, images[level], newCoord, rgba[i]);
    }
 }
 
 
 static void
 sample_cube_nearest_mipmap_linear(struct gl_context *ctx,
+                                  const struct gl_sampler_object *samp,
                                   const struct gl_texture_object *tObj,
                                   GLuint n, const GLfloat texcoord[][4],
                                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -2444,14 +2479,14 @@ sample_cube_nearest_mipmap_linear(struct gl_context *ctx,
       level = MAX2(level - 1, 0); /* see comment above */
       images = choose_cube_face(tObj, texcoord[i], newCoord);
       if (level >= tObj->_MaxLevel) {
-         sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
+         sample_2d_nearest(ctx, samp, images[tObj->_MaxLevel],
                            newCoord, rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_2d_nearest(ctx, tObj, images[level  ], newCoord, t0);
-         sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
+         sample_2d_nearest(ctx, samp, images[level  ], newCoord, t0);
+         sample_2d_nearest(ctx, samp, images[level+1], newCoord, t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -2460,6 +2495,7 @@ sample_cube_nearest_mipmap_linear(struct gl_context *ctx,
 
 static void
 sample_cube_linear_mipmap_linear(struct gl_context *ctx,
+                                 const struct gl_sampler_object *samp,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -2473,14 +2509,14 @@ sample_cube_linear_mipmap_linear(struct gl_context *ctx,
       level = MAX2(level - 1, 0); /* see comment above */
       images = choose_cube_face(tObj, texcoord[i], newCoord);
       if (level >= tObj->_MaxLevel) {
-         sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
+         sample_2d_linear(ctx, samp, images[tObj->_MaxLevel],
                           newCoord, rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];
          const GLfloat f = FRAC(lambda[i]);
-         sample_2d_linear(ctx, tObj, images[level  ], newCoord, t0);
-         sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
+         sample_2d_linear(ctx, samp, images[level  ], newCoord, t0);
+         sample_2d_linear(ctx, samp, images[level+1], newCoord, t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -2490,6 +2526,7 @@ sample_cube_linear_mipmap_linear(struct gl_context *ctx,
 /** Sample cube texture, using lambda to choose between min/magnification */
 static void
 sample_lambda_cube(struct gl_context *ctx,
+                   const struct gl_sampler_object *samp,
 		   const struct gl_texture_object *tObj, GLuint n,
 		   const GLfloat texcoords[][4], const GLfloat lambda[],
 		   GLfloat rgba[][4])
@@ -2498,38 +2535,38 @@ sample_lambda_cube(struct gl_context *ctx,
    GLuint magStart, magEnd;  /* texels with magnification */
 
    ASSERT(lambda != NULL);
-   compute_min_mag_ranges(tObj, n, lambda,
+   compute_min_mag_ranges(samp, n, lambda,
                           &minStart, &minEnd, &magStart, &magEnd);
 
    if (minStart < minEnd) {
       /* do the minified texels */
       const GLuint m = minEnd - minStart;
-      switch (tObj->Sampler.MinFilter) {
+      switch (samp->MinFilter) {
       case GL_NEAREST:
-         sample_nearest_cube(ctx, tObj, m, texcoords + minStart,
+         sample_nearest_cube(ctx, samp, tObj, m, texcoords + minStart,
                              lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR:
-         sample_linear_cube(ctx, tObj, m, texcoords + minStart,
+         sample_linear_cube(ctx, samp, tObj, m, texcoords + minStart,
                             lambda + minStart, rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_NEAREST:
-         sample_cube_nearest_mipmap_nearest(ctx, tObj, m,
+         sample_cube_nearest_mipmap_nearest(ctx, samp, tObj, m,
                                             texcoords + minStart,
                                            lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_NEAREST:
-         sample_cube_linear_mipmap_nearest(ctx, tObj, m,
+         sample_cube_linear_mipmap_nearest(ctx, samp, tObj, m,
                                            texcoords + minStart,
                                            lambda + minStart, rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_LINEAR:
-         sample_cube_nearest_mipmap_linear(ctx, tObj, m,
+         sample_cube_nearest_mipmap_linear(ctx, samp, tObj, m,
                                            texcoords + minStart,
                                            lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_LINEAR:
-         sample_cube_linear_mipmap_linear(ctx, tObj, m,
+         sample_cube_linear_mipmap_linear(ctx, samp, tObj, m,
                                           texcoords + minStart,
                                           lambda + minStart, rgba + minStart);
          break;
@@ -2542,13 +2579,13 @@ sample_lambda_cube(struct gl_context *ctx,
    if (magStart < magEnd) {
       /* do the magnified texels */
       const GLuint m = magEnd - magStart;
-      switch (tObj->Sampler.MagFilter) {
+      switch (samp->MagFilter) {
       case GL_NEAREST:
-         sample_nearest_cube(ctx, tObj, m, texcoords + magStart,
+         sample_nearest_cube(ctx, samp, tObj, m, texcoords + magStart,
                              lambda + magStart, rgba + magStart);
          break;
       case GL_LINEAR:
-         sample_linear_cube(ctx, tObj, m, texcoords + magStart,
+         sample_linear_cube(ctx, samp, tObj, m, texcoords + magStart,
                             lambda + magStart, rgba + magStart);
          break;
       default:
@@ -2566,6 +2603,7 @@ sample_lambda_cube(struct gl_context *ctx,
 
 static void
 sample_nearest_rect(struct gl_context *ctx,
+                    const struct gl_sampler_object *samp,
 		    const struct gl_texture_object *tObj, GLuint n,
                     const GLfloat texcoords[][4], const GLfloat lambda[],
                     GLfloat rgba[][4])
@@ -2579,19 +2617,19 @@ sample_nearest_rect(struct gl_context *ctx,
    (void) ctx;
    (void) lambda;
 
-   ASSERT(tObj->Sampler.WrapS == GL_CLAMP ||
-          tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE ||
-          tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER);
-   ASSERT(tObj->Sampler.WrapT == GL_CLAMP ||
-          tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE ||
-          tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER);
+   ASSERT(samp->WrapS == GL_CLAMP ||
+          samp->WrapS == GL_CLAMP_TO_EDGE ||
+          samp->WrapS == GL_CLAMP_TO_BORDER);
+   ASSERT(samp->WrapT == GL_CLAMP ||
+          samp->WrapT == GL_CLAMP_TO_EDGE ||
+          samp->WrapT == GL_CLAMP_TO_BORDER);
 
    for (i = 0; i < n; i++) {
       GLint row, col;
-      col = clamp_rect_coord_nearest(tObj->Sampler.WrapS, texcoords[i][0], width);
-      row = clamp_rect_coord_nearest(tObj->Sampler.WrapT, texcoords[i][1], height);
+      col = clamp_rect_coord_nearest(samp->WrapS, texcoords[i][0], width);
+      row = clamp_rect_coord_nearest(samp->WrapT, texcoords[i][1], height);
       if (col < 0 || col >= width || row < 0 || row >= height)
-         get_border_color(tObj, img, rgba[i]);
+         get_border_color(samp, img, rgba[i]);
       else
          swImg->FetchTexel(swImg, col, row, 0, rgba[i]);
    }
@@ -2600,6 +2638,7 @@ sample_nearest_rect(struct gl_context *ctx,
 
 static void
 sample_linear_rect(struct gl_context *ctx,
+                   const struct gl_sampler_object *samp,
 		   const struct gl_texture_object *tObj, GLuint n,
                    const GLfloat texcoords[][4],
 		   const GLfloat lambda[], GLfloat rgba[][4])
@@ -2613,12 +2652,12 @@ sample_linear_rect(struct gl_context *ctx,
    (void) ctx;
    (void) lambda;
 
-   ASSERT(tObj->Sampler.WrapS == GL_CLAMP ||
-          tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE ||
-          tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER);
-   ASSERT(tObj->Sampler.WrapT == GL_CLAMP ||
-          tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE ||
-          tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER);
+   ASSERT(samp->WrapS == GL_CLAMP ||
+          samp->WrapS == GL_CLAMP_TO_EDGE ||
+          samp->WrapS == GL_CLAMP_TO_BORDER);
+   ASSERT(samp->WrapT == GL_CLAMP ||
+          samp->WrapT == GL_CLAMP_TO_EDGE ||
+          samp->WrapT == GL_CLAMP_TO_BORDER);
 
    for (i = 0; i < n; i++) {
       GLint i0, j0, i1, j1;
@@ -2626,9 +2665,9 @@ sample_linear_rect(struct gl_context *ctx,
       GLfloat a, b;
       GLbitfield useBorderColor = 0x0;
 
-      clamp_rect_coord_linear(tObj->Sampler.WrapS, texcoords[i][0], width,
+      clamp_rect_coord_linear(samp->WrapS, texcoords[i][0], width,
                               &i0, &i1, &a);
-      clamp_rect_coord_linear(tObj->Sampler.WrapT, texcoords[i][1], height,
+      clamp_rect_coord_linear(samp->WrapT, texcoords[i][1], height,
                               &j0, &j1, &b);
 
       /* compute integer rows/columns */
@@ -2639,22 +2678,22 @@ sample_linear_rect(struct gl_context *ctx,
 
       /* get four texel samples */
       if (useBorderColor & (I0BIT | J0BIT))
-         get_border_color(tObj, img, t00);
+         get_border_color(samp, img, t00);
       else
          swImg->FetchTexel(swImg, i0, j0, 0, t00);
 
       if (useBorderColor & (I1BIT | J0BIT))
-         get_border_color(tObj, img, t10);
+         get_border_color(samp, img, t10);
       else
          swImg->FetchTexel(swImg, i1, j0, 0, t10);
 
       if (useBorderColor & (I0BIT | J1BIT))
-         get_border_color(tObj, img, t01);
+         get_border_color(samp, img, t01);
       else
          swImg->FetchTexel(swImg, i0, j1, 0, t01);
 
       if (useBorderColor & (I1BIT | J1BIT))
-         get_border_color(tObj, img, t11);
+         get_border_color(samp, img, t11);
       else
          swImg->FetchTexel(swImg, i1, j1, 0, t11);
 
@@ -2666,6 +2705,7 @@ sample_linear_rect(struct gl_context *ctx,
 /** Sample Rect texture, using lambda to choose between min/magnification */
 static void
 sample_lambda_rect(struct gl_context *ctx,
+                   const struct gl_sampler_object *samp,
 		   const struct gl_texture_object *tObj, GLuint n,
 		   const GLfloat texcoords[][4], const GLfloat lambda[],
 		   GLfloat rgba[][4])
@@ -2675,26 +2715,26 @@ sample_lambda_rect(struct gl_context *ctx,
    /* We only need lambda to decide between minification and magnification.
     * There is no mipmapping with rectangular textures.
     */
-   compute_min_mag_ranges(tObj, n, lambda,
+   compute_min_mag_ranges(samp, n, lambda,
                           &minStart, &minEnd, &magStart, &magEnd);
 
    if (minStart < minEnd) {
-      if (tObj->Sampler.MinFilter == GL_NEAREST) {
-         sample_nearest_rect(ctx, tObj, minEnd - minStart,
+      if (samp->MinFilter == GL_NEAREST) {
+         sample_nearest_rect(ctx, samp, tObj, minEnd - minStart,
                              texcoords + minStart, NULL, rgba + minStart);
       }
       else {
-         sample_linear_rect(ctx, tObj, minEnd - minStart,
+         sample_linear_rect(ctx, samp, tObj, minEnd - minStart,
                             texcoords + minStart, NULL, rgba + minStart);
       }
    }
    if (magStart < magEnd) {
-      if (tObj->Sampler.MagFilter == GL_NEAREST) {
-         sample_nearest_rect(ctx, tObj, magEnd - magStart,
+      if (samp->MagFilter == GL_NEAREST) {
+         sample_nearest_rect(ctx, samp, tObj, magEnd - magStart,
                              texcoords + magStart, NULL, rgba + magStart);
       }
       else {
-         sample_linear_rect(ctx, tObj, magEnd - magStart,
+         sample_linear_rect(ctx, samp, tObj, magEnd - magStart,
                             texcoords + magStart, NULL, rgba + magStart);
       }
    }
@@ -2710,7 +2750,7 @@ sample_lambda_rect(struct gl_context *ctx,
  */
 static void
 sample_2d_array_nearest(struct gl_context *ctx,
-                        const struct gl_texture_object *tObj,
+                        const struct gl_sampler_object *samp,
                         const struct gl_texture_image *img,
                         const GLfloat texcoord[4],
                         GLfloat rgba[4])
@@ -2723,15 +2763,15 @@ sample_2d_array_nearest(struct gl_context *ctx,
    GLint array;
    (void) ctx;
 
-   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
-   j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
+   i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
+   j = nearest_texel_location(samp->WrapT, img, height, texcoord[1]);
    array = tex_array_slice(texcoord[2], depth);
 
    if (i < 0 || i >= (GLint) img->Width ||
        j < 0 || j >= (GLint) img->Height ||
        array < 0 || array >= (GLint) img->Depth) {
       /* Need this test for GL_CLAMP_TO_BORDER mode */
-      get_border_color(tObj, img, rgba);
+      get_border_color(samp, img, rgba);
    }
    else {
       swImg->FetchTexel(swImg, i, j, array, rgba);
@@ -2744,7 +2784,7 @@ sample_2d_array_nearest(struct gl_context *ctx,
  */
 static void
 sample_2d_array_linear(struct gl_context *ctx,
-                       const struct gl_texture_object *tObj,
+                       const struct gl_sampler_object *samp,
                        const struct gl_texture_image *img,
                        const GLfloat texcoord[4],
                        GLfloat rgba[4])
@@ -2759,12 +2799,12 @@ sample_2d_array_linear(struct gl_context *ctx,
    GLfloat a, b;
    GLfloat t00[4], t01[4], t10[4], t11[4];
 
-   linear_texel_locations(tObj->Sampler.WrapS, img, width,  texcoord[0], &i0, &i1, &a);
-   linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
+   linear_texel_locations(samp->WrapS, img, width,  texcoord[0], &i0, &i1, &a);
+   linear_texel_locations(samp->WrapT, img, height, texcoord[1], &j0, &j1, &b);
    array = tex_array_slice(texcoord[2], depth);
 
    if (array < 0 || array >= depth) {
-      COPY_4V(rgba, tObj->Sampler.BorderColor.f);
+      COPY_4V(rgba, samp->BorderColor.f);
    }
    else {
       if (img->Border) {
@@ -2783,25 +2823,25 @@ sample_2d_array_linear(struct gl_context *ctx,
 
       /* Fetch texels */
       if (useBorderColor & (I0BIT | J0BIT)) {
-         get_border_color(tObj, img, t00);
+         get_border_color(samp, img, t00);
       }
       else {
 	 swImg->FetchTexel(swImg, i0, j0, array, t00);
       }
       if (useBorderColor & (I1BIT | J0BIT)) {
-         get_border_color(tObj, img, t10);
+         get_border_color(samp, img, t10);
       }
       else {
 	 swImg->FetchTexel(swImg, i1, j0, array, t10);
       }
       if (useBorderColor & (I0BIT | J1BIT)) {
-         get_border_color(tObj, img, t01);
+         get_border_color(samp, img, t01);
       }
       else {
 	 swImg->FetchTexel(swImg, i0, j1, array, t01);
       }
       if (useBorderColor & (I1BIT | J1BIT)) {
-         get_border_color(tObj, img, t11);
+         get_border_color(samp, img, t11);
       }
       else {
 	 swImg->FetchTexel(swImg, i1, j1, array, t11);
@@ -2815,6 +2855,7 @@ sample_2d_array_linear(struct gl_context *ctx,
 
 static void
 sample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx,
+                                       const struct gl_sampler_object *samp,
                                        const struct gl_texture_object *tObj,
                                        GLuint n, const GLfloat texcoord[][4],
                                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -2822,7 +2863,7 @@ sample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx,
    GLuint i;
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
+      sample_2d_array_nearest(ctx, samp, tObj->Image[0][level], texcoord[i],
                               rgba[i]);
    }
 }
@@ -2830,6 +2871,7 @@ sample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx,
 
 static void
 sample_2d_array_linear_mipmap_nearest(struct gl_context *ctx,
+                                      const struct gl_sampler_object *samp,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -2838,7 +2880,7 @@ sample_2d_array_linear_mipmap_nearest(struct gl_context *ctx,
    ASSERT(lambda != NULL);
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_2d_array_linear(ctx, tObj, tObj->Image[0][level],
+      sample_2d_array_linear(ctx, samp, tObj->Image[0][level],
                              texcoord[i], rgba[i]);
    }
 }
@@ -2846,6 +2888,7 @@ sample_2d_array_linear_mipmap_nearest(struct gl_context *ctx,
 
 static void
 sample_2d_array_nearest_mipmap_linear(struct gl_context *ctx,
+                                      const struct gl_sampler_object *samp,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -2855,15 +2898,15 @@ sample_2d_array_nearest_mipmap_linear(struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_2d_array_nearest(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                                  texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level  ],
+         sample_2d_array_nearest(ctx, samp, tObj->Image[0][level  ],
                                  texcoord[i], t0);
-         sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level+1],
+         sample_2d_array_nearest(ctx, samp, tObj->Image[0][level+1],
                                  texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
@@ -2873,6 +2916,7 @@ sample_2d_array_nearest_mipmap_linear(struct gl_context *ctx,
 
 static void
 sample_2d_array_linear_mipmap_linear(struct gl_context *ctx,
+                                     const struct gl_sampler_object *samp,
                                      const struct gl_texture_object *tObj,
                                      GLuint n, const GLfloat texcoord[][4],
                                      const GLfloat lambda[], GLfloat rgba[][4])
@@ -2882,15 +2926,15 @@ sample_2d_array_linear_mipmap_linear(struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_2d_array_linear(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                           texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_2d_array_linear(ctx, tObj, tObj->Image[0][level  ],
+         sample_2d_array_linear(ctx, samp, tObj->Image[0][level  ],
                                 texcoord[i], t0);
-         sample_2d_array_linear(ctx, tObj, tObj->Image[0][level+1],
+         sample_2d_array_linear(ctx, samp, tObj->Image[0][level+1],
                                 texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
@@ -2901,6 +2945,7 @@ sample_2d_array_linear_mipmap_linear(struct gl_context *ctx,
 /** Sample 2D Array texture, nearest filtering for both min/magnification */
 static void
 sample_nearest_2d_array(struct gl_context *ctx,
+                        const struct gl_sampler_object *samp,
                         const struct gl_texture_object *tObj, GLuint n,
                         const GLfloat texcoords[][4], const GLfloat lambda[],
                         GLfloat rgba[][4])
@@ -2909,7 +2954,7 @@ sample_nearest_2d_array(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_2d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_2d_array_nearest(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -2918,6 +2963,7 @@ sample_nearest_2d_array(struct gl_context *ctx,
 /** Sample 2D Array texture, linear filtering for both min/magnification */
 static void
 sample_linear_2d_array(struct gl_context *ctx,
+                       const struct gl_sampler_object *samp,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4],
                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -2926,7 +2972,7 @@ sample_linear_2d_array(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_2d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_2d_array_linear(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -2934,6 +2980,7 @@ sample_linear_2d_array(struct gl_context *ctx,
 /** Sample 2D Array texture, using lambda to choose between min/magnification */
 static void
 sample_lambda_2d_array(struct gl_context *ctx,
+                       const struct gl_sampler_object *samp,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4], const GLfloat lambda[],
                        GLfloat rgba[][4])
@@ -2943,43 +2990,43 @@ sample_lambda_2d_array(struct gl_context *ctx,
    GLuint i;
 
    ASSERT(lambda != NULL);
-   compute_min_mag_ranges(tObj, n, lambda,
+   compute_min_mag_ranges(samp, n, lambda,
                           &minStart, &minEnd, &magStart, &magEnd);
 
    if (minStart < minEnd) {
       /* do the minified texels */
       GLuint m = minEnd - minStart;
-      switch (tObj->Sampler.MinFilter) {
+      switch (samp->MinFilter) {
       case GL_NEAREST:
          for (i = minStart; i < minEnd; i++)
-            sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_2d_array_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                                     texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = minStart; i < minEnd; i++)
-            sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_2d_array_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                                    texcoords[i], rgba[i]);
          break;
       case GL_NEAREST_MIPMAP_NEAREST:
-         sample_2d_array_nearest_mipmap_nearest(ctx, tObj, m,
+         sample_2d_array_nearest_mipmap_nearest(ctx, samp, tObj, m,
                                                 texcoords + minStart,
                                                 lambda + minStart,
                                                 rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_NEAREST:
-         sample_2d_array_linear_mipmap_nearest(ctx, tObj, m, 
+         sample_2d_array_linear_mipmap_nearest(ctx, samp, tObj, m,
                                                texcoords + minStart,
                                                lambda + minStart,
                                                rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_LINEAR:
-         sample_2d_array_nearest_mipmap_linear(ctx, tObj, m,
+         sample_2d_array_nearest_mipmap_linear(ctx, samp, tObj, m,
                                                texcoords + minStart,
                                                lambda + minStart,
                                                rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_LINEAR:
-         sample_2d_array_linear_mipmap_linear(ctx, tObj, m, 
+         sample_2d_array_linear_mipmap_linear(ctx, samp, tObj, m,
                                               texcoords + minStart,
                                               lambda + minStart, 
                                               rgba + minStart);
@@ -2992,15 +3039,15 @@ sample_lambda_2d_array(struct gl_context *ctx,
 
    if (magStart < magEnd) {
       /* do the magnified texels */
-      switch (tObj->Sampler.MagFilter) {
+      switch (samp->MagFilter) {
       case GL_NEAREST:
          for (i = magStart; i < magEnd; i++)
-            sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_2d_array_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                               texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = magStart; i < magEnd; i++)
-            sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_2d_array_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                                    texcoords[i], rgba[i]);
          break;
       default:
@@ -3022,7 +3069,7 @@ sample_lambda_2d_array(struct gl_context *ctx,
  */
 static void
 sample_1d_array_nearest(struct gl_context *ctx,
-                        const struct gl_texture_object *tObj,
+                        const struct gl_sampler_object *samp,
                         const struct gl_texture_image *img,
                         const GLfloat texcoord[4],
                         GLfloat rgba[4])
@@ -3034,13 +3081,13 @@ sample_1d_array_nearest(struct gl_context *ctx,
    GLint array;
    (void) ctx;
 
-   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
+   i = nearest_texel_location(samp->WrapS, img, width, texcoord[0]);
    array = tex_array_slice(texcoord[1], height);
 
    if (i < 0 || i >= (GLint) img->Width ||
        array < 0 || array >= (GLint) img->Height) {
       /* Need this test for GL_CLAMP_TO_BORDER mode */
-      get_border_color(tObj, img, rgba);
+      get_border_color(samp, img, rgba);
    }
    else {
       swImg->FetchTexel(swImg, i, array, 0, rgba);
@@ -3053,7 +3100,7 @@ sample_1d_array_nearest(struct gl_context *ctx,
  */
 static void
 sample_1d_array_linear(struct gl_context *ctx,
-                       const struct gl_texture_object *tObj,
+                       const struct gl_sampler_object *samp,
                        const struct gl_texture_image *img,
                        const GLfloat texcoord[4],
                        GLfloat rgba[4])
@@ -3067,7 +3114,7 @@ sample_1d_array_linear(struct gl_context *ctx,
    GLfloat a;
    GLfloat t0[4], t1[4];
 
-   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
+   linear_texel_locations(samp->WrapS, img, width, texcoord[0], &i0, &i1, &a);
    array = tex_array_slice(texcoord[1], height);
 
    if (img->Border) {
@@ -3084,13 +3131,13 @@ sample_1d_array_linear(struct gl_context *ctx,
 
    /* Fetch texels */
    if (useBorderColor & (I0BIT | K0BIT)) {
-      get_border_color(tObj, img, t0);
+      get_border_color(samp, img, t0);
    }
    else {
       swImg->FetchTexel(swImg, i0, array, 0, t0);
    }
    if (useBorderColor & (I1BIT | K0BIT)) {
-      get_border_color(tObj, img, t1);
+      get_border_color(samp, img, t1);
    }
    else {
       swImg->FetchTexel(swImg, i1, array, 0, t1);
@@ -3103,6 +3150,7 @@ sample_1d_array_linear(struct gl_context *ctx,
 
 static void
 sample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx,
+                                       const struct gl_sampler_object *samp,
                                        const struct gl_texture_object *tObj,
                                        GLuint n, const GLfloat texcoord[][4],
                                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -3110,7 +3158,7 @@ sample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx,
    GLuint i;
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
+      sample_1d_array_nearest(ctx, samp, tObj->Image[0][level], texcoord[i],
                               rgba[i]);
    }
 }
@@ -3118,6 +3166,7 @@ sample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx,
 
 static void
 sample_1d_array_linear_mipmap_nearest(struct gl_context *ctx,
+                                      const struct gl_sampler_object *samp,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -3126,7 +3175,7 @@ sample_1d_array_linear_mipmap_nearest(struct gl_context *ctx,
    ASSERT(lambda != NULL);
    for (i = 0; i < n; i++) {
       GLint level = nearest_mipmap_level(tObj, lambda[i]);
-      sample_1d_array_linear(ctx, tObj, tObj->Image[0][level],
+      sample_1d_array_linear(ctx, samp, tObj->Image[0][level],
                              texcoord[i], rgba[i]);
    }
 }
@@ -3134,6 +3183,7 @@ sample_1d_array_linear_mipmap_nearest(struct gl_context *ctx,
 
 static void
 sample_1d_array_nearest_mipmap_linear(struct gl_context *ctx,
+                                      const struct gl_sampler_object *samp,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -3143,14 +3193,14 @@ sample_1d_array_nearest_mipmap_linear(struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_1d_array_nearest(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                                  texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
-         sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+         sample_1d_array_nearest(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_1d_array_nearest(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -3159,6 +3209,7 @@ sample_1d_array_nearest_mipmap_linear(struct gl_context *ctx,
 
 static void
 sample_1d_array_linear_mipmap_linear(struct gl_context *ctx,
+                                     const struct gl_sampler_object *samp,
                                      const struct gl_texture_object *tObj,
                                      GLuint n, const GLfloat texcoord[][4],
                                      const GLfloat lambda[], GLfloat rgba[][4])
@@ -3168,14 +3219,14 @@ sample_1d_array_linear_mipmap_linear(struct gl_context *ctx,
    for (i = 0; i < n; i++) {
       GLint level = linear_mipmap_level(tObj, lambda[i]);
       if (level >= tObj->_MaxLevel) {
-         sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+         sample_1d_array_linear(ctx, samp, tObj->Image[0][tObj->_MaxLevel],
                           texcoord[i], rgba[i]);
       }
       else {
          GLfloat t0[4], t1[4];  /* texels */
          const GLfloat f = FRAC(lambda[i]);
-         sample_1d_array_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
-         sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+         sample_1d_array_linear(ctx, samp, tObj->Image[0][level  ], texcoord[i], t0);
+         sample_1d_array_linear(ctx, samp, tObj->Image[0][level+1], texcoord[i], t1);
          lerp_rgba(rgba[i], f, t0, t1);
       }
    }
@@ -3185,6 +3236,7 @@ sample_1d_array_linear_mipmap_linear(struct gl_context *ctx,
 /** Sample 1D Array texture, nearest filtering for both min/magnification */
 static void
 sample_nearest_1d_array(struct gl_context *ctx,
+                        const struct gl_sampler_object *samp,
                         const struct gl_texture_object *tObj, GLuint n,
                         const GLfloat texcoords[][4], const GLfloat lambda[],
                         GLfloat rgba[][4])
@@ -3193,7 +3245,7 @@ sample_nearest_1d_array(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_1d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_1d_array_nearest(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -3201,6 +3253,7 @@ sample_nearest_1d_array(struct gl_context *ctx,
 /** Sample 1D Array texture, linear filtering for both min/magnification */
 static void
 sample_linear_1d_array(struct gl_context *ctx,
+                       const struct gl_sampler_object *samp,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4],
                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -3209,7 +3262,7 @@ sample_linear_1d_array(struct gl_context *ctx,
    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
    (void) lambda;
    for (i = 0; i < n; i++) {
-      sample_1d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+      sample_1d_array_linear(ctx, samp, image, texcoords[i], rgba[i]);
    }
 }
 
@@ -3217,6 +3270,7 @@ sample_linear_1d_array(struct gl_context *ctx,
 /** Sample 1D Array texture, using lambda to choose between min/magnification */
 static void
 sample_lambda_1d_array(struct gl_context *ctx,
+                       const struct gl_sampler_object *samp,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4], const GLfloat lambda[],
                        GLfloat rgba[][4])
@@ -3226,39 +3280,39 @@ sample_lambda_1d_array(struct gl_context *ctx,
    GLuint i;
 
    ASSERT(lambda != NULL);
-   compute_min_mag_ranges(tObj, n, lambda,
+   compute_min_mag_ranges(samp, n, lambda,
                           &minStart, &minEnd, &magStart, &magEnd);
 
    if (minStart < minEnd) {
       /* do the minified texels */
       GLuint m = minEnd - minStart;
-      switch (tObj->Sampler.MinFilter) {
+      switch (samp->MinFilter) {
       case GL_NEAREST:
          for (i = minStart; i < minEnd; i++)
-            sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_array_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                                     texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = minStart; i < minEnd; i++)
-            sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_array_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                                    texcoords[i], rgba[i]);
          break;
       case GL_NEAREST_MIPMAP_NEAREST:
-         sample_1d_array_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+         sample_1d_array_nearest_mipmap_nearest(ctx, samp, tObj, m, texcoords + minStart,
                                                 lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_NEAREST:
-         sample_1d_array_linear_mipmap_nearest(ctx, tObj, m, 
+         sample_1d_array_linear_mipmap_nearest(ctx, samp, tObj, m, 
                                                texcoords + minStart,
                                                lambda + minStart,
                                                rgba + minStart);
          break;
       case GL_NEAREST_MIPMAP_LINEAR:
-         sample_1d_array_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+         sample_1d_array_nearest_mipmap_linear(ctx, samp, tObj, m, texcoords + minStart,
                                                lambda + minStart, rgba + minStart);
          break;
       case GL_LINEAR_MIPMAP_LINEAR:
-         sample_1d_array_linear_mipmap_linear(ctx, tObj, m, 
+         sample_1d_array_linear_mipmap_linear(ctx, samp, tObj, m, 
                                               texcoords + minStart,
                                               lambda + minStart, 
                                               rgba + minStart);
@@ -3271,15 +3325,15 @@ sample_lambda_1d_array(struct gl_context *ctx,
 
    if (magStart < magEnd) {
       /* do the magnified texels */
-      switch (tObj->Sampler.MagFilter) {
+      switch (samp->MagFilter) {
       case GL_NEAREST:
          for (i = magStart; i < magEnd; i++)
-            sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_array_nearest(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                               texcoords[i], rgba[i]);
          break;
       case GL_LINEAR:
          for (i = magStart; i < magEnd; i++)
-            sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+            sample_1d_array_linear(ctx, samp, tObj->Image[0][tObj->BaseLevel],
                                    texcoords[i], rgba[i]);
          break;
       default:
@@ -3390,17 +3444,18 @@ shadow_compare4(GLenum function, GLfloat coord,
  * Choose the mipmap level to use when sampling from a depth texture.
  */
 static int
-choose_depth_texture_level(const struct gl_texture_object *tObj, GLfloat lambda)
+choose_depth_texture_level(const struct gl_sampler_object *samp,
+                           const struct gl_texture_object *tObj, GLfloat lambda)
 {
    GLint level;
 
-   if (tObj->Sampler.MinFilter == GL_NEAREST || tObj->Sampler.MinFilter == GL_LINEAR) {
+   if (samp->MinFilter == GL_NEAREST || samp->MinFilter == GL_LINEAR) {
       /* no mipmapping - use base level */
       level = tObj->BaseLevel;
    }
    else {
       /* choose mipmap level */
-      lambda = CLAMP(lambda, tObj->Sampler.MinLod, tObj->Sampler.MaxLod);
+      lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);
       level = (GLint) lambda;
       level = CLAMP(level, tObj->BaseLevel, tObj->_MaxLevel);
    }
@@ -3415,11 +3470,12 @@ choose_depth_texture_level(const struct gl_texture_object *tObj, GLfloat lambda)
  */
 static void
 sample_depth_texture( struct gl_context *ctx,
+                      const struct gl_sampler_object *samp,
                       const struct gl_texture_object *tObj, GLuint n,
                       const GLfloat texcoords[][4], const GLfloat lambda[],
                       GLfloat texel[][4] )
 {
-   const GLint level = choose_depth_texture_level(tObj, lambda[0]);
+   const GLint level = choose_depth_texture_level(samp, tObj, lambda[0]);
    const struct gl_texture_image *img = tObj->Image[0][level];
    const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
    const GLint width = img->Width;
@@ -3441,27 +3497,27 @@ sample_depth_texture( struct gl_context *ctx,
           tObj->Target == GL_TEXTURE_2D_ARRAY_EXT ||
           tObj->Target == GL_TEXTURE_CUBE_MAP);
 
-   ambient = tObj->Sampler.CompareFailValue;
+   ambient = samp->CompareFailValue;
 
-   /* XXXX if tObj->Sampler.MinFilter != tObj->Sampler.MagFilter, we're ignoring lambda */
+   /* XXXX if samp->MinFilter != samp->MagFilter, we're ignoring lambda */
 
-   function = (tObj->Sampler.CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ?
-      tObj->Sampler.CompareFunc : GL_NONE;
+   function = (samp->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ?
+      samp->CompareFunc : GL_NONE;
 
-   if (tObj->Sampler.MagFilter == GL_NEAREST) {
+   if (samp->MagFilter == GL_NEAREST) {
       GLuint i;
       for (i = 0; i < n; i++) {
          GLfloat depthSample, depthRef;
          GLint col, row, slice;
 
-         nearest_texcoord(tObj, level, texcoords[i], &col, &row, &slice);
+         nearest_texcoord(samp, tObj, level, texcoords[i], &col, &row, &slice);
 
          if (col >= 0 && row >= 0 && col < width && row < height && 
              slice >= 0 && slice < depth) {
             swImg->FetchTexel(swImg, col, row, slice, &depthSample);
          }
          else {
-            depthSample = tObj->Sampler.BorderColor.f[0];
+            depthSample = samp->BorderColor.f[0];
          }
 
          depthRef = CLAMP(texcoords[i][compare_coord], 0.0F, 1.0F);
@@ -3489,7 +3545,7 @@ sample_depth_texture( struct gl_context *ctx,
    }
    else {
       GLuint i;
-      ASSERT(tObj->Sampler.MagFilter == GL_LINEAR);
+      ASSERT(samp->MagFilter == GL_LINEAR);
       for (i = 0; i < n; i++) {
          GLfloat depth00, depth01, depth10, depth11, depthRef;
          GLint i0, i1, j0, j1;
@@ -3497,7 +3553,7 @@ sample_depth_texture( struct gl_context *ctx,
          GLfloat wi, wj;
          GLuint useBorderTexel;
 
-         linear_texcoord(tObj, level, texcoords[i], &i0, &i1, &j0, &j1, &slice,
+         linear_texcoord(samp, tObj, level, texcoords[i], &i0, &i1, &j0, &j1, &slice,
                          &wi, &wj);
 
          useBorderTexel = 0;
@@ -3517,21 +3573,21 @@ sample_depth_texture( struct gl_context *ctx,
          }
 
          if (slice < 0 || slice >= (GLint) depth) {
-            depth00 = tObj->Sampler.BorderColor.f[0];
-            depth01 = tObj->Sampler.BorderColor.f[0];
-            depth10 = tObj->Sampler.BorderColor.f[0];
-            depth11 = tObj->Sampler.BorderColor.f[0];
+            depth00 = samp->BorderColor.f[0];
+            depth01 = samp->BorderColor.f[0];
+            depth10 = samp->BorderColor.f[0];
+            depth11 = samp->BorderColor.f[0];
          }
          else {
             /* get four depth samples from the texture */
             if (useBorderTexel & (I0BIT | J0BIT)) {
-               depth00 = tObj->Sampler.BorderColor.f[0];
+               depth00 = samp->BorderColor.f[0];
             }
             else {
                swImg->FetchTexel(swImg, i0, j0, slice, &depth00);
             }
             if (useBorderTexel & (I1BIT | J0BIT)) {
-               depth10 = tObj->Sampler.BorderColor.f[0];
+               depth10 = samp->BorderColor.f[0];
             }
             else {
                swImg->FetchTexel(swImg, i1, j0, slice, &depth10);
@@ -3539,13 +3595,13 @@ sample_depth_texture( struct gl_context *ctx,
 
             if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
                if (useBorderTexel & (I0BIT | J1BIT)) {
-                  depth01 = tObj->Sampler.BorderColor.f[0];
+                  depth01 = samp->BorderColor.f[0];
                }
                else {
                   swImg->FetchTexel(swImg, i0, j1, slice, &depth01);
                }
                if (useBorderTexel & (I1BIT | J1BIT)) {
-                  depth11 = tObj->Sampler.BorderColor.f[0];
+                  depth11 = samp->BorderColor.f[0];
                }
                else {
                   swImg->FetchTexel(swImg, i1, j1, slice, &depth11);
@@ -3590,6 +3646,7 @@ sample_depth_texture( struct gl_context *ctx,
  */
 static void
 null_sample_func( struct gl_context *ctx,
+                  const struct gl_sampler_object *samp,
 		  const struct gl_texture_object *tObj, GLuint n,
 		  const GLfloat texcoords[][4], const GLfloat lambda[],
 		  GLfloat rgba[][4])
@@ -3599,6 +3656,7 @@ null_sample_func( struct gl_context *ctx,
    (void) tObj;
    (void) texcoords;
    (void) lambda;
+   (void) samp;
    for (i = 0; i < n; i++) {
       rgba[i][RCOMP] = 0;
       rgba[i][GCOMP] = 0;
@@ -3621,7 +3679,7 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
    }
    else {
       const GLboolean needLambda =
-         (GLboolean) (t->Sampler.MinFilter != t->Sampler.MagFilter);
+         (GLboolean) (sampler->MinFilter != sampler->MagFilter);
       const GLenum format = t->Image[0][t->BaseLevel]->_BaseFormat;
 
       switch (t->Target) {
@@ -3632,11 +3690,11 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
          else if (needLambda) {
             return &sample_lambda_1d;
          }
-         else if (t->Sampler.MinFilter == GL_LINEAR) {
+         else if (sampler->MinFilter == GL_LINEAR) {
             return &sample_linear_1d;
          }
          else {
-            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
+            ASSERT(sampler->MinFilter == GL_NEAREST);
             return &sample_nearest_1d;
          }
       case GL_TEXTURE_2D:
@@ -3645,13 +3703,13 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
          }
          else if (needLambda) {
             /* Anisotropic filtering extension. Activated only if mipmaps are used */
-            if (t->Sampler.MaxAnisotropy > 1.0 &&
-                t->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
+            if (sampler->MaxAnisotropy > 1.0 &&
+                sampler->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
                return &sample_lambda_2d_aniso;
             }
             return &sample_lambda_2d;
          }
-         else if (t->Sampler.MinFilter == GL_LINEAR) {
+         else if (sampler->MinFilter == GL_LINEAR) {
             return &sample_linear_2d;
          }
          else {
@@ -3661,10 +3719,10 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
                swrast_texture_image_const(img);
             texture_sample_func func;
 
-            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
+            ASSERT(sampler->MinFilter == GL_NEAREST);
             func = &sample_nearest_2d;
-            if (t->Sampler.WrapS == GL_REPEAT &&
-                t->Sampler.WrapT == GL_REPEAT &&
+            if (sampler->WrapS == GL_REPEAT &&
+                sampler->WrapT == GL_REPEAT &&
                 swImg->_IsPowerOfTwo &&
                 img->Border == 0) {
                if (img->TexFormat == MESA_FORMAT_RGB888)
@@ -3679,11 +3737,11 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
          if (needLambda) {
             return &sample_lambda_3d;
          }
-         else if (t->Sampler.MinFilter == GL_LINEAR) {
+         else if (sampler->MinFilter == GL_LINEAR) {
             return &sample_linear_3d;
          }
          else {
-            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
+            ASSERT(sampler->MinFilter == GL_NEAREST);
             return &sample_nearest_3d;
          }
       case GL_TEXTURE_CUBE_MAP:
@@ -3693,11 +3751,11 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
 	 else if (needLambda) {
             return &sample_lambda_cube;
          }
-         else if (t->Sampler.MinFilter == GL_LINEAR) {
+         else if (sampler->MinFilter == GL_LINEAR) {
             return &sample_linear_cube;
          }
          else {
-            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
+            ASSERT(sampler->MinFilter == GL_NEAREST);
             return &sample_nearest_cube;
          }
       case GL_TEXTURE_RECTANGLE_NV:
@@ -3707,11 +3765,11 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
          else if (needLambda) {
             return &sample_lambda_rect;
          }
-         else if (t->Sampler.MinFilter == GL_LINEAR) {
+         else if (sampler->MinFilter == GL_LINEAR) {
             return &sample_linear_rect;
          }
          else {
-            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
+            ASSERT(sampler->MinFilter == GL_NEAREST);
             return &sample_nearest_rect;
          }
       case GL_TEXTURE_1D_ARRAY_EXT:
@@ -3721,11 +3779,11 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
 	 else if (needLambda) {
             return &sample_lambda_1d_array;
          }
-         else if (t->Sampler.MinFilter == GL_LINEAR) {
+         else if (sampler->MinFilter == GL_LINEAR) {
             return &sample_linear_1d_array;
          }
          else {
-            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
+            ASSERT(sampler->MinFilter == GL_NEAREST);
             return &sample_nearest_1d_array;
          }
       case GL_TEXTURE_2D_ARRAY_EXT:
@@ -3735,11 +3793,11 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
 	 else if (needLambda) {
             return &sample_lambda_2d_array;
          }
-         else if (t->Sampler.MinFilter == GL_LINEAR) {
+         else if (sampler->MinFilter == GL_LINEAR) {
             return &sample_linear_2d_array;
          }
          else {
-            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
+            ASSERT(sampler->MinFilter == GL_NEAREST);
             return &sample_nearest_2d_array;
          }
       default:
diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c
index 7687ae0..74772db 100644
--- a/src/mesa/tnl/t_vb_program.c
+++ b/src/mesa/tnl/t_vb_program.c
@@ -35,6 +35,7 @@
 #include "main/colormac.h"
 #include "main/macros.h"
 #include "main/imports.h"
+#include "main/samplerobj.h"
 #include "math/m_xform.h"
 #include "program/prog_instruction.h"
 #include "program/prog_statevars.h"
@@ -197,7 +198,8 @@ vp_fetch_texel(struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
    /* XXX use a float-valued TextureSample routine here!!! */
-   swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
+   swrast->TextureSample[unit](ctx, _mesa_get_samplerobj(ctx, unit),
+                               ctx->Texture.Unit[unit]._Current,
                                1, (const GLfloat (*)[4]) texcoord,
                                &lambda,  (GLfloat (*)[4]) color);
 }
-- 
1.7.9.5



More information about the mesa-dev mailing list