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