Rework gl[Copy]Tex[Sub]Image() error checking so that all level, width, height
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 4 Apr 2003 17:17:50 +0000 (17:17 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 4 Apr 2003 17:17:50 +0000 (17:17 +0000)
and depth checks are done via ctx->Driver.TestProxyTexImage().  This allows
more flexiblity, like supporting larger, non-cubic 3D textures.

src/mesa/drivers/osmesa/osmesa.c
src/mesa/drivers/x11/xm_dd.c
src/mesa/main/config.h
src/mesa/main/teximage.c
src/mesa/main/teximage.h
src/mesa/main/texstore.c
src/mesa/main/texstore.h

index 286662b628e7538927e3c771f6eb3fbe0a15d015..195b432885cc5e5e1711de9542a2411541481c3c 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id: osmesa.c,v 1.103 2003/04/01 17:28:55 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
@@ -48,6 +46,7 @@
 #include "mtypes.h"
 #include "texformat.h"
 #include "texobj.h"
+#include "teximage.h"
 #include "texstore.h"
 #include "array_cache/acache.h"
 #include "swrast/swrast.h"
index eec0d8ad323c7ff0491b296259ad0e8c81f1d472..30a8b51723f97d8b3f5bf5f69f11f04b433a7161 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id: xm_dd.c,v 1.47 2003/04/01 17:28:11 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
@@ -36,6 +34,7 @@
 #include "mtypes.h"
 #include "state.h"
 #include "texobj.h"
+#include "teximage.h"
 #include "texstore.h"
 #include "texformat.h"
 #include "xmesaP.h"
@@ -924,6 +923,39 @@ void xmesa_update_state( GLcontext *ctx, GLuint new_state )
 
 
 
+/**
+ * Called via ctx->Driver.TestProxyTeximage().  Normally, we'd just use
+ * the _mesa_test_proxy_teximage() fallback function, but we're going to
+ * special-case the 3D texture case to allow textures up to 512x512x32
+ * texels.
+ */
+static GLboolean
+test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
+                    GLint internalFormat, GLenum format, GLenum type,
+                    GLint width, GLint height, GLint depth, GLint border)
+{
+   if (target == GL_PROXY_TEXTURE_3D) {
+      /* special case for 3D textures */
+      if (width * height * depth > 512 * 512 * 64 ||
+          width  < 2 * border || _mesa_bitcount(width  - 2 * border) != 1 ||
+          height < 2 * border || _mesa_bitcount(height - 2 * border) != 1 ||
+          depth  < 2 * border || _mesa_bitcount(depth  - 2 * border) != 1) {
+         /* Bad size, or too many texels */
+         return GL_FALSE;
+      }
+      return GL_TRUE;
+   }
+   else {
+      /* use the fallback routine for 1D, 2D, cube and rect targets */
+      return _mesa_test_proxy_teximage(ctx, target, level, internalFormat,
+                                       format, type, width, height, depth,
+                                       border);
+   }
+}
+
+
+
+
 /* Setup pointers and other driver state that is constant for the life
  * of a context.
  */
@@ -957,7 +989,7 @@ void xmesa_init_pointers( GLcontext *ctx )
    ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
    ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
    ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
-   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+   ctx->Driver.TestProxyTexImage = test_proxy_teximage;
 
    ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
    ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
index 264b57c279ef01708ee2ff2e5a387b425676416f..85acb0f292fbaf203074a0304841e9e737fef6ee 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id: config.h,v 1.45 2003/03/29 17:01:03 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
 #define MAX_TEXTURE_LEVELS 12
 
 /* Number of 3D texture mipmap levels */
-#define MAX_3D_TEXTURE_LEVELS 8
+#define MAX_3D_TEXTURE_LEVELS 9
 
 /* Number of cube texture mipmap levels - GL_ARB_texture_cube_map */
 #define MAX_CUBE_TEXTURE_LEVELS 12
index 11247b50028aa5046069a31820b498d9f6b0d83b..1c10aaea016500fa377739784a6e9a3d17def351 100644 (file)
@@ -785,7 +785,7 @@ make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
 
 
 
