swrast: Support sampler object for texture fetching state
authorPauli Nieminen <pauli.nieminen@linux.intel.com>
Tue, 12 Jun 2012 18:38:56 +0000 (21:38 +0300)
committerEric Anholt <eric@anholt.net>
Wed, 1 Aug 2012 22:55:51 +0000 (15:55 -0700)
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.

v2: Fix NULL deref in _swrast_choose_triangle(), because the _Current
    values aren't set yet, so we need to look at our texObj2D. (anholt)

Signed-off-by: Pauli Nieminen <pauli.nieminen@linux.intel.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/swrast/s_atifragshader.c
src/mesa/swrast/s_context.c
src/mesa/swrast/s_context.h
src/mesa/swrast/s_fragprog.c
src/mesa/swrast/s_span.c
src/mesa/swrast/s_texcombine.c
src/mesa/swrast/s_texfetch.c
src/mesa/swrast/s_texfetch.h
src/mesa/swrast/s_texfilter.c
src/mesa/swrast/s_triangle.c
src/mesa/tnl/t_vb_program.c

index 1eb026e0092052cf73a4eeafa4cfc3a345b863ba..394fac50b66c6a13533ddb04cfce4760e36f5b08 100644 (file)
@@ -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);
 }
 
index 432db71c8b0b355c3b8a03fd6e23e3d1c4d29df7..4ed7b94c7bf0831665a20b1d9e7a505dfedf0d23 100644 (file)
@@ -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));
index 26b97f78decdfc322dd67d2ef8d8162ed9026e2c..18353c4167b399b0ea24f711224cdba6fa299c64 100644 (file)
@@ -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]);
index 8d59371c8367c718b4934a1523c8be466654aa2a..812189f094687b48e327e308b5b63f3fb078757e 100644 (file)
@@ -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);
    }
index 627ef1136aa5dd5d0dd504f80054fe64c18bece6..ef51479fdcfd9844a64d84e2b82d432a3a4bcd3a 100644 (file)
@@ -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;
index 8fbf988b415991711ac6aa85d7055ab25488ccae..2a323613ea8661c858993bf996c8d2af5ba75f87 100644 (file)
@@ -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) {
index 12ee47963d74f30927fc9ec09d1c8492eb670f40..db7c887b6737d0d7a583682d1e3be9a7c7f23080 100644 (file)
@@ -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"
@@ -1147,13 +1148,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);
    }
@@ -1163,17 +1165,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);
          }
       }
index 1aa7ce573e27008dd99ca6344b2a4dc6405e99a7..33950ce440c4c81fd6de85e43da4df8acc10e2bd 100644 (file)
@@ -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 */
index 103b4425b538b203d6400ce0518146ccedbc5b1a..51c8992087a1dd0f2335cae0626aae3536671e3a 100644 (file)
@@ -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:
index e89a999a9342645ef807958f6dc033f79410da19..893859db0832f37c5b426a00f9fd3baa06771bfe 100644 (file)
@@ -36,6 +36,7 @@
 #include "main/macros.h"
 #include "main/mtypes.h"
 #include "main/state.h"
+#include "main/samplerobj.h"
 #include "program/prog_instruction.h"
 
 #include "s_aatriangle.h"
@@ -1045,18 +1046,25 @@ _swrast_choose_triangle( struct gl_context *ctx )
           swrast->_FogEnabled) {
          /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
          const struct gl_texture_object *texObj2D;
+         const struct gl_sampler_object *samp;
          const struct gl_texture_image *texImg;
          const struct swrast_texture_image *swImg;
          GLenum minFilter, magFilter, envMode;
          gl_format format;
          texObj2D = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];
+         if (ctx->Texture.Unit[0].Sampler)
+            samp = ctx->Texture.Unit[0].Sampler;
+         else if (texObj2D)
+            samp = &texObj2D->Sampler;
+         else
+            samp = NULL;
 
          texImg = texObj2D ? texObj2D->Image[0][texObj2D->BaseLevel] : NULL;
          swImg = swrast_texture_image_const(texImg);
 
          format = texImg ? texImg->TexFormat : MESA_FORMAT_NONE;
-         minFilter = texObj2D ? texObj2D->Sampler.MinFilter : GL_NONE;
-         magFilter = texObj2D ? texObj2D->Sampler.MagFilter : GL_NONE;
+         minFilter = texObj2D ? samp->MinFilter : GL_NONE;
+         magFilter = texObj2D ? samp->MagFilter : GL_NONE;
          envMode = ctx->Texture.Unit[0].EnvMode;
 
          /* First see if we can use an optimized 2-D texture function */
@@ -1065,8 +1073,8 @@ _swrast_choose_triangle( struct gl_context *ctx )
              && !ctx->ATIFragmentShader._Enabled
              && ctx->Texture._EnabledUnits == 0x1
              && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
-             && texObj2D->Sampler.WrapS == GL_REPEAT
-             && texObj2D->Sampler.WrapT == GL_REPEAT
+             && samp->WrapS == GL_REPEAT
+             && samp->WrapT == GL_REPEAT
              && texObj2D->_Swizzle == SWIZZLE_NOOP
              && swImg->_IsPowerOfTwo
              && texImg->Border == 0
index 7687ae0b3cf39ed7980e3f2c4caf2df1dbe32171..74772dbbe537ac8f08fbce9f0ff95e38d2479066 100644 (file)
@@ -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);
 }