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 }