texcompress_rgtc.c revision af69d88d
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 "mipmap.h" 42#include "texcompress.h" 43#include "texcompress_rgtc.h" 44#include "texstore.h" 45 46 47#define RGTC_DEBUG 0 48 49static void unsigned_encode_rgtc_ubyte(GLubyte *blkaddr, GLubyte srccolors[4][4], 50 GLint numxpixels, GLint numypixels); 51static void signed_encode_rgtc_ubyte(GLbyte *blkaddr, GLbyte srccolors[4][4], 52 GLint numxpixels, GLint numypixels); 53 54static void unsigned_fetch_texel_rgtc(unsigned srcRowStride, const GLubyte *pixdata, 55 unsigned i, unsigned j, GLubyte *value, unsigned comps); 56 57static void signed_fetch_texel_rgtc(unsigned srcRowStride, const GLbyte *pixdata, 58 unsigned i, unsigned j, GLbyte *value, unsigned comps); 59 60static void extractsrc_u( GLubyte srcpixels[4][4], const GLubyte *srcaddr, 61 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 62{ 63 GLubyte i, j; 64 const GLubyte *curaddr; 65 for (j = 0; j < numypixels; j++) { 66 curaddr = srcaddr + j * srcRowStride * comps; 67 for (i = 0; i < numxpixels; i++) { 68 srcpixels[j][i] = *curaddr; 69 curaddr += comps; 70 } 71 } 72} 73 74static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr, 75 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 76{ 77 GLubyte i, j; 78 const GLfloat *curaddr; 79 for (j = 0; j < numypixels; j++) { 80 curaddr = srcaddr + j * srcRowStride * comps; 81 for (i = 0; i < numxpixels; i++) { 82 srcpixels[j][i] = FLOAT_TO_BYTE_TEX(*curaddr); 83 curaddr += comps; 84 } 85 } 86} 87 88 89GLboolean 90_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS) 91{ 92 GLubyte *dst; 93 const GLubyte *tempImage = NULL; 94 int i, j; 95 int numxpixels, numypixels; 96 const GLubyte *srcaddr; 97 GLubyte srcpixels[4][4]; 98 GLubyte *blkaddr; 99 GLint dstRowDiff; 100 ASSERT(dstFormat == MESA_FORMAT_R_RGTC1_UNORM || 101 dstFormat == MESA_FORMAT_L_LATC1_UNORM); 102 103 tempImage = _mesa_make_temp_ubyte_image(ctx, dims, 104 baseInternalFormat, 105 _mesa_get_format_base_format(dstFormat), 106 srcWidth, srcHeight, srcDepth, 107 srcFormat, srcType, srcAddr, 108 srcPacking); 109 if (!tempImage) 110 return GL_FALSE; /* out of memory */ 111 112 dst = dstSlices[0]; 113 114 blkaddr = dst; 115 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 116 for (j = 0; j < srcHeight; j+=4) { 117 if (srcHeight > j + 3) numypixels = 4; 118 else numypixels = srcHeight - j; 119 srcaddr = tempImage + j * srcWidth; 120 for (i = 0; i < srcWidth; i += 4) { 121 if (srcWidth > i + 3) numxpixels = 4; 122 else numxpixels = srcWidth - i; 123 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 124 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 125 srcaddr += numxpixels; 126 blkaddr += 8; 127 } 128 blkaddr += dstRowDiff; 129 } 130 131 free((void *) tempImage); 132 133 return GL_TRUE; 134} 135 136GLboolean 137_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS) 138{ 139 GLbyte *dst; 140 const GLfloat *tempImage = NULL; 141 int i, j; 142 int numxpixels, numypixels; 143 const GLfloat *srcaddr; 144 GLbyte srcpixels[4][4]; 145 GLbyte *blkaddr; 146 GLint dstRowDiff; 147 ASSERT(dstFormat == MESA_FORMAT_R_RGTC1_SNORM || 148 dstFormat == MESA_FORMAT_L_LATC1_SNORM); 149 150 tempImage = _mesa_make_temp_float_image(ctx, dims, 151 baseInternalFormat, 152 _mesa_get_format_base_format(dstFormat), 153 srcWidth, srcHeight, srcDepth, 154 srcFormat, srcType, srcAddr, 155 srcPacking, 0x0); 156 if (!tempImage) 157 return GL_FALSE; /* out of memory */ 158 159 dst = (GLbyte *) dstSlices[0]; 160 161 blkaddr = dst; 162 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 163 for (j = 0; j < srcHeight; j+=4) { 164 if (srcHeight > j + 3) numypixels = 4; 165 else numypixels = srcHeight - j; 166 srcaddr = tempImage + j * srcWidth; 167 for (i = 0; i < srcWidth; i += 4) { 168 if (srcWidth > i + 3) numxpixels = 4; 169 else numxpixels = srcWidth - i; 170 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 171 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 172 srcaddr += numxpixels; 173 blkaddr += 8; 174 } 175 blkaddr += dstRowDiff; 176 } 177 178 free((void *) tempImage); 179 180 return GL_TRUE; 181} 182 183GLboolean 184_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS) 185{ 186 GLubyte *dst; 187 const GLubyte *tempImage = NULL; 188 int i, j; 189 int numxpixels, numypixels; 190 const GLubyte *srcaddr; 191 GLubyte srcpixels[4][4]; 192 GLubyte *blkaddr; 193 GLint dstRowDiff; 194 195 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM || 196 dstFormat == MESA_FORMAT_LA_LATC2_UNORM); 197 198 tempImage = _mesa_make_temp_ubyte_image(ctx, dims, 199 baseInternalFormat, 200 _mesa_get_format_base_format(dstFormat), 201 srcWidth, srcHeight, srcDepth, 202 srcFormat, srcType, srcAddr, 203 srcPacking); 204 if (!tempImage) 205 return GL_FALSE; /* out of memory */ 206 207 dst = dstSlices[0]; 208 209 blkaddr = dst; 210 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0; 211 for (j = 0; j < srcHeight; j+=4) { 212 if (srcHeight > j + 3) numypixels = 4; 213 else numypixels = srcHeight - j; 214 srcaddr = tempImage + j * srcWidth * 2; 215 for (i = 0; i < srcWidth; i += 4) { 216 if (srcWidth > i + 3) numxpixels = 4; 217 else numxpixels = srcWidth - i; 218 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2); 219 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 220 221 blkaddr += 8; 222 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2); 223 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 224 225 blkaddr += 8; 226 227 srcaddr += numxpixels * 2; 228 } 229 blkaddr += dstRowDiff; 230 } 231 232 free((void *) tempImage); 233 234 return GL_TRUE; 235} 236 237GLboolean 238_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS) 239{ 240 GLbyte *dst; 241 const GLfloat *tempImage = NULL; 242 int i, j; 243 int numxpixels, numypixels; 244 const GLfloat *srcaddr; 245 GLbyte srcpixels[4][4]; 246 GLbyte *blkaddr; 247 GLint dstRowDiff; 248 249 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2_SNORM || 250 dstFormat == MESA_FORMAT_LA_LATC2_SNORM); 251 252 tempImage = _mesa_make_temp_float_image(ctx, dims, 253 baseInternalFormat, 254 _mesa_get_format_base_format(dstFormat), 255 srcWidth, srcHeight, srcDepth, 256 srcFormat, srcType, srcAddr, 257 srcPacking, 0x0); 258 if (!tempImage) 259 return GL_FALSE; /* out of memory */ 260 261 dst = (GLbyte *) dstSlices[0]; 262 263 blkaddr = dst; 264 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0; 265 for (j = 0; j < srcHeight; j += 4) { 266 if (srcHeight > j + 3) numypixels = 4; 267 else numypixels = srcHeight - j; 268 srcaddr = tempImage + j * srcWidth * 2; 269 for (i = 0; i < srcWidth; i += 4) { 270 if (srcWidth > i + 3) numxpixels = 4; 271 else numxpixels = srcWidth - i; 272 273 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2); 274 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 275 blkaddr += 8; 276 277 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2); 278 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 279 blkaddr += 8; 280 281 srcaddr += numxpixels * 2; 282 283 } 284 blkaddr += dstRowDiff; 285 } 286 287 free((void *) tempImage); 288 289 return GL_TRUE; 290} 291 292 293#define TAG(x) unsigned_##x 294 295#define TYPE GLubyte 296#define T_MIN 0 297#define T_MAX 0xff 298 299#include "texcompress_rgtc_tmp.h" 300 301#undef TAG 302#undef TYPE 303#undef T_MIN 304#undef T_MAX 305 306#define TAG(x) signed_##x 307#define TYPE GLbyte 308#define T_MIN (GLbyte)-128 309#define T_MAX (GLbyte)127 310 311#include "texcompress_rgtc_tmp.h" 312 313#undef TAG 314#undef TYPE 315#undef T_MIN 316#undef T_MAX 317 318 319 320static void 321fetch_red_rgtc1(const GLubyte *map, 322 GLint rowStride, GLint i, GLint j, GLfloat *texel) 323{ 324 GLubyte red; 325 unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1); 326 texel[RCOMP] = UBYTE_TO_FLOAT(red); 327 texel[GCOMP] = 0.0; 328 texel[BCOMP] = 0.0; 329 texel[ACOMP] = 1.0; 330} 331 332static void 333fetch_l_latc1(const GLubyte *map, 334 GLint rowStride, GLint i, GLint j, GLfloat *texel) 335{ 336 GLubyte red; 337 unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1); 338 texel[RCOMP] = 339 texel[GCOMP] = 340 texel[BCOMP] = UBYTE_TO_FLOAT(red); 341 texel[ACOMP] = 1.0; 342} 343 344static void 345fetch_signed_red_rgtc1(const GLubyte *map, 346 GLint rowStride, GLint i, GLint j, GLfloat *texel) 347{ 348 GLbyte red; 349 signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map, 350 i, j, &red, 1); 351 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); 352 texel[GCOMP] = 0.0; 353 texel[BCOMP] = 0.0; 354 texel[ACOMP] = 1.0; 355} 356 357static void 358fetch_signed_l_latc1(const GLubyte *map, 359 GLint rowStride, GLint i, GLint j, GLfloat *texel) 360{ 361 GLbyte red; 362 signed_fetch_texel_rgtc(rowStride, (GLbyte *) map, 363 i, j, &red, 1); 364 texel[RCOMP] = 365 texel[GCOMP] = 366 texel[BCOMP] = BYTE_TO_FLOAT(red); 367 texel[ACOMP] = 1.0; 368} 369 370static void 371fetch_rg_rgtc2(const GLubyte *map, 372 GLint rowStride, GLint i, GLint j, GLfloat *texel) 373{ 374 GLubyte red, green; 375 unsigned_fetch_texel_rgtc(rowStride, 376 map, 377 i, j, &red, 2); 378 unsigned_fetch_texel_rgtc(rowStride, 379 map + 8, 380 i, j, &green, 2); 381 texel[RCOMP] = UBYTE_TO_FLOAT(red); 382 texel[GCOMP] = UBYTE_TO_FLOAT(green); 383 texel[BCOMP] = 0.0; 384 texel[ACOMP] = 1.0; 385} 386 387static void 388fetch_la_latc2(const GLubyte *map, 389 GLint rowStride, GLint i, GLint j, GLfloat *texel) 390{ 391 GLubyte red, green; 392 unsigned_fetch_texel_rgtc(rowStride, 393 map, 394 i, j, &red, 2); 395 unsigned_fetch_texel_rgtc(rowStride, 396 map + 8, 397 i, j, &green, 2); 398 texel[RCOMP] = 399 texel[GCOMP] = 400 texel[BCOMP] = UBYTE_TO_FLOAT(red); 401 texel[ACOMP] = UBYTE_TO_FLOAT(green); 402} 403 404 405static void 406fetch_signed_rg_rgtc2(const GLubyte *map, 407 GLint rowStride, GLint i, GLint j, GLfloat *texel) 408{ 409 GLbyte red, green; 410 signed_fetch_texel_rgtc(rowStride, 411 (GLbyte *) map, 412 i, j, &red, 2); 413 signed_fetch_texel_rgtc(rowStride, 414 (GLbyte *) map + 8, 415 i, j, &green, 2); 416 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); 417 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green); 418 texel[BCOMP] = 0.0; 419 texel[ACOMP] = 1.0; 420} 421 422 423static void 424fetch_signed_la_latc2(const GLubyte *map, 425 GLint rowStride, GLint i, GLint j, GLfloat *texel) 426{ 427 GLbyte red, green; 428 signed_fetch_texel_rgtc(rowStride, 429 (GLbyte *) map, 430 i, j, &red, 2); 431 signed_fetch_texel_rgtc(rowStride, 432 (GLbyte *) map + 8, 433 i, j, &green, 2); 434 texel[RCOMP] = 435 texel[GCOMP] = 436 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red); 437 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green); 438} 439 440 441compressed_fetch_func 442_mesa_get_compressed_rgtc_func(mesa_format format) 443{ 444 switch (format) { 445 case MESA_FORMAT_R_RGTC1_UNORM: 446 return fetch_red_rgtc1; 447 case MESA_FORMAT_L_LATC1_UNORM: 448 return fetch_l_latc1; 449 case MESA_FORMAT_R_RGTC1_SNORM: 450 return fetch_signed_red_rgtc1; 451 case MESA_FORMAT_L_LATC1_SNORM: 452 return fetch_signed_l_latc1; 453 case MESA_FORMAT_RG_RGTC2_UNORM: 454 return fetch_rg_rgtc2; 455 case MESA_FORMAT_LA_LATC2_UNORM: 456 return fetch_la_latc2; 457 case MESA_FORMAT_RG_RGTC2_SNORM: 458 return fetch_signed_rg_rgtc2; 459 case MESA_FORMAT_LA_LATC2_SNORM: 460 return fetch_signed_la_latc2; 461 default: 462 return NULL; 463 } 464} 465