Fix sample_depth_texture() to handle texture rectangle coords.
authorBrian <brian@yutani.localnet.net>
Sat, 14 Apr 2007 15:33:20 +0000 (09:33 -0600)
committerBrian <brian@yutani.localnet.net>
Sat, 14 Apr 2007 15:33:20 +0000 (09:33 -0600)
src/mesa/swrast/s_texfilter.c

index b2c5574..5413fc0 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.2
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -2026,6 +2026,60 @@ sample_lambda_cube( GLcontext *ctx,
 /*               Texture Rectangle Sampling Functions                 */
 /**********************************************************************/
 
+
+/**
+ * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
+ */
+static INLINE GLint
+clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max)
+{
+   if (wrapMode == GL_CLAMP) {
+      return IFLOOR( CLAMP(coord, 0.0F, max - 1) );
+   }
+   else if (wrapMode == GL_CLAMP_TO_EDGE) {
+      return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) );
+   }
+   else {
+      return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) );
+   }
+}
+
+
+/*
+ * As above, but GL_LINEAR filtering.
+ */
+static INLINE void
+clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
+                        GLint *i0out, GLint *i1out)
+{
+   GLfloat fcol;
+   GLint i0, i1;
+   if (wrapMode == GL_CLAMP) {
+      /* Not exactly what the spec says, but it matches NVIDIA output */
+      fcol = CLAMP(coord - 0.5F, 0.0, max-1);
+      i0 = IFLOOR(fcol);
+      i1 = i0 + 1;
+   }
+   else if (wrapMode == GL_CLAMP_TO_EDGE) {
+      fcol = CLAMP(coord, 0.5F, max - 0.5F);
+      fcol -= 0.5F;
+      i0 = IFLOOR(fcol);
+      i1 = i0 + 1;
+      if (i1 > max - 1)
+         i1 = max - 1;
+   }
+   else {
+      ASSERT(wrapMode == GL_CLAMP_TO_BORDER);
+      fcol = CLAMP(coord, -0.5F, max + 0.5F);
+      fcol -= 0.5F;
+      i0 = IFLOOR(fcol);
+      i1 = i0 + 1;
+   }
+   *i0out = i0;
+   *i1out = i1;
+}
+
+
 static void
 sample_nearest_rect(GLcontext *ctx,
                    const struct gl_texture_object *tObj, GLuint n,
@@ -2050,29 +2104,10 @@ sample_nearest_rect(GLcontext *ctx,
           tObj->WrapT == GL_CLAMP_TO_BORDER);
    ASSERT(img->_BaseFormat != GL_COLOR_INDEX);
 
-   /* XXX move Wrap mode tests outside of loops for common cases */
    for (i = 0; i < n; i++) {
       GLint row, col;
-      /* NOTE: we DO NOT use [0, 1] texture coordinates! */
-      if (tObj->WrapS == GL_CLAMP) {
-         col = IFLOOR( CLAMP(texcoords[i][0], 0.0F, width - 1) );
-      }
-      else if (tObj->WrapS == GL_CLAMP_TO_EDGE) {
-         col = IFLOOR( CLAMP(texcoords[i][0], 0.5F, width - 0.5F) );
-      }
-      else {
-         col = IFLOOR( CLAMP(texcoords[i][0], -0.5F, width + 0.5F) );
-      }
-      if (tObj->WrapT == GL_CLAMP) {
-         row = IFLOOR( CLAMP(texcoords[i][1], 0.0F, height - 1) );
-      }
-      else if (tObj->WrapT == GL_CLAMP_TO_EDGE) {
-         row = IFLOOR( CLAMP(texcoords[i][1], 0.5F, height - 0.5F) );
-      }
-      else {
-         row = IFLOOR( CLAMP(texcoords[i][1], -0.5F, height + 0.5F) );
-      }
-
+      col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width);
+      row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
       if (col < 0 || col > width_minus_1 || row < 0 || row > height_minus_1)
          COPY_CHAN4(rgba[i], tObj->_BorderChan);
       else
@@ -2286,9 +2321,17 @@ sample_depth_texture( GLcontext *ctx,
       for (i = 0; i < n; i++) {
          GLfloat depthSample;
          GLint col, row;
-         /* XXX fix for texture rectangle! */
-         COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0], width, col);
-         COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1], height, row);
+
+         if (tObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
+            col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width);
+            row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
+         }
+         else {
+            COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0],
+                                           width, col);
+            COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1],
+                                           height, row);
+         }
          if (col >= 0 && row >= 0 && col < width && row < height) {
             img->FetchTexelf(img, col, row, 0, &depthSample);
          }
@@ -2362,9 +2405,18 @@ sample_depth_texture( GLcontext *ctx,
          GLfloat u, v;
          GLuint useBorderTexel;
 
-         /* XXX fix for texture rectangle! */
-         COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0], u, width, i0, i1);
-         COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1], v, height,j0, j1);
+         if (tObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
+            clamp_rect_coord_linear(tObj->WrapS, texcoords[i][0],
+                                    width, &i0, &i1);
+            clamp_rect_coord_linear(tObj->WrapT, texcoords[i][1],
+                                    height, &j0, &j1);
+         }
+         else {
+            COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0],
+                                           u, width, i0, i1);
+            COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1],
+                                           v, height,j0, j1);
+         }
 
          useBorderTexel = 0;
          if (img->Border) {
@@ -2727,7 +2779,10 @@ _swrast_choose_texture_sample_func( GLcontext *ctx,
             return &sample_nearest_cube;
          }
       case GL_TEXTURE_RECTANGLE_NV:
-         if (needLambda) {
+         if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
+            return &sample_depth_texture;
+         }
+         else if (needLambda) {
             return &sample_lambda_rect;
          }
          else if (t->MinFilter == GL_LINEAR) {