texcompress_rgtc.c revision b29f2d5ff54c5031e5b0f0ae9f89acb4eb38b219
1/* 2 * Copyright (C) 2011 Red Hat Inc. 3 * 4 * block compression parts are: 5 * Copyright (C) 2004 Roland Scheidegger 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 (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 * DEALINGS IN THE SOFTWARE. 25 * 26 * Author: 27 * Dave Airlie 28 */ 29 30/** 31 * \file texcompress_rgtc.c 32 * GL_EXT_texture_compression_rgtc support. 33 */ 34 35 36#include "glheader.h" 37#include "imports.h" 38#include "colormac.h" 39#include "image.h" 40#include "macros.h" 41#include "mfeatures.h" 42#include "mipmap.h" 43#include "texcompress.h" 44#include "texcompress_rgtc.h" 45#include "texstore.h" 46 47 48#define RGTC_DEBUG 0 49 50static void unsigned_encode_rgtc_ubyte(GLubyte *blkaddr, GLubyte srccolors[4][4], 51 GLint numxpixels, GLint numypixels); 52static void signed_encode_rgtc_ubyte(GLbyte *blkaddr, GLbyte srccolors[4][4], 53 GLint numxpixels, GLint numypixels); 54 55static void unsigned_fetch_texel_rgtc(unsigned srcRowStride, const GLubyte *pixdata, 56 unsigned i, unsigned j, GLubyte *value, unsigned comps); 57 58static void signed_fetch_texel_rgtc(unsigned srcRowStride, const GLbyte *pixdata, 59 unsigned i, unsigned j, GLbyte *value, unsigned comps); 60 61static void extractsrc_u( GLubyte srcpixels[4][4], const GLubyte *srcaddr, 62 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 63{ 64 GLubyte i, j; 65 const GLubyte *curaddr; 66 for (j = 0; j < numypixels; j++) { 67 curaddr = srcaddr + j * srcRowStride * comps; 68 for (i = 0; i < numxpixels; i++) { 69 srcpixels[j][i] = *curaddr; 70 curaddr += comps; 71 } 72 } 73} 74 75static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr, 76 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 77{ 78 GLubyte i, j; 79 const GLfloat *curaddr; 80 for (j = 0; j < numypixels; j++) { 81 curaddr = srcaddr + j * srcRowStride * comps; 82 for (i = 0; i < numxpixels; i++) { 83 srcpixels[j][i] = FLOAT_TO_BYTE_TEX(*curaddr); 84 curaddr += comps; 85 } 86 } 87} 88 89 90GLboolean 91_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS) 92{ 93 GLubyte *dst; 94 const GLubyte *tempImage = NULL; 95 int i, j; 96 int numxpixels, numypixels; 97 const GLubyte *srcaddr; 98 GLubyte srcpixels[4][4]; 99 GLubyte *blkaddr; 100 GLint dstRowDiff; 101 ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1 || 102 dstFormat == MESA_FORMAT_L_LATC1); 103 104 tempImage = _mesa_make_temp_ubyte_image(ctx, dims, 105 baseInternalFormat, 106 _mesa_get_format_base_format(dstFormat), 107 srcWidth, srcHeight, srcDepth, 108 srcFormat, srcType, srcAddr, 109 srcPacking); 110 if (!tempImage) 111 return GL_FALSE; /* out of memory */ 112 113 dst = dstSlices[0]; 114 115 blkaddr = dst; 116 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 117 for (j = 0; j < srcHeight; j+=4) { 118 if (srcHeight > j + 3) numypixels = 4; 119 else numypixels = srcHeight - j; 120 srcaddr = tempImage + j * srcWidth; 121 for (i = 0; i < srcWidth; i += 4) { 122 if (srcWidth > i + 3) numxpixels = 4; 123 else numxpixels = srcWidth - i; 124 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 125 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 126 srcaddr += numxpixels; 127 blkaddr += 8; 128 } 129 blkaddr += dstRowDiff; 130 } 131 132 free((void *) tempImage); 133 134 return GL_TRUE; 135} 136 137GLboolean 138_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS) 139{ 140 GLbyte *dst; 141 const GLfloat *tempImage = NULL; 142 int i, j; 143 int numxpixels, numypixels; 144 const GLfloat *srcaddr; 145 GLbyte srcpixels[4][4]; 146 GLbyte *blkaddr; 147 GLint dstRowDiff; 148 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 || 149 dstFormat == MESA_FORMAT_SIGNED_L_LATC1); 150 151 tempImage = _mesa_make_temp_float_image(ctx, dims, 152 baseInternalFormat, 153 _mesa_get_format_base_format(dstFormat), 154 srcWidth, srcHeight, srcDepth, 155 srcFormat, srcType, srcAddr, 156 srcPacking, 0x0); 157 if (!tempImage) 158 return GL_FALSE; /* out of memory */ 159 160 dst = (GLbyte *) dstSlices[0]; 161 162 blkaddr = dst; 163 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 164 for (j = 0; j < srcHeight; j+=4) { 165 if (srcHeight > j + 3) numypixels = 4; 166 else numypixels = srcHeight - j; 167 srcaddr = tempImage + j * srcWidth; 168 for (i = 0; i < srcWidth; i += 4) { 169 if (srcWidth > i + 3) numxpixels = 4; 170 else numxpixels = srcWidth - i; 171 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 172 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 173 srcaddr += numxpixels; 174 blkaddr += 8; 175 } 176 blkaddr += dstRowDiff; 177 } 178 179 free((void *) tempImage); 180 181 return GL_TRUE; 182} 183 184GLboolean 185_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS) 186{ 187 GLubyte *dst; 188 const GLubyte *tempImage = NULL; 189 int i, j; 190 int numxpixels, numypixels; 191 const GLubyte *srcaddr; 192 GLubyte srcpixels[4][4]; 193 GLubyte *blkaddr; 194 GLint dstRowDiff; 195 196 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2 || 197 dstFormat == MESA_FORMAT_LA_LATC2); 198 199 tempImage = _mesa_make_temp_ubyte_image(ctx, dims, 200 baseInternalFormat, 201 _mesa_get_format_base_format(dstFormat), 202 srcWidth, srcHeight, srcDepth, 203 srcFormat, srcType, srcAddr, 204 srcPacking); 205 if (!tempImage) 206 return GL_FALSE; /* out of memory */ 207 208 dst = dstSlices[0]; 209 210 blkaddr = dst; 211 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0; 212 for (j = 0; j < srcHeight; j+=4) { 213 if (srcHeight > j + 3) numypixels = 4; 214 else numypixels = srcHeight - j; 215 srcaddr = tempImage + j * srcWidth * 2; 216 for (i = 0; i < srcWidth; i += 4) { 217 if (srcWidth > i + 3) numxpixels = 4; 218 else numxpixels = srcWidth - i; 219 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2); 220 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 221 222 blkaddr += 8; 223 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2); 224 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 225 226 blkaddr += 8; 227 228 srcaddr += numxpixels * 2; 229 } 230 blkaddr += dstRowDiff; 231 } 232 233 free((void *) tempImage); 234 235 return GL_TRUE; 236} 237 238GLboolean 239_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS) 240{ 241 GLbyte *dst; 242 const GLfloat *tempImage = NULL; 243 int i, j; 244 int numxpixels, numypixels; 245 const GLfloat *srcaddr; 246 GLbyte srcpixels[4][4]; 247 GLbyte *blkaddr; 248 GLint dstRowDiff; 249 250 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 || 251 dstFormat == MESA_FORMAT_SIGNED_LA_LATC2); 252 253 tempImage = _mesa_make_temp_float_image(ctx, dims, 254 baseInternalFormat, 255 _mesa_get_format_base_format(dstFormat), 256 srcWidth, srcHeight, srcDepth, 257 srcFormat, srcType, srcAddr, 258 srcPacking, 0x0); 259 if (!tempImage) 260 return GL_FALSE; /* out of memory */ 261 262 dst = (GLbyte *) dstSlices[0]; 263 264 blkaddr = dst; 265 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0; 266 for (j = 0; j < srcHeight; j += 4) { 267 if (srcHeight > j + 3) numypixels = 4; 268 else numypixels = srcHeight - j; 269 srcaddr = tempImage + j * srcWidth * 2; 270 for (i = 0; i < srcWidth; i += 4) { 271 if (srcWidth > i + 3) numxpixels = 4; 272 else numxpixels = srcWidth - i; 273 274 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2); 275 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 276 blkaddr += 8; 277 278 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2); 279 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 280 blkaddr += 8; 281 282 srcaddr += numxpixels * 2; 283 284 } 285 blkaddr += dstRowDiff; 286 } 287 288 free((void *) tempImage); 289 290 return GL_TRUE; 291} 292 293 294#define TAG(x) unsigned_##x 295 296#define TYPE GLubyte 297#define T_MIN 0 298#define T_MAX 0xff 299 300#include "texcompress_rgtc_tmp.h" 301 302#undef TAG 303#undef TYPE 304#undef T_MIN 305#undef T_MAX 306 307#define TAG(x) signed_##x 308#define TYPE GLbyte 309#define T_MIN (GLbyte)-128 310#define T_MAX (GLbyte)127 311 312#include "texcompress_rgtc_tmp.h" 313 314#undef TAG 315#undef TYPE 316#undef T_MIN 317#undef T_MAX 318 319 320 321static void 322fetch_red_rgtc1(const GLubyte *map, const GLuint imageOffsets[], 323 GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) 324{ 325 GLubyte red; 326 GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; 327 unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); 328 texel[RCOMP] = UBYTE_TO_FLOAT(red); 329 texel[GCOMP] = 0.0; 330 texel[BCOMP] = 0.0; 331 texel[ACOMP] = 1.0; 332} 333 334static void 335fetch_l_latc1(const GLubyte *map, const GLuint imageOffsets[], 336 GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) 337{ 338 GLubyte red; 339 GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; 340 unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); 341 texel[RCOMP] = 342 texel[GCOMP] = 343 texel[BCOMP] = UBYTE_TO_FLOAT(red); 344 texel[ACOMP] = 1.0; 345} 346 347static void 348fetch_signed_red_rgtc1(const GLubyte *map, const GLuint imageOffsets[], 349 GLint rowStride, GLint i, GLint j, GLint k, 350 GLfloat *texel) 351{ 352 GLbyte red; 353 GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; 354 signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map + sliceOffset, 355 i, j, &red, 1); 356 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); 357 texel[GCOMP] = 0.0; 358 texel[BCOMP] = 0.0; 359 texel[ACOMP] = 1.0; 360} 361 362static void 363fetch_signed_l_latc1(const GLubyte *map, const GLuint imageOffsets[], 364 GLint rowStride, GLint i, GLint j, GLint k, 365 GLfloat *texel) 366{ 367 GLubyte red; 368 GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; 369 unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); 370 texel[RCOMP] = 371 texel[GCOMP] = 372 texel[BCOMP] = BYTE_TO_FLOAT(red); 373 texel[ACOMP] = 1.0; 374} 375 376static void 377fetch_rg_rgtc2(const GLubyte *map, const GLuint imageOffsets[], 378 GLint rowStride, GLint i, GLint j, GLint k, 379 GLfloat *texel) 380{ 381 GLubyte red, green; 382 GLuint sliceOffset = k ? imageOffsets[k] : 0; 383 unsigned_fetch_texel_rgtc(rowStride, 384 map + sliceOffset, 385 i, j, &red, 2); 386 unsigned_fetch_texel_rgtc(rowStride, 387 map + sliceOffset + 8, 388 i, j, &green, 2); 389 texel[RCOMP] = UBYTE_TO_FLOAT(red); 390 texel[GCOMP] = UBYTE_TO_FLOAT(green); 391 texel[BCOMP] = 0.0; 392 texel[ACOMP] = 1.0; 393} 394 395static void 396fetch_la_latc2(const GLubyte *map, const GLuint imageOffsets[], 397 GLint rowStride, GLint i, GLint j, GLint k, 398 GLfloat *texel) 399{ 400 GLubyte red, green; 401 GLuint sliceOffset = k ? imageOffsets[k] : 0; 402 unsigned_fetch_texel_rgtc(rowStride, 403 map + sliceOffset, 404 i, j, &red, 2); 405 unsigned_fetch_texel_rgtc(rowStride, 406 map + sliceOffset + 8, 407 i, j, &green, 2); 408 texel[RCOMP] = 409 texel[GCOMP] = 410 texel[BCOMP] = UBYTE_TO_FLOAT(red); 411 texel[ACOMP] = UBYTE_TO_FLOAT(green); 412} 413 414 415static void 416fetch_signed_rg_rgtc2(const GLubyte *map, const GLuint imageOffsets[], 417 GLint rowStride, GLint i, GLint j, GLint k, 418 GLfloat *texel) 419{ 420 GLbyte red, green; 421 GLuint sliceOffset = k ? imageOffsets[k] : 0; 422 signed_fetch_texel_rgtc(rowStride, 423 (GLbyte *) map + sliceOffset, 424 i, j, &red, 2); 425 signed_fetch_texel_rgtc(rowStride, 426 (GLbyte *) map + sliceOffset + 8, 427 i, j, &green, 2); 428 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); 429 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green); 430 texel[BCOMP] = 0.0; 431 texel[ACOMP] = 1.0; 432} 433 434 435static void 436fetch_signed_la_latc2(const GLubyte *map, const GLuint imageOffsets[], 437 GLint rowStride, GLint i, GLint j, GLint k, 438 GLfloat *texel) 439{ 440 GLbyte red, green; 441 GLuint sliceOffset = k ? imageOffsets[k] : 0; 442 signed_fetch_texel_rgtc(rowStride, 443 (GLbyte *) map + sliceOffset, 444 i, j, &red, 2); 445 signed_fetch_texel_rgtc(rowStride, 446 (GLbyte *) map + sliceOffset + 8, 447 i, j, &green, 2); 448 texel[RCOMP] = 449 texel[GCOMP] = 450 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red); 451 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green); 452} 453 454 455compressed_fetch_func 456_mesa_get_compressed_rgtc_func(gl_format format) 457{ 458 switch (format) { 459 case MESA_FORMAT_RED_RGTC1: 460 return fetch_red_rgtc1; 461 case MESA_FORMAT_L_LATC1: 462 return fetch_l_latc1; 463 case MESA_FORMAT_SIGNED_RED_RGTC1: 464 return fetch_signed_red_rgtc1; 465 case MESA_FORMAT_SIGNED_L_LATC1: 466 return fetch_signed_l_latc1; 467 case MESA_FORMAT_RG_RGTC2: 468 return fetch_rg_rgtc2; 469 case MESA_FORMAT_LA_LATC2: 470 return fetch_la_latc2; 471 case MESA_FORMAT_SIGNED_RG_RGTC2: 472 return fetch_signed_rg_rgtc2; 473 case MESA_FORMAT_SIGNED_LA_LATC2: 474 return fetch_signed_la_latc2; 475 default: 476 return NULL; 477 } 478} 479