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 51static void unsigned_encode_rgtc_ubyte(GLubyte *blkaddr, GLubyte srccolors[4][4], 52 GLint numxpixels, GLint numypixels); 53static void signed_encode_rgtc_ubyte(GLbyte *blkaddr, GLbyte srccolors[4][4], 54 GLint numxpixels, GLint numypixels); 55 56static void unsigned_fetch_texel_rgtc(unsigned srcRowStride, const GLubyte *pixdata, 57 unsigned i, unsigned j, GLubyte *value, unsigned comps); 58 59static void signed_fetch_texel_rgtc(unsigned srcRowStride, const GLbyte *pixdata, 60 unsigned i, unsigned j, GLbyte *value, unsigned comps); 61 62static 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 76static 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 91GLboolean 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 138GLboolean 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 185GLboolean 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 239GLboolean 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 294void 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 309void 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 324void 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 342void 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 360void 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 375void 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 390void 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 408void 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