-/*
+/**
  * Reset the fields of a gl_texture_image struct to zero.
  * This is called when a proxy texture test fails, we set all the
  * image members (except DriverData) to zero.
@@ -871,12 +871,103 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
 }
 
 
+/**
+ * This is the fallback for Driver.TestProxyTexImage().  Test the texture
+ * level, width, height and depth against the ctx->Const limits for textures.
+ *
+ * A hardware driver might override this function if, for example, the
+ * max 3D texture size is 512x512x64 (i.e. not a cube).
+ *
+ * \param target  one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
+ *                GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
+ *                GL_PROXY_TEXTURE_CUBE_MAP_ARB.
+ * \param level  as passed to glTexImage
+ * \param internalFormat  as passed to glTexImage
+ * \param format  as passed to glTexImage
+ * \param type  as passed to glTexImage
+ * \param width  as passed to glTexImage
+ * \param height  as passed to glTexImage
+ * \param depth  as passed to glTexImage
+ * \param border  as passed to glTexImage
+ * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
+ */
+GLboolean
+_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
+                          GLint internalFormat, GLenum format, GLenum type,
+                          GLint width, GLint height, GLint depth, GLint border)
+{
+   GLint maxSize;
 
-/*
+   (void) internalFormat;
+   (void) format;
+   (void) type;
+
+   switch (target) {
+   case GL_PROXY_TEXTURE_1D:
+      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+      if (width < 2 * border || width > 2 + maxSize ||
+          _mesa_bitcount(width - 2 * border) != 1 ||
+          level >= ctx->Const.MaxTextureLevels) {
+         /* bad width or level */
+         return GL_FALSE;
+      }
+      return GL_TRUE;
+   case GL_PROXY_TEXTURE_2D:
+      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+      if (width < 2 * border || width > 2 + maxSize ||
+          _mesa_bitcount(width - 2 * border) != 1 ||
+          height < 2 * border || height > 2 + maxSize ||
+          _mesa_bitcount(height - 2 * border) != 1 ||
+          level >= ctx->Const.MaxTextureLevels) {
+         /* bad width or height or level */
+         return GL_FALSE;
+      }
+      return GL_TRUE;
+   case GL_PROXY_TEXTURE_3D:
+      maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
+      if (width < 2 * border || width > 2 + maxSize ||
+          _mesa_bitcount(width - 2 * border) != 1 ||
+          height < 2 * border || height > 2 + maxSize ||
+          _mesa_bitcount(height - 2 * border) != 1 ||
+          depth < 2 * border || depth > 2 + maxSize ||
+          _mesa_bitcount(depth - 2 * border) != 1 ||
+          level >= ctx->Const.Max3DTextureLevels) {
+         /* bad width or height or depth or level */
+         return GL_FALSE;
+      }
+      return GL_TRUE;
+   case GL_PROXY_TEXTURE_RECTANGLE_NV:
+      if (width < 1 || width > ctx->Const.MaxTextureRectSize ||
+          height < 1 || height > ctx->Const.MaxTextureRectSize ||
+          level != 0) {
+         /* bad width or height or level */
+         return GL_FALSE;
+      }
+      return GL_TRUE;
+   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
+      if (width < 2 * border || width > 2 + maxSize ||
+          _mesa_bitcount(width - 2 * border) != 1 ||
+          height < 2 * border || height > 2 + maxSize ||
+          _mesa_bitcount(height - 2 * border) != 1 ||
+          level >= ctx->Const.MaxCubeTextureLevels) {
+         /* bad width or height */
+         return GL_FALSE;
+      }
+      return GL_TRUE;
+   default:
+      _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
+      return GL_FALSE;
+   }
+}
+
+
+/**
  * Test glTexImage[123]D() parameters for errors.
- * Input:
- *         dimensions - must be 1 or 2 or 3
- * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
+ * This function calls the ctx->Driver.TestProxyTexImage() function to
+ * check the level and size.
+ * \param dimensions  must be 1 or 2 or 3
+ * \return  GL_TRUE if an error was detected or GL_FALSE if no errors
  */
 static GLboolean
 texture_error_check( GLcontext *ctx, GLenum target,
@@ -886,63 +977,74 @@ texture_error_check( GLcontext *ctx, GLenum target,
                      GLint width, GLint height,
                      GLint depth, GLint border )
 {
-   GLboolean isProxy;
-   GLint maxLevels = 0, maxTextureSize;
+   const GLboolean isProxy = is_proxy_target(target);
+   GLboolean sizeOK;
 
-   if (dimensions == 1) {
-      if (target == GL_PROXY_TEXTURE_1D) {
-         isProxy = GL_TRUE;
+   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
+   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+      if (!isProxy) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glTexImage%dD(level=%d)", dimensions, level);
       }
-      else if (target == GL_TEXTURE_1D) {
-         isProxy = GL_FALSE;
+      return GL_TRUE;
+   }
+
+   /* Check border */
+   if (border < 0 || border > 1 ||
+       ((target == GL_TEXTURE_RECTANGLE_NV ||
+         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
+      if (!isProxy) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glTexImage%dD(border=%d)", dimensions, border);
+      }
+      return GL_TRUE;
+   }
+
+   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
+    * level, width, height and depth.
+    */
+   if (dimensions == 1) {
+      if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
+         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
+                                                level, internalFormat,
+                                                format, type,
+                                                width, 1, 1, border);
       }
       else {
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
          return GL_TRUE;
       }
-      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (dimensions == 2) {
-      if (target == GL_PROXY_TEXTURE_2D) {
-         isProxy = GL_TRUE;
-         maxLevels = ctx->Const.MaxTextureLevels;
-      }
-      else if (target == GL_TEXTURE_2D) {
-         isProxy = GL_FALSE;
-         maxLevels = ctx->Const.MaxTextureLevels;
-      }
-      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
+      if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
+         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
+                                                level, internalFormat,
+                                                format, type,
+                                                width, height, 1, border);
+      }
+      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
+               (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+                target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
          if (!ctx->Extensions.ARB_texture_cube_map) {
             _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
             return GL_TRUE;
          }
-         isProxy = GL_TRUE;
-         maxLevels = ctx->Const.MaxCubeTextureLevels;
+         sizeOK = (width == height) &&
+            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
+                                          level, internalFormat, format, type,
+                                          width, height, 1, border);
       }
-      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
-               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
-         if (!ctx->Extensions.ARB_texture_cube_map) {
-            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
-            return GL_TRUE;
-         }
-         isProxy = GL_FALSE;
-         maxLevels = ctx->Const.MaxCubeTextureLevels;
-      }
-      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
-         if (!ctx->Extensions.NV_texture_rectangle) {
-            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
-            return GL_TRUE;
-         }
-         isProxy = GL_TRUE;
-         maxLevels = 1;
-      }
-      else if (target == GL_TEXTURE_RECTANGLE_NV) {
+      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+               target == GL_TEXTURE_RECTANGLE_NV) {
          if (!ctx->Extensions.NV_texture_rectangle) {
             _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
             return GL_TRUE;
          }
-         isProxy = GL_FALSE;
-         maxLevels = 1;
+         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
+                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
+                                                level, internalFormat,
+                                                format, type,
+                                                width, height, 1, border);
       }
       else {
          _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
@@ -950,132 +1052,32 @@ texture_error_check( GLcontext *ctx, GLenum target,
       }
    }
    else if (dimensions == 3) {
-      if (target == GL_PROXY_TEXTURE_3D) {
-         isProxy = GL_TRUE;
-      }
-      else if (target == GL_TEXTURE_3D) {
-         isProxy = GL_FALSE;
+      if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
+         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_3D,
+                                                level, internalFormat,
+                                                format, type,
+                                                width, height, depth, border);
       }
       else {
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
          return GL_TRUE;
       }
