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