1 /* 2 Copyright (c) 2019-2022 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.resource.dds; 29 30 import std.stdio; 31 import std.file; 32 import std.algorithm; 33 34 import dlib.core.memory; 35 import dlib.core.stream; 36 import dlib.image.io.utils; 37 38 import dagon.core.bindings; 39 import dagon.graphics.texture; 40 41 //version = DDSDebug; 42 43 struct DDSPixelFormat 44 { 45 uint size; 46 uint flags; 47 uint fourCC; 48 uint bpp; 49 uint redMask; 50 uint greenMask; 51 uint blueMask; 52 uint alphaMask; 53 } 54 55 enum DDSHeaderFlags 56 { 57 TEXTURE = 0x00001007, 58 MIPMAPS = 0x00020000, 59 LINEARSIZE = 0x00080000, 60 VOLUME = 0x00800000 61 } 62 63 enum DDPF 64 { 65 ALPHAPIXELS = 0x1, 66 ALPHA = 0x2, 67 FOURCC = 0x4, 68 RGB = 0x40, 69 YUV = 0x200, 70 LUMINANCE = 0x20000 71 } 72 73 enum DDSCaps 74 { 75 RESERVED1 = 0x00000001, 76 RESERVED2 = 0x00800000, 77 RESERVED3 = 0x00000400, 78 _3DDEVICE = 0x00002000, 79 ALLOCONLOAD = 0x04000000, 80 ALPHA = 0x00000002, 81 BACKBUFFER = 0x00000004, 82 COMPLEX = 0x00000008, 83 EXECUTEBUFFER = 0x00800000, 84 FLIP = 0x00000010, 85 FRONTBUFFER = 0x00000020, 86 HWCODEC = 0x00100000, 87 LIVEVIDEO = 0x00080000, 88 LOCALVIDMEM = 0x10000000, 89 MIPMAP = 0x00400000, 90 MODEX = 0x00200000, 91 NONLOCALVIDMEM = 0x20000000, 92 OFFSCREENPLAIN = 0x00000040, 93 OVERLAY = 0x00000080, 94 OPTIMIZED = 0x80000000, 95 OWNDC = 0x00040000, 96 PALETTE = 0x00000100, 97 PRIMARYSURFACE = 0x00000200, 98 PRIMARYSURFACELEFT = 0x00000000, 99 STANDARDVGAMODE = 0x40000000, 100 SYSTEMMEMORY = 0x00000800, 101 TEXTURE = 0x00001000, 102 VIDEOMEMORY = 0x00004000, 103 VIDEOPORT = 0x08000000, 104 VISIBLE = 0x00008000, 105 WRITEONLY = 0x00010000, 106 ZBUFFER = 0x00020000 107 } 108 109 enum DDSCaps2 110 { 111 RESERVED1 = 0x00000020, 112 RESERVED2 = 0x00000040, 113 RESERVED3 = 0x04000000, 114 RESERVED4 = 0x00000002, 115 ADDITIONALPRIMARY = 0x80000000, 116 CUBEMAP = 0x00000200, 117 CUBEMAP_POSITIVEX = 0x00000400, 118 CUBEMAP_NEGATIVEX = 0x00000800, 119 CUBEMAP_POSITIVEY = 0x00001000, 120 CUBEMAP_NEGATIVEY = 0x00002000, 121 CUBEMAP_POSITIVEZ = 0x00004000, 122 CUBEMAP_NEGATIVEZ = 0x00008000, 123 CUBEMAP_ALLFACES = 0x00000400 | 0x00000800 | 0x00001000 | 0x00002000 | 0x00004000 | 0x00008000, 124 D3DTEXTUREMANAGE = 0x00020000, 125 DISCARDBACKBUFFER = 0x10000000, 126 DONOTPERSIST = 0x00040000, 127 ENABLEALPHACHANNEL = 0x20000000, 128 VERTEXBUFFER = 0x00000020, 129 COMMANDBUFFER = 0x00000040, 130 INDEXBUFFER = 0x04000000, 131 EXTENDEDFORMATPRIMARY = 0x40000000, 132 HARDWAREDEINTERLACE = 0x00000000, 133 HINTANTIALIASING = 0x00000100, 134 HINTDYNAMIC = 0x00000004, 135 HINTSTATIC = 0x00000008, 136 MIPMAPSUBLEVEL = 0x00010000, 137 NOTUSERLOCKABLE = 0x00400000, 138 NPATCHES = 0x02000000, 139 POINTS = 0x00800000, 140 RTPATCHES = 0x01000000, 141 OPAQUE = 0x00000080, 142 STEREOSURFACELEFT = 0x00080000, 143 TEXTUREMANAGE = 0x00000010, 144 VOLUME = 0x00200000 145 } 146 147 enum DDSCaps3 148 { 149 RESERVED1 = 0x00000100, 150 RESERVED2 = 0x00000200, 151 AUTOGENMIPMAP = 0x00000800, 152 CREATESHAREDRESOURCE = 0x00002000, 153 DMAP = 0x00001000, 154 LIGHTWEIGHTMIPMAP = 0x00000400, 155 MULTISAMPLE_MASK = 0x0000001F, 156 MULTISAMPLE_QUALITY_MASK = 0x000000E0, 157 MULTISAMPLE_QUALITY_SHIFT = 5, 158 OPENSHAREDRESOURCE = 0x00008000, 159 READONLYRESOURCE = 0x00004000, 160 VIDEO = 0x00000200 161 } 162 163 struct DDSColorKey 164 { 165 uint lowVal; 166 uint highVal; 167 } 168 169 struct DDSHeader 170 { 171 uint size; 172 uint flags; 173 uint height; 174 uint width; 175 uint pitch; 176 uint depth; 177 uint mipMapLevels; 178 uint alphaBitDepth; 179 uint reserved; 180 uint surface; 181 182 DDSColorKey ckDestOverlay; 183 DDSColorKey ckDestBlt; 184 DDSColorKey ckSrcOverlay; 185 DDSColorKey ckSrcBlt; 186 187 DDSPixelFormat format; 188 uint caps; 189 uint caps2; 190 uint caps3; 191 uint caps4; 192 193 uint textureStage; 194 } 195 196 enum DXGIFormat 197 { 198 UNKNOWN = 0, 199 R32G32B32A32_TYPELESS = 1, 200 R32G32B32A32_FLOAT = 2, 201 R32G32B32A32_UINT = 3, 202 R32G32B32A32_SINT = 4, 203 R32G32B32_TYPELESS = 5, 204 R32G32B32_FLOAT = 6, 205 R32G32B32_UINT = 7, 206 R32G32B32_SINT = 8, 207 R16G16B16A16_TYPELESS = 9, 208 R16G16B16A16_FLOAT = 10, 209 R16G16B16A16_UNORM = 11, 210 R16G16B16A16_UINT = 12, 211 R16G16B16A16_SNORM = 13, 212 R16G16B16A16_SINT = 14, 213 R32G32_TYPELESS = 15, 214 R32G32_FLOAT = 16, 215 R32G32_UINT = 17, 216 R32G32_SINT = 18, 217 R32G8X24_TYPELESS = 19, 218 D32_FLOAT_S8X24_UINT = 20, 219 R32_FLOAT_X8X24_TYPELESS = 21, 220 X32_TYPELESS_G8X24_UINT = 22, 221 R10G10B10A2_TYPELESS = 23, 222 R10G10B10A2_UNORM = 24, 223 R10G10B10A2_UINT = 25, 224 R11G11B10_FLOAT = 26, 225 R8G8B8A8_TYPELESS = 27, 226 R8G8B8A8_UNORM = 28, 227 R8G8B8A8_UNORM_SRGB = 29, 228 R8G8B8A8_UINT = 30, 229 R8G8B8A8_SNORM = 31, 230 R8G8B8A8_SINT = 32, 231 R16G16_TYPELESS = 33, 232 R16G16_FLOAT = 34, 233 R16G16_UNORM = 35, 234 R16G16_UINT = 36, 235 R16G16_SNORM = 37, 236 R16G16_SINT = 38, 237 R32_TYPELESS = 39, 238 D32_FLOAT = 40, 239 R32_FLOAT = 41, 240 R32_UINT = 42, 241 R32_SINT = 43, 242 R24G8_TYPELESS = 44, 243 D24_UNORM_S8_UINT = 45, 244 R24_UNORM_X8_TYPELESS = 46, 245 X24_TYPELESS_G8_UINT = 47, 246 R8G8_TYPELESS = 48, 247 R8G8_UNORM = 49, 248 R8G8_UINT = 50, 249 R8G8_SNORM = 51, 250 R8G8_SINT = 52, 251 R16_TYPELESS = 53, 252 R16_FLOAT = 54, 253 D16_UNORM = 55, 254 R16_UNORM = 56, 255 R16_UINT = 57, 256 R16_SNORM = 58, 257 R16_SINT = 59, 258 R8_TYPELESS = 60, 259 R8_UNORM = 61, 260 R8_UINT = 62, 261 R8_SNORM = 63, 262 R8_SINT = 64, 263 A8_UNORM = 65, 264 R1_UNORM = 66, 265 R9G9B9E5_SHAREDEXP = 67, 266 R8G8_B8G8_UNORM = 68, 267 G8R8_G8B8_UNORM = 69, 268 BC1_TYPELESS = 70, 269 BC1_UNORM = 71, 270 BC1_UNORM_SRGB = 72, 271 BC2_TYPELESS = 73, 272 BC2_UNORM = 74, 273 BC2_UNORM_SRGB = 75, 274 BC3_TYPELESS = 76, 275 BC3_UNORM = 77, 276 BC3_UNORM_SRGB = 78, 277 BC4_TYPELESS = 79, 278 BC4_UNORM = 80, 279 BC4_SNORM = 81, 280 BC5_TYPELESS = 82, 281 BC5_UNORM = 83, 282 BC5_SNORM = 84, 283 B5G6R5_UNORM = 85, 284 B5G5R5A1_UNORM = 86, 285 B8G8R8A8_UNORM = 87, 286 B8G8R8X8_UNORM = 88, 287 R10G10B10_XR_BIAS_A2_UNORM = 89, 288 B8G8R8A8_TYPELESS = 90, 289 B8G8R8A8_UNORM_SRGB = 91, 290 B8G8R8X8_TYPELESS = 92, 291 B8G8R8X8_UNORM_SRGB = 93, 292 BC6H_TYPELESS = 94, 293 BC6H_UF16 = 95, 294 BC6H_SF16 = 96, 295 BC7_TYPELESS = 97, 296 BC7_UNORM = 98, 297 BC7_UNORM_SRGB = 99, 298 AYUV = 100, 299 Y410 = 101, 300 Y416 = 102, 301 NV12 = 103, 302 P010 = 104, 303 P016 = 105, 304 OPAQUE_420 = 106, 305 YUY2 = 107, 306 Y210 = 108, 307 Y216 = 109, 308 NV11 = 110, 309 AI44 = 111, 310 IA44 = 112, 311 P8 = 113, 312 A8P8 = 114, 313 B4G4R4A4_UNORM = 115, 314 P208 = 130, 315 V208 = 131, 316 V408 = 132, 317 ASTC_4X4_UNORM = 134, 318 ASTC_4X4_UNORM_SRGB = 135, 319 ASTC_5X4_TYPELESS = 137, 320 ASTC_5X4_UNORM = 138, 321 ASTC_5X4_UNORM_SRGB = 139, 322 ASTC_5X5_TYPELESS = 141, 323 ASTC_5X5_UNORM = 142, 324 ASTC_5X5_UNORM_SRGB = 143, 325 ASTC_6X5_TYPELESS = 145, 326 ASTC_6X5_UNORM = 146, 327 ASTC_6X5_UNORM_SRGB = 147, 328 ASTC_6X6_TYPELESS = 149, 329 ASTC_6X6_UNORM = 150, 330 ASTC_6X6_UNORM_SRGB = 151, 331 ASTC_8X5_TYPELESS = 153, 332 ASTC_8X5_UNORM = 154, 333 ASTC_8X5_UNORM_SRGB = 155, 334 ASTC_8X6_TYPELESS = 157, 335 ASTC_8X6_UNORM = 158, 336 ASTC_8X6_UNORM_SRGB = 159, 337 ASTC_8X8_TYPELESS = 161, 338 ASTC_8X8_UNORM = 162, 339 ASTC_8X8_UNORM_SRGB = 163, 340 ASTC_10X5_TYPELESS = 165, 341 ASTC_10X5_UNORM = 166, 342 ASTC_10X5_UNORM_SRGB = 167, 343 ASTC_10X6_TYPELESS = 169, 344 ASTC_10X6_UNORM = 170, 345 ASTC_10X6_UNORM_SRGB = 171, 346 ASTC_10X8_TYPELESS = 173, 347 ASTC_10X8_UNORM = 174, 348 ASTC_10X8_UNORM_SRGB = 175, 349 ASTC_10X10_TYPELESS = 177, 350 ASTC_10X10_UNORM = 178, 351 ASTC_10X10_UNORM_SRGB = 179, 352 ASTC_12X10_TYPELESS = 181, 353 ASTC_12X10_UNORM = 182, 354 ASTC_12X10_UNORM_SRGB = 183, 355 ASTC_12X12_TYPELESS = 185, 356 ASTC_12X12_UNORM = 186, 357 ASTC_12X12_UNORM_SRGB = 187 358 } 359 360 struct DDSHeaderDXT10 361 { 362 uint dxgiFormat; 363 uint resourceDimension; 364 uint miscFlag; 365 uint arraySize; 366 uint miscFlags2; 367 } 368 369 enum D3D10ResourceDimension 370 { 371 Unknown = 0, 372 Buffer = 1, 373 Texture1D = 2, 374 Texture2D = 3, 375 Texture3D = 4 376 } 377 378 enum D3D10ResourceMisc 379 { 380 GenerateMips = 0x01, 381 MiscShared = 0x02, 382 TextureCube = 0x04, 383 SharedKeyedMutex = 0x10, 384 GDICompatible = 0x20 385 } 386 387 uint makeFourCC(char ch0, char ch1, char ch2, char ch3) 388 { 389 return 390 ((cast(uint)ch3 << 24) & 0xFF000000) | 391 ((cast(uint)ch2 << 16) & 0x00FF0000) | 392 ((cast(uint)ch1 << 8) & 0x0000FF00) | 393 ((cast(uint)ch0) & 0x000000FF); 394 } 395 396 enum FOURCC_DXT1 = makeFourCC('D', 'X', 'T', '1'); 397 enum FOURCC_DXT3 = makeFourCC('D', 'X', 'T', '3'); 398 enum FOURCC_DXT5 = makeFourCC('D', 'X', 'T', '5'); 399 enum FOURCC_DX10 = makeFourCC('D', 'X', '1', '0'); 400 401 enum FOURCC_BC4U = makeFourCC('B', 'C', '4', 'U'); 402 enum FOURCC_BC4S = makeFourCC('B', 'C', '4', 'S'); 403 enum FOURCC_ATI2 = makeFourCC('A', 'T', 'I', '2'); 404 enum FOURCC_BC5S = makeFourCC('B', 'C', '5', 'S'); 405 enum FOURCC_RGBG = makeFourCC('R', 'G', 'B', 'G'); 406 enum FOURCC_GRGB = makeFourCC('G', 'R', 'G', 'B'); 407 408 enum FOURCC_DXT2 = makeFourCC('D', 'X', 'T', '2'); 409 410 DXGIFormat resourceFormatFromFourCC(uint fourCC) 411 { 412 DXGIFormat format; 413 414 switch(fourCC) 415 { 416 case FOURCC_DXT1: format = DXGIFormat.BC1_UNORM; break; 417 case FOURCC_DXT3: format = DXGIFormat.BC2_UNORM; break; 418 case FOURCC_DXT5: format = DXGIFormat.BC3_UNORM; break; 419 case FOURCC_BC4U: format = DXGIFormat.BC4_UNORM; break; 420 case FOURCC_BC4S: format = DXGIFormat.BC4_SNORM; break; 421 case FOURCC_ATI2: format = DXGIFormat.BC5_UNORM; break; 422 case FOURCC_BC5S: format = DXGIFormat.BC5_SNORM; break; 423 case FOURCC_RGBG: format = DXGIFormat.R8G8_B8G8_UNORM; break; 424 case FOURCC_GRGB: format = DXGIFormat.G8R8_G8B8_UNORM; break; 425 case 36: format = DXGIFormat.R16G16B16A16_UNORM; break; 426 case 110: format = DXGIFormat.R16G16B16A16_SNORM; break; 427 case 111: format = DXGIFormat.R16_FLOAT; break; 428 case 112: format = DXGIFormat.R16G16_FLOAT; break; 429 case 113: format = DXGIFormat.R16G16B16A16_FLOAT; break; 430 case 114: format = DXGIFormat.R32_FLOAT; break; 431 case 115: format = DXGIFormat.R32G32_FLOAT; break; 432 case 116: format = DXGIFormat.R32G32B32A32_FLOAT; break; 433 default: format = DXGIFormat.UNKNOWN; break; 434 } 435 436 return format; 437 } 438 439 bool loadDDS(InputStream istrm, TextureBuffer* buffer) 440 { 441 bool error(string errorMsg) 442 { 443 writeln(errorMsg); 444 return false; 445 } 446 447 char[4] magic; 448 449 if (!istrm.fillArray(magic)) 450 { 451 return error("loadDDS error: not a DDS file or corrupt data"); 452 } 453 454 version(DDSDebug) 455 { 456 writeln("Signature: ", magic); 457 } 458 459 if (magic != "DDS ") 460 { 461 return error("loadDDS error: not a DDS file"); 462 } 463 464 DDSHeader hdr = readStruct!DDSHeader(istrm); 465 466 version(DDSDebug) 467 { 468 writeln("hdr.size: ", hdr.size); 469 writeln("hdr.flags: ", hdr.flags); 470 writeln("hdr.height: ", hdr.height); 471 writeln("hdr.width: ", hdr.width); 472 writeln("hdr.pitch: ", hdr.pitch); 473 writeln("hdr.depth: ", hdr.depth); 474 writeln("hdr.mipMapLevels: ", hdr.mipMapLevels); 475 writeln("hdr.alphaBitDepth: ", hdr.alphaBitDepth); 476 writeln("hdr.reserved: ", hdr.reserved); 477 writeln("hdr.surface: ", hdr.surface); 478 479 writeln("hdr.ckDestOverlay.lowVal: ", hdr.ckDestOverlay.lowVal); 480 writeln("hdr.ckDestOverlay.highVal: ", hdr.ckDestOverlay.highVal); 481 writeln("hdr.ckDestBlt.lowVal: ", hdr.ckDestBlt.lowVal); 482 writeln("hdr.ckDestBlt.highVal: ", hdr.ckDestBlt.highVal); 483 writeln("hdr.ckSrcOverlay.lowVal: ", hdr.ckSrcOverlay.lowVal); 484 writeln("hdr.ckSrcOverlay.highVal: ", hdr.ckSrcOverlay.highVal); 485 writeln("hdr.ckSrcBlt.lowVal: ", hdr.ckSrcBlt.lowVal); 486 writeln("hdr.ckSrcBlt.highVal: ", hdr.ckSrcBlt.highVal); 487 488 writeln("hdr.format.size: ", hdr.format.size); 489 writeln("hdr.format.flags: ", hdr.format.flags); 490 writeln("hdr.format.fourCC: ", hdr.format.fourCC); 491 writeln("hdr.format.bpp: ", hdr.format.bpp); 492 writeln("hdr.format.redMask: ", hdr.format.redMask); 493 writeln("hdr.format.greenMask: ", hdr.format.greenMask); 494 writeln("hdr.format.blueMask: ", hdr.format.blueMask); 495 writeln("hdr.format.alphaMask: ", hdr.format.alphaMask); 496 497 writeln("hdr.caps: ", hdr.caps); 498 writeln("hdr.caps2: ", hdr.caps2); 499 writeln("hdr.caps3: ", hdr.caps3); 500 writeln("hdr.caps4: ", hdr.caps4); 501 502 writeln("hdr.textureStage: ", hdr.textureStage); 503 } 504 505 TextureFormat format; 506 507 DXGIFormat fmt; 508 if (hdr.format.flags & DDPF.FOURCC) 509 { 510 if (hdr.format.fourCC == FOURCC_DX10) 511 { 512 DDSHeaderDXT10 dx10 = readStruct!DDSHeaderDXT10(istrm); 513 fmt = cast(DXGIFormat)dx10.dxgiFormat; 514 } 515 else 516 { 517 fmt = resourceFormatFromFourCC(hdr.format.fourCC); 518 } 519 } 520 else if (hdr.flags & DDSHeaderFlags.VOLUME) 521 { 522 if (hdr.format.bpp == 32) 523 fmt = DXGIFormat.R8G8B8A8_UNORM; 524 else if (hdr.format.bpp == 16) 525 fmt = DXGIFormat.R8G8_UNORM; 526 else if (hdr.format.bpp == 8) 527 fmt = DXGIFormat.R8_UNORM; 528 } 529 530 version(DDSDebug) writeln("format: ", fmt); 531 532 switch(fmt) 533 { 534 case DXGIFormat.R8_UNORM: 535 format.format = GL_RED; 536 format.internalFormat = GL_R8; 537 format.pixelType = GL_UNSIGNED_BYTE; 538 break; 539 case DXGIFormat.R8G8_UNORM: 540 format.format = GL_RG; 541 format.internalFormat = GL_RG8; 542 format.pixelType = GL_UNSIGNED_BYTE; 543 break; 544 case DXGIFormat.R8G8B8A8_UNORM: 545 format.format = GL_RGBA; 546 format.internalFormat = GL_RGBA8; 547 format.pixelType = GL_UNSIGNED_BYTE; 548 break; 549 case DXGIFormat.R32G32B32A32_FLOAT: 550 format.format = GL_RGBA; 551 format.internalFormat = GL_RGBA32F; 552 format.pixelType = GL_FLOAT; 553 break; 554 case DXGIFormat.R16G16B16A16_FLOAT: 555 format.format = GL_RGBA; 556 format.internalFormat = GL_RGBA16F; 557 format.pixelType = GL_HALF_FLOAT; 558 break; 559 case DXGIFormat.BC1_UNORM: 560 format.internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; 561 format.blockSize = 8; 562 break; 563 case DXGIFormat.BC2_UNORM: 564 format.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; 565 format.blockSize = 16; 566 break; 567 case DXGIFormat.BC3_UNORM: 568 format.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; 569 format.blockSize = 16; 570 break; 571 case DXGIFormat.BC4_UNORM: 572 format.internalFormat = GL_COMPRESSED_RED_RGTC1; 573 format.blockSize = 16; 574 break; 575 case DXGIFormat.BC4_SNORM: 576 format.internalFormat = GL_COMPRESSED_SIGNED_RED_RGTC1; 577 format.blockSize = 16; 578 break; 579 case DXGIFormat.BC5_UNORM: 580 format.internalFormat = GL_COMPRESSED_RG_RGTC2; 581 format.blockSize = 16; 582 break; 583 case DXGIFormat.BC5_SNORM: 584 format.internalFormat = GL_COMPRESSED_SIGNED_RG_RGTC2; 585 format.blockSize = 16; 586 break; 587 case DXGIFormat.BC6H_SF16: 588 format.internalFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB; 589 format.blockSize = 16; 590 break; 591 case DXGIFormat.BC6H_UF16: 592 format.internalFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB; 593 format.blockSize = 16; 594 break; 595 case DXGIFormat.BC7_UNORM: 596 format.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; 597 format.blockSize = 16; 598 break; 599 case DXGIFormat.BC7_UNORM_SRGB: 600 format.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB; 601 format.blockSize = 16; 602 break; 603 case DXGIFormat.ASTC_4X4_UNORM: 604 format.internalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; 605 format.blockSize = 16; 606 break; 607 case DXGIFormat.ASTC_4X4_UNORM_SRGB: 608 format.internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR; 609 format.blockSize = 16; 610 break; 611 // TODO: other ASTC formats 612 default: 613 return error("loadDDS error: unsupported resource format"); 614 } 615 616 bool hasMipmaps = cast(bool)(hdr.flags & DDSHeaderFlags.MIPMAPS); 617 618 bool isComplex = cast(bool)(hdr.caps & DDSCaps.COMPLEX); 619 bool isVolume = cast(bool)(hdr.caps2 & DDSCaps2.VOLUME); 620 621 bool isCubemap = false; 622 if (hdr.caps2 & DDSCaps2.CUBEMAP) 623 { 624 if (hdr.caps2 & DDSCaps2.CUBEMAP_ALLFACES) 625 isCubemap = true; 626 else 627 return error("loadDDS error: incomplete cubemap"); 628 } 629 630 version(DDSDebug) writeln("hasMipmaps: ", hasMipmaps); 631 version(DDSDebug) writeln("isComplex: ", isComplex); 632 version(DDSDebug) writeln("isVolume: ", isVolume); 633 version(DDSDebug) writeln("isCubemap: ", isCubemap); 634 635 size_t bufferSize = cast(size_t)(istrm.size - istrm.getPosition); 636 version(DDSDebug) writeln("bufferSize: ", bufferSize); 637 638 buffer.data = New!(ubyte[])(bufferSize); 639 istrm.readBytes(buffer.data.ptr, bufferSize); 640 641 TextureSize size; 642 size.width = hdr.width; 643 size.height = hdr.height; 644 645 if (isVolume) 646 size.depth = hdr.depth; 647 else 648 size.depth = 0; 649 650 if (isCubemap) 651 { 652 format.target = GL_TEXTURE_CUBE_MAP; 653 format.cubeFaces = CubeFaceBit.All; 654 } 655 else if (isVolume) 656 { 657 format.target = GL_TEXTURE_3D; 658 } 659 else 660 { 661 format.target = GL_TEXTURE_2D; 662 } 663 664 buffer.format = format; 665 buffer.size = size; 666 667 if (hasMipmaps) 668 buffer.mipLevels = hdr.mipMapLevels; 669 else 670 buffer.mipLevels = 1; 671 672 return true; 673 }