-      maxLevels = ctx->Const.Max3DTextureLevels;
    }
    else {
       _mesa_problem( ctx, "bad dims in texture_error_check" );
       return GL_TRUE;
    }
 
-   ASSERT(maxLevels > 0);
-   maxTextureSize = 1 << (maxLevels - 1);
-
-   /* Border */
-   if (border != 0 && border != 1) {
-      if (!isProxy) {
-         _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glTexImage%dD(border=%d)", dimensions, border);
-      }
-      return GL_TRUE;
-   }
-   if ((target == GL_TEXTURE_RECTANGLE_NV ||
-        target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0) {
-      return GL_TRUE;
-   }
-
-   /* Width */
-   if (target == GL_TEXTURE_RECTANGLE_NV ||
-       target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
-      if (width < 1 || width > ctx->Const.MaxTextureRectSize) {
-         if (!isProxy) {
-            _mesa_error(ctx, GL_INVALID_VALUE,
-                        "glTexImage%dD(width=%d)", dimensions, width);
-         }
-         return GL_TRUE;
-      }
-   }
-   else if (width < 2 * border || width > 2 + maxTextureSize
-       || logbase2( width - 2 * border ) < 0) {
-      if (!isProxy) {
-         _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glTexImage%dD(width=%d)", dimensions, width);
-      }
-      return GL_TRUE;
-   }
-
-   /* Height */
-   if (target == GL_TEXTURE_RECTANGLE_NV ||
-       target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
-      if (height < 1 || height > ctx->Const.MaxTextureRectSize) {
-         if (!isProxy) {
-            _mesa_error(ctx, GL_INVALID_VALUE,
-                        "glTexImage%dD(height=%d)", dimensions, height);
-         }
-         return GL_TRUE;
-      }
-   }
-   else if (dimensions >= 2) {
-      if (height < 2 * border || height > 2 + maxTextureSize
-          || logbase2( height - 2 * border ) < 0) {
-         if (!isProxy) {
-            _mesa_error(ctx, GL_INVALID_VALUE,
-                        "glTexImage%dD(height=%d)", dimensions, height);
-         }
-         return GL_TRUE;
-      }
-   }
-
-   /* For cube map, width must equal height */
-   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
-       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
-      if (width != height) {
-         if (!isProxy) {
-            _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
-         }
-         return GL_TRUE;
-      }
-   }
-
-   /* Depth */
-   if (dimensions >= 3) {
-      if (depth < 2 * border || depth > 2 + maxTextureSize
-          || logbase2( depth - 2 * border ) < 0) {
-         if (!isProxy) {
-            _mesa_error( ctx, GL_INVALID_VALUE,
-                         "glTexImage3D(depth=%d)", depth );
-         }
-         return GL_TRUE;
-      }
-   }
-
-   /* Level */
-   if (target == GL_TEXTURE_RECTANGLE_NV ||
-       target == GL_PROXY_TEXTURE_RECTANGLE_NV) {
-      if (level != 0) {
-         if (!isProxy) {
-            _mesa_error(ctx, GL_INVALID_VALUE,
-                        "glTexImage2D(level=%d)", level);
-         }
-         return GL_TRUE;
-      }
-   }
-   else if (level < 0 || level >= maxLevels) {
+   if (!sizeOK) {
       if (!isProxy) {
          _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glTexImage%dD(level=%d)", dimensions, level);
+                     "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
+                     dimensions, level, width, height, depth);
       }
       return GL_TRUE;
    }
 
