texcompress_rgtc.c revision 6eff8479af1a137d81d7bffc0c55a39910c28ce9
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#define RGTC_DEBUG 0 48 49static void unsigned_encode_rgtc_chan(GLubyte *blkaddr, GLubyte srccolors[4][4], 50 GLint numxpixels, GLint numypixels); 51static void signed_encode_rgtc_chan(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 GLchan *srcaddr, 61 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 62{ 63 GLubyte i, j; 64 const GLchan *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 / (CHAN_MAX / 255); 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 GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */ 94 const GLchan *tempImage = NULL; 95 int i, j; 96 int numxpixels, numypixels; 97 const GLchan *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 ASSERT(dstXoffset % 4 == 0); 104 ASSERT(dstYoffset % 4 == 0); 105 ASSERT(dstZoffset % 4 == 0); 106 (void) dstZoffset; 107 (void) dstImageOffsets; 108 109 110 tempImage = _mesa_make_temp_chan_image(ctx, dims, 111 baseInternalFormat, 112 _mesa_get_format_base_format(dstFormat), 113 srcWidth, srcHeight, srcDepth, 114 srcFormat, srcType, srcAddr, 115 srcPacking); 116 if (!tempImage) 117 return GL_FALSE; /* out of memory */ 118 119 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 120 dstFormat, 121 texWidth, (GLubyte *) dstAddr); 122 123 blkaddr = dst; 124 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 125 for (j = 0; j < srcHeight; j+=4) { 126 if (srcHeight > j + 3) numypixels = 4; 127 else numypixels = srcHeight - j; 128 srcaddr = tempImage + j * srcWidth; 129 for (i = 0; i < srcWidth; i += 4) { 130 if (srcWidth > i + 3) numxpixels = 4; 131 else numxpixels = srcWidth - i; 132 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 133 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels); 134 srcaddr += numxpixels; 135 blkaddr += 8; 136 } 137 blkaddr += dstRowDiff; 138 } 139 if (tempImage) 140 free((void *) tempImage); 141 142 return GL_TRUE; 143} 144 145GLboolean 146_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS) 147{ 148 GLbyte *dst; 149 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */ 150 const GLfloat *tempImage = NULL; 151 int i, j; 152 int numxpixels, numypixels; 153 const GLfloat *srcaddr; 154 GLbyte srcpixels[4][4]; 155 GLbyte *blkaddr; 156 GLint dstRowDiff; 157 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 || 158 dstFormat == MESA_FORMAT_SIGNED_L_LATC1); 159 ASSERT(dstXoffset % 4 == 0); 160 ASSERT(dstYoffset % 4 == 0); 161 ASSERT(dstZoffset % 4 == 0); 162 (void) dstZoffset; 163 (void) dstImageOffsets; 164 165 tempImage = _mesa_make_temp_float_image(ctx, dims, 166 baseInternalFormat, 167 _mesa_get_format_base_format(dstFormat), 168 srcWidth, srcHeight, srcDepth, 169 srcFormat, srcType, srcAddr, 170 srcPacking, 0x0); 171 if (!tempImage) 172 return GL_FALSE; /* out of memory */ 173 174 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 175 dstFormat, 176 texWidth, (GLubyte *) dstAddr); 177 178 blkaddr = dst; 179 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 180 for (j = 0; j < srcHeight; j+=4) { 181 if (srcHeight > j + 3) numypixels = 4; 182 else numypixels = srcHeight - j; 183 srcaddr = tempImage + j * srcWidth; 184 for (i = 0; i < srcWidth; i += 4) { 185 if (srcWidth > i + 3) numxpixels = 4; 186 else numxpixels = srcWidth - i; 187 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 188 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels); 189 srcaddr += numxpixels; 190 blkaddr += 8; 191 } 192 blkaddr += dstRowDiff; 193 } 194 if (tempImage) 195 free((void *) tempImage); 196 197 return GL_TRUE; 198} 199 200GLboolean 201_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS) 202{ 203 GLubyte *dst; 204 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */ 205 const GLchan *tempImage = NULL; 206 int i, j; 207 int numxpixels, numypixels; 208 const GLchan *srcaddr; 209 GLubyte srcpixels[4][4]; 210 GLubyte *blkaddr; 211 GLint dstRowDiff; 212 213 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2 || 214 dstFormat == MESA_FORMAT_LA_LATC2); 215 ASSERT(dstXoffset % 4 == 0); 216 ASSERT(dstYoffset % 4 == 0); 217 ASSERT(dstZoffset % 4 == 0); 218 (void) dstZoffset; 219 (void) dstImageOffsets; 220 221 tempImage = _mesa_make_temp_chan_image(ctx, dims, 222 baseInternalFormat, 223 _mesa_get_format_base_format(dstFormat), 224 srcWidth, srcHeight, srcDepth, 225 srcFormat, srcType, srcAddr, 226 srcPacking); 227 if (!tempImage) 228 return GL_FALSE; /* out of memory */ 229 230 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 231 dstFormat, 232 texWidth, (GLubyte *) dstAddr); 233 234 blkaddr = dst; 235 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0; 236 for (j = 0; j < srcHeight; j+=4) { 237 if (srcHeight > j + 3) numypixels = 4; 238 else numypixels = srcHeight - j; 239 srcaddr = tempImage + j * srcWidth * 2; 240 for (i = 0; i < srcWidth; i += 4) { 241 if (srcWidth > i + 3) numxpixels = 4; 242 else numxpixels = srcWidth - i; 243 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2); 244 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels); 245 246 blkaddr += 8; 247 extractsrc_u(srcpixels, (GLchan *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2); 248 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels); 249 250 blkaddr += 8; 251 252 srcaddr += numxpixels * 2; 253 } 254 blkaddr += dstRowDiff; 255 } 256 if (tempImage) 257 free((void *) tempImage); 258 259 return GL_TRUE; 260} 261 262GLboolean 263_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS) 264{ 265 GLbyte *dst; 266 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */ 267 const GLfloat *tempImage = NULL; 268 int i, j; 269 int numxpixels, numypixels; 270 const GLfloat *srcaddr; 271 GLbyte srcpixels[4][4]; 272 GLbyte *blkaddr; 273 GLint dstRowDiff; 274 275 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 || 276 dstFormat == MESA_FORMAT_SIGNED_LA_LATC2); 277 ASSERT(dstXoffset % 4 == 0); 278 ASSERT(dstYoffset % 4 == 0); 279 ASSERT(dstZoffset % 4 == 0); 280 (void) dstZoffset; 281 (void) dstImageOffsets; 282 283 tempImage = _mesa_make_temp_float_image(ctx, dims, 284 baseInternalFormat, 285 _mesa_get_format_base_format(dstFormat), 286 srcWidth, srcHeight, srcDepth, 287 srcFormat, srcType, srcAddr, 288 srcPacking, 0x0); 289 if (!tempImage) 290 return GL_FALSE; /* out of memory */ 291 292 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0, 293 dstFormat, 294 texWidth, (GLubyte *) dstAddr); 295 296 blkaddr = dst; 297 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0; 298 for (j = 0; j < srcHeight; j += 4) { 299 if (srcHeight > j + 3) numypixels = 4; 300 else numypixels = srcHeight - j; 301 srcaddr = tempImage + j * srcWidth * 2; 302 for (i = 0; i < srcWidth; i += 4) { 303 if (srcWidth > i + 3) numxpixels = 4; 304 else numxpixels = srcWidth - i; 305 306 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2); 307 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels); 308 blkaddr += 8; 309 310 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2); 311 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels); 312 blkaddr += 8; 313 314 srcaddr += numxpixels * 2; 315 316 } 317 blkaddr += dstRowDiff; 318 } 319 if (tempImage) 320 free((void *) tempImage); 321 322 return GL_TRUE; 323} 324 325void 326_mesa_fetch_texel_2d_f_red_rgtc1(const struct gl_texture_image *texImage, 327 GLint i, GLint j, GLint k, GLfloat *texel) 328{ 329 GLubyte red; 330 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data), 331 i, j, &red, 1); 332 texel[RCOMP] = UBYTE_TO_FLOAT(red); 333 texel[GCOMP] = 0.0; 334 texel[BCOMP] = 0.0; 335 texel[ACOMP] = 1.0; 336} 337 338void 339_mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct gl_texture_image *texImage, 340 GLint i, GLint j, GLint k, GLfloat *texel) 341{ 342 GLbyte red; 343 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), 344 i, j, &red, 1); 345 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); 346 texel[GCOMP] = 0.0; 347 texel[BCOMP] = 0.0; 348 texel[ACOMP] = 1.0; 349} 350 351void 352_mesa_fetch_texel_2d_f_rg_rgtc2(const struct gl_texture_image *texImage, 353 GLint i, GLint j, GLint k, GLfloat *texel) 354{ 355 GLubyte red, green; 356 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data), 357 i, j, &red, 2); 358 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8, 359 i, j, &green, 2); 360 texel[RCOMP] = UBYTE_TO_FLOAT(red); 361 texel[GCOMP] = UBYTE_TO_FLOAT(green); 362 texel[BCOMP] = 0.0; 363 texel[ACOMP] = 1.0; 364} 365 366void 367_mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage, 368 GLint i, GLint j, GLint k, GLfloat *texel) 369{ 370 GLbyte red, green; 371 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), 372 i, j, &red, 2); 373 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8, 374 i, j, &green, 2); 375 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red); 376 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green); 377 texel[BCOMP] = 0.0; 378 texel[ACOMP] = 1.0; 379} 380 381void 382_mesa_fetch_texel_2d_f_l_latc1(const struct gl_texture_image *texImage, 383 GLint i, GLint j, GLint k, GLfloat *texel) 384{ 385 GLubyte red; 386 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data), 387 i, j, &red, 1); 388 texel[RCOMP] = 389 texel[GCOMP] = 390 texel[BCOMP] = UBYTE_TO_FLOAT(red); 391 texel[ACOMP] = 1.0; 392} 393 394void 395_mesa_fetch_texel_2d_f_signed_l_latc1(const struct gl_texture_image *texImage, 396 GLint i, GLint j, GLint k, GLfloat *texel) 397{ 398 GLbyte red; 399 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), 400 i, j, &red, 1); 401 texel[RCOMP] = 402 texel[GCOMP] = 403 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red); 404 texel[ACOMP] = 1.0; 405} 406 407void 408_mesa_fetch_texel_2d_f_la_latc2(const struct gl_texture_image *texImage, 409 GLint i, GLint j, GLint k, GLfloat *texel) 410{ 411 GLubyte red, green; 412 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data), 413 i, j, &red, 2); 414 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8, 415 i, j, &green, 2); 416 texel[RCOMP] = 417 texel[GCOMP] = 418 texel[BCOMP] = UBYTE_TO_FLOAT(red); 419 texel[ACOMP] = UBYTE_TO_FLOAT(green); 420} 421 422void 423_mesa_fetch_texel_2d_f_signed_la_latc2(const struct gl_texture_image *texImage, 424 GLint i, GLint j, GLint k, GLfloat *texel) 425{ 426 GLbyte red, green; 427 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data), 428 i, j, &red, 2); 429 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8, 430 i, j, &green, 2); 431 texel[RCOMP] = 432 texel[GCOMP] = 433 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red); 434 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green); 435} 436 437#define TAG(x) unsigned_##x 438 439#define TYPE GLubyte 440#define T_MIN 0 441#define T_MAX 0xff 442 443#include "texcompress_rgtc_tmp.h" 444 445#undef TAG 446#undef TYPE 447#undef T_MIN 448#undef T_MAX 449 450#define TAG(x) signed_##x 451#define TYPE GLbyte 452#define T_MIN (GLbyte)-128 453#define T_MAX (GLbyte)127 454 455#include "texcompress_rgtc_tmp.h" 456 457#undef TAG 458#undef TYPE 459#undef T_MIN 460#undef T_MAX 461