mesa: Remove unnecessary header.
[mesa.git] / src / mesa / main / texcompress.c
index 5ad936419b639f3f5cf4cca4f3ddecd84222e608..cff6de89ee30bd2e0c8278902cfdae779c337d1e 100644 (file)
@@ -3,6 +3,7 @@
  * Version:  6.5.1
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 #include "imports.h"
 #include "colormac.h"
 #include "context.h"
-#include "image.h"
-#include "mipmap.h"
+#include "formats.h"
 #include "texcompress.h"
-#include "texformat.h"
-#include "texstore.h"
 
 
 /**
@@ -56,276 +54,177 @@ GLuint
 _mesa_get_compressed_formats(GLcontext *ctx, GLint *formats, GLboolean all)
 {
    GLuint n = 0;
-   if (ctx->Extensions.ARB_texture_compression) {
-      if (ctx->Extensions.TDFX_texture_compression_FXT1) {
-         if (formats) {
-            formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX;
-            formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX;
-         }
-         else {
-            n += 2;
-         }
+   if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+      if (formats) {
+         formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX;
+         formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX;
       }
-      if (ctx->Extensions.EXT_texture_compression_s3tc) {
-         if (formats) {
-            formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
-            /* This format has some restrictions/limitations and so should
-             * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query.
-             * Specifically, all transparent pixels become black.  NVIDIA
-             * omits this format too.
-             */
-            if (all)
-               formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-            formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
-            formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
-         }
-         else {
-            n += 3;
-            if (all)
-               n += 1;
-         }
+      else {
+         n += 2;
       }
-      if (ctx->Extensions.S3_s3tc) {
-         if (formats) {
-            formats[n++] = GL_RGB_S3TC;
-            formats[n++] = GL_RGB4_S3TC;
-            formats[n++] = GL_RGBA_S3TC;
-            formats[n++] = GL_RGBA4_S3TC;
-         }
-         else {
-            n += 4;
-         }
+   }
+   if (ctx->Extensions.EXT_texture_compression_s3tc) {
+      if (formats) {
+         formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+         /* This format has some restrictions/limitations and so should
+          * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query.
+          * Specifically, all transparent pixels become black.  NVIDIA
+          * omits this format too.
+          */
+         if (all)
+             formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+         formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+         formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      }
+      else {
+         n += 3;
+         if (all)
+             n += 1;
+      }
+   }
+   if (ctx->Extensions.S3_s3tc) {
+      if (formats) {
+         formats[n++] = GL_RGB_S3TC;
+         formats[n++] = GL_RGB4_S3TC;
+         formats[n++] = GL_RGBA_S3TC;
+         formats[n++] = GL_RGBA4_S3TC;
+      }
+      else {
+         n += 4;
       }
+   }
 #if FEATURE_EXT_texture_sRGB
-      if (ctx->Extensions.EXT_texture_sRGB) {
-         if (formats) {
-            formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
-            formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
-            formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
-            formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
-         }
-         else {
-            n += 4;
-         }
+   if (ctx->Extensions.EXT_texture_sRGB) {
+      if (formats) {
+         formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+         formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+         formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+         formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+      }
+      else {
+         n += 4;
       }
-#endif /* FEATURE_EXT_texture_sRGB */
    }
+#endif /* FEATURE_EXT_texture_sRGB */
    return n;
 }
 
 
-
 /**
- * Return number of bytes needed to store a texture of the given size
- * using the specified compressed format.
- * This is called via the ctx->Driver.CompressedTextureSize function,
- * unless a device driver overrides it.
- *
- * \param width texture width in texels.
- * \param height texture height in texels.
- * \param depth texture depth in texels.
- * \param mesaFormat  one of the MESA_FORMAT_* compressed formats
- *
- * \return size in bytes, or zero if bad format
+ * Convert a compressed MESA_FORMAT_x to a GLenum.
  */
