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#include <stdlib.h> 36 37#include "config.h" 38#include "glheader.h" 39 40#include "image.h" 41#include "macros.h" 42#include "mipmap.h" 43#include "texcompress.h" 44#include "util/rgtc.h" 45#include "texcompress_rgtc.h" 46#include "texstore.h" 47 48static void extractsrc_u( GLubyte srcpixels[4][4], const GLubyte *srcaddr, 49 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 50{ 51 GLubyte i, j; 52 const GLubyte *curaddr; 53 for (j = 0; j < numypixels; j++) { 54 curaddr = srcaddr + j * srcRowStride * comps; 55 for (i = 0; i < numxpixels; i++) { 56 srcpixels[j][i] = *curaddr; 57 curaddr += comps; 58 } 59 } 60} 61 62static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr, 63 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 64{ 65 GLubyte i, j; 66 const GLfloat *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] = FLOAT_TO_BYTE_TEX(*curaddr); 71 curaddr += comps; 72 } 73 } 74} 75 76 77GLboolean 78_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS) 79{ 80 GLubyte *dst; 81 const GLubyte *tempImage = NULL; 82 int i, j; 83 int numxpixels, numypixels; 84 const GLubyte *srcaddr; 85 GLubyte srcpixels[4][4]; 86 GLubyte *blkaddr; 87 GLint dstRowDiff, redRowStride; 88 GLubyte *tempImageSlices[1]; 89 90 assert(dstFormat == MESA_FORMAT_R_RGTC1_UNORM || 91 dstFormat == MESA_FORMAT_L_LATC1_UNORM); 92 93 tempImage = malloc(srcWidth * srcHeight * 1 * sizeof(GLubyte)); 94 if (!tempImage) 95 return GL_FALSE; /* out of memory */ 96 redRowStride = 1 * srcWidth * sizeof(GLubyte); 97 tempImageSlices[0] = (GLubyte *) tempImage; 98 _mesa_texstore(ctx, dims, 99 baseInternalFormat, 100 MESA_FORMAT_R_UNORM8, 101 redRowStride, tempImageSlices, 102 srcWidth, srcHeight, srcDepth, 103 srcFormat, srcType, srcAddr, 104 srcPacking); 105 106 dst = dstSlices[0]; 107 108 blkaddr = dst; 109 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 110 for (j = 0; j < srcHeight; j+=4) { 111 if (srcHeight > j + 3) numypixels = 4; 112 else numypixels = srcHeight - j; 113 srcaddr = tempImage + j * srcWidth; 114 for (i = 0; i < srcWidth; i += 4) { 115 if (srcWidth > i + 3) numxpixels = 4; 116 else numxpixels = srcWidth - i; 117 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 118 util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 119 srcaddr += numxpixels; 120 blkaddr += 8; 121 } 122 blkaddr += dstRowDiff; 123 } 124 125 free((void *) tempImage); 126 127 return GL_TRUE; 128} 129 130GLboolean 131_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS) 132{ 133 GLbyte *dst; 134 const GLfloat *tempImage = NULL; 135 int i, j; 136 int numxpixels, numypixels; 137 const GLfloat *srcaddr; 138 GLbyte srcpixels[4][4]; 139 GLbyte *blkaddr; 140 GLint dstRowDiff, redRowStride; 141 GLfloat *tempImageSlices[1]; 142 143 assert(dstFormat == MESA_FORMAT_R_RGTC1_SNORM || 144 dstFormat == MESA_FORMAT_L_LATC1_SNORM); 145 146 redRowStride = 1 * srcWidth * sizeof(GLfloat); 147 tempImage = malloc(srcWidth * srcHeight * 1 * sizeof(GLfloat)); 148 if (!tempImage) 149 return GL_FALSE; /* out of memory */ 150 tempImageSlices[0] = (GLfloat *) tempImage; 151 _mesa_texstore(ctx, dims, 152 baseInternalFormat, 153 MESA_FORMAT_R_FLOAT32, 154 redRowStride, (GLubyte **)tempImageSlices, 155 srcWidth, srcHeight, srcDepth, 156 srcFormat, srcType, srcAddr, 157 srcPacking); 158 159 dst = (GLbyte *) dstSlices[0]; 160 161 blkaddr = dst; 162 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0; 163 for (j = 0; j < srcHeight; j+=4) { 164 if (srcHeight > j + 3) numypixels = 4; 165 else numypixels = srcHeight - j; 166 srcaddr = tempImage + j * srcWidth; 167 for (i = 0; i < srcWidth; i += 4) { 168 if (srcWidth > i + 3) numxpixels = 4; 169 else numxpixels = srcWidth - i; 170 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1); 171 util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels); 172 srcaddr += numxpixels; 173 blkaddr += 8; 174 } 175 blkaddr += dstRowDiff; 176 } 177 178 free((void *) tempImage); 179 180 return GL_TRUE; 181} 182 183GLboolean 184_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS) 185{ 186 GLubyte *dst; 187 const GLubyte *tempImage = NULL; 188 int i, j; 189 int numxpixels, numypixels; 190 const GLubyte *srcaddr; 191 GLubyte srcpixels[4][4]; 192 GLubyte *blkaddr; 193 GLint dstRowDiff, rgRowStride; 194 mesa_format tempFormat; 195 GLubyte *tempImageSlices[1]; 196 197 assert(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM || 198 dstFormat == MESA_FORMAT_LA_LATC2_UNORM); 199 200 if (baseInternalFormat == GL_RG) 201 tempFormat = MESA_FORMAT_RG_UNORM8; 202 else 203 tempFormat = MESA_FORMAT_LA_UNORM8; 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 248GLboolean 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 314static void 315fetch_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 326static void 327fetch_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 338static void 339fetch_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 351static void 352fetch_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 364static void 365fetch_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 381static void 382fetch_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 399static void 400fetch_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 417static void 418fetch_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 435compressed_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