Parent Directory
|
Revision Log
1.2.1 release
1 /* 2 DDS GIMP plugin 3 4 Copyright (C) 2004 Shawn Kirst <skirst@fuse.net>, 5 with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified. 6 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; see the file COPYING. If not, write to 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. 21 */ 22 23 #ifdef WIN32 24 #include <windows.h> 25 #else 26 #include <dlfcn.h> 27 #endif 28 #include <string.h> 29 #include <math.h> 30 #include <GL/glew.h> 31 #include <GL/glut.h> 32 #include <glib.h> 33 34 35 #include "dds.h" 36 #include "endian.h" 37 38 #define IS_POT(x) (!((x) & ((x) - 1))) 39 #define LERP(a, b, t) ((a) + ((b) - (a)) * (t)) 40 41 static int generate_mipmaps_software(unsigned char *dst, unsigned char *src, 42 unsigned int width, unsigned int height, 43 int bpp, int indexed, int mipmaps); 44 45 #ifdef USE_SOFTWARE_COMPRESSION 46 #ifdef WIN32 47 HANDLE hdxtn = NULL; 48 #define DXTN_DLL "dxtn.dll" 49 #define dlopen(handle, flags) LoadLibrary(handle) 50 #define dlsym(handle, symbol) GetProcAddress(handle, symbol) 51 #define dlclose(handle) FreeLibrary(handle) 52 #define RTLD_LAZY 0 53 #define RTLD_GLOBAL 0 54 #else 55 void *hdxtn = NULL; 56 #define DXTN_DLL "libtxc_dxtn.so" 57 #endif 58 static void (*compress_dxtn)(int, int, int, const unsigned char*, int, unsigned char *) = NULL; 59 #endif // #ifdef USE_SOFTWARE_COMPRESSION 60 61 char *initialize_opengl(void) 62 { 63 int argc = 1, err; 64 char *argv[] = { "dds" }; 65 66 glutInit(&argc, argv); 67 glutInitDisplayMode(GLUT_RGBA); 68 glutInitWindowSize(1, 1); 69 glutCreateWindow("GIMP DDS"); 70 71 err = glewInit(); 72 if(err != GLEW_OK) 73 return((char*)glewGetErrorString(err)); 74 75 #ifndef USE_SOFTWARE_COMPRESSION 76 if(!GLEW_ARB_texture_compression) 77 return("GL_ARB_texture_compression is not supported by your OpenGL " 78 "implementation.\n"); 79 if(!GLEW_S3_s3tc && !GLEW_EXT_texture_compression_s3tc) 80 return("GL_S3_s3tc or GL_EXT_texture_compression_s3tc is not supported " 81 "by your OpenGL implementation.\n"); 82 83 glHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST); 84 #else 85 hdxtn = dlopen(DXTN_DLL, RTLD_LAZY | RTLD_GLOBAL); 86 if(hdxtn == NULL) 87 return("Unable to load library " DXTN_DLL); 88 compress_dxtn = (void*)dlsym(hdxtn, "tx_compress_dxtn"); 89 if(compress_dxtn == NULL) 90 { 91 dlclose(hdxtn); 92 return("Missing symbol `tx_compress_dxtn' in " DXTN_DLL); 93 } 94 #endif 95 96 glPixelStorei(GL_PACK_ALIGNMENT, 1); 97 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 98 99 if(GLEW_SGIS_generate_mipmap) 100 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); 101 102 return(0); 103 } 104 105 int get_num_mipmaps(int width, int height) 106 { 107 int w = width << 1; 108 int h = height << 1; 109 int n = 0; 110 111 while(w != 1 || h != 1) 112 { 113 if(w > 1) w >>= 1; 114 if(h > 1) h >>= 1; 115 ++n; 116 } 117 118 return(n); 119 } 120 121 unsigned int get_mipmapped_size(int width, int height, int bpp, 122 int level, int num, int format) 123 { 124 int w, h, n = 0; 125 unsigned int size = 0; 126 127 w = width >> level; 128 h = height >> level; 129 if(w == 0) w = 1; 130 if(h == 0) h = 1; 131 w <<= 1; 132 h <<= 1; 133 134 while(n < num && (w != 1 || h != 1)) 135 { 136 if(w > 1) w >>= 1; 137 if(h > 1) h >>= 1; 138 if(format == DDS_COMPRESS_NONE) 139 size += (w * h); 140 else 141 size += ((w + 3) >> 2) * ((h + 3) >> 2); 142 ++n; 143 } 144 145 if(format == DDS_COMPRESS_NONE) 146 size *= bpp; 147 else 148 { 149 if(format == DDS_COMPRESS_DXT1 || format == DDS_COMPRESS_ATI1) 150 size *= 8; 151 else 152 size *= 16; 153 } 154 155 return(size); 156 } 157 158 unsigned int get_volume_mipmapped_size(int width, int height, 159 int depth, int bpp, int level, 160 int num, int format) 161 { 162 int w, h, d, n = 0; 163 unsigned int size = 0; 164 165 w = width >> level; 166 h = height >> level; 167 d = depth >> level; 168 if(w == 0) w = 1; 169 if(h == 0) h = 1; 170 if(d == 0) d = 1; 171 w <<= 1; 172 h <<= 1; 173 d <<= 1; 174 175 while(n < num && (w != 1 || h != 1)) 176 { 177 if(w > 1) w >>= 1; 178 if(h > 1) h >>= 1; 179 if(d > 1) d >>= 1; 180 if(format == DDS_COMPRESS_NONE) 181 size += (w * h * d); 182 else 183 size += (((w + 3) >> 2) * ((h + 3) >> 2) * d); 184 ++n; 185 } 186 187 if(format == DDS_COMPRESS_NONE) 188 size *= bpp; 189 else 190 { 191 if(format == DDS_COMPRESS_DXT1 || format == DDS_COMPRESS_ATI1) 192 size *= 8; 193 else 194 size *= 16; 195 } 196 197 return(size); 198 } 199 200 static void compress_3dc(unsigned char *dst, unsigned char *src, 201 int width, int height, int bpp, int mipmaps, 202 int format) 203 { 204 int i, j, w, h; 205 unsigned int offset, size; 206 unsigned char *s1, *s2, *d1, *d2, *dtmp, *stmp; 207 208 #ifdef USE_SOFTWARE_COMPRESSION 209 210 if(format == DDS_COMPRESS_ATI1) 211 { 212 size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE); 213 stmp = g_malloc(size); 214 memset(stmp, 0, size); 215 216 for(i = j = 0; j < size; i += bpp, j += 4) 217 stmp[j + 3] = src[i]; 218 219 size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5); 220 dtmp = g_malloc(size); 221 222 offset = 0; 223 w = width; 224 h = height; 225 s1 = stmp; 226 227 for(i = 0; i < mipmaps; ++i) 228 { 229 compress_dxtn(4, w, h, s1, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 230 dtmp + offset); 231 s1 += (w * h * 4); 232 offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5); 233 if(w > 1) w >>= 1; 234 if(h > 1) h >>= 1; 235 } 236 237 for(i = j = 0; i < size; i += 16, j += 8) 238 memcpy(dst + j, dtmp + i, 8); 239 240 g_free(dtmp); 241 g_free(stmp); 242 } 243 else if(format == DDS_COMPRESS_ATI2) 244 { 245 size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE); 246 stmp = g_malloc(size * 2); 247 memset(stmp, 0, size * 2); 248 249 s1 = stmp; 250 s2 = stmp + size; 251 252 for(i = j = 0; j < size; i += bpp, j += 4) 253 { 254 s1[j + 3] = src[i + 1]; 255 s2[j + 3] = src[i]; 256 } 257 258 size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5); 259 dtmp = g_malloc(size * 2); 260 261 d1 = dtmp; 262 d2 = dtmp + size; 263 264 offset = 0; 265 w = width; 266 h = height; 267 268 for(i = 0; i < mipmaps; ++i) 269 { 270 compress_dxtn(4, w, h, s1, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, d1 + offset); 271 compress_dxtn(4, w, h, s2, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, d2 + offset); 272 s1 += (w * h * 4); 273 s2 += (w * h * 4); 274 offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5); 275 if(w > 1) w >>= 1; 276 if(h > 1) h >>= 1; 277 } 278 279 for(i = 0; i < size; i += 16) 280 { 281 memcpy(dst + i + 0, d1 + i, 8); 282 memcpy(dst + i + 8, d2 + i, 8); 283 } 284 285 g_free(dtmp); 286 g_free(stmp); 287 } 288 289 #else // #ifdef USE_SOFTWARE_COMPRESSION 290 291 if(GLEW_SGIS_generate_mipmap) 292 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); 293 294 if(format == DDS_COMPRESS_ATI1) 295 { 296 size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE); 297 stmp = g_malloc(size); 298 memset(stmp, 0, size); 299 300 for(i = j = 0; j < size; i += bpp, j += 4) 301 stmp[j + 3] = src[i]; 302 303 size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5); 304 dtmp = g_malloc(size); 305 306 offset = 0; 307 w = width; 308 h = height; 309 s1 = stmp; 310 311 for(i = 0; i < mipmaps; ++i) 312 { 313 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 314 w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s1); 315 glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, dtmp + offset); 316 s1 += (w * h * 4); 317 offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5); 318 if(w > 1) w >>= 1; 319 if(h > 1) h >>= 1; 320 } 321 322 for(i = j = 0; i < size; i += 16, j += 8) 323 memcpy(dst + j, dtmp + i, 8); 324 325 g_free(dtmp); 326 g_free(stmp); 327 } 328 else if(format == DDS_COMPRESS_ATI2) 329 { 330 size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE); 331 stmp = g_malloc(size * 2); 332 memset(stmp, 0, size * 2); 333 334 s1 = stmp; 335 s2 = stmp + size; 336 337 for(i = j = 0; j < size; i += bpp, j += 4) 338 { 339 s1[j + 3] = src[i + 1]; 340 s2[j + 3] = src[i]; 341 } 342 343 size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5); 344 dtmp = g_malloc(size * 2); 345 346 d1 = dtmp; 347 d2 = dtmp + size; 348 349 offset = 0; 350 w = width; 351 h = height; 352 353 for(i = 0; i < mipmaps; ++i) 354 { 355 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 356 w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s1); 357 glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, d1 + offset); 358 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 359 w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s2); 360 glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, d2 + offset); 361 s1 += (w * h * 4); 362 s2 += (w * h * 4); 363 offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5); 364 if(w > 1) w >>= 1; 365 if(h > 1) h >>= 1; 366 } 367 368 for(i = 0; i < size; i += 16) 369 { 370 memcpy(dst + i + 0, d1 + i, 8); 371 memcpy(dst + i + 8, d2 + i, 8); 372 } 373 374 g_free(dtmp); 375 g_free(stmp); 376 } 377 378 #endif // #ifdef USE_SOFTWARE_COMPRESSION 379 } 380 381 int dxt_compress(unsigned char *dst, unsigned char *src, int format, 382 unsigned int width, unsigned int height, int bpp, 383 int mipmaps) 384 { 385 GLenum internal = 0; 386 GLenum type = 0; 387 int i, size, w, h; 388 unsigned int offset; 389 unsigned char *tmp; 390 #ifdef USE_SOFTWARE_COMPRESSION 391 int j; 392 unsigned char *tmp2, *s, c; 393 #endif 394 395 if(!(IS_POT(width) && IS_POT(height))) 396 return(0); 397 398 switch(bpp) 399 { 400 case 1: type = GL_LUMINANCE; break; 401 case 2: type = GL_LUMINANCE_ALPHA; break; 402 case 3: type = GL_BGR; break; 403 case 4: type = GL_BGRA; break; 404 } 405 406 if(format == DDS_COMPRESS_DXT1) 407 { 408 internal = (bpp == 4 || bpp == 2) ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT : 409 GL_COMPRESSED_RGB_S3TC_DXT1_EXT; 410 } 411 else if(format == DDS_COMPRESS_DXT3) 412 internal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; 413 else if(format == DDS_COMPRESS_DXT5) 414 internal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; 415 416 #ifdef USE_SOFTWARE_COMPRESSION 417 418 size = get_mipmapped_size(width, height, bpp, 0, mipmaps, 419 DDS_COMPRESS_NONE); 420 tmp = g_malloc(size); 421 generate_mipmaps_software(tmp, src, width, height, bpp, 0, mipmaps); 422 423 if(bpp == 1) 424 { 425 /* grayscale promoted to RGB */ 426 427 size = get_mipmapped_size(width, height, 3, 0, mipmaps, 428 DDS_COMPRESS_NONE); 429 tmp2 = g_malloc(size); 430 431 for(i = j = 0; j < size; ++i, j += 3) 432 { 433 tmp2[j + 0] = tmp[i]; 434 tmp2[j + 1] = tmp[i]; 435 tmp2[j + 2] = tmp[i]; 436 } 437 438 g_free(tmp); 439 tmp = tmp2; 440 bpp = 3; 441 } 442 else if(bpp == 2) 443 { 444 /* gray-alpha promoted to RGBA */ 445 446 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 447 DDS_COMPRESS_NONE); 448 tmp2 = g_malloc(size); 449 450 for(i = j = 0; j < size; i += 2, j += 4) 451 { 452 tmp2[j + 0] = tmp[i]; 453 tmp2[j + 1] = tmp[i]; 454 tmp2[j + 2] = tmp[i]; 455 tmp2[j + 3] = tmp[i + 1]; 456 } 457 458 g_free(tmp); 459 tmp = tmp2; 460 bpp = 4; 461 } 462 else /* bpp >= 3 */ 463 { 464 /* libtxc_dxtn wants BGRA pixels */ 465 for(i = 0; i < size; i += bpp) 466 { 467 c = tmp[i]; 468 tmp[i] = tmp[i + 2]; 469 tmp[i + 2] = c; 470 } 471 } 472 473 /* add an opaque alpha channel if need be */ 474 if(bpp == 3 && (format == DDS_COMPRESS_DXT3 || format == DDS_COMPRESS_DXT5)) 475 { 476 size = get_mipmapped_size(width, height, 4, 0, mipmaps, 477 DDS_COMPRESS_NONE); 478 tmp2 = g_malloc(size); 479 480 for(i = j = 0; j < size; i += bpp, j += 4) 481 { 482 tmp2[j + 0] = tmp[i + 0]; 483 tmp2[j + 1] = tmp[i + 1]; 484 tmp2[j + 2] = tmp[i + 2]; 485 tmp2[j + 3] = 255; 486 } 487 488 g_free(tmp); 489 tmp = tmp2; 490 bpp = 4; 491 } 492 493 offset = 0; 494 w = width; 495 h = height; 496 s = tmp; 497 498 if(format <= DDS_COMPRESS_DXT5) 499 { 500 for(i = 0; i < mipmaps; ++i) 501 { 502 compress_dxtn(bpp, w, h, s, internal, dst + offset); 503 s += (w * h * bpp); 504 offset += get_mipmapped_size(w, h, 0, 0, 1, format); 505 if(w > 1) w >>= 1; 506 if(h > 1) h >>= 1; 507 } 508 } 509 else /* 3Dc */ 510 compress_3dc(dst, s, w, h, bpp, mipmaps, format); 511 512 g_free(tmp); 513 514 #else 515 516 if(format >= DDS_COMPRESS_ATI1) 517 { 518 size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE); 519 tmp = g_malloc(size); 520 521 if(GLEW_SGIS_generate_mipmap) 522 { 523 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 524 mipmaps > 1 ? GL_TRUE : GL_FALSE); 525 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 526 type, GL_UNSIGNED_BYTE, src); 527 528 offset = 0; 529 for(i = 0; i < mipmaps; ++i) 530 { 531 glGetTexImage(GL_TEXTURE_2D, i, GL_RGBA, GL_UNSIGNED_BYTE, 532 tmp + offset); 533 offset += get_mipmapped_size(width, height, 4, i, 1, 534 DDS_COMPRESS_NONE); 535 } 536 } 537 else 538 generate_mipmaps_software(tmp, src, width, height, bpp, 0, mipmaps); 539 540 compress_3dc(dst, tmp, width, height, 4, mipmaps, format); 541 542 g_free(tmp); 543 544 return(1); 545 } 546 547 if(GLEW_SGIS_generate_mipmap) 548 { 549 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 550 mipmaps > 1 ? GL_TRUE : GL_FALSE); 551 glTexImage2D(GL_TEXTURE_2D, 0, internal, width, height, 0, 552 type, GL_UNSIGNED_BYTE, src); 553 } 554 else 555 { 556 size = get_mipmapped_size(width, height, bpp, 0, mipmaps, 557 DDS_COMPRESS_NONE); 558 tmp = g_malloc(size); 559 generate_mipmaps_software(tmp, src, width, height, bpp, 0, mipmaps); 560 561 offset = 0; 562 w = width; 563 h = height; 564 565 for(i = 0; i < mipmaps; ++i) 566 { 567 glTexImage2D(GL_TEXTURE_2D, i, internal, w, h, 0, type, 568 GL_UNSIGNED_BYTE, tmp + offset); 569 offset += (w * h * bpp); 570 if(w > 1) w >>= 1; 571 if(h > 1) h >>= 1; 572 } 573 574 g_free(tmp); 575 } 576 577 glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, dst); 578 579 if(mipmaps > 1) 580 { 581 offset = 0; 582 for(i = 1; i < mipmaps; ++i) 583 { 584 glGetTexLevelParameteriv(GL_TEXTURE_2D, i - 1, 585 GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &size); 586 offset += size; 587 glGetCompressedTexImageARB(GL_TEXTURE_2D, i, dst + offset); 588 } 589 } 590 591 #endif // #ifdef USE_SOFTWARE_COMPRESSION 592 593 return(1); 594 } 595 596 #ifdef USE_SOFTWARE_COMPRESSION 597 598 static void decode_color_block(unsigned char *dst, unsigned char *src, 599 int w, int h, int rowbytes, int format) 600 { 601 int i, x, y; 602 unsigned int indexes, idx; 603 unsigned char *d; 604 unsigned char colors[4][3]; 605 unsigned short c0, c1; 606 607 c0 = GETL16(&src[0]); 608 c1 = GETL16(&src[2]); 609 610 colors[0][0] = ((c0 >> 11) & 0x1f) << 3; 611 colors[0][1] = ((c0 >> 5) & 0x3f) << 2; 612 colors[0][2] = ((c0 ) & 0x1f) << 3; 613 614 colors[1][0] = ((c1 >> 11) & 0x1f) << 3; 615 colors[1][1] = ((c1 >> 5) & 0x3f) << 2; 616 colors[1][2] = ((c1 ) & 0x1f) << 3; 617 618 if((c0 > c1) || (format == DDS_COMPRESS_DXT5)) 619 { 620 for(i = 0; i < 3; ++i) 621 { 622 colors[2][i] = (2 * colors[0][i] + colors[1][i] + 1) / 3; 623 colors[3][i] = (2 * colors[1][i] + colors[0][i] + 1) / 3; 624 } 625 } 626 else 627 { 628 for(i = 0; i < 3; ++i) 629 { 630 colors[2][i] = (colors[0][i] + colors[1][i] + 1) >> 1; 631 colors[3][i] = 255; 632 } 633 } 634 635 src += 4; 636 for(y = 0; y < h; ++y) 637 { 638 d = dst + (y * rowbytes); 639 indexes = src[y]; 640 for(x = 0; x < w; ++x) 641 { 642 idx = indexes & 0x03; 643 d[0] = colors[idx][0]; 644 d[1] = colors[idx][1]; 645 d[2] = colors[idx][2]; 646 if(format == DDS_COMPRESS_DXT1) 647 d[3] = ((c0 <= c1) && idx == 3) ? 0 : 255; 648 indexes >>= 2; 649 d += 4; 650 } 651 } 652 } 653 654 static void decode_dxt3_alpha(unsigned char *dst, unsigned char *src, 655 int w, int h, int rowbytes) 656 { 657 int x, y; 658 unsigned char *d; 659 unsigned int bits; 660 661 for(y = 0; y < h; ++y) 662 { 663 d = dst + (y * rowbytes); 664 bits = GETL16(&src[2 * y]); 665 bits = GETL16(&src[2 * y]); 666 for(x = 0; x < w; ++x) 667 { 668 d[0] = (bits & 0x0f) * 17; 669 bits >>= 4; 670 d += 4; 671 } 672 } 673 } 674 675 #endif // #ifdef USE_SOFTWARE_COMPRESSION 676 677 static void decode_dxt5_alpha(unsigned char *dst, unsigned char *src, 678 int w, int h, int bpp, int rowbytes) 679 { 680 int x, y, code; 681 unsigned char *d; 682 unsigned char a0 = src[0]; 683 unsigned char a1 = src[1]; 684 unsigned long long bits = GETL64(src) >> 16; 685 686 for(y = 0; y < h; ++y) 687 { 688 d = dst + (y * rowbytes); 689 for(x = 0; x < w; ++x) 690 { 691 code = ((unsigned int)bits) & 0x07; 692 if(code == 0) 693 d[0] = a0; 694 else if(code == 1) 695 d[0] = a1; 696 else if(a0 > a1) 697 d[0] = ((8 - code) * a0 + (code - 1) * a1) / 7; 698 else if(code >= 6) 699 d[0] = (code == 6) ? 0 : 255; 700 else 701 d[0] = ((6 - code) * a0 + (code - 1) * a1) / 5; 702 bits >>= 3; 703 d += bpp; 704 } 705 if(w < 4) bits >>= (3 * (4 - w)); 706 } 707 } 708 709 int dxt_decompress(unsigned char *dst, unsigned char *src, int format, 710 unsigned int size, unsigned int width, unsigned int height, 711 int bpp) 712 { 713 #ifdef USE_SOFTWARE_COMPRESSION 714 715 unsigned char *d, *s; 716 unsigned int x, y, sx, sy; 717 718 if(!(IS_POT(width) && IS_POT(height))) 719 return(0); 720 721 sx = (width < 4) ? width : 4; 722 sy = (height < 4) ? height : 4; 723 724 s = src; 725 726 for(y = 0; y < height; y += 4) 727 { 728 for(x = 0; x < width; x += 4) 729 { 730 d = dst + (y * width + x) * bpp; 731 if(format == DDS_COMPRESS_DXT3) 732 { 733 decode_dxt3_alpha(d + 3, s, sx, sy, width * bpp); 734 s += 8; 735 } 736 else if(format == DDS_COMPRESS_DXT5) 737 { 738 decode_dxt5_alpha(d + 3, s, sx, sy, bpp, width * bpp); 739 s += 8; 740 } 741 else if(format == DDS_COMPRESS_ATI1) 742 { 743 decode_dxt5_alpha(d, s, sx, sy, bpp, width * bpp); 744 s += 8; 745 } 746 else if(format == DDS_COMPRESS_ATI2) 747 { 748 decode_dxt5_alpha(d, s + 8, sx, sy, bpp, width * bpp); 749 decode_dxt5_alpha(d + 1, s, sx, sy, bpp, width * bpp); 750 s += 16; 751 } 752 753 if(format <= DDS_COMPRESS_DXT5) 754 { 755 decode_color_block(d, s, sx, sy, width * bpp, format); 756 s += 8; 757 } 758 } 759 } 760 761 #else // #ifdef USE_SOFTWARE_COMPRESSION 762 763 GLenum internal = GL_NONE, type = GL_RGB; 764 unsigned char *d, *s; 765 unsigned int x, y, sx, sy; 766 767 if(!(IS_POT(width) && IS_POT(height))) 768 return(0); 769 770 if(format >= DDS_COMPRESS_ATI1) /* 3Dc */ 771 { 772 sx = (width < 4) ? width : 4; 773 sy = (height < 4) ? height : 4; 774 775 s = src; 776 777 for(y = 0; y < height; y += 4) 778 { 779 for(x = 0; x < width; x += 4) 780 { 781 d = dst + (y * width + x) * bpp; 782 if(format == DDS_COMPRESS_ATI1) 783 { 784 decode_dxt5_alpha(d, s, sx, sy, bpp, width * bpp); 785 s += 8; 786 } 787 else if(format == DDS_COMPRESS_ATI2) 788 { 789 decode_dxt5_alpha(d, s + 8, sx, sy, bpp, width * bpp); 790 decode_dxt5_alpha(d + 1, s, sx, sy, bpp, width * bpp); 791 s += 16; 792 } 793 } 794 } 795 return(1); 796 } 797 798 switch(bpp) 799 { 800 case 1: type = GL_LUMINANCE; break; 801 case 2: type = GL_LUMINANCE_ALPHA; break; 802 case 3: type = GL_RGB; break; 803 case 4: type = GL_RGBA; break; 804 } 805 806 switch(format) 807 { 808 case DDS_COMPRESS_DXT1: 809 internal = (bpp == 4) ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT : 810 GL_COMPRESSED_RGB_S3TC_DXT1_EXT; 811 break; 812 case DDS_COMPRESS_DXT3: 813 internal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; 814 break; 815 case DDS_COMPRESS_DXT5: 816 internal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; 817 break; 818 } 819 820 glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, internal, width, height, 0, size, src); 821 glGetTexImage(GL_TEXTURE_2D, 0, type, GL_UNSIGNED_BYTE, dst); 822 823 #endif // #ifdef USE_SOFTWARE_COMPRESSION 824 825 return(1); 826 } 827 828 float cubic_interpolate(float a, float b, float c, float d, float x) 829 { 830 float v0, v1, v2, v3, x2; 831 832 x2 = x * x; 833 v0 = d - c - a + b; 834 v1 = a - b - v0; 835 v2 = c - a; 836 v3 = b; 837 838 return(v0 * x * x2 + v1 * x2 + v2 * x + v3); 839 } 840 841 static void scale_image_cubic(unsigned char *dst, int dw, int dh, 842 unsigned char *src, int sw, int sh, 843 int bpp) 844 { 845 int n, x, y; 846 int ix, iy; 847 float fx, fy; 848 float dx, dy, val; 849 float r0, r1, r2, r3; 850 int srowbytes = sw * bpp; 851 int drowbytes = dw * bpp; 852 853 #define VAL(x, y, c) \ 854 (float)src[((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes + \ 855 (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c] 856 857 for(y = 0; y < dh; ++y) 858 { 859 fy = ((float)y / (float)dh) * (float)sh; 860 iy = (int)fy; 861 dy = fy - (float)iy; 862 for(x = 0; x < dw; ++x) 863 { 864 fx = ((float)x / (float)dw) * (float)sw; 865 ix = (int)fx; 866 dx = fx - (float)ix; 867 868 for(n = 0; n < bpp; ++n) 869 { 870 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, n), 871 VAL(ix, iy - 1, n), 872 VAL(ix + 1, iy - 1, n), 873 VAL(ix + 2, iy - 1, n), dx); 874 r1 = cubic_interpolate(VAL(ix - 1, iy, n), 875 VAL(ix, iy, n), 876 VAL(ix + 1, iy, n), 877 VAL(ix + 2, iy, n), dx); 878 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, n), 879 VAL(ix, iy + 1, n), 880 VAL(ix + 1, iy + 1, n), 881 VAL(ix + 2, iy + 1, n), dx); 882 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, n), 883 VAL(ix, iy + 2, n), 884 VAL(ix + 1, iy + 2, n), 885 VAL(ix + 2, iy + 2, n), dx); 886 val = cubic_interpolate(r0, r1, r2, r3, dy); 887 if(val < 0) val = 0; 888 if(val > 255) val = 255; 889 dst[y * drowbytes + (x * bpp) + n] = (unsigned char)val; 890 } 891 } 892 } 893 #undef VAL 894 } 895 896 static void scale_image_nearest(unsigned char *dst, int dw, int dh, 897 unsigned char *src, int sw, int sh, 898 int bpp) 899 { 900 int n, x, y; 901 int ix, iy; 902 int srowbytes = sw * bpp; 903 int drowbytes = dw * bpp; 904 905 for(y = 0; y < dh; ++y) 906 { 907 iy = (y * sh + sh / 2) / dh; 908 for(x = 0; x < dw; ++x) 909 { 910 ix = (x * sw + sw / 2) / dw; 911 for(n = 0; n < bpp; ++n) 912 { 913 dst[y * drowbytes + (x * bpp) + n] = 914 src[iy * srowbytes + (ix * bpp) + n]; 915 } 916 } 917 } 918 } 919 920 static int generate_mipmaps_software(unsigned char *dst, unsigned char *src, 921 unsigned int width, unsigned int height, 922 int bpp, int indexed, int mipmaps) 923 { 924 int i; 925 unsigned int w, h; 926 unsigned int offset; 927 928 memcpy(dst, src, width * height * bpp); 929 offset = width * height * bpp; 930 931 for(i = 1; i < mipmaps; ++i) 932 { 933 w = width >> i; 934 h = height >> i; 935 if(w < 1) w = 1; 936 if(h < 1) h = 1; 937 938 if(indexed) 939 scale_image_nearest(dst + offset, w, h, src, width, height, bpp); 940 else 941 scale_image_cubic(dst + offset, w, h, src, width, height, bpp); 942 943 offset += (w * h * bpp); 944 } 945 946 return(1); 947 } 948 949 int generate_mipmaps(unsigned char *dst, unsigned char *src, 950 unsigned int width, unsigned int height, int bpp, 951 int indexed, int mipmaps) 952 { 953 int i; 954 unsigned int w, h; 955 GLenum internal = 0; 956 GLenum format = 0; 957 unsigned int offset; 958 959 if(!GLEW_SGIS_generate_mipmap || indexed || 960 (!(IS_POT(width) && IS_POT(height)) && 961 !GLEW_ARB_texture_non_power_of_two)) 962 { 963 return(generate_mipmaps_software(dst, src, width, height, bpp, indexed, 964 mipmaps)); 965 } 966 967 switch(bpp) 968 { 969 case 1: internal = format = GL_LUMINANCE; break; 970 case 2: internal = format = GL_LUMINANCE_ALPHA; break; 971 case 3: internal = GL_RGB; format = GL_BGR; break; 972 case 4: internal = GL_RGBA; format = GL_BGRA; break; 973 } 974 975 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 976 glTexImage2D(GL_TEXTURE_2D, 0, internal, width, height, 0, 977 format, GL_UNSIGNED_BYTE, src); 978 979 memcpy(dst, src, width * height * bpp); 980 981 offset = width * height * bpp; 982 983 for(i = 1; i < mipmaps; ++i) 984 { 985 w = width >> i; 986 h = height >> i; 987 if(w < 1) w = 1; 988 if(h < 1) h = 1; 989 990 glGetTexImage(GL_TEXTURE_2D, i, format, GL_UNSIGNED_BYTE, dst + offset); 991 992 offset += (w * h * bpp); 993 } 994 995 return(1); 996 } 997 998 static void scale_volume_image_cubic(unsigned char *dst, int dw, int dh, int dd, 999 unsigned char *src, int sw, int sh, int sd, 1000 int bpp) 1001 { 1002 int n, x, y, z; 1003 int ix, iy, iz; 1004 float fx, fy, fz; 1005 float dx, dy, dz, val; 1006 float r0, r1, r2, r3; 1007 float v0, v1, v2, v3; 1008 int srowbytes = sw * bpp; 1009 int drowbytes = dw * bpp; 1010 int sslicebytes = sw * sh * bpp; 1011 int dslicebytes = dw * dh * bpp; 1012 1013 #define VAL(x, y, z, c) \ 1014 (float)src[(((z) < 0 ? 0 : (z) >= sd ? sd - 1 : (z)) * sslicebytes) + \ 1015 (((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes) + \ 1016 (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c] 1017 1018 for(z = 0; z < dd; ++z) 1019 { 1020 fz = ((float)z / (float)dd) * (float)sd; 1021 iz = (int)fz; 1022 dz = fz - (float)iz; 1023 for(y = 0; y < dh; ++y) 1024 { 1025 fy = ((float)y / (float)dh) * (float)sh; 1026 iy = (int)fy; 1027 dy = fy - (float)iy; 1028 for(x = 0; x < dw; ++x) 1029 { 1030 fx = ((float)x / (float)dw) * (float)sw; 1031 ix = (int)fx; 1032 dx = fx - (float)ix; 1033 for(n = 0; n < bpp; ++n) 1034 { 1035 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z - 1, n), 1036 VAL(ix, iy - 1, z - 1, n), 1037 VAL(ix + 1, iy - 1, z - 1, n), 1038 VAL(ix + 2, iy - 1, z - 1, n), dx); 1039 r1 = cubic_interpolate(VAL(ix - 1, iy, z - 1, n), 1040 VAL(ix, iy, z - 1, n), 1041 VAL(ix + 1, iy, z - 1, n), 1042 VAL(ix + 2, iy, z - 1, n), dx); 1043 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z - 1, n), 1044 VAL(ix, iy + 1, z - 1, n), 1045 VAL(ix + 1, iy + 1, z - 1, n), 1046 VAL(ix + 2, iy + 1, z - 1, n), dx); 1047 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z - 1, n), 1048 VAL(ix, iy + 2, z - 1, n), 1049 VAL(ix + 1, iy + 2, z - 1, n), 1050 VAL(ix + 2, iy + 2, z - 1, n), dx); 1051 v0 = cubic_interpolate(r0, r1, r2, r3, dy); 1052 1053 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z, n), 1054 VAL(ix, iy - 1, z, n), 1055 VAL(ix + 1, iy - 1, z, n), 1056 VAL(ix + 2, iy - 1, z, n), dx); 1057 r1 = cubic_interpolate(VAL(ix - 1, iy, z, n), 1058 VAL(ix, iy, z, n), 1059 VAL(ix + 1, iy, z, n), 1060 VAL(ix + 2, iy, z, n), dx); 1061 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z, n), 1062 VAL(ix, iy + 1, z, n), 1063 VAL(ix + 1, iy + 1, z, n), 1064 VAL(ix + 2, iy + 1, z, n), dx); 1065 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z, n), 1066 VAL(ix, iy + 2, z, n), 1067 VAL(ix + 1, iy + 2, z, n), 1068 VAL(ix + 2, iy + 2, z, n), dx); 1069 v1 = cubic_interpolate(r0, r1, r2, r3, dy); 1070 1071 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 1, n), 1072 VAL(ix, iy - 1, z + 1, n), 1073 VAL(ix + 1, iy - 1, z + 1, n), 1074 VAL(ix + 2, iy - 1, z + 1, n), dx); 1075 r1 = cubic_interpolate(VAL(ix - 1, iy, z + 1, n), 1076 VAL(ix, iy, z + 1, n), 1077 VAL(ix + 1, iy, z + 1, n), 1078 VAL(ix + 2, iy, z + 1, n), dx); 1079 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 1, n), 1080 VAL(ix, iy + 1, z + 1, n), 1081 VAL(ix + 1, iy + 1, z + 1, n), 1082 VAL(ix + 2, iy + 1, z + 1, n), dx); 1083 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 1, n), 1084 VAL(ix, iy + 2, z + 1, n), 1085 VAL(ix + 1, iy + 2, z + 1, n), 1086 VAL(ix + 2, iy + 2, z + 1, n), dx); 1087 v2 = cubic_interpolate(r0, r1, r2, r3, dy); 1088 1089 r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 2, n), 1090 VAL(ix, iy - 1, z + 2, n), 1091 VAL(ix + 1, iy - 1, z + 2, n), 1092 VAL(ix + 2, iy - 1, z + 2, n), dx); 1093 r1 = cubic_interpolate(VAL(ix - 1, iy, z + 2, n), 1094 VAL(ix, iy, z + 2, n), 1095 VAL(ix + 1, iy, z + 2, n), 1096 VAL(ix + 2, iy, z + 2, n), dx); 1097 r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 2, n), 1098 VAL(ix, iy + 1, z + 2, n), 1099 VAL(ix + 1, iy + 1, z + 2, n), 1100 VAL(ix + 2, iy + 1, z + 2, n), dx); 1101 r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 2, n), 1102 VAL(ix, iy + 2, z + 2, n), 1103 VAL(ix + 1, iy + 2, z + 2, n), 1104 VAL(ix + 2, iy + 2, z + 2, n), dx); 1105 v3 = cubic_interpolate(r0, r1, r2, r3, dy); 1106 1107 val = cubic_interpolate(v0, v1, v2, v3, dz); 1108 1109 if(val < 0) val = 0; 1110 if(val > 255) val = 255; 1111 1112 dst[(z * dslicebytes) + (y * drowbytes) + (x * bpp) + n] = 1113 (unsigned char)val; 1114 } 1115 } 1116 } 1117 } 1118 #undef VAL 1119 } 1120 1121 static void scale_volume_image_nearest(unsigned char *dst, int dw, int dh, int dd, 1122 unsigned char *src, int sw, int sh, int sd, 1123 int bpp) 1124 { 1125 int n, x, y, z; 1126 int ix, iy, iz; 1127 1128 for(z = 0; z < dd; ++z) 1129 { 1130 iz = (z * sd + sd / 2) / dd; 1131 for(y = 0; y < dh; ++y) 1132 { 1133 iy = (y * sh + sh / 2) / dh; 1134 for(x = 0; x < dw; ++x) 1135 { 1136 ix = (x * sw + sw / 2) / dw; 1137 for(n = 0; n < bpp; ++n) 1138 { 1139 dst[(z * (dw * dh)) + (y * dw) + (x * bpp) + n] = 1140 src[(iz * (sw * sh)) + (iy * sw) + (ix * bpp) + n]; 1141 } 1142 } 1143 } 1144 } 1145 } 1146 1147 static int generate_volume_mipmaps_software(unsigned char *dst, unsigned char *src, 1148 unsigned int width, unsigned int height, 1149 unsigned int depth, int bpp, int indexed, 1150 int mipmaps) 1151 { 1152 int i; 1153 unsigned int w, h, d; 1154 unsigned int offset; 1155 1156 memcpy(dst, src, width * height * depth * bpp); 1157 offset = width * height * depth * bpp; 1158 1159 for(i = 1; i < mipmaps; ++i) 1160 { 1161 w = width >> i; 1162 h = height >> i; 1163 d = depth >> i; 1164 if(w < 1) w = 1; 1165 if(h < 1) h = 1; 1166 if(d < 1) d = 1; 1167 1168 if(indexed) 1169 { 1170 scale_volume_image_nearest(dst + offset, w, h, d, src, width, height, 1171 depth, bpp); 1172 } 1173 else 1174 { 1175 scale_volume_image_cubic(dst + offset, w, h, d, src, width, height, 1176 depth, bpp); 1177 } 1178 1179 offset += (w * h * d * bpp); 1180 } 1181 1182 return(1); 1183 } 1184 1185 int generate_volume_mipmaps(unsigned char *dst, unsigned char *src, 1186 unsigned int width, unsigned int height, 1187 unsigned int depth, int bpp, int indexed, 1188 int mipmaps) 1189 { 1190 int i; 1191 unsigned int w, h, d; 1192 GLenum internal = 0; 1193 GLenum format = 0; 1194 unsigned int offset; 1195 1196 if(!GLEW_SGIS_generate_mipmap || indexed || 1197 (!(IS_POT(width) && IS_POT(height) && IS_POT(depth)) && 1198 !GLEW_ARB_texture_non_power_of_two)) 1199 { 1200 return(generate_volume_mipmaps_software(dst, src, width, height, depth, bpp, 1201 indexed, mipmaps)); 1202 } 1203 1204 switch(bpp) 1205 { 1206 case 1: internal = format = GL_LUMINANCE; break; 1207 case 2: internal = format = GL_LUMINANCE_ALPHA; break; 1208 case 3: internal = GL_RGB; format = GL_BGR; break; 1209 case 4: internal = GL_RGBA; format = GL_BGRA; break; 1210 } 1211 1212 glTexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 1213 glTexImage3D(GL_TEXTURE_3D, 0, internal, width, height, depth, 0, 1214 format, GL_UNSIGNED_BYTE, src); 1215 1216 memcpy(dst, src, width * height * bpp * depth); 1217 1218 offset = width * height * bpp * depth; 1219 1220 for(i = 1; i < mipmaps; ++i) 1221 { 1222 w = width >> i; 1223 h = height >> i; 1224 d = depth >> i; 1225 if(w < 1) w = 1; 1226 if(h < 1) h = 1; 1227 if(d < 1) d = 1; 1228 1229 glGetTexImage(GL_TEXTURE_3D, i, format, GL_UNSIGNED_BYTE, dst + offset); 1230 1231 offset += (w * h * bpp * d); 1232 } 1233 1234 return(1); 1235 }
| ViewVC Help | |
| Powered by ViewVC 1.0.4 |