Merge branch 'llvm-cliptest-viewport'
[mesa.git] / src / mesa / swrast / s_texfilter.c
index 76b65cc755e4c9bb1f058a3e2d2228ebb6be9bd6..ec281776d0d1f998fffc9a36bd8d7cdf464fa7ac 100644 (file)
@@ -135,8 +135,11 @@ lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c,
 
 
 /**
- * If A is a signed integer, A % B doesn't give the right value for A < 0
- * (in terms of texture repeat).  Just casting to unsigned fixes that.
+ * Used for GL_REPEAT wrap mode.  Using A % B doesn't produce the
+ * right results for A<0.  Casting to A to be unsigned only works if B
+ * is a power of two.  Adding a bias to A (which is a multiple of B)
+ * avoids the problems with A < 0 (for reasonable A) without using a
+ * conditional.
  */
 #define REMAINDER(A, B) (((A) + (B) * 1024) % (B))
 
@@ -445,7 +448,7 @@ clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
    switch (wrapMode) {
    case GL_CLAMP:
       /* Not exactly what the spec says, but it matches NVIDIA output */
-      fcol = CLAMP(coord - 0.5F, 0.0, max-1);
+      fcol = CLAMP(coord - 0.5F, 0.0F, max - 1);
       i0 = IFLOOR(fcol);
       i1 = i0 + 1;
       break;
@@ -474,16 +477,29 @@ clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
 }
 
 