-GLuint
-_mesa_compressed_texture_size( GLcontext *ctx,
-                               GLsizei width, GLsizei height, GLsizei depth,
-                               GLuint mesaFormat )
+gl_format
+_mesa_glenum_to_compressed_format(GLenum format)
 {
-   GLuint size;
-
-   ASSERT(depth == 1);
-   (void) depth;
-   (void) size;
-
-   switch (mesaFormat) {
-#if FEATURE_texture_fxt1
-   case MESA_FORMAT_RGB_FXT1:
-   case MESA_FORMAT_RGBA_FXT1:
-      /* round up width to next multiple of 8, height to next multiple of 4 */
-      width = (width + 7) & ~7;
-      height = (height + 3) & ~3;
-      /* 16 bytes per 8x4 tile of RGB[A] texels */
-      size = width * height / 2;
-      /* Textures smaller than 8x4 will effectively be made into 8x4 and
-       * take 16 bytes.
-       */
-      if (size < 16)
-         size = 16;
-      return size;
-#endif
-#if FEATURE_texture_s3tc
-   case MESA_FORMAT_RGB_DXT1:
-   case MESA_FORMAT_RGBA_DXT1:
-      /* round up width, height to next multiple of 4 */
-      width = (width + 3) & ~3;
-      height = (height + 3) & ~3;
-      /* 8 bytes per 4x4 tile of RGB[A] texels */
-      size = width * height / 2;
-      /* Textures smaller than 4x4 will effectively be made into 4x4 and
-       * take 8 bytes.
-       */
-      if (size < 8)
-         size = 8;
-      return size;
-   case MESA_FORMAT_RGBA_DXT3:
-   case MESA_FORMAT_RGBA_DXT5:
-      /* round up width, height to next multiple of 4 */
-      width = (width + 3) & ~3;
-      height = (height + 3) & ~3;
-      /* 16 bytes per 4x4 tile of RGBA texels */
-      size = width * height; /* simple! */
-      /* Textures smaller than 4x4 will effectively be made into 4x4 and
-       * take 16 bytes.
-       */
-      if (size < 16)
-         size = 16;
-      return size;
-#endif
-   default:
-      _mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size");
-      return 0;
-   }
-}
-
-
-/**
- * As above, but format is specified by a GLenum (GL_COMPRESSED_*) token.
- *
- * Note: This function CAN NOT return a padded hardware texture size.
- * That's why we don't call the ctx->Driver.CompressedTextureSize() function.
- *
- * We use this function to validate the <imageSize> parameter
- * of glCompressedTex[Sub]Image1/2/3D(), which must be an exact match.
- */
-GLuint
-_mesa_compressed_texture_size_glenum(GLcontext *ctx,
-                                     GLsizei width, GLsizei height,
-                                     GLsizei depth, GLenum glformat)
-{
-   GLuint mesaFormat;
-
-   switch (glformat) {
-#if FEATURE_texture_fxt1
+   switch (format) {
    case GL_COMPRESSED_RGB_FXT1_3DFX:
-      mesaFormat = MESA_FORMAT_RGB_FXT1;
-      break;
+      return MESA_FORMAT_RGB_FXT1;
    case GL_COMPRESSED_RGBA_FXT1_3DFX:
-      mesaFormat = MESA_FORMAT_RGBA_FXT1;
-      break;
-#endif
-#if FEATURE_texture_s3tc
+      return MESA_FORMAT_RGBA_FXT1;
+
    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    case GL_RGB_S3TC:
-      mesaFormat = MESA_FORMAT_RGB_DXT1;
-      break;
+      return MESA_FORMAT_RGB_DXT1;
    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    case GL_RGB4_S3TC:
-      mesaFormat = MESA_FORMAT_RGBA_DXT1;
-      break;
+      return MESA_FORMAT_RGBA_DXT1;
    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    case GL_RGBA_S3TC:
-      mesaFormat = MESA_FORMAT_RGBA_DXT3;
-      break;
+      return MESA_FORMAT_RGBA_DXT3;
    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
    case GL_RGBA4_S3TC:
-      mesaFormat = MESA_FORMAT_RGBA_DXT5;
-      break;
-#endif
+      return MESA_FORMAT_RGBA_DXT5;
+
+   case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+      return MESA_FORMAT_SRGB_DXT1;
+   case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+      return MESA_FORMAT_SRGBA_DXT1;
+   case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+      return MESA_FORMAT_SRGBA_DXT3;
+   case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+      return MESA_FORMAT_SRGBA_DXT5;
+
    default:
-      return 0;
+      return MESA_FORMAT_NONE;
    }
-
-   return _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
 }
 
 
-/*
- * Compute the bytes per row in a compressed texture image.
- * We use this for computing the destination address for sub-texture updates.
- * \param mesaFormat  one of the MESA_FORMAT_* compressed formats
- * \param width  image width in pixels
- * \return stride, in bytes, between rows for compressed image
+/**
+ * Given a compressed MESA_FORMAT_x value, return the corresponding
+ * GLenum for that format.
+ * This is needed for glGetTexLevelParameter(GL_TEXTURE_INTERNAL_FORMAT)
+ * which must return the specific texture format used when the user might
+ * have originally specified a generic compressed format in their
+ * glTexImage2D() call.
+ * For non-compressed textures, we always return the user-specified
+ * internal format unchanged.
  */
-GLint
-_mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width)
+GLenum
+_mesa_compressed_format_to_glenum(GLcontext *ctx, GLuint mesaFormat)
 {
-   GLint stride;
-
    switch (mesaFormat) {
 #if FEATURE_texture_fxt1
    case MESA_FORMAT_RGB_FXT1:
+      return GL_COMPRESSED_RGB_FXT1_3DFX;
    case MESA_FORMAT_RGBA_FXT1:
-      stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */
-      break;
+      return GL_COMPRESSED_RGBA_FXT1_3DFX;
 #endif
 #if FEATURE_texture_s3tc
    case MESA_FORMAT_RGB_DXT1:
+      return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
    case MESA_FORMAT_RGBA_DXT1:
-      stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */
-      break;
+      return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
    case MESA_FORMAT_RGBA_DXT3:
+      return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
    case MESA_FORMAT_RGBA_DXT5:
-      stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */
-      break;
+      return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+#if FEATURE_EXT_texture_sRGB
+   case MESA_FORMAT_SRGB_DXT1:
+      return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+   case MESA_FORMAT_SRGBA_DXT1:
+      return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+   case MESA_FORMAT_SRGBA_DXT3:
+      return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+   case MESA_FORMAT_SRGBA_DXT5:
+      return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+#endif
 #endif
    default:
-      _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_row_stride");
+      _mesa_problem(ctx, "Unexpected mesa texture format in"
+                    " _mesa_compressed_format_to_glenum()");
       return 0;
    }
-
-   return stride;
 }
 
 
 /*
  * Return the address of the pixel at (col, row, img) in a
  * compressed texture image.
- * \param col, row, img - image position (3D)
+ * \param col, row, img - image position (3D), should be a multiple of the
+ *                        format's block size.
  * \param format - compressed image format
- * \param width - image width
+ * \param width - image width (stride) in pixels
  * \param image - the image address
- * \return address of pixel at (row, col)
+ * \return address of pixel at (row, col, img)
  */
 GLubyte *
 _mesa_compressed_image_address(GLint col, GLint row, GLint img,
-                               GLuint mesaFormat,
+                               gl_format mesaFormat,
                                GLsizei width, const GLubyte *image)
 {
-   GLubyte *addr;
+   /* XXX only 2D images implemented, not 3D */
+   const GLuint blockSize = _mesa_get_format_bytes(mesaFormat);
+   GLuint bw, bh;
+   GLint offset;
 
-   (void) img;
+   _mesa_get_format_block_size(mesaFormat, &bw, &bh);
 
-   /* We try to spot a "complete" subtexture "above" ROW, COL;
-    * this texture is given by appropriate rounding of WIDTH x ROW.
-    * Then we just add the amount left (usually on the left).
-    *
-    * Example for X*Y microtiles (Z bytes each)
-    * offset = Z * (((width + X - 1) / X) * (row / Y) + col / X);
-    */
+   ASSERT(col % bw == 0);
+   ASSERT(row % bh == 0);
 
-   switch (mesaFormat) {
-#if FEATURE_texture_fxt1
-   case MESA_FORMAT_RGB_FXT1:
-   case MESA_FORMAT_RGBA_FXT1:
-      addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8);
-      break;
-#endif
-#if FEATURE_texture_s3tc
-   case MESA_FORMAT_RGB_DXT1:
-   case MESA_FORMAT_RGBA_DXT1:
-      addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4);
-      break;
-   case MESA_FORMAT_RGBA_DXT3:
-   case MESA_FORMAT_RGBA_DXT5:
-      addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4);
-      break;
-#endif
-   default:
-      _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_image_address");
-      addr = NULL;
-   }
+   offset = ((width + bw - 1) / bw) * (row / bh) + col / bw;
+   offset *= blockSize;
 
-   return addr;
+   return (GLubyte *) image + offset;
 }