texcompress.c revision 33fa5e4bfad8005f09ad3c9fc92c40fa863935d1
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.TDFX_texture_compression_FXT1) { 60 if (formats) { 61 formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX; 62 formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX; 63 } 64 else { 65 n += 2; 66 } 67 } 68 if (ctx->Extensions.EXT_texture_compression_s3tc) { 69 if (formats) { 70 formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; 71 /* This format has some restrictions/limitations and so should 72 * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query. 73 * Specifically, all transparent pixels become black. NVIDIA 74 * omits this format too. 75 */ 76 if (all) 77 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; 78 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; 79 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; 80 } 81 else { 82 n += 3; 83 if (all) 84 n += 1; 85 } 86 } 87 if (ctx->Extensions.S3_s3tc) { 88 if (formats) { 89 formats[n++] = GL_RGB_S3TC; 90 formats[n++] = GL_RGB4_S3TC; 91 formats[n++] = GL_RGBA_S3TC; 92 formats[n++] = GL_RGBA4_S3TC; 93 } 94 else { 95 n += 4; 96 } 97 } 98#if FEATURE_EXT_texture_sRGB 99 if (ctx->Extensions.EXT_texture_sRGB) { 100 if (formats) { 101 formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; 102 formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; 103 formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; 104 formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; 105 } 106 else { 107 n += 4; 108 } 109 } 110#endif /* FEATURE_EXT_texture_sRGB */ 111 return n; 112} 113 114 115 116/** 117 * Return number of bytes needed to store a texture of the given size 118 * using the specified compressed format. 119 * This is called via the ctx->Driver.CompressedTextureSize function, 120 * unless a device driver overrides it. 121 * 122 * \param width texture width in texels. 123 * \param height texture height in texels. 124 * \param depth texture depth in texels. 125 * \param mesaFormat one of the MESA_FORMAT_* compressed formats 126 * 127 * \return size in bytes, or zero if bad format 128 */ 129GLuint 130_mesa_compressed_texture_size( GLcontext *ctx, 131 GLsizei width, GLsizei height, GLsizei depth, 132 GLuint mesaFormat ) 133{ 134 GLuint size; 135 136 ASSERT(depth == 1); 137 (void) depth; 138 139 switch (mesaFormat) { 140 case MESA_FORMAT_RGB_FXT1: 141 case MESA_FORMAT_RGBA_FXT1: 142 /* round up width to next multiple of 8, height to next multiple of 4 */ 143 width = (width + 7) & ~7; 144 height = (height + 3) & ~3; 145 /* 16 bytes per 8x4 tile of RGB[A] texels */ 146 size = width * height / 2; 147 /* Textures smaller than 8x4 will effectively be made into 8x4 and 148 * take 16 bytes. 149 */ 150 return size; 151 case MESA_FORMAT_RGB_DXT1: 152 case MESA_FORMAT_RGBA_DXT1: 153 /* round up width, height to next multiple of 4 */ 154 width = (width + 3) & ~3; 155 height = (height + 3) & ~3; 156 /* 8 bytes per 4x4 tile of RGB[A] texels */ 157 size = width * height / 2; 158 /* Textures smaller than 4x4 will effectively be made into 4x4 and 159 * take 8 bytes. 160 */ 161 return size; 162 case MESA_FORMAT_RGBA_DXT3: 163 case MESA_FORMAT_RGBA_DXT5: 164 /* round up width, height to next multiple of 4 */ 165 width = (width + 3) & ~3; 166 height = (height + 3) & ~3; 167 /* 16 bytes per 4x4 tile of RGBA texels */ 168 size = width * height; /* simple! */ 169 /* Textures smaller than 4x4 will effectively be made into 4x4 and 170 * take 16 bytes. 171 */ 172 return size; 173 default: 174 _mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size"); 175 return 0; 176 } 177} 178 179 180/** 181 * As above, but format is specified by a GLenum (GL_COMPRESSED_*) token. 182 * 183 * Note: This function CAN NOT return a padded hardware texture size. 184 * That's why we don't call the ctx->Driver.CompressedTextureSize() function. 185 * 186 * We use this function to validate the <imageSize> parameter 187 * of glCompressedTex[Sub]Image1/2/3D(), which must be an exact match. 188 */ 189GLuint 190_mesa_compressed_texture_size_glenum(GLcontext *ctx, 191 GLsizei width, GLsizei height, 192 GLsizei depth, GLenum glformat) 193{ 194 GLuint mesaFormat; 195 196 switch (glformat) { 197 case GL_COMPRESSED_RGB_FXT1_3DFX: 198 mesaFormat = MESA_FORMAT_RGB_FXT1; 199 break; 200 case GL_COMPRESSED_RGBA_FXT1_3DFX: 201 mesaFormat = MESA_FORMAT_RGBA_FXT1; 202 break; 203 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 204 case GL_RGB_S3TC: 205 mesaFormat = MESA_FORMAT_RGB_DXT1; 206 break; 207 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 208 case GL_RGB4_S3TC: 209 mesaFormat = MESA_FORMAT_RGBA_DXT1; 210 break; 211 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 212 case GL_RGBA_S3TC: 213 mesaFormat = MESA_FORMAT_RGBA_DXT3; 214 break; 215 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 216 case GL_RGBA4_S3TC: 217 mesaFormat = MESA_FORMAT_RGBA_DXT5; 218 break; 219 default: 220 return 0; 221 } 222 223 return _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat); 224} 225 226 227/* 228 * Compute the bytes per row in a compressed texture image. 229 * We use this for computing the destination address for sub-texture updates. 230 * \param mesaFormat one of the MESA_FORMAT_* compressed formats 231 * \param width image width in pixels 232 * \return stride, in bytes, between rows for compressed image 233 */ 234GLint 235_mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width) 236{ 237 GLint stride; 238 239 switch (mesaFormat) { 240 case MESA_FORMAT_RGB_FXT1: 241 case MESA_FORMAT_RGBA_FXT1: 242 stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */ 243 break; 244 case MESA_FORMAT_RGB_DXT1: 245 case MESA_FORMAT_RGBA_DXT1: 246 stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */ 247 break; 248 case MESA_FORMAT_RGBA_DXT3: 249 case MESA_FORMAT_RGBA_DXT5: 250 stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */ 251 break; 252 default: 253 _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_row_stride"); 254 return 0; 255 } 256 257 return stride; 258} 259 260 261/* 262 * Return the address of the pixel at (col, row, img) in a 263 * compressed texture image. 264 * \param col, row, img - image position (3D) 265 * \param format - compressed image format 266 * \param width - image width 267 * \param image - the image address 268 * \return address of pixel at (row, col) 269 */ 270GLubyte * 271_mesa_compressed_image_address(GLint col, GLint row, GLint img, 272 GLuint mesaFormat, 273 GLsizei width, const GLubyte *image) 274{ 275 GLubyte *addr; 276 277 (void) img; 278 279 /* We try to spot a "complete" subtexture "above" ROW, COL; 280 * this texture is given by appropriate rounding of WIDTH x ROW. 281 * Then we just add the amount left (usually on the left). 282 * 283 * Example for X*Y microtiles (Z bytes each) 284 * offset = Z * (((width + X - 1) / X) * (row / Y) + col / X); 285 */ 286 287 switch (mesaFormat) { 288 case MESA_FORMAT_RGB_FXT1: 289 case MESA_FORMAT_RGBA_FXT1: 290 addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8); 291 break; 292 case MESA_FORMAT_RGB_DXT1: 293 case MESA_FORMAT_RGBA_DXT1: 294 addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4); 295 break; 296 case MESA_FORMAT_RGBA_DXT3: 297 case MESA_FORMAT_RGBA_DXT5: 298 addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4); 299 break; 300 default: 301 _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_image_address"); 302 addr = NULL; 303 } 304 305 return addr; 306} 307