-   /* For cube map, width must equal height */
-   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
-       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
-      if (width != height) {
-         _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
-         return GL_TRUE;
-      }
-   }
-
+   /* Check internalFormat */
    if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
       if (!isProxy) {
          _mesa_error(ctx, GL_INVALID_VALUE,
@@ -1085,6 +1087,7 @@ texture_error_check( GLcontext *ctx, GLenum target,
       return GL_TRUE;
    }
 
+   /* Check incoming image format and type */
    if (!_mesa_is_legal_format_and_type(format, type)) {
       /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
        * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
@@ -1176,52 +1179,47 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
 {
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    struct gl_texture_image *destTex;
-   GLint maxLevels = 0;
 
+   /* Check target */
    if (dimensions == 1) {
-      if (target == GL_TEXTURE_1D) {
-         maxLevels = ctx->Const.MaxTextureLevels;
-      }
-      else {
+      if (target != GL_TEXTURE_1D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
          return GL_TRUE;
       }
    }
    else if (dimensions == 2) {
-      if (ctx->Extensions.ARB_texture_cube_map &&
-          target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
           target <=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
-         maxLevels = ctx->Const.MaxCubeTextureLevels;
+         if (!ctx->Extensions.ARB_texture_cube_map) {
+            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
+            return GL_TRUE;
+         }
       }
       else if (ctx->Extensions.NV_texture_rectangle &&
                target == GL_TEXTURE_RECTANGLE_NV) {
-         maxLevels = 1;
-      }
-      else if (target == GL_TEXTURE_2D) {
-         maxLevels = ctx->Const.MaxTextureLevels;
+         if (!ctx->Extensions.NV_texture_rectangle) {
+            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
+            return GL_TRUE;
+         }
       }
-      else {
+      else if (target != GL_TEXTURE_2D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
          return GL_TRUE;
       }
    }
    else if (dimensions == 3) {
-      if (target == GL_TEXTURE_3D) {
-         maxLevels = ctx->Const.Max3DTextureLevels;
-      }
-      else {
+      if (target != GL_TEXTURE_3D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
          return GL_TRUE;
       }
    }
    else {
-      _mesa_problem( ctx, "bad dims in texture_error_check" );
+      _mesa_problem( ctx, "invalid dims in texture_error_check" );
       return GL_TRUE;
    }
 
-   ASSERT(maxLevels > 0);
-
-   if (level < 0 || level >= maxLevels) {
+   /* Basic level check */
+   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
       return GL_TRUE;
    }
@@ -1237,32 +1235,38 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
       return GL_TRUE;
    }
    if (depth < 0 && dimensions > 2) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(depth=%d)", dimensions, depth);
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glTexSubImage%dD(depth=%d)", dimensions, depth);
       return GL_TRUE;
    }
 
    destTex = _mesa_select_tex_image(ctx, texUnit, target, level);
 
    if (!destTex) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
+      /* undefined image level */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
       return GL_TRUE;
    }
 
    if (xoffset < -((GLint)destTex->Border)) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
+      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
+                  dimensions);
       return GL_TRUE;
    }
    if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
+      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
+                  dimensions);
       return GL_TRUE;
    }
    if (dimensions > 1) {
       if (yoffset < -((GLint)destTex->Border)) {
-         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
+         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
+                     dimensions);
          return GL_TRUE;
       }
       if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
