mesa: remove unused var
[mesa.git] / src / mesa / main / texcompress.c
index 0a92c9268361cd15654716910836c6a5d91f5d86..cff6de89ee30bd2e0c8278902cfdae779c337d1e 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.5.1
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * 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 "formats.h"
 #include "texcompress.h"
-#include "texformat.h"
-#include "texstore.h"
+
 
 /**
- * Get the list of supported internal compression formats.
+ * Return list of (and count of) all specific texture compression
+ * formats that are supported.
  *
- * \param ctx GL context.
- * \param formats the resulting format list (may be NULL).
+ * \param ctx  the GL context
+ * \param formats  the resulting format list (may be NULL).
+ * \param all  if true return all formats, even those with  some kind
+ *             of restrictions/limitations (See GL_ARB_texture_compression
+ *             spec for more info).
  *
  * \return number of formats.
  */
 GLuint
-_mesa_get_compressed_formats( GLcontext *ctx, GLint *formats )
+_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;
+      }
+      else {
+         n += 2;
       }
-      if (ctx->Extensions.EXT_texture_compression_s3tc) {
-         if (formats) {
-            formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
-            /* Skip this one because it has a restriction (all transparent
-             * pixels become black).  See the texture compressions spec for
-             * a detailed explanation.  This is what NVIDIA does.
-            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 (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;
       }
-      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;
-         }
+      else {
+         n += 3;
+         if (all)
+             n += 1;
       }
    }
-   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
- */
-GLuint
-_mesa_compressed_texture_size( GLcontext *ctx,
-                               GLsizei width, GLsizei height, GLsizei depth,
-                               GLuint mesaFormat )
-{
-   GLuint size;
-
-   ASSERT(depth == 1);
-   (void) depth;
-
-   switch (mesaFormat) {
-   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;
-   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;
-   default:
-      _mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size");
-      return 0;
+   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;
+      }
+   }
+#endif /* FEATURE_EXT_texture_sRGB */
+   return n;
 }
 
 
 /**
- * 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.
+ * Convert a compressed MESA_FORMAT_x to a GLenum.
  */
-GLuint
-_mesa_compressed_texture_size_glenum(GLcontext *ctx,
-                                     GLsizei width, GLsizei height,
-                                     GLsizei depth, GLenum glformat)
+gl_format
+_mesa_glenum_to_compressed_format(GLenum format)
 {
-   GLuint mesaFormat;
-
-   switch (glformat) {
+   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;
+      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;
+      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) {
-   case MESA_FORMAT_RGB_FXT1:
-   case MESA_FORMAT_RGBA_FXT1:
-      addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8);
-      break;
-   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;
-   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;
 }