Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / mesa / main / teximage.c
index 36557f19fd40f47c49b08b076080a77c805d4223..a5e0db736ed7c82729225dde4de223244731d1a4 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Mesa 3-D graphics library
+ * mesa 3-D graphics library
  * Version:  7.1
  *
- * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2008  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"),
@@ -241,13 +241,12 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
       }
    }
 
-   if (ctx->Extensions.SGIX_depth_texture ||
-       ctx->Extensions.ARB_depth_texture) {
+   if (ctx->Extensions.ARB_depth_texture) {
       switch (internalFormat) {
          case GL_DEPTH_COMPONENT:
-         case GL_DEPTH_COMPONENT16_SGIX:
-         case GL_DEPTH_COMPONENT24_SGIX:
-         case GL_DEPTH_COMPONENT32_SGIX:
+         case GL_DEPTH_COMPONENT16:
+         case GL_DEPTH_COMPONENT24:
+         case GL_DEPTH_COMPONENT32:
             return GL_DEPTH_COMPONENT;
          default:
             ; /* fallthrough */
@@ -389,9 +388,10 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
  * index, depth, stencil, etc).
  * \param format  the image format value (may by an internal texture format)
  * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
+ * XXX maybe move this func to image.c
  */
-static GLboolean
-is_color_format(GLenum format)
+GLboolean
+_mesa_is_color_format(GLenum format)
 {
    switch (format) {
       case GL_RED:
@@ -492,6 +492,7 @@ is_color_format(GLenum format)
 #endif /* FEATURE_EXT_texture_sRGB */
          return GL_TRUE;
       case GL_YCBCR_MESA:  /* not considered to be RGB */
+         /* fall-through */
       default:
          return GL_FALSE;
    }
@@ -526,9 +527,9 @@ static GLboolean
 is_depth_format(GLenum format)
 {
    switch (format) {
-      case GL_DEPTH_COMPONENT16_ARB:
-      case GL_DEPTH_COMPONENT24_ARB:
-      case GL_DEPTH_COMPONENT32_ARB:
+      case GL_DEPTH_COMPONENT16:
+      case GL_DEPTH_COMPONENT24:
+      case GL_DEPTH_COMPONENT32:
       case GL_DEPTH_COMPONENT:
          return GL_TRUE;
       default:
@@ -1243,9 +1244,9 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
    img->IsCompressed = GL_FALSE;
    img->CompressedSize = 0;
 
-   if ((width == 1 || _mesa_bitcount(img->Width2) == 1) &&
-       (height == 1 || _mesa_bitcount(img->Height2) == 1) &&
-       (depth == 1 || _mesa_bitcount(img->Depth2) == 1))
+   if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
+       (height == 1 || _mesa_is_pow_two(img->Height2)) &&
+       (depth == 1 || _mesa_is_pow_two(img->Depth2)))
       img->_IsPowerOfTwo = GL_TRUE;
    else
       img->_IsPowerOfTwo = GL_FALSE;
@@ -1316,7 +1317,7 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
       if (width < 2 * border || width > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           width >0 && _mesa_bitcount(width - 2 * border) != 1) ||
+           width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
           level >= ctx->Const.MaxTextureLevels) {
          /* bad width or level */
          return GL_FALSE;
@@ -1326,10 +1327,10 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
       if (width < 2 * border || width > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
+           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
           height < 2 * border || height > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           height > 0 && _mesa_bitcount(height - 2 * border) != 1) ||
+           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
           level >= ctx->Const.MaxTextureLevels) {
          /* bad width or height or level */
          return GL_FALSE;
@@ -1339,13 +1340,13 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
       maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
       if (width < 2 * border || width > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
+           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
           height < 2 * border || height > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           height > 0 && _mesa_bitcount(height - 2 * border) != 1) ||
+           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
           depth < 2 * border || depth > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           depth > 0 && _mesa_bitcount(depth - 2 * border) != 1) ||
+           depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
           level >= ctx->Const.Max3DTextureLevels) {
          /* bad width or height or depth or level */
          return GL_FALSE;
@@ -1363,10 +1364,10 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
       maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
       if (width < 2 * border || width > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
+           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
           height < 2 * border || height > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           height > 0 && _mesa_bitcount(height - 2 * border) != 1) ||
+           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
           level >= ctx->Const.MaxCubeTextureLevels) {
          /* bad width or height */
          return GL_FALSE;
@@ -1376,7 +1377,7 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
       if (width < 2 * border || width > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
+           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
           level >= ctx->Const.MaxTextureLevels) {
          /* bad width or level */
          return GL_FALSE;
@@ -1390,10 +1391,10 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
       if (width < 2 * border || width > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
+           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
           height < 2 * border || height > 2 + maxSize ||
           (!ctx->Extensions.ARB_texture_non_power_of_two &&
-           height > 0 && _mesa_bitcount(height - 2 * border) != 1) ||
+           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
           level >= ctx->Const.MaxTextureLevels) {
          /* bad width or height or level */
          return GL_FALSE;
@@ -1588,9 +1589,9 @@ texture_error_check( GLcontext *ctx, GLenum target,
    }
 
    /* make sure internal format and format basically agree */
-   colorFormat = is_color_format(format);
+   colorFormat = _mesa_is_color_format(format);
    indexFormat = is_index_format(format);
-   if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
+   if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
        (is_index_format(internalFormat) && !indexFormat) ||
        (is_depth_format(internalFormat) != is_depth_format(format)) ||
        (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
@@ -2017,7 +2018,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
    }
 
    if (is_compressed_format(ctx, internalFormat)) {
-      if (target != GL_TEXTURE_2D) {
+      if (!target_can_be_compressed(ctx, target)) {
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glCopyTexImage%d(target)", dimensions);
          return GL_TRUE;
@@ -2052,30 +2053,20 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
 
 /**
  * Test glCopyTexSubImage[12]D() parameters for errors.
+ * Note that this is the first part of error checking.
+ * See also copytexsubimage_error_check2() below for the second part.
  * 
  * \param ctx GL context.
  * \param dimensions texture image dimensions (must be 1, 2 or 3).
  * \param target texture target given by the user.
  * \param level image level given by the user.
- * \param xoffset sub-image x offset given by the user.
- * \param yoffset sub-image y offset given by the user.
- * \param zoffset sub-image z offset given by the user.
- * \param width image width given by the user.
- * \param height image height given by the user.
  * 
  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
- * 
- * Verifies each of the parameters against the constants specified in
- * __GLcontextRec::Const and the supported extensions, and according to the
- * OpenGL specification.
  */
 static GLboolean
-copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
-                             GLenum target, GLint level,
-                             GLint xoffset, GLint yoffset, GLint zoffset,
-                             GLsizei width, GLsizei height)
+copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions,
+                              GLenum target, GLint level)
 {
-   /* Check target */
    /* Check that the source buffer is complete */
    if (ctx->ReadBuffer->Name) {
       _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
@@ -2086,6 +2077,7 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
       }
    }
 
+   /* Check target */
    if (dimensions == 1) {
       if (target != GL_TEXTURE_1D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
@@ -2133,21 +2125,18 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
       return GL_TRUE;
    }
 
-   /* Check size */
-   if (width < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
-      return GL_TRUE;
-   }
-   if (dimensions > 1 && height < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
-      return GL_TRUE;
-   }
-
    return GL_FALSE;
 }
 
+
+/**
+ * Second part of error checking for glCopyTexSubImage[12]D().
+ * \param xoffset sub-image x offset given by the user.
+ * \param yoffset sub-image y offset given by the user.
+ * \param zoffset sub-image z offset given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ */
 static GLboolean
 copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
                              GLenum target, GLint level,
@@ -2155,6 +2144,7 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
                              GLsizei width, GLsizei height,
                              const struct gl_texture_image *teximage )
 {
+   /* check that dest tex image exists */
    if (!teximage) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glCopyTexSubImage%dD(undefined texture level: %d)",
@@ -2162,6 +2152,19 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
       return GL_TRUE;
    }
 
+   /* Check size */
+   if (width < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
+      return GL_TRUE;
+   }
+   if (dimensions > 1 && height < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
+      return GL_TRUE;
+   }
+
+   /* check x/y offsets */
    if (xoffset < -((GLint)teximage->Border)) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
@@ -2186,6 +2189,7 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
       }
    }
 
+   /* check z offset */
    if (dimensions > 2) {
       if (zoffset < -((GLint)teximage->Border)) {
          _mesa_error(ctx, GL_INVALID_VALUE,
@@ -2200,7 +2204,7 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
    }
 
    if (teximage->IsCompressed) {
-      if (target != GL_TEXTURE_2D) {
+      if (!target_can_be_compressed(ctx, target)) {
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glCopyTexSubImage%d(target)", dimensions);
          return GL_TRUE;
@@ -2308,8 +2312,7 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
       return;
    }
 
-   if (!ctx->Extensions.SGIX_depth_texture &&
-       !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
+   if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
       return;
    }
@@ -2338,8 +2341,8 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
        * texture's format.  Note that a color index texture can be converted
        * to RGBA so that combo is allowed.
        */
-      if (is_color_format(format)
-         && !is_color_format(texImage->TexFormat->BaseFormat)
+      if (_mesa_is_color_format(format)
+         && !_mesa_is_color_format(texImage->TexFormat->BaseFormat)
          && !is_index_format(texImage->TexFormat->BaseFormat)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
         goto out;
@@ -2432,7 +2435,7 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
 #if FEATURE_convolve
-   if (is_color_format(internalFormat)) {
+   if (_mesa_is_color_format(internalFormat)) {
       _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
    }
 #endif
@@ -2529,7 +2532,7 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
 #if FEATURE_convolve
-   if (is_color_format(internalFormat)) {
+   if (_mesa_is_color_format(internalFormat)) {
       _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
                                         &postConvHeight);
    }
@@ -2711,8 +2714,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
       }
       else {
          /* no error, set the tex image parameters */
-         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-                                    border, internalFormat);
+         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+                                    depth, border, internalFormat);
          texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
                                           internalFormat, format, type);
       }
@@ -2754,7 +2757,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
 
 #if FEATURE_convolve
    /* XXX should test internal format */
-   if (is_color_format(format)) {
+   if (_mesa_is_color_format(format)) {
       _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
    }
 #endif
@@ -2814,7 +2817,7 @@ _mesa_TexSubImage2D( GLenum target, GLint level,
 
 #if FEATURE_convolve
    /* XXX should test internal format */
-   if (is_color_format(format)) {
+   if (_mesa_is_color_format(format)) {
       _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
                                          &postConvHeight);
    }
@@ -2929,7 +2932,7 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
       _mesa_update_state(ctx);
 
 #if FEATURE_convolve
-   if (is_color_format(internalFormat)) {
+   if (_mesa_is_color_format(internalFormat)) {
       _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
    }
 #endif
@@ -2994,11 +2997,12 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
       _mesa_update_state(ctx);
 
 #if FEATURE_convolve
-   if (is_color_format(internalFormat)) {
+   if (_mesa_is_color_format(internalFormat)) {
       _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
                                          &postConvHeight);
    }
 #endif
+
    if (copytexture_error_check(ctx, 2, target, level, internalFormat,
                                postConvWidth, postConvHeight, border))
       return;
@@ -3060,13 +3064,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
    if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
-#if FEATURE_convolve
-   /* XXX should test internal format */
-   _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
-#endif
-
-   if (copytexsubimage_error_check(ctx, 1, target, level,
-                                   xoffset, 0, 0, postConvWidth, 1))
+   if (copytexsubimage_error_check1(ctx, 1, target, level))
       return;
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
@@ -3076,6 +3074,12 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
    {
       texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
+#if FEATURE_convolve
+      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
+         _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
+      }
+#endif
+
       if (copytexsubimage_error_check2(ctx, 1, target, level,
                                       xoffset, 0, 0, postConvWidth, 1,
                                       texImage))
@@ -3115,13 +3119,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
    if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
-#if FEATURE_convolve
-   /* XXX should test internal format */
-   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
-#endif
-
-   if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
-                                   postConvWidth, postConvHeight))
+   if (copytexsubimage_error_check1(ctx, 2, target, level))
       return;
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
@@ -3131,6 +3129,13 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
    {
       texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
+#if FEATURE_convolve
+      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
+         _mesa_adjust_image_for_convolution(ctx, 2,
+                                            &postConvWidth, &postConvHeight);
+      }
+#endif
+
       if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
                                       postConvWidth, postConvHeight, texImage))
         goto out;
@@ -3169,13 +3174,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
    if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
-#if FEATURE_convolve
-   /* XXX should test internal format */
-   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
-#endif
-
-   if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
-                                   zoffset, postConvWidth, postConvHeight))
+   if (copytexsubimage_error_check1(ctx, 3, target, level))
       return;
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
@@ -3185,6 +3184,13 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
    {
       texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
+#if FEATURE_convolve
+      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
+         _mesa_adjust_image_for_convolution(ctx, 2,
+                                            &postConvWidth, &postConvHeight);
+      }
+#endif
+
       if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
                                       zoffset, postConvWidth, postConvHeight,
                                       texImage))
@@ -3278,16 +3284,16 @@ compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
     * XXX We should probably use the proxy texture error check function here.
     */
    if (width < 1 || width > maxTextureSize ||
-       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1))
+       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
       return GL_INVALID_VALUE;
 
    if ((height < 1 || height > maxTextureSize ||
-       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1))
+       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
        && dimensions > 1)
       return GL_INVALID_VALUE;
 
    if ((depth < 1 || depth > maxTextureSize ||
-       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1))
+       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
        && dimensions > 2)
       return GL_INVALID_VALUE;