-         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
+         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
+                     dimensions);
          return GL_TRUE;
       }
    }
@@ -1336,82 +1340,93 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
                          GLenum target, GLint level, GLint internalFormat,
                          GLint width, GLint height, GLint border )
 {
-   GLint maxLevels = 0, maxTextureSize;
+   GLenum format, type;
+   GLboolean sizeOK;
 
+   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
+   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyTexImage%dD(level=%d)", dimensions, level);
+      return GL_TRUE;
+   }
+
+   /* Check border */
+   if (border < 0 || border > 1 ||
+       ((target == GL_TEXTURE_RECTANGLE_NV ||
+         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
+      return GL_TRUE;
+   }
+
+   /* The format and type aren't really significant here, but we need to pass
+    * something to TestProxyTexImage().
+    */
+   format = _mesa_base_tex_format(ctx, internalFormat);
+   type = GL_FLOAT;
+
+   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
+    * level, width, height and depth.
+    */
    if (dimensions == 1) {
-      if (target != GL_TEXTURE_1D) {
+      if (target == GL_TEXTURE_1D) {
+         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
+                                                level, internalFormat,
+                                                format, type,
+                                                width, 1, 1, border);
+      }
+      else {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
          return GL_TRUE;
       }
-      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (dimensions == 2) {
-      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
-          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+      if (target == GL_TEXTURE_2D) {
+         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
+                                                level, internalFormat,
+                                                format, type,
+                                                width, height, 1, border);
+      }
+      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
          if (!ctx->Extensions.ARB_texture_cube_map) {
             _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
             return GL_TRUE;
          }
+         sizeOK = (width == height) &&
+            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
+                                          level, internalFormat, format, type,
+                                          width, height, 1, border);
       }
       else if (target == GL_TEXTURE_RECTANGLE_NV) {
          if (!ctx->Extensions.NV_texture_rectangle) {
             _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
             return GL_TRUE;
          }
+         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
+                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
+                                                level, internalFormat,
+                                                format, type,
+                                                width, height, 1, border);
       }
-      else if (target != GL_TEXTURE_2D) {
+      else {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
          return GL_TRUE;
       }
-      if (target == GL_TEXTURE_2D)
-         maxLevels = ctx->Const.MaxTextureLevels;
-      else if (target == GL_TEXTURE_RECTANGLE_NV)
-         maxLevels = 1;
-      else
-         maxLevels = ctx->Const.MaxCubeTextureLevels;
-   }
-
-   ASSERT(maxLevels > 0);
-   maxTextureSize = 1 << (maxLevels - 1);
-
-   /* Border */
-   if (border != 0 && border != 1) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyTexImage%dD(border)", dimensions);
-      return GL_TRUE;
    }
