texcompress.c revision e961a5da77cbcdb0e32400ec707c16fcfe9d7083
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.1 4 * 5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26/** 27 * \file texcompress.c 28 * Helper functions for texture compression. 29 */ 30 31 32#include "glheader.h" 33#include "imports.h" 34#include "colormac.h" 35#include "context.h" 36#include "image.h" 37#include "mipmap.h" 38#include "texcompress.h" 39#include "texformat.h" 40#include "texstore.h" 41 42 43/** 44 * Return list of (and count of) all specific texture compression 45 * formats that are supported. 46 * 47 * \param ctx the GL context 48 * \param formats the resulting format list (may be NULL). 49 * \param all if true return all formats, even those with some kind 50 * of restrictions/limitations (See GL_ARB_texture_compression 51 * spec for more info). 52 * 53 * \return number of formats. 54 */ 55GLuint 56_mesa_get_compressed_formats(GLcontext *ctx, GLint *formats, GLboolean all) 57{ 58 GLuint n = 0; 59 if (ctx->Extensions.ARB_texture_compression) { 60 if (ctx->Extensions.TDFX_texture_compression_FXT1) { 61 if (formats) { 62 formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX; 63 formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX; 64 } 65 else { 66 n += 2; 67 } 68 } 69 if (ctx->Extensions.EXT_texture_compression_s3tc) { 70 if (formats) { 71 formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; 72 /* This format has some restrictions/limitations and so should 73 * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query. 74 * Specifically, all transparent pixels become black. NVIDIA 75 * omits this format too. 76 */ 77 if (all) 78 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; 79 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; 80 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; 81 } 82 else { 83 n += 3; 84 if (all) 85 n += 1; 86 } 87 } 88 if (ctx->Extensions.S3_s3tc) { 89 if (formats) { 90 formats[n++] = GL_RGB_S3TC; 91 formats[n++] = GL_RGB4_S3TC; 92 formats[n++] = GL_RGBA_S3TC; 93 formats[n++] = GL_RGBA4_S3TC; 94 } 95 else { 96 n += 4; 97 } 98 } 99#if FEATURE_EXT_texture_sRGB 100 if (ctx->Extensions.EXT_texture_sRGB) { 101 if (formats) { 102 formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; 103 formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; 104 formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; 105 formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; 106 } 107 else { 108 n += 4; 109 } 110 } 111#endif /* FEATURE_EXT_texture_sRGB */ 112 } 113 return n; 114} 115 116 117 118/** 119 * Return number of bytes needed to store a texture of the given size 120 * using the specified compressed format. 121 * This is called via the ctx->Driver.CompressedTextureSize function, 122 * unless a device driver overrides it. 123 * 124 * \param width texture width in texels. 125 * \param height texture height in texels. 126 * \param depth texture depth in texels. 127 * \param mesaFormat one of the MESA_FORMAT_* compressed formats 128 * 129 * \return size in bytes, or zero if bad format 130 */ 131GLuint 132_mesa_compressed_texture_size( GLcontext *ctx, 133 GLsizei width, GLsizei height, GLsizei depth, 134 GLuint mesaFormat ) 135{ 136 GLuint size; 137 138 ASSERT(depth == 1); 139 (void) depth; 140 (void) size; 141 142 switch (mesaFormat) { 143#if FEATURE_texture_fxt1 144 case MESA_FORMAT_RGB_FXT1: 145 case MESA_FORMAT_RGBA_FXT1: 146 /* round up width to next multiple of 8, height to next multiple of 4 */ 147 width = (width + 7) & ~7; 148 height = (height + 3) & ~3; 149 /* 16 bytes per 8x4 tile of RGB[A] texels */ 150 size = width * height / 2; 151 /* Textures smaller than 8x4 will effectively be made into 8x4 and 152 * take 16 bytes. 153 */ 154 if (size < 16) 155 size = 16; 156 return size; 157#endif 158#if FEATURE_texture_s3tc 159 case MESA_FORMAT_RGB_DXT1: 160 case MESA_FORMAT_RGBA_DXT1: 161 /* round up width, height to next multiple of 4 */ 162 width = (width + 3) & ~3; 163 height = (height + 3) & ~3; 164 /* 8 bytes per 4x4 tile of RGB[A] texels */ 165 size = width * height / 2; 166 /* Textures smaller than 4x4 will effectively be made into 4x4 and 167 * take 8 bytes. 168 */ 169 if (size < 8) 170 size = 8; 171 return size; 172 case MESA_FORMAT_RGBA_DXT3: 173 case MESA_FORMAT_RGBA_DXT5: 174 /* round up width, height to next multiple of 4 */ 175 width = (width + 3) & ~3; 176 height = (height + 3) & ~3; 177 /* 16 bytes per 4x4 tile of RGBA texels */ 178 size = width * height; /* simple! */ 179 /* Textures smaller than 4x4 will effectively be made into 4x4 and 180 * take 16 bytes. 181 */ 182 if (size < 16) 183 size = 16; 184 return size; 185#endif 186 default: 187 _mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size"); 188 return 0; 189 } 190} 191 192 193/** 194 * As above, but format is specified by a GLenum (GL_COMPRESSED_*) token. 195 * 196 * Note: This function CAN NOT return a padded hardware texture size. 197 * That's why we don't call the ctx->Driver.CompressedTextureSize() function. 198 * 199 * We use this function to validate the <imageSize> parameter 200 * of glCompressedTex[Sub]Image1/2/3D(), which must be an exact match. 201 */ 202GLuint 203_mesa_compressed_texture_size_glenum(GLcontext *ctx, 204 GLsizei width, GLsizei height, 205 GLsizei depth, GLenum glformat) 206{ 207 GLuint mesaFormat; 208 209 switch (glformat) { 210#if FEATURE_texture_fxt1 211 case GL_COMPRESSED_RGB_FXT1_3DFX: 212 mesaFormat = MESA_FORMAT_RGB_FXT1; 213 break; 214 case GL_COMPRESSED_RGBA_FXT1_3DFX: 215 mesaFormat = MESA_FORMAT_RGBA_FXT1; 216 break; 217#endif 218#if FEATURE_texture_s3tc 219 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 220 case GL_RGB_S3TC: 221 mesaFormat = MESA_FORMAT_RGB_DXT1; 222 break; 223 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 224 case GL_RGB4_S3TC: 225 mesaFormat = MESA_FORMAT_RGBA_DXT1; 226 break; 227 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 228 case GL_RGBA_S3TC: 229 mesaFormat = MESA_FORMAT_RGBA_DXT3; 230 break; 231 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 232 case GL_RGBA4_S3TC: 233 mesaFormat = MESA_FORMAT_RGBA_DXT5; 234 break; 235#endif 236 default: 237 return 0; 238 } 239 240 return _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat); 241} 242 243 244/* 245 * Compute the bytes per row in a compressed texture image. 246 * We use this for computing the destination address for sub-texture updates. 247 * \param mesaFormat one of the MESA_FORMAT_* compressed formats 248 * \param width image width in pixels 249 * \return stride, in bytes, between rows for compressed image 250 */ 251GLint 252_mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width) 253{ 254 GLint stride; 255 256 switch (mesaFormat) { 257#if FEATURE_texture_fxt1 258 case MESA_FORMAT_RGB_FXT1: 259 case MESA_FORMAT_RGBA_FXT1: 260 stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */ 261 break; 262#endif 263#if FEATURE_texture_s3tc 264 case MESA_FORMAT_RGB_DXT1: 265 case MESA_FORMAT_RGBA_DXT1: 266 stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */ 267 break; 268 case MESA_FORMAT_RGBA_DXT3: 269 case MESA_FORMAT_RGBA_DXT5: 270 stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */ 271 break; 272#endif 273 default: 274 _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_row_stride"); 275 return 0; 276 } 277 278 return stride; 279} 280 281 282/* 283 * Return the address of the pixel at (col, row, img) in a 284 * compressed texture image. 285 * \param col, row, img - image position (3D) 286 * \param format - compressed image format 287 * \param width - image width 288 * \param image - the image address 289 * \return address of pixel at (row, col) 290 */ 291GLubyte * 292_mesa_compressed_image_address(GLint col, GLint row, GLint img, 293 GLuint mesaFormat, 294 GLsizei width, const GLubyte *image) 295{ 296 GLubyte *addr; 297 298 (void) img; 299 300 /* We try to spot a "complete" subtexture "above" ROW, COL; 301 * this texture is given by appropriate rounding of WIDTH x ROW. 302 * Then we just add the amount left (usually on the left). 303 * 304 * Example for X*Y microtiles (Z bytes each) 305 * offset = Z * (((width + X - 1) / X) * (row / Y) + col / X); 306 */ 307 308 switch (mesaFormat) { 309#if FEATURE_texture_fxt1 310 case MESA_FORMAT_RGB_FXT1: 311 case MESA_FORMAT_RGBA_FXT1: 312 addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8); 313 break; 314#endif 315#if FEATURE_texture_s3tc 316 case MESA_FORMAT_RGB_DXT1: 317 case MESA_FORMAT_RGBA_DXT1: 318 addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4); 319 break; 320 case MESA_FORMAT_RGBA_DXT3: 321 case MESA_FORMAT_RGBA_DXT5: 322 addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4); 323 break; 324#endif 325 default: 326 _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_image_address"); 327 addr = NULL; 328 } 329 330 return addr; 331} 332