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