-
-   /* Width */
-   if (width < 2 * border || width > 2 + maxTextureSize
-       || logbase2( width - 2 * border ) < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyTexImage%dD(width=%d)", dimensions, width);
+   else {
+      _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
       return GL_TRUE;
    }
 
-   /* Height */
-   if (dimensions >= 2) {
-      if (height < 2 * border || height > 2 + maxTextureSize
-          || logbase2( height - 2 * border ) < 0) {
+   if (!sizeOK) {
+      if (dimensions == 1) {
          _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glCopyTexImage%dD(height=%d)", dimensions, height);
-         return GL_TRUE;
+                     "glCopyTexImage1D(width=%d)", width);
       }
-   }
-
-   /* For cube map, width must equal height */
-   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
-       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
-      if (width != height) {
-         _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
-         return GL_TRUE;
+      else {
+         ASSERT(dimensions == 2);
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glCopyTexImage2D(width=%d, height=%d)", width, height);
       }
-   }
-
-   /* Level */
-   if (level < 0 || level >= maxLevels) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyTexImage%dD(level=%d)", dimensions, level);
       return GL_TRUE;
    }
 
@@ -1447,14 +1462,13 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
 {
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    struct gl_texture_image *teximage;
-   GLint maxLevels = 0;
 
+   /* Check target */
    if (dimensions == 1) {
       if (target != GL_TEXTURE_1D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
          return GL_TRUE;
       }
-      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (dimensions == 2) {
       if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
@@ -1474,29 +1488,22 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
          return GL_TRUE;
       }
-      if (target == GL_TEXTURE_2D)
-         maxLevels = ctx->Const.MaxTextureLevels;
-      else if (target == GL_TEXTURE_RECTANGLE_NV)
-         maxLevels = 1;
-      else
-         maxLevels = ctx->Const.MaxCubeTextureLevels;
    }
    else if (dimensions == 3) {
       if (target != GL_TEXTURE_3D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
          return GL_TRUE;
       }
-      maxLevels = ctx->Const.Max3DTextureLevels;
    }
 
-   ASSERT(maxLevels > 0);
-
-   if (level < 0 || level >= maxLevels) {
+   /* Check level */
+   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glCopyTexSubImage%dD(level=%d)", dimensions, level);
       return GL_TRUE;
    }
 
+   /* Check size */
    if (width < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glCopyTexSubImage%dD(width=%d)", dimensions, width);
@@ -1792,30 +1799,22 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
    }
    else if (target == GL_PROXY_TEXTURE_1D) {
       /* Proxy texture: check for errors and update proxy state */
-      GLboolean error = texture_error_check(ctx, target, level, internalFormat,
-                                 format, type, 1, postConvWidth, 1, 1, border);
-      if (!error) {
-         ASSERT(ctx->Driver.TestProxyTexImage);
-         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
-                                                  internalFormat, format, type,
-                                                  postConvWidth, 1, 1, border);
-      }
-      if (error) {
-         /* if error, clear all proxy texture image parameters */
-         struct gl_texture_image *texImage;
-         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+      struct gl_texture_image *texImage;
+      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+      if (texture_error_check(ctx, target, level, internalFormat,
+                              format, type, 1, postConvWidth, 1, 1, border)) {
+         /* when error, clear all proxy texture image parameters */
          if (texImage)
             clear_teximage_fields(texImage);
       }
       else {
          /* no error, set the tex image parameters */
-         struct gl_texture_unit *texUnit;
-         struct gl_texture_image *texImage;
-         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+         ASSERT(texImage);
          _mesa_init_teximage_fields(ctx, target, texImage,
                                     postConvWidth, 1, 1,
                                     border, internalFormat);
+         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+                                          internalFormat, format, type);
       }
    }
    else {
@@ -1901,30 +1900,22 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
             (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
              ctx->Extensions.NV_texture_rectangle)) {
       /* Proxy texture: check for errors and update proxy state */
-      GLboolean error = texture_error_check(ctx, target, level, internalFormat,
-                    format, type, 2, postConvWidth, postConvHeight, 1, border);
-      if (!error) {
-         ASSERT(ctx->Driver.TestProxyTexImage);
-         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
-                                    internalFormat, format, type,
-                                    postConvWidth, postConvHeight, 1, border);
-      }
-      if (error) {
-         /* if error, clear all proxy texture image parameters */
-         struct gl_texture_image *texImage;
-         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+      struct gl_texture_image *texImage;
+      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+      if (texture_error_check(ctx, target, level, internalFormat,
+                              format, type, 2, postConvWidth, postConvHeight,
+                              1, border)) {
+         /* when error, clear all proxy texture image parameters */
          if (texImage)
             clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
       }
       else {
          /* no error, set the tex image parameters */
-         struct gl_texture_unit *texUnit;
-         struct gl_texture_image *texImage;
-         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
          _mesa_init_teximage_fields(ctx, target, texImage,
                                     postConvWidth, postConvHeight, 1,
                                     border, internalFormat);
+         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+                                          internalFormat, format, type);
       }
    }
    else {
@@ -1996,29 +1987,20 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
    }
    else if (target == GL_PROXY_TEXTURE_3D) {
       /* Proxy texture: check for errors and update proxy state */
-      GLboolean error = texture_error_check(ctx, target, level, internalFormat,
-                                format, type, 3, width, height, depth, border);
-      if (!error) {
-         ASSERT(ctx->Driver.TestProxyTexImage);
-         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
-                                                 internalFormat, format, type,
-                                                 width, height, depth, border);
-      }
-      if (error) {
-         /* if error, clear all proxy texture image parameters */
-         struct gl_texture_image *texImage;
-         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+      struct gl_texture_image *texImage;
+      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+      if (texture_error_check(ctx, target, level, internalFormat,
+                              format, type, 3, width, height, depth, border)) {
+         /* when error, clear all proxy texture image parameters */
          if (texImage)
             clear_teximage_fields(texImage);
       }
       else {
          /* no error, set the tex image parameters */
-         struct gl_texture_unit *texUnit;
-         struct gl_texture_image *texImage;
-         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
          _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
                                     border, internalFormat);
+         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+                                          internalFormat, format, type);
       }
    }
    else {
index 7ab6810209dc353466c8c5707c2a68a5d1c29390..ed0008e37f89c480059f80f295741155cb749e5c 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: teximage.h,v 1.23 2003/04/01 16:41:54 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  5.1
  *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2003  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"),
@@ -83,6 +81,11 @@ extern GLint
 _mesa_max_texture_levels(GLcontext *ctx, GLenum target);
 
 
+extern GLboolean
+_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
+                         GLint internalFormat, GLenum format, GLenum type,
+                         GLint width, GLint height, GLint depth, GLint border);
+
 /*** API entry point functions ***/
 
 