+/**
+ * Compute slice/image to use for 1D or 2D array texture.
+ */
+static INLINE GLint
+tex_array_slice(GLfloat coord, GLsizei size)
+{
+   GLint slice = IFLOOR(coord + 0.5f);
+   slice = CLAMP(slice, 0, size - 1);
+   return slice;
+}
+
+
 /**
  * Compute nearest integer texcoords for given texobj and coordinate.
+ * NOTE: only used for depth texture sampling.
  */
 static INLINE void
 nearest_texcoord(const struct gl_texture_object *texObj,
+                 GLuint level,
                  const GLfloat texcoord[4],
                  GLint *i, GLint *j, GLint *k)
 {
-   const GLint baseLevel = texObj->BaseLevel;
-   const struct gl_texture_image *img = texObj->Image[0][baseLevel];
+   const struct gl_texture_image *img = texObj->Image[0][level];
    const GLint width = img->Width;
    const GLint height = img->Height;
    const GLint depth = img->Depth;
@@ -506,13 +522,13 @@ nearest_texcoord(const struct gl_texture_object *texObj,
       break;
    case GL_TEXTURE_1D_ARRAY_EXT:
       *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
-      *j = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+      *j = tex_array_slice(texcoord[1], height);
       *k = 0;
       break;
    case GL_TEXTURE_2D_ARRAY_EXT:
       *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
       *j = nearest_texel_location(texObj->WrapT, img, height, texcoord[1]);
-      *k = clamp_rect_coord_nearest(texObj->WrapR, texcoord[2], depth);
+      *k = tex_array_slice(texcoord[2], depth);
       break;
    default:
       *i = *j = *k = 0;
@@ -522,15 +538,16 @@ nearest_texcoord(const struct gl_texture_object *texObj,
 
 /**
  * Compute linear integer texcoords for given texobj and coordinate.
+ * NOTE: only used for depth texture sampling.
  */
 static INLINE void
 linear_texcoord(const struct gl_texture_object *texObj,
+                GLuint level,
                 const GLfloat texcoord[4],
                 GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice,
                 GLfloat *wi, GLfloat *wj)
 {
-   const GLint baseLevel = texObj->BaseLevel;
-   const struct gl_texture_image *img = texObj->Image[0][baseLevel];
+   const struct gl_texture_image *img = texObj->Image[0][level];
    const GLint width = img->Width;
    const GLint height = img->Height;
    const GLint depth = img->Depth;
@@ -556,7 +573,7 @@ linear_texcoord(const struct gl_texture_object *texObj,
    case GL_TEXTURE_1D_ARRAY_EXT:
       linear_texel_locations(texObj->WrapS, img, width,
                              texcoord[0], i0, i1, wi);
-      *j0 = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+      *j0 = tex_array_slice(texcoord[1], height);
       *j1 = *j0;
       *slice = 0;
       break;
@@ -566,7 +583,7 @@ linear_texcoord(const struct gl_texture_object *texObj,
                              texcoord[0], i0, i1, wi);
       linear_texel_locations(texObj->WrapT, img, height,
                              texcoord[1], j0, j1, wj);
-      *slice = clamp_rect_coord_nearest(texObj->WrapR, texcoord[2], depth);
+      *slice = tex_array_slice(texcoord[2], depth);
       break;
 
    default:
@@ -781,7 +798,7 @@ get_border_color(const struct gl_texture_object *tObj,
  * Return the texture sample for coordinate (s) using GL_NEAREST filter.
  */
 static INLINE void
-sample_1d_nearest(GLcontext *ctx,
+sample_1d_nearest(struct gl_context *ctx,
                   const struct gl_texture_object *tObj,
                   const struct gl_texture_image *img,
                   const GLfloat texcoord[4], GLfloat rgba[4])
@@ -805,7 +822,7 @@ sample_1d_nearest(GLcontext *ctx,
  * Return the texture sample for coordinate (s) using GL_LINEAR filter.
  */
 static INLINE void
-sample_1d_linear(GLcontext *ctx,
+sample_1d_linear(struct gl_context *ctx,
                  const struct gl_texture_object *tObj,
                  const struct gl_texture_image *img,
                  const GLfloat texcoord[4], GLfloat rgba[4])
@@ -846,7 +863,7 @@ sample_1d_linear(GLcontext *ctx,
 
 
 static void
-sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
+sample_1d_nearest_mipmap_nearest(struct gl_context *ctx,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -861,7 +878,7 @@ sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_1d_linear_mipmap_nearest(GLcontext *ctx,
+sample_1d_linear_mipmap_nearest(struct gl_context *ctx,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -876,7 +893,7 @@ sample_1d_linear_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_1d_nearest_mipmap_linear(GLcontext *ctx,
+sample_1d_nearest_mipmap_linear(struct gl_context *ctx,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -901,7 +918,7 @@ sample_1d_nearest_mipmap_linear(GLcontext *ctx,
 
 
 static void
-sample_1d_linear_mipmap_linear(GLcontext *ctx,
+sample_1d_linear_mipmap_linear(struct gl_context *ctx,
                                const struct gl_texture_object *tObj,
                                GLuint n, const GLfloat texcoord[][4],
                                const GLfloat lambda[], GLfloat rgba[][4])
@@ -927,7 +944,7 @@ sample_1d_linear_mipmap_linear(GLcontext *ctx,
 
 /** Sample 1D texture, nearest filtering for both min/magnification */
 static void
-sample_nearest_1d( GLcontext *ctx,
+sample_nearest_1d( struct gl_context *ctx,
                    const struct gl_texture_object *tObj, GLuint n,
                    const GLfloat texcoords[][4], const GLfloat lambda[],
                    GLfloat rgba[][4] )
@@ -943,7 +960,7 @@ sample_nearest_1d( GLcontext *ctx,
 
 /** Sample 1D texture, linear filtering for both min/magnification */
 static void
-sample_linear_1d( GLcontext *ctx,
+sample_linear_1d( struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4], const GLfloat lambda[],
                   GLfloat rgba[][4] )
@@ -959,7 +976,7 @@ sample_linear_1d( GLcontext *ctx,
 
 /** Sample 1D texture, using lambda to choose between min/magnification */
 static void
-sample_lambda_1d( GLcontext *ctx,
+sample_lambda_1d( struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4] )
@@ -1038,7 +1055,7 @@ sample_lambda_1d( GLcontext *ctx,
  * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
  */
 static INLINE void
-sample_2d_nearest(GLcontext *ctx,
+sample_2d_nearest(struct gl_context *ctx,
                   const struct gl_texture_object *tObj,
                   const struct gl_texture_image *img,
                   const GLfloat texcoord[4],
@@ -1071,7 +1088,7 @@ sample_2d_nearest(GLcontext *ctx,
  * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
  */
 static INLINE void
-sample_2d_linear(GLcontext *ctx,
+sample_2d_linear(struct gl_context *ctx,
                  const struct gl_texture_object *tObj,
                  const struct gl_texture_image *img,
                  const GLfloat texcoord[4],
@@ -1135,7 +1152,7 @@ sample_2d_linear(GLcontext *ctx,
  * We don't have to worry about the texture border.
  */
 static INLINE void
-sample_2d_linear_repeat(GLcontext *ctx,
+sample_2d_linear_repeat(struct gl_context *ctx,
                         const struct gl_texture_object *tObj,
                         const struct gl_texture_image *img,
                         const GLfloat texcoord[4],
@@ -1168,7 +1185,7 @@ sample_2d_linear_repeat(GLcontext *ctx,
 
 
 static void
-sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
+sample_2d_nearest_mipmap_nearest(struct gl_context *ctx,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -1182,7 +1199,7 @@ sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_2d_linear_mipmap_nearest(GLcontext *ctx,
+sample_2d_linear_mipmap_nearest(struct gl_context *ctx,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -1197,7 +1214,7 @@ sample_2d_linear_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_2d_nearest_mipmap_linear(GLcontext *ctx,
+sample_2d_nearest_mipmap_linear(struct gl_context *ctx,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -1222,7 +1239,7 @@ sample_2d_nearest_mipmap_linear(GLcontext *ctx,
 
 
 static void
-sample_2d_linear_mipmap_linear( GLcontext *ctx,
+sample_2d_linear_mipmap_linear( struct gl_context *ctx,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4] )
@@ -1247,7 +1264,7 @@ sample_2d_linear_mipmap_linear( GLcontext *ctx,
 
 
 static void
-sample_2d_linear_mipmap_linear_repeat(GLcontext *ctx,
+sample_2d_linear_mipmap_linear_repeat(struct gl_context *ctx,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -1277,7 +1294,7 @@ sample_2d_linear_mipmap_linear_repeat(GLcontext *ctx,
 
 /** Sample 2D texture, nearest filtering for both min/magnification */
 static void
-sample_nearest_2d(GLcontext *ctx,
+sample_nearest_2d(struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -1293,7 +1310,7 @@ sample_nearest_2d(GLcontext *ctx,
 
 /** Sample 2D texture, linear filtering for both min/magnification */
 static void
-sample_linear_2d(GLcontext *ctx,
+sample_linear_2d(struct gl_context *ctx,
                  const struct gl_texture_object *tObj, GLuint n,
                  const GLfloat texcoords[][4],
                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -1326,7 +1343,7 @@ sample_linear_2d(GLcontext *ctx,
  *    Format = GL_RGB
  */
 static void
-opt_sample_rgb_2d(GLcontext *ctx,
+opt_sample_rgb_2d(struct gl_context *ctx,
                   const struct gl_texture_object *tObj,
                   GLuint n, const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -1367,7 +1384,7 @@ opt_sample_rgb_2d(GLcontext *ctx,
  *    Format = GL_RGBA
  */
 static void
-opt_sample_rgba_2d(GLcontext *ctx,
+opt_sample_rgba_2d(struct gl_context *ctx,
                    const struct gl_texture_object *tObj,
                    GLuint n, const GLfloat texcoords[][4],
                    const GLfloat lambda[], GLfloat rgba[][4])
@@ -1402,7 +1419,7 @@ opt_sample_rgba_2d(GLcontext *ctx,
 
 /** Sample 2D texture, using lambda to choose between min/magnification */
 static void
-sample_lambda_2d(GLcontext *ctx,
+sample_lambda_2d(struct gl_context *ctx,
                  const struct gl_texture_object *tObj,
                  GLuint n, const GLfloat texcoords[][4],
                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -1523,7 +1540,7 @@ sample_lambda_2d(GLcontext *ctx,
  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  */
 static INLINE void
-sample_3d_nearest(GLcontext *ctx,
+sample_3d_nearest(struct gl_context *ctx,
                   const struct gl_texture_object *tObj,
                   const struct gl_texture_image *img,
                   const GLfloat texcoord[4],
@@ -1555,7 +1572,7 @@ sample_3d_nearest(GLcontext *ctx,
  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  */
 static void
-sample_3d_linear(GLcontext *ctx,
+sample_3d_linear(struct gl_context *ctx,
                  const struct gl_texture_object *tObj,
                  const struct gl_texture_image *img,
                  const GLfloat texcoord[4],
@@ -1649,7 +1666,7 @@ sample_3d_linear(GLcontext *ctx,
 
 
 static void
-sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
+sample_3d_nearest_mipmap_nearest(struct gl_context *ctx,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4] )
@@ -1663,7 +1680,7 @@ sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_3d_linear_mipmap_nearest(GLcontext *ctx,
+sample_3d_linear_mipmap_nearest(struct gl_context *ctx,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -1678,7 +1695,7 @@ sample_3d_linear_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_3d_nearest_mipmap_linear(GLcontext *ctx,
+sample_3d_nearest_mipmap_linear(struct gl_context *ctx,
                                 const struct gl_texture_object *tObj,
                                 GLuint n, const GLfloat texcoord[][4],
                                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -1703,7 +1720,7 @@ sample_3d_nearest_mipmap_linear(GLcontext *ctx,
 
 
 static void
-sample_3d_linear_mipmap_linear(GLcontext *ctx,
+sample_3d_linear_mipmap_linear(struct gl_context *ctx,
                                const struct gl_texture_object *tObj,
                                GLuint n, const GLfloat texcoord[][4],
                                const GLfloat lambda[], GLfloat rgba[][4])
@@ -1729,7 +1746,7 @@ sample_3d_linear_mipmap_linear(GLcontext *ctx,
 
 /** Sample 3D texture, nearest filtering for both min/magnification */
 static void
-sample_nearest_3d(GLcontext *ctx,
+sample_nearest_3d(struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4], const GLfloat lambda[],
                   GLfloat rgba[][4])
@@ -1745,7 +1762,7 @@ sample_nearest_3d(GLcontext *ctx,
 
 /** Sample 3D texture, linear filtering for both min/magnification */
 static void
-sample_linear_3d(GLcontext *ctx,
+sample_linear_3d(struct gl_context *ctx,
                  const struct gl_texture_object *tObj, GLuint n,
                  const GLfloat texcoords[][4],
                 const GLfloat lambda[], GLfloat rgba[][4])
@@ -1761,7 +1778,7 @@ sample_linear_3d(GLcontext *ctx,
 
 /** Sample 3D texture, using lambda to choose between min/magnification */
 static void
-sample_lambda_3d(GLcontext *ctx,
+sample_lambda_3d(struct gl_context *ctx,
                  const struct gl_texture_object *tObj, GLuint n,
                  const GLfloat texcoords[][4], const GLfloat lambda[],
                  GLfloat rgba[][4])
@@ -1916,7 +1933,7 @@ choose_cube_face(const struct gl_texture_object *texObj,
 
 
 static void
-sample_nearest_cube(GLcontext *ctx,
+sample_nearest_cube(struct gl_context *ctx,
                    const struct gl_texture_object *tObj, GLuint n,
                     const GLfloat texcoords[][4], const GLfloat lambda[],
                     GLfloat rgba[][4])
@@ -1934,7 +1951,7 @@ sample_nearest_cube(GLcontext *ctx,
 
 
 static void
-sample_linear_cube(GLcontext *ctx,
+sample_linear_cube(struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                    const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -1952,7 +1969,7 @@ sample_linear_cube(GLcontext *ctx,
 
 
 static void
-sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
+sample_cube_nearest_mipmap_nearest(struct gl_context *ctx,
                                    const struct gl_texture_object *tObj,
                                    GLuint n, const GLfloat texcoord[][4],
                                    const GLfloat lambda[], GLfloat rgba[][4])
@@ -1981,7 +1998,7 @@ sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_cube_linear_mipmap_nearest(GLcontext *ctx,
+sample_cube_linear_mipmap_nearest(struct gl_context *ctx,
                                   const struct gl_texture_object *tObj,
                                   GLuint n, const GLfloat texcoord[][4],
                                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -2000,7 +2017,7 @@ sample_cube_linear_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_cube_nearest_mipmap_linear(GLcontext *ctx,
+sample_cube_nearest_mipmap_linear(struct gl_context *ctx,
                                   const struct gl_texture_object *tObj,
                                   GLuint n, const GLfloat texcoord[][4],
                                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -2029,7 +2046,7 @@ sample_cube_nearest_mipmap_linear(GLcontext *ctx,
 
 
 static void
-sample_cube_linear_mipmap_linear(GLcontext *ctx,
+sample_cube_linear_mipmap_linear(struct gl_context *ctx,
                                  const struct gl_texture_object *tObj,
                                  GLuint n, const GLfloat texcoord[][4],
                                  const GLfloat lambda[], GLfloat rgba[][4])
@@ -2059,7 +2076,7 @@ sample_cube_linear_mipmap_linear(GLcontext *ctx,
 
 /** Sample cube texture, using lambda to choose between min/magnification */
 static void
-sample_lambda_cube(GLcontext *ctx,
+sample_lambda_cube(struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4], const GLfloat lambda[],
                   GLfloat rgba[][4])
@@ -2133,7 +2150,7 @@ sample_lambda_cube(GLcontext *ctx,
 
 
 static void
-sample_nearest_rect(GLcontext *ctx,
+sample_nearest_rect(struct gl_context *ctx,
                    const struct gl_texture_object *tObj, GLuint n,
                     const GLfloat texcoords[][4], const GLfloat lambda[],
                     GLfloat rgba[][4])
@@ -2167,7 +2184,7 @@ sample_nearest_rect(GLcontext *ctx,
 
 
 static void
-sample_linear_rect(GLcontext *ctx,
+sample_linear_rect(struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                    const GLfloat texcoords[][4],
                   const GLfloat lambda[], GLfloat rgba[][4])
@@ -2233,7 +2250,7 @@ sample_linear_rect(GLcontext *ctx,
 
 /** Sample Rect texture, using lambda to choose between min/magnification */
 static void
-sample_lambda_rect(GLcontext *ctx,
+sample_lambda_rect(struct gl_context *ctx,
                   const struct gl_texture_object *tObj, GLuint n,
                   const GLfloat texcoords[][4], const GLfloat lambda[],
                   GLfloat rgba[][4])
@@ -2269,7 +2286,6 @@ sample_lambda_rect(GLcontext *ctx,
 }
 
 
-
 /**********************************************************************/
 /*                2D Texture Array Sampling Functions                 */
 /**********************************************************************/
@@ -2278,7 +2294,7 @@ sample_lambda_rect(GLcontext *ctx,
  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  */
 static void
-sample_2d_array_nearest(GLcontext *ctx,
+sample_2d_array_nearest(struct gl_context *ctx,
                         const struct gl_texture_object *tObj,
                         const struct gl_texture_image *img,
                         const GLfloat texcoord[4],
@@ -2293,7 +2309,7 @@ sample_2d_array_nearest(GLcontext *ctx,
 
    i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
    j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]);
-   array = clamp_rect_coord_nearest(tObj->WrapR, texcoord[2], depth);
+   array = tex_array_slice(texcoord[2], depth);
 
    if (i < 0 || i >= (GLint) img->Width ||
        j < 0 || j >= (GLint) img->Height ||
@@ -2311,7 +2327,7 @@ sample_2d_array_nearest(GLcontext *ctx,
  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  */
 static void
-sample_2d_array_linear(GLcontext *ctx,
+sample_2d_array_linear(struct gl_context *ctx,
                        const struct gl_texture_object *tObj,
                        const struct gl_texture_image *img,
                        const GLfloat texcoord[4],
@@ -2328,7 +2344,7 @@ sample_2d_array_linear(GLcontext *ctx,
 
    linear_texel_locations(tObj->WrapS, img, width,  texcoord[0], &i0, &i1, &a);
    linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
-   array = clamp_rect_coord_nearest(tObj->WrapR, texcoord[2], depth);
+   array = tex_array_slice(texcoord[2], depth);
 
    if (array < 0 || array >= depth) {
       COPY_4V(rgba, tObj->BorderColor.f);
@@ -2381,7 +2397,7 @@ sample_2d_array_linear(GLcontext *ctx,
 
 
 static void
-sample_2d_array_nearest_mipmap_nearest(GLcontext *ctx,
+sample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx,
                                        const struct gl_texture_object *tObj,
                                        GLuint n, const GLfloat texcoord[][4],
                                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -2396,7 +2412,7 @@ sample_2d_array_nearest_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_2d_array_linear_mipmap_nearest(GLcontext *ctx,
+sample_2d_array_linear_mipmap_nearest(struct gl_context *ctx,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -2412,7 +2428,7 @@ sample_2d_array_linear_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_2d_array_nearest_mipmap_linear(GLcontext *ctx,
+sample_2d_array_nearest_mipmap_linear(struct gl_context *ctx,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -2439,7 +2455,7 @@ sample_2d_array_nearest_mipmap_linear(GLcontext *ctx,
 
 
 static void
-sample_2d_array_linear_mipmap_linear(GLcontext *ctx,
+sample_2d_array_linear_mipmap_linear(struct gl_context *ctx,
                                      const struct gl_texture_object *tObj,
                                      GLuint n, const GLfloat texcoord[][4],
                                      const GLfloat lambda[], GLfloat rgba[][4])
@@ -2467,7 +2483,7 @@ sample_2d_array_linear_mipmap_linear(GLcontext *ctx,
 
 /** Sample 2D Array texture, nearest filtering for both min/magnification */
 static void
-sample_nearest_2d_array(GLcontext *ctx,
+sample_nearest_2d_array(struct gl_context *ctx,
                         const struct gl_texture_object *tObj, GLuint n,
                         const GLfloat texcoords[][4], const GLfloat lambda[],
                         GLfloat rgba[][4])
@@ -2484,7 +2500,7 @@ sample_nearest_2d_array(GLcontext *ctx,
 
 /** Sample 2D Array texture, linear filtering for both min/magnification */
 static void
-sample_linear_2d_array(GLcontext *ctx,
+sample_linear_2d_array(struct gl_context *ctx,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4],
                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -2500,7 +2516,7 @@ sample_linear_2d_array(GLcontext *ctx,
 
 /** Sample 2D Array texture, using lambda to choose between min/magnification */
 static void
-sample_lambda_2d_array(GLcontext *ctx,
+sample_lambda_2d_array(struct gl_context *ctx,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4], const GLfloat lambda[],
                        GLfloat rgba[][4])
@@ -2588,7 +2604,7 @@ sample_lambda_2d_array(GLcontext *ctx,
  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  */
 static void
-sample_1d_array_nearest(GLcontext *ctx,
+sample_1d_array_nearest(struct gl_context *ctx,
                         const struct gl_texture_object *tObj,
                         const struct gl_texture_image *img,
                         const GLfloat texcoord[4],
@@ -2601,7 +2617,7 @@ sample_1d_array_nearest(GLcontext *ctx,
    (void) ctx;
 
    i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
-   array = clamp_rect_coord_nearest(tObj->WrapT, texcoord[1], height);
+   array = tex_array_slice(texcoord[1], height);
 
    if (i < 0 || i >= (GLint) img->Width ||
        array < 0 || array >= (GLint) img->Height) {
@@ -2618,7 +2634,7 @@ sample_1d_array_nearest(GLcontext *ctx,
  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  */
 static void
-sample_1d_array_linear(GLcontext *ctx,
+sample_1d_array_linear(struct gl_context *ctx,
                        const struct gl_texture_object *tObj,
                        const struct gl_texture_image *img,
                        const GLfloat texcoord[4],
@@ -2633,7 +2649,7 @@ sample_1d_array_linear(GLcontext *ctx,
    GLfloat t0[4], t1[4];
 
    linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
-   array = clamp_rect_coord_nearest(tObj->WrapT, texcoord[1], height);
+   array = tex_array_slice(texcoord[1], height);
 
    if (img->Border) {
       i0 += img->Border;
@@ -2667,7 +2683,7 @@ sample_1d_array_linear(GLcontext *ctx,
 
 
 static void
-sample_1d_array_nearest_mipmap_nearest(GLcontext *ctx,
+sample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx,
                                        const struct gl_texture_object *tObj,
                                        GLuint n, const GLfloat texcoord[][4],
                                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -2682,7 +2698,7 @@ sample_1d_array_nearest_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_1d_array_linear_mipmap_nearest(GLcontext *ctx,
+sample_1d_array_linear_mipmap_nearest(struct gl_context *ctx,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -2698,7 +2714,7 @@ sample_1d_array_linear_mipmap_nearest(GLcontext *ctx,
 
 
 static void
-sample_1d_array_nearest_mipmap_linear(GLcontext *ctx,
+sample_1d_array_nearest_mipmap_linear(struct gl_context *ctx,
                                       const struct gl_texture_object *tObj,
                                       GLuint n, const GLfloat texcoord[][4],
                                       const GLfloat lambda[], GLfloat rgba[][4])
@@ -2723,7 +2739,7 @@ sample_1d_array_nearest_mipmap_linear(GLcontext *ctx,
 
 
 static void
-sample_1d_array_linear_mipmap_linear(GLcontext *ctx,
+sample_1d_array_linear_mipmap_linear(struct gl_context *ctx,
                                      const struct gl_texture_object *tObj,
                                      GLuint n, const GLfloat texcoord[][4],
                                      const GLfloat lambda[], GLfloat rgba[][4])
@@ -2749,7 +2765,7 @@ sample_1d_array_linear_mipmap_linear(GLcontext *ctx,
 
 /** Sample 1D Array texture, nearest filtering for both min/magnification */
 static void
-sample_nearest_1d_array(GLcontext *ctx,
+sample_nearest_1d_array(struct gl_context *ctx,
                         const struct gl_texture_object *tObj, GLuint n,
                         const GLfloat texcoords[][4], const GLfloat lambda[],
                         GLfloat rgba[][4])
@@ -2765,7 +2781,7 @@ sample_nearest_1d_array(GLcontext *ctx,
 
 /** Sample 1D Array texture, linear filtering for both min/magnification */
 static void
-sample_linear_1d_array(GLcontext *ctx,
+sample_linear_1d_array(struct gl_context *ctx,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4],
                        const GLfloat lambda[], GLfloat rgba[][4])
@@ -2781,7 +2797,7 @@ sample_linear_1d_array(GLcontext *ctx,
 
 /** Sample 1D Array texture, using lambda to choose between min/magnification */
 static void
-sample_lambda_1d_array(GLcontext *ctx,
+sample_lambda_1d_array(struct gl_context *ctx,
                        const struct gl_texture_object *tObj, GLuint n,
                        const GLfloat texcoords[][4], const GLfloat lambda[],
                        GLfloat rgba[][4])
@@ -2952,16 +2968,40 @@ shadow_compare4(GLenum function, GLfloat coord,
 
 
 /**
- * Sample a shadow/depth texture.
+ * 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)
+{
+   GLint level;
+
+   if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+      /* no mipmapping - use base level */
+      level = tObj->BaseLevel;
+   }
+   else {
+      /* choose mipmap level */
+      lambda = CLAMP(lambda, tObj->MinLod, tObj->MaxLod);
+      level = (GLint) lambda;
+      level = CLAMP(level, tObj->BaseLevel, tObj->_MaxLevel);
+   }
+
+   return level;
+}
+
+
+/**
+ * Sample a shadow/depth texture.  This function is incomplete.  It doesn't
+ * check for minification vs. magnification, etc.
  */
 static void
-sample_depth_texture( GLcontext *ctx,
+sample_depth_texture( struct gl_context *ctx,
                       const struct gl_texture_object *tObj, GLuint n,
                       const GLfloat texcoords[][4], const GLfloat lambda[],
                       GLfloat texel[][4] )
 {
-   const GLint baseLevel = tObj->BaseLevel;
-   const struct gl_texture_image *img = tObj->Image[0][baseLevel];
+   const GLint level = choose_depth_texture_level(tObj, lambda[0]);
+   const struct gl_texture_image *img = tObj->Image[0][level];
    const GLint width = img->Width;
    const GLint height = img->Height;
    const GLint depth = img->Depth;
@@ -2971,8 +3011,6 @@ sample_depth_texture( GLcontext *ctx,
    GLenum function;
    GLfloat result;
 
-   (void) lambda;
-
    ASSERT(img->_BaseFormat == GL_DEPTH_COMPONENT ||
           img->_BaseFormat == GL_DEPTH_STENCIL_EXT);
 
@@ -2995,7 +3033,7 @@ sample_depth_texture( GLcontext *ctx,
          GLfloat depthSample;
          GLint col, row, slice;
 
-         nearest_texcoord(tObj, texcoords[i], &col, &row, &slice);
+         nearest_texcoord(tObj, level, texcoords[i], &col, &row, &slice);
 
          if (col >= 0 && row >= 0 && col < width && row < height && 
              slice >= 0 && slice < depth) {
@@ -3018,6 +3056,9 @@ sample_depth_texture( GLcontext *ctx,
          case GL_ALPHA:
             ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
             break;
+         case GL_RED:
+            ASSIGN_4V(texel[i], result, 0.0F, 0.0F, 1.0F);
+            break;
          default:
             _mesa_problem(ctx, "Bad depth texture mode");
          }
@@ -3033,7 +3074,7 @@ sample_depth_texture( GLcontext *ctx,
          GLfloat wi, wj;
          GLuint useBorderTexel;
 
-         linear_texcoord(tObj, texcoords[i], &i0, &i1, &j0, &j1, &slice,
+         linear_texcoord(tObj, level, texcoords[i], &i0, &i1, &j0, &j1, &slice,
                          &wi, &wj);
 
          useBorderTexel = 0;
@@ -3123,7 +3164,7 @@ sample_depth_texture( GLcontext *ctx,
  * Note: fragment programs don't observe the texture enable/disable flags.
  */
 static void
-null_sample_func( GLcontext *ctx,
+null_sample_func( struct gl_context *ctx,
                  const struct gl_texture_object *tObj, GLuint n,
                  const GLfloat texcoords[][4], const GLfloat lambda[],
                  GLfloat rgba[][4])
@@ -3146,7 +3187,7 @@ null_sample_func( GLcontext *ctx,
  * Choose the texture sampling function for the given texture object.
  */
 texture_sample_func
-_swrast_choose_texture_sample_func( GLcontext *ctx,
+_swrast_choose_texture_sample_func( struct gl_context *ctx,
                                    const struct gl_texture_object *t )
 {
    if (!t || !t->_Complete) {