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