index 08e625bc0d4816b4a6fdcb00298fe736cb3d68de..f9afbb6b87ff8fe3a81698d5a9b2f251c41713c1 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id: texstore.c,v 1.55 2003/04/01 16:41:55 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
@@ -1264,40 +1262,6 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
 }
 
 
-
-
-
-/*
- * This is the fallback for Driver.TestProxyTexImage().
- */
-GLboolean
-_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
-                          GLint internalFormat, GLenum format, GLenum type,
-                          GLint width, GLint height, GLint depth, GLint border)
-{
-   struct gl_texture_image *texImage;
-
-   (void) format;
-   (void) type;
-
-   texImage = _mesa_get_proxy_tex_image(ctx, target, level);
-
-   /* We always pass.
-    * The core Mesa code will have already tested the image size, etc.
-    * If a driver has more stringent texture limits to enforce it will
-    * have to override this function.
-    */
-   /* choose the texture format */
-   assert(ctx->Driver.ChooseTextureFormat);
-   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
-                                          internalFormat, format, type);
-   assert(texImage->TexFormat);
-
-   return GL_TRUE;
-}
-
-
-
 /*
  * Average together two rows of a source image to produce a single new
  * row in the dest image.  It's legal for the two source rows to point
index 8d1e149102b9c347e61080f9e3bb0abc419b2cba..6d3a4397b2da78a7b29a097ae3b576f282c4a87f 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: texstore.h,v 1.11 2002/09/27 02:45:38 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  4.1
+ * Version:  5.1
  *
- * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2003  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"),
@@ -165,12 +163,6 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
                                 struct gl_texture_image *texImage);
 
 
-extern GLboolean
-_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
-                         GLint internalFormat, GLenum format, GLenum type,
-                         GLint width, GLint height, GLint depth, GLint border);
-
-
 extern void
 _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
                       const struct gl_texture_unit *texUnit,