texcompress_s3tc.c revision cdc920a0
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.3 4 * 5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6 * Copyright (c) 2008 VMware, Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27/** 28 * \file texcompress_s3tc.c 29 * GL_EXT_texture_compression_s3tc support. 30 */ 31 32#ifndef USE_EXTERNAL_DXTN_LIB 33#define USE_EXTERNAL_DXTN_LIB 1 34#endif 35 36#include "glheader.h" 37#include "imports.h" 38#include "colormac.h" 39#include "context.h" 40#include "convolve.h" 41#include "dlopen.h" 42#include "image.h" 43#include "texcompress.h" 44#include "texcompress_s3tc.h" 45#include "texstore.h" 46 47 48#if FEATURE_texture_s3tc 49 50 51#ifdef __MINGW32__ 52#define DXTN_LIBNAME "dxtn.dll" 53#define RTLD_LAZY 0 54#define RTLD_GLOBAL 0 55#elif defined(__DJGPP__) 56#define DXTN_LIBNAME "dxtn.dxe" 57#else 58#define DXTN_LIBNAME "libtxc_dxtn.so" 59#endif 60 61#if FEATURE_EXT_texture_sRGB 62/** 63 * Convert an 8-bit sRGB value from non-linear space to a 64 * linear RGB value in [0, 1]. 65 * Implemented with a 256-entry lookup table. 66 */ 67static INLINE GLfloat 68nonlinear_to_linear(GLubyte cs8) 69{ 70 static GLfloat table[256]; 71 static GLboolean tableReady = GL_FALSE; 72 if (!tableReady) { 73 /* compute lookup table now */ 74 GLuint i; 75 for (i = 0; i < 256; i++) { 76 const GLfloat cs = UBYTE_TO_FLOAT(i); 77 if (cs <= 0.04045) { 78 table[i] = cs / 12.92f; 79 } 80 else { 81 table[i] = (GLfloat) _mesa_pow((cs + 0.055) / 1.055, 2.4); 82 } 83 } 84 tableReady = GL_TRUE; 85 } 86 return table[cs8]; 87} 88#endif /* FEATURE_EXT_texture_sRGB */ 89 90typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut ); 91 92dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL; 93dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL; 94dxtFetchTexelFuncExt fetch_ext_rgba_dxt3 = NULL; 95dxtFetchTexelFuncExt fetch_ext_rgba_dxt5 = NULL; 96 97typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width, 98 GLint height, const GLchan *srcPixData, 99 GLenum destformat, GLubyte *dest, 100 GLint dstRowStride); 101 102static dxtCompressTexFuncExt ext_tx_compress_dxtn = NULL; 103 104static void *dxtlibhandle = NULL; 105 106 107void 108_mesa_init_texture_s3tc( GLcontext *ctx ) 109{ 110 /* called during context initialization */ 111 ctx->Mesa_DXTn = GL_FALSE; 112#if USE_EXTERNAL_DXTN_LIB 113 if (!dxtlibhandle) { 114 dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0); 115 if (!dxtlibhandle) { 116 _mesa_warning(ctx, "couldn't open " DXTN_LIBNAME ", software DXTn " 117 "compression/decompression unavailable"); 118 } 119 else { 120 /* the fetch functions are not per context! Might be problematic... */ 121 fetch_ext_rgb_dxt1 = (dxtFetchTexelFuncExt) 122 _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1"); 123 fetch_ext_rgba_dxt1 = (dxtFetchTexelFuncExt) 124 _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1"); 125 fetch_ext_rgba_dxt3 = (dxtFetchTexelFuncExt) 126 _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3"); 127 fetch_ext_rgba_dxt5 = (dxtFetchTexelFuncExt) 128 _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5"); 129 ext_tx_compress_dxtn = (dxtCompressTexFuncExt) 130 _mesa_dlsym(dxtlibhandle, "tx_compress_dxtn"); 131 132 if (!fetch_ext_rgb_dxt1 || 133 !fetch_ext_rgba_dxt1 || 134 !fetch_ext_rgba_dxt3 || 135 !fetch_ext_rgba_dxt5 || 136 !ext_tx_compress_dxtn) { 137 _mesa_warning(ctx, "couldn't reference all symbols in " 138 DXTN_LIBNAME ", software DXTn compression/decompression " 139 "unavailable"); 140 fetch_ext_rgb_dxt1 = NULL; 141 fetch_ext_rgba_dxt1 = NULL; 142 fetch_ext_rgba_dxt3 = NULL; 143 fetch_ext_rgba_dxt5 = NULL; 144 ext_tx_compress_dxtn = NULL; 145 _mesa_dlclose(dxtlibhandle); 146 dxtlibhandle = NULL; 147 } 148 } 149 } 150 if (dxtlibhandle) { 151 ctx->Mesa_DXTn = GL_TRUE; 152 _mesa_warning(ctx, "software DXTn compression/decompression available"); 153 } 154#else 155 (void) ctx; 156#endif 157} 158 159/** 160 * Store user's image in rgb_dxt1 format. 161 */ 162GLboolean 163_mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS) 164{ 165 const GLchan *pixels; 166 GLint srcRowStride; 167 GLubyte *dst; 168 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */ 169 const GLchan *tempImage = NULL; 170 171 ASSERT(dstFormat == MESA_FORMAT_RGB_DXT1); 172 ASSERT(dstXoffset % 4 == 0); 173 ASSERT(dstYoffset % 4 == 0); 174 ASSERT(dstZoffset % 4 == 0); 175 (void) dstZoffset; 176 (void) dstImageOffsets; 177 178 if (srcFormat != GL_RGB || 179 srcType != CHAN_TYPE || 180 ctx->_ImageTransferState || 181 srcPacking->SwapBytes) { 182 /* convert image to RGB/GLchan */ 183 tempImage = _mesa_make_temp_chan_image(ctx, dims, 184 baseInternalFormat, 185 _mesa_get_format_base_format(dstFormat), 186 srcWidth, srcHeight, srcDepth, 187 srcFormat, srcType, srcAddr, 188 srcPacking); 189 if (!tempImage) 190 return GL_FALSE; /* out of memory */ 191 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 192 pixels = tempImage; 193 srcRowStride = 3 * srcWidth; 194 srcFormat = GL_RGB; 195 } 196 else { 197 pixels = (const GLchan *) srcAddr; 198 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, 199 srcType) / sizeof(GLchan); 200 } 201 202 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 203 dstFormat, 204 texWidth, (GLubyte *) dstAddr); 205 206 if (ext_tx_compress_dxtn) { 207 (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels, 208 GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 209 dst, dstRowStride); 210 } 211 else { 212 _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1"); 213 } 214 215 if (tempImage) 216 free((void *) tempImage); 217 218 return GL_TRUE; 219} 220 221 222/** 223 * Store user's image in rgba_dxt1 format. 224 */ 225GLboolean 226_mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS) 227{ 228 const GLchan *pixels; 229 GLint srcRowStride; 230 GLubyte *dst; 231 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */ 232 const GLchan *tempImage = NULL; 233 234 ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT1); 235 ASSERT(dstXoffset % 4 == 0); 236 ASSERT(dstYoffset % 4 == 0); 237 ASSERT(dstZoffset % 4 == 0); 238 (void) dstZoffset; 239 (void) dstImageOffsets; 240 241 if (srcFormat != GL_RGBA || 242 srcType != CHAN_TYPE || 243 ctx->_ImageTransferState || 244 srcPacking->SwapBytes) { 245 /* convert image to RGBA/GLchan */ 246 tempImage = _mesa_make_temp_chan_image(ctx, dims, 247 baseInternalFormat, 248 _mesa_get_format_base_format(dstFormat), 249 srcWidth, srcHeight, srcDepth, 250 srcFormat, srcType, srcAddr, 251 srcPacking); 252 if (!tempImage) 253 return GL_FALSE; /* out of memory */ 254 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 255 pixels = tempImage; 256 srcRowStride = 4 * srcWidth; 257 srcFormat = GL_RGBA; 258 } 259 else { 260 pixels = (const GLchan *) srcAddr; 261 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, 262 srcType) / sizeof(GLchan); 263 } 264 265 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 266 dstFormat, 267 texWidth, (GLubyte *) dstAddr); 268 if (ext_tx_compress_dxtn) { 269 (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, 270 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 271 dst, dstRowStride); 272 } 273 else { 274 _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1"); 275 } 276 277 if (tempImage) 278 free((void*) tempImage); 279 280 return GL_TRUE; 281} 282 283 284/** 285 * Store user's image in rgba_dxt3 format. 286 */ 287GLboolean 288_mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS) 289{ 290 const GLchan *pixels; 291 GLint srcRowStride; 292 GLubyte *dst; 293 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */ 294 const GLchan *tempImage = NULL; 295 296 ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT3); 297 ASSERT(dstXoffset % 4 == 0); 298 ASSERT(dstYoffset % 4 == 0); 299 ASSERT(dstZoffset % 4 == 0); 300 (void) dstZoffset; 301 (void) dstImageOffsets; 302 303 if (srcFormat != GL_RGBA || 304 srcType != CHAN_TYPE || 305 ctx->_ImageTransferState || 306 srcPacking->SwapBytes) { 307 /* convert image to RGBA/GLchan */ 308 tempImage = _mesa_make_temp_chan_image(ctx, dims, 309 baseInternalFormat, 310 _mesa_get_format_base_format(dstFormat), 311 srcWidth, srcHeight, srcDepth, 312 srcFormat, srcType, srcAddr, 313 srcPacking); 314 if (!tempImage) 315 return GL_FALSE; /* out of memory */ 316 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 317 pixels = tempImage; 318 srcRowStride = 4 * srcWidth; 319 } 320 else { 321 pixels = (const GLchan *) srcAddr; 322 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, 323 srcType) / sizeof(GLchan); 324 } 325 326 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 327 dstFormat, 328 texWidth, (GLubyte *) dstAddr); 329 if (ext_tx_compress_dxtn) { 330 (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, 331 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 332 dst, dstRowStride); 333 } 334 else { 335 _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt3"); 336 } 337 338 if (tempImage) 339 free((void *) tempImage); 340 341 return GL_TRUE; 342} 343 344 345/** 346 * Store user's image in rgba_dxt5 format. 347 */ 348GLboolean 349_mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS) 350{ 351 const GLchan *pixels; 352 GLint srcRowStride; 353 GLubyte *dst; 354 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */ 355 const GLchan *tempImage = NULL; 356 357 ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT5); 358 ASSERT(dstXoffset % 4 == 0); 359 ASSERT(dstYoffset % 4 == 0); 360 ASSERT(dstZoffset % 4 == 0); 361 (void) dstZoffset; 362 (void) dstImageOffsets; 363 364 if (srcFormat != GL_RGBA || 365 srcType != CHAN_TYPE || 366 ctx->_ImageTransferState || 367 srcPacking->SwapBytes) { 368 /* convert image to RGBA/GLchan */ 369 tempImage = _mesa_make_temp_chan_image(ctx, dims, 370 baseInternalFormat, 371 _mesa_get_format_base_format(dstFormat), 372 srcWidth, srcHeight, srcDepth, 373 srcFormat, srcType, srcAddr, 374 srcPacking); 375 if (!tempImage) 376 return GL_FALSE; /* out of memory */ 377 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 378 pixels = tempImage; 379 srcRowStride = 4 * srcWidth; 380 } 381 else { 382 pixels = (const GLchan *) srcAddr; 383 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, 384 srcType) / sizeof(GLchan); 385 } 386 387 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 388 dstFormat, 389 texWidth, (GLubyte *) dstAddr); 390 if (ext_tx_compress_dxtn) { 391 (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, 392 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 393 dst, dstRowStride); 394 } 395 else { 396 _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt5"); 397 } 398 399 if (tempImage) 400 free((void *) tempImage); 401 402 return GL_TRUE; 403} 404 405 406static void 407fetch_texel_2d_rgb_dxt1( const struct gl_texture_image *texImage, 408 GLint i, GLint j, GLint k, GLchan *texel ) 409{ 410 (void) k; 411 if (fetch_ext_rgb_dxt1) { 412 ASSERT (sizeof(GLchan) == sizeof(GLubyte)); 413 fetch_ext_rgb_dxt1(texImage->RowStride, 414 (GLubyte *)(texImage)->Data, i, j, texel); 415 } 416 else 417 _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgb_dxt1"); 418} 419 420 421void 422_mesa_fetch_texel_2d_f_rgb_dxt1(const struct gl_texture_image *texImage, 423 GLint i, GLint j, GLint k, GLfloat *texel) 424{ 425 /* just sample as GLchan and convert to float here */ 426 GLchan rgba[4]; 427 fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba); 428 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); 429 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); 430 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); 431 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 432} 433 434 435static void 436fetch_texel_2d_rgba_dxt1( const struct gl_texture_image *texImage, 437 GLint i, GLint j, GLint k, GLchan *texel ) 438{ 439 (void) k; 440 if (fetch_ext_rgba_dxt1) { 441 fetch_ext_rgba_dxt1(texImage->RowStride, 442 (GLubyte *)(texImage)->Data, i, j, texel); 443 } 444 else 445 _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt1\n"); 446} 447 448 449void 450_mesa_fetch_texel_2d_f_rgba_dxt1(const struct gl_texture_image *texImage, 451 GLint i, GLint j, GLint k, GLfloat *texel) 452{ 453 /* just sample as GLchan and convert to float here */ 454 GLchan rgba[4]; 455 fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba); 456 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); 457 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); 458 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); 459 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 460} 461 462 463static void 464fetch_texel_2d_rgba_dxt3( const struct gl_texture_image *texImage, 465 GLint i, GLint j, GLint k, GLchan *texel ) 466{ 467 (void) k; 468 if (fetch_ext_rgba_dxt3) { 469 ASSERT (sizeof(GLchan) == sizeof(GLubyte)); 470 fetch_ext_rgba_dxt3(texImage->RowStride, (GLubyte *)(texImage)->Data, 471 i, j, texel); 472 } 473 else 474 _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt3\n"); 475} 476 477 478void 479_mesa_fetch_texel_2d_f_rgba_dxt3(const struct gl_texture_image *texImage, 480 GLint i, GLint j, GLint k, GLfloat *texel) 481{ 482 /* just sample as GLchan and convert to float here */ 483 GLchan rgba[4]; 484 fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba); 485 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); 486 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); 487 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); 488 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 489} 490 491 492static void 493fetch_texel_2d_rgba_dxt5( const struct gl_texture_image *texImage, 494 GLint i, GLint j, GLint k, GLchan *texel ) 495{ 496 (void) k; 497 if (fetch_ext_rgba_dxt5) { 498 fetch_ext_rgba_dxt5(texImage->RowStride, (GLubyte *)(texImage)->Data, 499 i, j, texel); 500 } 501 else 502 _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt5\n"); 503} 504 505 506void 507_mesa_fetch_texel_2d_f_rgba_dxt5(const struct gl_texture_image *texImage, 508 GLint i, GLint j, GLint k, GLfloat *texel) 509{ 510 /* just sample as GLchan and convert to float here */ 511 GLchan rgba[4]; 512 fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba); 513 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); 514 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); 515 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); 516 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 517} 518 519#if FEATURE_EXT_texture_sRGB 520void 521_mesa_fetch_texel_2d_f_srgb_dxt1( const struct gl_texture_image *texImage, 522 GLint i, GLint j, GLint k, GLfloat *texel ) 523{ 524 /* just sample as GLchan and convert to float here */ 525 GLchan rgba[4]; 526 fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba); 527 texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); 528 texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); 529 texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); 530 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 531} 532 533void 534_mesa_fetch_texel_2d_f_srgba_dxt1(const struct gl_texture_image *texImage, 535 GLint i, GLint j, GLint k, GLfloat *texel) 536{ 537 /* just sample as GLchan and convert to float here */ 538 GLchan rgba[4]; 539 fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba); 540 texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); 541 texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); 542 texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); 543 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 544} 545 546void 547_mesa_fetch_texel_2d_f_srgba_dxt3(const struct gl_texture_image *texImage, 548 GLint i, GLint j, GLint k, GLfloat *texel) 549{ 550 /* just sample as GLchan and convert to float here */ 551 GLchan rgba[4]; 552 fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba); 553 texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); 554 texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); 555 texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); 556 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 557} 558 559void 560_mesa_fetch_texel_2d_f_srgba_dxt5(const struct gl_texture_image *texImage, 561 GLint i, GLint j, GLint k, GLfloat *texel) 562{ 563 /* just sample as GLchan and convert to float here */ 564 GLchan rgba[4]; 565 fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba); 566 texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); 567 texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); 568 texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); 569 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); 570} 571#endif /* FEATURE_EXT_texture_sRGB */ 572 573 574#endif /* FEATURE_texture_s3tc */ 575