1 /********************************************************************************
2 * *
3 * D D S I n p u t / O u t p u t *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1998,2021 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/> *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "FXArray.h"
26 #include "FXHash.h"
27 #include "FXhalf.h"
28 #include "FXElement.h"
29 #include "FXStream.h"
30
31 /*
32 Notes:
33 - For cubic environment maps, one or more faces of a cube are written to the file, using either uncompressed or
34 compressed formats, and all faces must be the same size. Each face can have mipmaps defined, although all faces
35 must have the same number of mipmap levels. If a file contains a cube map, DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP,
36 and one or more of DSCAPS2_CUBEMAP_POSITIVEX/Y/Z and/or DDSCAPS2_CUBEMAP_NEGATIVEX/Y/Z should be set.
37 The faces are written in the order: positive x, negative x, positive y, negative y, positive z, negative z,
38 with any missing faces omitted. Each face is written with its main image, followed by any mipmap levels.
39 - For a volume texture, use the DDSCAPS_COMPLEX, DDSCAPS2_VOLUME, DDSD_DEPTH, flags and set and dwDepth.
40 A volume texture is an extension of a standard texture for Direct3D 9; a volume texture is can be defined with
41 or without mipmaps. For volumes without mipmaps, each depth slice is written to the file in order.
42 If mipmaps are included, all depth slices for a given mipmap level are written together, with each level
43 containing half as many slices as the previous level with a minimum of 1.
44 - Volume textures do not support compression in Direct3D 9.
45 - For an uncompressed texture, use the DDSD_PITCH and DDPF_RGB flags; for a compressed texture,
46 use the DDSD_LINEARSIZE and DDPF_FOURCC flags.
47 - For a mipmapped texture, use the DDSD_MIPMAPCOUNT, DDSCAPS_MIPMAP, and DDSCAPS_COMPLEX flags also as
48 well as the mipmap count member. If mipmaps are generated, all levels down to 1-by-1 are usually written.
49 */
50
51
52
53 // Magic file header constant
54 #define DDSD_MAGIC 0x20534444
55
56 // DDSHeader flags
57 #define DDSD_CAPS 0x00000001
58 #define DDSD_HEIGHT 0x00000002
59 #define DDSD_WIDTH 0x00000004
60 #define DDSD_PITCH 0x00000008
61 #define DDSD_PIXELFORMAT 0x00001000
62 #define DDSD_MIPMAPCOUNT 0x00020000
63 #define DDSD_LINEARSIZE 0x00080000
64 #define DDSD_DEPTH 0x00800000
65
66 // DDSPixelFormat flags
67 #define DDPF_ALPHAPIXELS 0x00000001
68 #define DDPF_ALPHA 0x00000002
69 #define DDPF_FOURCC 0x00000004
70 #define DDPF_PALETTEINDEXED4 0x00000008
71 #define DDPF_PALETTEINDEXED8 0x00000020
72 #define DDPF_RGB 0x00000040
73 #define DDPF_COMPRESSED 0x00000080
74 #define DDPF_RGBTOYUV 0x00000100
75 #define DDPF_YUV 0x00000200
76 #define DDPF_ZBUFFER 0x00000400
77 #define DDPF_PALETTEINDEXED1 0x00000800
78 #define DDPF_PALETTEINDEXED2 0x00001000
79 #define DDPF_ZPIXELS 0x00002000
80 #define DDPF_STENCILBUFFER 0x00004000
81 #define DDPF_ALPHAPREMULT 0x00008000
82 #define DDPF_LUMINANCE 0x00020000
83 #define DDPF_BUMPLUMINANCE 0x00040000
84 #define DDPF_NORMAL 0x80000000
85
86 // DDSHeader CAPS field
87 #define DDSCAPS_COMPLEX 0x00000008
88 #define DDSCAPS_TEXTURE 0x00001000
89 #define DDSCAPS_MIPMAP 0x00400000
90
91 // DDSHeader CAPS2 field
92 #define DDSCAPS2_CUBEMAP 0x00000200
93 #define DDSCAPS2_VOLUME 0x00200000
94
95 // DDSHeader Cube maps
96 #define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
97 #define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
98 #define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
99 #define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
100 #define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
101 #define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
102
103
104 // DDSPixelFormat FOURCC constants (Compressed texture formats)
105 #define D3DFMT_DXT1 0x31545844 // DXT1
106 #define D3DFMT_DXT2 0x32545844 // DXT2
107 #define D3DFMT_DXT3 0x33545844 // DXT3
108 #define D3DFMT_DXT4 0x34545844 // DXT4
109 #define D3DFMT_DXT5 0x35545844 // DXT5
110
111 // DDSPixelFormat FOURCC constants (Nonstandard formats)
112 #define D3DFMT_DX10 0x30315844 // DX10
113 #define D3DFMT_RXGB 0x42475852 // RXGB (AKA DOOM III)
114 #define D3DFMT_ATI1 0x31495441 // ATI1
115 #define D3DFMT_ATI2 0x32495441 // ATI2 (AKA 3Dc)
116 #define D3DFMT_A2XY 0x59583241 // A2XY
117 #define D3DFMT_UYVY 0x59565955 // UYVY format
118 #define D3DFMT_YUY2 0x32595559 // YUY2 format
119 #define D3DFMT_R8G8_B8G8 0x47424752 // Pairs of pixels, [RG][BG] consecutive pixels share R and G (G0R0,G1B0, G2R2,G3B2) etc.
120 #define D3DFMT_G8R8_G8B8 0x42475247 // Pairs of pixels, [GR][GB] consecutive pixels share R and B (R0G0,B0G1, R2G2,B2G3) etc.
121
122 // DDSPixelFormat FOURCC constants (Floating point)
123 #define D3DFMT_R16F 111 // 16-bit float format using 16 bits for the red channel.
124 #define D3DFMT_G16R16F 112 // 32-bit float format using 16 bits for the red channel and 16 bits for the green channel.
125 #define D3DFMT_A16B16G16R16F 113 // 64-bit float format using 16 bits for the each channel (alpha, blue, green, red).
126 #define D3DFMT_R32F 114 // 32-bit float format using 32 bits for the red channel.
127 #define D3DFMT_G32R32F 115 // 64-bit float format using 32 bits for the red channel and 32 bits for the green channel.
128 #define D3DFMT_A32B32G32R32F 116 // 128-bit float format using 32 bits for the each channel (alpha, blue, green, red).
129
130 // DDSPixelFormat FOURCC constants (Signed integer formats)
131 #define D3DFMT_V8U8 60 // 16-bit bump-map format using 8 bits each for u and v data.
132 #define D3DFMT_L6V5U5 61 // 16-bit bump-map format with luminance using 6 bits for luminance, and 5 bits each for v and u.
133 #define D3DFMT_X8L8V8U8 62 // 32-bit bump-map format with luminance using 8 bits for each channel.
134 #define D3DFMT_Q8W8V8U8 63 // 32-bit bump-map format using 8 bits for each channel.
135 #define D3DFMT_V16U16 64 // 32-bit bump-map format using 16 bits for each channel.
136 #define D3DFMT_A2W10V10U10 67 // 32-bit bump-map format using 2 bits for alpha and 10 bits each for w, v, and u.
137 #define D3DFMT_Q16W16V16U16 110 // 64-bit bump-map format using 16 bits for each component.
138 #define D3DFMT_CxV8U8 117 // 16-bit normal compression format. The texture sampler computes the C channel from: C = sqrt(1 - U2 - V2).
139
140 // DDSPixelFormat FOURCC constants (Unsigned integer formats)
141 #define D3DFMT_R8G8B8 20 // 24-bit RGB pixel format with 8 bits per channel.
142 #define D3DFMT_A8R8G8B8 21 // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
143 #define D3DFMT_X8R8G8B8 22 // 32-bit RGB pixel format, where 8 bits are reserved for each color.
144 #define D3DFMT_R5G6B5 23 // 16-bit RGB pixel format with 5 bits for red, 6 bits for green, and 5 bits for blue.
145 #define D3DFMT_X1R5G5B5 24 // 16-bit pixel format where 5 bits are reserved for each color.
146 #define D3DFMT_A1R5G5B5 25 // 16-bit pixel format where 5 bits are reserved for each color and 1 bit is reserved for alpha.
147 #define D3DFMT_A4R4G4B4 26 // 16-bit ARGB pixel format with 4 bits for each channel.
148 #define D3DFMT_R3G3B2 27 // 8-bit RGB texture format using 3 bits for red, 3 bits for green, and 2 bits for blue.
149 #define D3DFMT_A8 28 // 8-bit alpha only.
150 #define D3DFMT_A8R3G3B2 29 // 16-bit ARGB texture format using 8 bits for alpha, 3 bits each for red and green, and 2 bits for blue.
151 #define D3DFMT_X4R4G4B4 30 // 16-bit RGB pixel format using 4 bits for each color.
152 #define D3DFMT_A2B10G10R10 31 // 32-bit pixel format using 10 bits for each color and 2 bits for alpha.
153 #define D3DFMT_A8B8G8R8 32 // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
154 #define D3DFMT_X8B8G8R8 33 // 32-bit RGB pixel format, where 8 bits are reserved for each color.
155 #define D3DFMT_G16R16 34 // 32-bit pixel format using 16 bits each for green and red.
156 #define D3DFMT_A2R10G10B10 35 // 32-bit pixel format using 10 bits each for red, green, and blue, and 2 bits for alpha.
157 #define D3DFMT_A16B16G16R16 36 // 64-bit pixel format using 16 bits for each component.
158 #define D3DFMT_A8P8 40 // 8-bit color indexed with 8 bits of alpha.
159 #define D3DFMT_P8 41 // 8-bit color indexed.
160 #define D3DFMT_L8 50 // 8-bit luminance only.
161 #define D3DFMT_A8L8 51 // 16-bit using 8 bits each for alpha and luminance.
162 #define D3DFMT_A4L4 52 // 8-bit using 4 bits each for alpha and luminance.
163 #define D3DFMT_L16 81 // 16-bit luminance only.
164 #define D3DFMT_A1 118 // 1-bit monochrome.
165 #define D3DFMT_A2B10G10R10_XR_BIAS 119 // 2.8-biased fixed point.
166 #define D3DFMT_BINARYBUFFER 199 // Binary format indicating that the data has no inherent type.
167
168 // DDSPixelFormat FOURCC constants (Buffer formats)
169 #define D3DFMT_D16_LOCKABLE 70 // 16-bit z-buffer bit depth.
170 #define D3DFMT_D32 71 // 32-bit z-buffer bit depth.
171 #define D3DFMT_D15S1 73 // 16-bit z-buffer bit depth where 15 bits are reserved for the depth channel and 1 bit is reserved for the stencil channel.
172 #define D3DFMT_D24S8 75 // 32-bit z-buffer bit depth using 24 bits for the depth channel and 8 bits for the stencil channel.
173 #define D3DFMT_D24X8 77 // 32-bit z-buffer bit depth using 24 bits for the depth channel.
174 #define D3DFMT_D24X4S4 79 // 32-bit z-buffer bit depth using 24 bits for the depth channel and 4 bits for the stencil channel.
175 #define D3DFMT_D16 80 // 16-bit z-buffer bit depth.
176 #define D3DFMT_D32F_LOCKABLE 82 // A lockable format where the depth value is represented as a standard IEEE floating-point number.
177 #define D3DFMT_D24FS8 83 // A non-lockable format that contains 24 bits of depth (in a 24-bit floating point format - 20e4) and 8 bits of stencil.
178 #define D3DFMT_D32_LOCKABLE 84 // A lockable 32-bit depth buffer.
179 #define D3DFMT_S8_LOCKABLE 85 // A lockable 8-bit stencil buffer.
180 #define D3DFMT_VERTEXDATA 100 // Describes a vertex buffer surface.
181 #define D3DFMT_INDEX16 101 // 16-bit index buffer bit depth.
182 #define D3DFMT_INDEX32 102 // 32-bit index buffer bit depth.
183
184 // DDSXHeader Resource dimension
185 #define D3D10_RESOURCE_DIMENSION_UNKNOWN 0 // Resource is of unknown type.
186 #define D3D10_RESOURCE_DIMENSION_BUFFER 1 // Resource is a buffer.
187 #define D3D10_RESOURCE_DIMENSION_TEXTURE1D 2 // Resource is a 1D texture.
188 #define D3D10_RESOURCE_DIMENSION_TEXTURE2D 3 // Resource is a 2D texture.
189 #define D3D10_RESOURCE_DIMENSION_TEXTURE3D 4 // Resource is a 3D texture.
190
191 // DDSXHeader Miscellaneous flag
192 #define D3D10_RESOURCE_MISC_GENERATE_MIPS 0x1 // Enable mipmap generation
193 #define D3D10_RESOURCE_MISC_SHARED 0x2 // Enable share
194 #define D3D10_RESOURCE_MISC_TEXTURECUBE 0x4 // Enable cube map
195 #define D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX 0x10
196 #define D3D10_RESOURCE_MISC_GDI_COMPATIBLE 0x20
197
198 // DDSXHeader Formats
199 #define DXGI_FORMAT_UNKNOWN 0 // The format is not known.
200
201 #define DXGI_FORMAT_R32G32B32A32_TYPELESS 1 // A four-component, 128-bit typeless format.
202 #define DXGI_FORMAT_R32G32B32A32_FLOAT 2 // A four-component, 128-bit floating-point format
203 #define DXGI_FORMAT_R32G32B32A32_UINT 3 // A four-component, 128-bit unsigned-integer format
204 #define DXGI_FORMAT_R32G32B32A32_SINT 4 // A four-component, 128-bit signed-integer format.
205
206 #define DXGI_FORMAT_R32G32B32_TYPELESS 5 // A three-component, 96-bit typeless format.
207 #define DXGI_FORMAT_R32G32B32_FLOAT 6 // A three-component, 96-bit floating-point format.
208 #define DXGI_FORMAT_R32G32B32_UINT 7 // A three-component, 96-bit unsigned-integer format.
209 #define DXGI_FORMAT_R32G32B32_SINT 8 // A three-component, 96-bit signed-integer format.
210
211 #define DXGI_FORMAT_R16G16B16A16_TYPELESS 9 // A four-component, 64-bit typeless format.
212 #define DXGI_FORMAT_R16G16B16A16_FLOAT 10 // A four-component, 64-bit floating-point format.
213 #define DXGI_FORMAT_R16G16B16A16_UNORM 11 // A four-component, 64-bit unsigned-integer format.
214 #define DXGI_FORMAT_R16G16B16A16_UINT 12 // A four-component, 64-bit unsigned-integer format.
215 #define DXGI_FORMAT_R16G16B16A16_SNORM 13 // A four-component, 64-bit signed-integer format.
216 #define DXGI_FORMAT_R16G16B16A16_SINT 14 // A four-component, 64-bit signed-integer format.
217
218 #define DXGI_FORMAT_R32G32_TYPELESS 15 // A two-component, 64-bit typeless format.
219 #define DXGI_FORMAT_R32G32_FLOAT 16 // A two-component, 64-bit floating-point format.
220 #define DXGI_FORMAT_R32G32_UINT 17 // A two-component, 64-bit unsigned-integer format.
221 #define DXGI_FORMAT_R32G32_SINT 18 // A two-component, 64-bit signed-integer format.
222
223 #define DXGI_FORMAT_R32G8X24_TYPELESS 19 // A two-component, 64-bit typeless format.
224 #define DXGI_FORMAT_D32_FLOAT_S8X24_UINT 20 // A 32-bit floating-point component, and two unsigned-integer components (with an additional 32 bits).
225 #define DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS 21 // A 32-bit floating-point component, and two typeless components (with an additional 32 bits).
226 #define DXGI_FORMAT_X32_TYPELESS_G8X24_UINT 22 // A 32-bit typeless component, and two unsigned-integer components (with an additional 32 bits).
227
228 #define DXGI_FORMAT_R10G10B10A2_TYPELESS 23 // A four-component, 32-bit typeless format.
229 #define DXGI_FORMAT_R10G10B10A2_UNORM 24 // A four-component, 32-bit unsigned-integer format.
230 #define DXGI_FORMAT_R10G10B10A2_UINT 25 // A four-component, 32-bit unsigned-integer format.
231
232 #define DXGI_FORMAT_R11G11B10_FLOAT 26 // A three-component, 32-bit floating-point format.
233
234 #define DXGI_FORMAT_R8G8B8A8_TYPELESS 27 // A three-component, 32-bit typeless format.
235 #define DXGI_FORMAT_R8G8B8A8_UNORM 28 // A four-component, 32-bit unsigned-integer format.
236 #define DXGI_FORMAT_R8G8B8A8_UNORM_SRGB 29 // A four-component, 32-bit unsigned-normalized integer sRGB format.
237 #define DXGI_FORMAT_R8G8B8A8_UINT 30 // A four-component, 32-bit unsigned-integer format.
238 #define DXGI_FORMAT_R8G8B8A8_SNORM 31 // A three-component, 32-bit signed-integer format.
239 #define DXGI_FORMAT_R8G8B8A8_SINT 32 // A three-component, 32-bit signed-integer format.
240
241 #define DXGI_FORMAT_R16G16_TYPELESS 33 // A two-component, 32-bit typeless format.
242 #define DXGI_FORMAT_R16G16_FLOAT 34 // A two-component, 32-bit floating-point format.
243 #define DXGI_FORMAT_R16G16_UNORM 35 // A two-component, 32-bit unsigned-integer format.
244 #define DXGI_FORMAT_R16G16_UINT 36 // A two-component, 32-bit unsigned-integer format.
245 #define DXGI_FORMAT_R16G16_SNORM 37 // A two-component, 32-bit signed-integer format.
246 #define DXGI_FORMAT_R16G16_SINT 38 // A two-component, 32-bit signed-integer format.
247
248 #define DXGI_FORMAT_R32_TYPELESS 39 // A single-component, 32-bit typeless format.
249 #define DXGI_FORMAT_D32_FLOAT 40 // A single-component, 32-bit floating-point format.
250 #define DXGI_FORMAT_R32_FLOAT 41 // A single-component, 32-bit floating-point format.
251 #define DXGI_FORMAT_R32_UINT 42 // A single-component, 32-bit unsigned-integer format.
252 #define DXGI_FORMAT_R32_SINT 43 // A single-component, 32-bit signed-integer format.
253
254 #define DXGI_FORMAT_R24G8_TYPELESS 44 // A two-component, 32-bit typeless format.
255 #define DXGI_FORMAT_D24_UNORM_S8_UINT 45 // A 32-bit z-buffer format that uses 24 bits for the depth channel and 8 bits for the stencil channel.
256 #define DXGI_FORMAT_R24_UNORM_X8_TYPELESS 46 // A 32-bit format, that contains a 24 bit, single-component, unsigned-normalized integer, with an additional typeless 8 bits.
257 #define DXGI_FORMAT_X24_TYPELESS_G8_UINT 47 // A 32-bit format, that contains a 24 bit, single-component, typeless format, with an additional 8 bit unsigned integer component.
258
259 #define DXGI_FORMAT_R8G8_TYPELESS 48 // A two-component, 16-bit typeless format.
260 #define DXGI_FORMAT_R8G8_UNORM 49 // A two-component, 16-bit unsigned-integer format.
261 #define DXGI_FORMAT_R8G8_UINT 50 // A two-component, 16-bit unsigned-integer format.
262 #define DXGI_FORMAT_R8G8_SNORM 51 // A two-component, 16-bit signed-integer format.
263 #define DXGI_FORMAT_R8G8_SINT 52 // A two-component, 16-bit signed-integer format.
264
265 #define DXGI_FORMAT_R16_TYPELESS 53 // A single-component, 16-bit typeless format.
266 #define DXGI_FORMAT_R16_FLOAT 54 // A single-component, 16-bit floating-point format.
267 #define DXGI_FORMAT_D16_UNORM 55 // A single-component, 16-bit unsigned-normalized integer format.
268 #define DXGI_FORMAT_R16_UNORM 56 // A single-component, 16-bit unsigned-integer format.
269 #define DXGI_FORMAT_R16_UINT 57 // A single-component, 16-bit unsigned-integer format.
270 #define DXGI_FORMAT_R16_SNORM 58 // A single-component, 16-bit signed-integer format.
271 #define DXGI_FORMAT_R16_SINT 59 // A single-component, 16-bit signed-integer format.
272
273 #define DXGI_FORMAT_R8_TYPELESS 60 // A single-component, 8-bit typeless format.
274 #define DXGI_FORMAT_R8_UNORM 61 // A single-component, 8-bit unsigned-integer format.
275 #define DXGI_FORMAT_R8_UINT 62 // A single-component, 8-bit unsigned-integer format.
276 #define DXGI_FORMAT_R8_SNORM 63 // A single-component, 8-bit signed-integer format.
277 #define DXGI_FORMAT_R8_SINT 64 // A single-component, 8-bit signed-integer format.
278 #define DXGI_FORMAT_A8_UNORM 65 // A single-component, 8-bit unsigned-integer format.
279
280 #define DXGI_FORMAT_R1_UNORM 66 // A single-component, 1-bit unsigned-normalized integer format.
281
282 #define DXGI_FORMAT_R9G9B9E5_SHAREDEXP 67 // A four-component, 32-bit floating-point format.
283
284 #define DXGI_FORMAT_R8G8_B8G8_UNORM 68 // A four-component, 32-bit unsigned-normalized integer format.
285 #define DXGI_FORMAT_G8R8_G8B8_UNORM 69 // A four-component, 32-bit unsigned-normalized integer format.
286
287 #define DXGI_FORMAT_BC1_TYPELESS 70 // 4-channel typeless block-compression format.
288 #define DXGI_FORMAT_BC1_UNORM 71 // 4-channel block-compression format.
289 #define DXGI_FORMAT_BC1_UNORM_SRGB 72 // 4-channel block-compression format for sRGB data.
290
291 #define DXGI_FORMAT_BC2_TYPELESS 73 // 4-channel typeless block-compression format.
292 #define DXGI_FORMAT_BC2_UNORM 74 // 4-channel block-compression format.
293 #define DXGI_FORMAT_BC2_UNORM_SRGB 75 // 4-channel block-compression format for sRGB data.
294
295 #define DXGI_FORMAT_BC3_TYPELESS 76 // 4-channel typeless block-compression format.
296 #define DXGI_FORMAT_BC3_UNORM 77 // 4-channel block-compression format.
297 #define DXGI_FORMAT_BC3_UNORM_SRGB 78 // 4-channel block-compression format for sRGB data.
298
299 #define DXGI_FORMAT_BC4_TYPELESS 79 // 1-channel typeless block-compression format.
300 #define DXGI_FORMAT_BC4_UNORM 80 // 1-channel block-compression format.
301 #define DXGI_FORMAT_BC4_SNORM 81 // 1-channel block-compression format.
302
303 #define DXGI_FORMAT_BC5_TYPELESS 82 // 2-channel typeless block-compression format.
304 #define DXGI_FORMAT_BC5_UNORM 83 // 2-channel block-compression format.
305 #define DXGI_FORMAT_BC5_SNORM 84 // 2-channel block-compression format.
306
307 #define DXGI_FORMAT_B5G6R5_UNORM 85 // A three-component, 16-bit unsigned-normalized integer format.
308 #define DXGI_FORMAT_B5G5R5A1_UNORM 86 // A four-component, 16-bit unsigned-normalized integer format that supports 1-bit alpha.
309 #define DXGI_FORMAT_B8G8R8A8_UNORM 87 // A four-component, 16-bit unsigned-normalized integer format that supports 8-bit alpha.
310 #define DXGI_FORMAT_B8G8R8X8_UNORM 88 // A four-component, 16-bit unsigned-normalized integer format.
311 #define DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM 89 // A four-component, 32-bit format that supports 2-bit alpha.
312 #define DXGI_FORMAT_B8G8R8A8_TYPELESS 90 // A four-component, 32-bit typeless format that supports 8-bit alpha.
313 #define DXGI_FORMAT_B8G8R8A8_UNORM_SRGB 91 // A four-component, 32-bit unsigned-normalized standard RGB format that supports 8-bit alpha.
314 #define DXGI_FORMAT_B8G8R8X8_TYPELESS 92 // A four-component, 32-bit typeless format.
315 #define DXGI_FORMAT_B8G8R8X8_UNORM_SRGB 93 // A four-component, 32-bit unsigned-normalized standard RGB format.
316 #define DXGI_FORMAT_BC6H_TYPELESS 94 // A typeless block-compression format
317 #define DXGI_FORMAT_BC6H_UF16 95 // A block-compression format.
318 #define DXGI_FORMAT_BC6H_SF16 96 // A block-compression format.
319 #define DXGI_FORMAT_BC7_TYPELESS 97 // A typeless block-compression format.
320 #define DXGI_FORMAT_BC7_UNORM 98 // A block-compression format.
321 #define DXGI_FORMAT_BC7_UNORM_SRGB 99 // A block-compression format.
322
323 #define DXGI_FORMAT_AYUV 100 // Most common YUV 4:4:4 video resource format
324 #define DXGI_FORMAT_Y410 101 // 10-bit per channel packed YUV 4:4:4 video resource format
325 #define DXGI_FORMAT_Y416 102 // 16-bit per channel packed YUV 4:4:4 video resource format
326 #define DXGI_FORMAT_NV12 103 // Most common YUV 4:2:0 video resource format
327 #define DXGI_FORMAT_P010 104 // 10-bit per channel planar YUV 4:2:0 video resource format
328 #define DXGI_FORMAT_P016 105 // 16-bit per channel planar YUV 4:2:0 video resource format
329 #define DXGI_FORMAT_420_OPAQUE 106 // 8-bit per channel planar YUV 4:2:0 video resource format
330 #define DXGI_FORMAT_YUY2 107 // Most common YUV 4:2:2 video resource format
331 #define DXGI_FORMAT_Y210 108 // 10-bit per channel packed YUV 4:2:2 video resource format
332 #define DXGI_FORMAT_Y216 109 // 16-bit per channel packed YUV 4:2:2 video resource format.
333 #define DXGI_FORMAT_NV11 110 // Most common planar YUV 4:1:1 video resource format
334 #define DXGI_FORMAT_AI44 111 // 4-bit palletized YUV format that is commonly used for DVD subpicture
335 #define DXGI_FORMAT_IA44 112 // 4-bit palletized YUV format that is commonly used for DVD subpicture
336 #define DXGI_FORMAT_P8 113 // 88-bit palletized format that is used for palletized RGB data when the processor processes ISDB-T data and for palletized YUV data when the processor processes BluRay data
337 #define DXGI_FORMAT_A8P8 114 // 8-bit palletized format with 8 bits of alpha that is used for palletized YUV data when the processor processes BluRay data
338 #define DXGI_FORMAT_B4G4R4A4_UNORM 115 // A four-component, 16-bit unsigned-normalized integer format that supports 4 bits for each channel including alpha
339
340
341 // Internal codes
342 #define CODE_NONE 0
343 #define CODE_DXT1 1
344 #define CODE_DXT2 2
345 #define CODE_DXT3 3
346 #define CODE_DXT4 4
347 #define CODE_DXT5 5
348
349 using namespace FX;
350
351 /*******************************************************************************/
352
353 namespace FX {
354
355 #ifndef FXLOADDDS
356 extern FXAPI FXbool fxcheckDDS(FXStream& store);
357 extern FXAPI FXbool fxloadDDS(FXStream& store,FXColor*& data,FXint& width,FXint& height,FXint& depth);
358 extern FXAPI FXbool fxsaveDDS(FXStream& store,FXColor* data,FXint width,FXint height,FXint depth);
359 #endif
360
361
362 // Pixel format
363 struct DDSPixelFormat {
364 FXuint dwSize;
365 FXuint dwFlags;
366 FXuint dwFourCC;
367 FXuint dwRGBBitCount;
368 FXuint dwRBitMask;
369 FXuint dwGBitMask;
370 FXuint dwBBitMask;
371 FXuint dwABitMask;
372 };
373
374
375 // DDS Header
376 struct DDSHeader {
377 FXuint dwSize;
378 FXuint dwFlags;
379 FXuint dwHeight;
380 FXuint dwWidth;
381 FXuint dwLinearSize;
382 FXuint dwDepth;
383 FXuint dwMipMapCount;
384 FXuint dwReserved1[11];
385 DDSPixelFormat ddpf;
386 FXuint dwCaps;
387 FXuint dwCaps2;
388 FXuint dwCaps3;
389 FXuint dwCaps4;
390 FXuint dwReserved2;
391 };
392
393
394 // DX10 extra header structure
395 struct DDSXHeader {
396 FXuint dxgiFormat;
397 FXuint resourceDimension;
398 FXuint miscFlag;
399 FXuint arraySize;
400 FXuint reserved;
401 };
402
403
404 // DDS Image
405 struct DDSImage {
406 FXuint magic;
407 DDSHeader header;
408 DDSXHeader xheader;
409 FXuint size;
410 FXuchar *data;
411 };
412
413
414 // Fast integer square root
isqrt(FXuint val)415 static FXuint isqrt(FXuint val){
416 FXuint temp,g=0,b=0x8000,bshft=15;
417 do{if(val>=(temp=(((g<<1)+b)<<bshft--))){g+=b;val-=temp;}}while(b>>=1);
418 return g;
419 }
420
421
422 // Undo premultiplied alpha
423 // The math: 255*X = (255*R * 255*A)/255, so 255*R = 255*X*255 / 255*A
dds_correct_color(FXuchar * image,FXuint size)424 static void dds_correct_color(FXuchar *image,FXuint size){
425 FXuint i,a;
426 for(i=0; i<size; i+=4){
427 if((a=image[i+3])>0){
428 image[i+0]=(image[i+0]*255)/a;
429 image[i+1]=(image[i+1]*255)/a;
430 image[i+2]=(image[i+2]*255)/a;
431 }
432 }
433 }
434
435
436 // Swizzle red and alpha for RXGB
dds_correct_swizzle(FXuchar * image,FXuint size)437 static void dds_correct_swizzle(FXuchar *image,FXuint size){
438 FXuint i;
439 for(i=0; i<size; i+=4){
440 image[i+2]^=image[i+3];
441 image[i+3]^=image[i+2];
442 image[i+2]^=image[i+3];
443 }
444 }
445
446
447 // Decompress DXT1/BC1 image
dds_decompress_DXT1(const DDSImage & dds,FXuchar * image)448 static FXbool dds_decompress_DXT1(const DDSImage& dds,FXuchar *image){
449 const FXuchar *temp=dds.data;
450 FXuint x,y,z,i,j,select,bitmask,offset;
451 FXuchar r0,g0,b0,r1,g1,b1;
452 FXushort c0,c1;
453 FXuchar colors[4][4];
454
455 FXTRACE((100,"dds_decompress_DXT1\n"));
456
457 // Loop over 4x4 blocks
458 for(z=0; z<dds.header.dwDepth; z+=1){
459 for(y=0; y<dds.header.dwHeight; y+=4){
460 for(x=0; x<dds.header.dwWidth; x+=4){
461
462 // Grab two 5,6,5 colors
463 c0=(((FXushort)temp[1])<<8) | (FXushort)temp[0];
464 c1=(((FXushort)temp[3])<<8) | (FXushort)temp[2];
465
466 r0=(c0>>11)&0x1f;
467 g0=(c0>>5)&0x3f;
468 b0=c0&0x1f;
469
470 r1=(c1>>11)&0x1f;
471 g1=(c1>>5)&0x3f;
472 b1=c1&0x1f;
473
474 colors[0][0]=(b0<<3)|(b0>>2); // Convert from 5,6,5 to 8,8,8 color #0
475 colors[0][1]=(g0<<2)|(g0>>4);
476 colors[0][2]=(r0<<3)|(r0>>2);
477 colors[0][3]=0xFF;
478
479 colors[1][0]=(b1<<3)|(b1>>2); // Convert from 5,6,5 to 8,8,8 color #1
480 colors[1][1]=(g1<<2)|(g1>>4);
481 colors[1][2]=(r1<<3)|(r1>>2);
482 colors[1][3]=0xFF;
483
484 // Four color block: 00=color #0, 01=color #1, 10=color #2, 11=color #3
485 if(c0>c1){
486 colors[2][0]=(2*colors[0][0]+colors[1][0]+1)/3;
487 colors[2][1]=(2*colors[0][1]+colors[1][1]+1)/3;
488 colors[2][2]=(2*colors[0][2]+colors[1][2]+1)/3;
489 colors[2][3]=255;
490 colors[3][0]=(colors[0][0]+2*colors[1][0]+1)/3;
491 colors[3][1]=(colors[0][1]+2*colors[1][1]+1)/3;
492 colors[3][2]=(colors[0][2]+2*colors[1][2]+1)/3;
493 colors[3][3]=255;
494 }
495
496 // Three color block: 00=color #0, 01=color #1, 10=color #2, 11=transparent
497 else{
498 colors[2][0]=(colors[0][0]+colors[1][0])/2;
499 colors[2][1]=(colors[0][1]+colors[1][1])/2;
500 colors[2][2]=(colors[0][2]+colors[1][2])/2;
501 colors[2][3]=255;
502 colors[3][0]=0;
503 colors[3][1]=0;
504 colors[3][2]=0;
505 colors[3][3]=0;
506 }
507
508 // Get index bits all at once
509 bitmask=(((FXuint)temp[7])<<24)|(((FXuint)temp[6])<<16)|(((FXuint)temp[5])<<8)|((FXuint)temp[4]);
510
511 // Decode the bits
512 for(j=0; j<4; ++j){
513 for(i=0; i<4; ++i){
514 if(((x+i)<dds.header.dwWidth) && ((y+j)<dds.header.dwHeight)){
515 offset=((z*dds.header.dwHeight+y+j)*dds.header.dwWidth+x+i)<<2;
516 select=bitmask&3;
517 image[offset+0]=colors[select][0];
518 image[offset+1]=colors[select][1];
519 image[offset+2]=colors[select][2];
520 image[offset+3]=colors[select][3];
521 }
522 bitmask>>=2;
523 }
524 }
525 temp+=8;
526 }
527 }
528 }
529 return true;
530 }
531
532
533 // Decompress DXT3/BC2 image
dds_decompress_DXT3(const DDSImage & dds,FXuchar * image)534 static FXbool dds_decompress_DXT3(const DDSImage& dds,FXuchar *image){
535 FXuchar *temp=dds.data;
536 FXuint x,y,z,i,j,select,bitmask,offset;
537 FXuchar r0,g0,b0,r1,g1,b1;
538 FXushort c0,c1;
539 FXuchar colors[4][4];
540 FXuchar alpha[4][4];
541
542 FXTRACE((100,"dds_decompress_DXT3\n"));
543
544 // Loop over 4x4 blocks
545 for(z=0; z<dds.header.dwDepth; z+=1){
546 for(y=0; y<dds.header.dwHeight; y+=4){
547 for(x=0; x<dds.header.dwWidth; x+=4){
548
549 // Grab 16 4-bit alpha values and convert them to 8-bit ones
550 alpha[0][0]=(temp[0]&15)*17;
551 alpha[0][1]=(temp[0]>>4)*17;
552 alpha[0][2]=(temp[1]&15)*17;
553 alpha[0][3]=(temp[1]>>4)*17;
554
555 alpha[1][0]=(temp[2]&15)*17;
556 alpha[1][1]=(temp[2]>>4)*17;
557 alpha[1][2]=(temp[3]&15)*17;
558 alpha[1][3]=(temp[3]>>4)*17;
559
560 alpha[2][0]=(temp[4]&15)*17;
561 alpha[2][1]=(temp[4]>>4)*17;
562 alpha[2][2]=(temp[5]&15)*17;
563 alpha[2][3]=(temp[5]>>4)*17;
564
565 alpha[3][0]=(temp[6]&15)*17;
566 alpha[3][1]=(temp[6]>>4)*17;
567 alpha[3][2]=(temp[7]&15)*17;
568 alpha[3][3]=(temp[7]>>4)*17;
569
570 // Grab two 5,6,5 colors
571 c0=(((FXushort)temp[9])<<8) | (FXushort)temp[8];
572 c1=(((FXushort)temp[11])<<8) | (FXushort)temp[10];
573
574 r0=(c0>>11)&0x1f;
575 g0=(c0>>5)&0x3f;
576 b0=c0&0x1f;
577
578 r1=(c1>>11)&0x1f;
579 g1=(c1>>5)&0x3f;
580 b1=c1&0x1f;
581
582 colors[0][0]=(b0<<3)|(b0>>2); // Convert from 5,6,5 to 8,8,8 color #0
583 colors[0][1]=(g0<<2)|(g0>>4);
584 colors[0][2]=(r0<<3)|(r0>>2);
585 colors[0][3]=0xFF;
586
587 colors[1][0]=(b1<<3)|(b1>>2); // Convert from 5,6,5 to 8,8,8 color #1
588 colors[1][1]=(g1<<2)|(g1>>4);
589 colors[1][2]=(r1<<3)|(r1>>2);
590 colors[1][3]=0xFF;
591
592 // Four color block: 00=color #0, 01=color #1, 10=color #2, 11=color #3
593 colors[2][0]=(2*colors[0][0]+colors[1][0]+1)/3;
594 colors[2][1]=(2*colors[0][1]+colors[1][1]+1)/3;
595 colors[2][2]=(2*colors[0][2]+colors[1][2]+1)/3;
596 colors[2][3]=0xFF;
597
598 colors[3][0]=(colors[0][0]+2*colors[1][0]+1)/3;
599 colors[3][1]=(colors[0][1]+2*colors[1][1]+1)/3;
600 colors[3][2]=(colors[0][2]+2*colors[1][2]+1)/3;
601 colors[3][3]=0xFF;
602
603 // Get index bits all at once
604 bitmask=(((FXuint)temp[15])<<24)|(((FXuint)temp[14])<<16)|(((FXuint)temp[13])<<8)|((FXuint)temp[12]);
605
606 // Decode the bits
607 for(j=0; j<4; ++j){
608 for(i=0; i<4; ++i){
609 if(((x+i)<dds.header.dwWidth) && ((y+j)<dds.header.dwHeight)){
610 offset=((z*dds.header.dwHeight+y+j)*dds.header.dwWidth+x+i)<<2;
611 select=bitmask&3;
612 image[offset+0]=colors[select][0];
613 image[offset+1]=colors[select][1];
614 image[offset+2]=colors[select][2];
615 image[offset+3]=alpha[j][i];
616 }
617 bitmask>>=2;
618 }
619 }
620 temp+=16;
621 }
622 }
623 }
624 return true;
625 }
626
627
628 // Decompress DXT2 image; has premultiplied alpha
dds_decompress_DXT2(const DDSImage & dds,FXuchar * image)629 static FXbool dds_decompress_DXT2(const DDSImage& dds,FXuchar *image){
630 if(dds_decompress_DXT3(dds,image)){
631 dds_correct_color(image,dds.header.dwWidth*dds.header.dwHeight*dds.header.dwDepth*4);
632 return true;
633 }
634 return false;
635 }
636
637
638 // Decompress DXT5/BC3 image
dds_decompress_DXT5(const DDSImage & dds,FXuchar * image)639 static FXbool dds_decompress_DXT5(const DDSImage& dds,FXuchar *image){
640 FXuchar *temp=dds.data;
641 FXuint x,y,z,i,j,select,bitmask,bits,offset;
642 FXuchar r0,g0,b0,r1,g1,b1;
643 FXushort c0,c1;
644 FXuchar colors[4][4];
645 FXuchar levels[8];
646 FXuchar alpha[4][4];
647
648 FXTRACE((150,"dds_decompress_DXT5\n"));
649
650 // Loop over 4x4 blocks
651 for(z=0; z<dds.header.dwDepth; z+=1){
652 for(y=0; y<dds.header.dwHeight; y+=4){
653 for(x=0; x<dds.header.dwWidth; x+=4){
654
655 // Grab two 8-bit alphas
656 levels[0]=temp[0];
657 levels[1]=temp[1];
658
659 // Six interpolated alpha levels
660 if(levels[0]>levels[1]){
661 levels[2]=(6*levels[0]+1*levels[1]+3)/7; // bit code 010
662 levels[3]=(5*levels[0]+2*levels[1]+3)/7; // bit code 011
663 levels[4]=(4*levels[0]+3*levels[1]+3)/7; // bit code 100
664 levels[5]=(3*levels[0]+4*levels[1]+3)/7; // bit code 101
665 levels[6]=(2*levels[0]+5*levels[1]+3)/7; // bit code 110
666 levels[7]=(1*levels[0]+6*levels[1]+3)/7; // bit code 111
667 }
668
669 // 4 interpolated alpha levels
670 else{
671 levels[2]=(4*levels[0]+1*levels[1]+2)/5; // Bit code 010
672 levels[3]=(3*levels[0]+2*levels[1]+2)/5; // Bit code 011
673 levels[4]=(2*levels[0]+3*levels[1]+2)/5; // Bit code 100
674 levels[5]=(1*levels[0]+4*levels[1]+2)/5; // Bit code 101
675 levels[6]=0x00; // Bit code 110
676 levels[7]=0xFF; // Bit code 111
677 }
678
679 // First three bytes
680 bits=(((FXuint)temp[4])<<16)|(((FXuint)temp[3])<<8)|((FXuint)temp[2]);
681 for(j=0; j<2; ++j){
682 for(i=0; i<4; ++i){
683 alpha[j][i]=levels[bits&7];
684 bits>>=3;
685 }
686 }
687
688 // Last three bytes
689 bits=(((FXuint)temp[7])<<16)|(((FXuint)temp[6])<<8)|((FXuint)temp[5]);
690 for(j=2; j<4; ++j){
691 for(i=0; i<4; ++i){
692 alpha[j][i]=levels[bits&7];
693 bits>>=3;
694 }
695 }
696
697 // Grab two 5,6,5 colors
698 c0=(((FXushort)temp[9])<<8) | (FXushort)temp[8];
699 c1=(((FXushort)temp[11])<<8) | (FXushort)temp[10];
700
701 r0=(c0>>11)&0x1f;
702 g0=(c0>>5)&0x3f;
703 b0=c0&0x1f;
704
705 r1=(c1>>11)&0x1f;
706 g1=(c1>>5)&0x3f;
707 b1=c1&0x1f;
708
709 colors[0][0]=(b0<<3)|(b0>>2); // Convert from 5,6,5 to 8,8,8 color #0
710 colors[0][1]=(g0<<2)|(g0>>4);
711 colors[0][2]=(r0<<3)|(r0>>2);
712 colors[0][3]=0xFF;
713
714 colors[1][0]=(b1<<3)|(b1>>2); // Convert from 5,6,5 to 8,8,8 color #1
715 colors[1][1]=(g1<<2)|(g1>>4);
716 colors[1][2]=(r1<<3)|(r1>>2);
717 colors[1][3]=0xFF;
718
719 // Four color block: 00=color #0, 01=color #1, 10=color #2, 11=color #3
720 colors[2][0]=(2*colors[0][0]+colors[1][0]+1)/3;
721 colors[2][1]=(2*colors[0][1]+colors[1][1]+1)/3;
722 colors[2][2]=(2*colors[0][2]+colors[1][2]+1)/3;
723 colors[2][3]=0xFF;
724
725 colors[3][0]=(colors[0][0]+2*colors[1][0]+1)/3;
726 colors[3][1]=(colors[0][1]+2*colors[1][1]+1)/3;
727 colors[3][2]=(colors[0][2]+2*colors[1][2]+1)/3;
728 colors[3][3]=0xFF;
729
730 // Get index bits all at once
731 bitmask=(((FXuint)temp[15])<<24)|(((FXuint)temp[14])<<16)|(((FXuint)temp[13])<<8)|((FXuint)temp[12]);
732
733 // Decode the bits
734 for(j=0; j<4; ++j){
735 for(i=0; i<4; ++i){
736 if(((x+i)<dds.header.dwWidth) && ((y+j)<dds.header.dwHeight)){
737 offset=((z*dds.header.dwHeight+y+j)*dds.header.dwWidth+x+i)<<2;
738 select=bitmask&3;
739 image[offset+0]=colors[select][0];
740 image[offset+1]=colors[select][1];
741 image[offset+2]=colors[select][2];
742 image[offset+3]=alpha[j][i];
743 }
744 bitmask>>=2;
745 }
746 }
747 temp+=16;
748 }
749 }
750 }
751 return true;
752 }
753
754
755 // Decompress DXT4 image; has premultiplied alpha
dds_decompress_DXT4(const DDSImage & dds,FXuchar * image)756 static FXbool dds_decompress_DXT4(const DDSImage& dds,FXuchar *image){
757 if(dds_decompress_DXT5(dds,image)){
758 dds_correct_color(image,dds.header.dwWidth*dds.header.dwHeight*dds.header.dwDepth*4);
759 return true;
760 }
761 return false;
762 }
763
764
765 // Decompress RXGB image
dds_decompress_RXGB(const DDSImage & dds,FXuchar * image)766 static FXbool dds_decompress_RXGB(const DDSImage& dds,FXuchar *image){
767 if(dds_decompress_DXT5(dds,image)){
768 dds_correct_swizzle(image,dds.header.dwWidth*dds.header.dwHeight*dds.header.dwDepth*4);
769 return true;
770 }
771 return false;
772 }
773
774
775 // Decompress BC4 (ATI1) image
dds_decompress_BC4(const DDSImage & dds,FXuchar * image)776 static FXbool dds_decompress_BC4(const DDSImage& dds,FXuchar *image){
777 FXuchar *temp=dds.data;
778 FXuint x,y,z,i,j,bits,offset;
779 FXuchar levels[8];
780
781 FXTRACE((150,"dds_decompress_BC4\n"));
782
783 // Loop over 4x4 blocks
784 for(z=0; z<dds.header.dwDepth; z+=1){
785 for(y=0; y<dds.header.dwHeight; y+=4){
786 for(x=0; x<dds.header.dwWidth; x+=4){
787
788 // Grab two 8-bit grey levels
789 levels[0]=temp[0];
790 levels[1]=temp[1];
791
792 // Six interpolated grey levels
793 if(levels[0]>levels[1]){
794 levels[2]=(6*levels[0]+1*levels[1]+3)/7;
795 levels[3]=(5*levels[0]+2*levels[1]+3)/7;
796 levels[4]=(4*levels[0]+3*levels[1]+3)/7;
797 levels[5]=(3*levels[0]+4*levels[1]+3)/7;
798 levels[6]=(2*levels[0]+5*levels[1]+3)/7;
799 levels[7]=(1*levels[0]+6*levels[1]+3)/7;
800 }
801
802 // 4 interpolated grey levels
803 else{
804 levels[2]=(4*levels[0]+1*levels[1]+2)/5;
805 levels[3]=(3*levels[0]+2*levels[1]+2)/5;
806 levels[4]=(2*levels[0]+3*levels[1]+2)/5;
807 levels[5]=(1*levels[0]+4*levels[1]+2)/5;
808 levels[6]=0;
809 levels[7]=255;
810 }
811
812 // First three bytes
813 bits=(((FXuint)temp[4])<<16)|(((FXuint)temp[3])<<8)|((FXuint)temp[2]);
814 for(j=0; j<2; ++j){
815 for(i=0; i<4; ++i){
816 if(((x+i)<dds.header.dwWidth) && ((y+j)<dds.header.dwHeight)){
817 offset=((z*dds.header.dwHeight+y+j)*dds.header.dwWidth+x+i)<<2;
818 image[offset+0]=image[offset+1]=image[offset+2]=image[offset+3]=levels[bits&7];
819 }
820 bits>>=3;
821 }
822 }
823
824 // Last three bytes
825 bits=(((FXuint)temp[7])<<16)|(((FXuint)temp[6])<<8)|((FXuint)temp[5]);
826 for(j=2; j<4; ++j){
827 for(i=0; i<4; ++i){
828 if(((x+i)<dds.header.dwWidth) && ((y+j)<dds.header.dwHeight)){
829 offset=((z*dds.header.dwHeight+y+j)*dds.header.dwWidth+x+i)<<2;
830 image[offset+0]=image[offset+1]=image[offset+2]=image[offset+3]=levels[bits&7];
831 }
832 bits>>=3;
833 }
834 }
835 temp+=8;
836 }
837 }
838 }
839 return true;
840 }
841
842
843 // Decompress 3DC (ATI2) image
dds_decompress_3DC(const DDSImage & dds,FXuchar * image)844 static FXbool dds_decompress_3DC(const DDSImage& dds,FXuchar *image){
845 FXuchar *temp=dds.data;
846 FXuint x,y,z,i,j,redbits,grnbits,offset;
847 FXint tx,ty,t;
848 FXuchar red[8];
849 FXuchar grn[8];
850
851 FXTRACE((150,"dds_decompress_3DC\n"));
852
853 // Loop over 4x4 blocks
854 for(z=0; z<dds.header.dwDepth; z+=1){
855 for(y=0; y<dds.header.dwHeight; y+=4){
856 for(x=0; x<dds.header.dwWidth; x+=4){
857
858 // Grab two reds
859 red[0]=temp[0];
860 red[1]=temp[1];
861
862 // Six interpolated values
863 if(red[0]>red[1]){
864 red[2]=(6*red[0]+1*red[1]+3)/7;
865 red[3]=(5*red[0]+2*red[1]+3)/7;
866 red[4]=(4*red[0]+3*red[1]+3)/7;
867 red[5]=(3*red[0]+4*red[1]+3)/7;
868 red[6]=(2*red[0]+5*red[1]+3)/7;
869 red[7]=(1*red[0]+6*red[1]+3)/7;
870 }
871
872 // Four interpolated values
873 else{
874 red[2]=(4*red[0]+1*red[1]+2)/5;
875 red[3]=(3*red[0]+2*red[1]+2)/5;
876 red[4]=(2*red[0]+3*red[1]+2)/5;
877 red[5]=(1*red[0]+4*red[1]+2)/5;
878 red[6]=0;
879 red[7]=255;
880 }
881
882 // Grab two greens
883 grn[0]=temp[8];
884 grn[1]=temp[9];
885
886 // Six interpolated values
887 if(grn[0]>grn[1]){
888 grn[2]=(6*grn[0]+1*grn[1]+3)/7;
889 grn[3]=(5*grn[0]+2*grn[1]+3)/7;
890 grn[4]=(4*grn[0]+3*grn[1]+3)/7;
891 grn[5]=(3*grn[0]+4*grn[1]+3)/7;
892 grn[6]=(2*grn[0]+5*grn[1]+3)/7;
893 grn[7]=(1*grn[0]+6*grn[1]+3)/7;
894 }
895
896 // Four interpolated values
897 else{
898 grn[2]=(4*grn[0]+1*grn[1]+2)/5;
899 grn[3]=(3*grn[0]+2*grn[1]+2)/5;
900 grn[4]=(2*grn[0]+3*grn[1]+2)/5;
901 grn[5]=(1*grn[0]+4*grn[1]+2)/5;
902 grn[6]=0;
903 grn[7]=255;
904 }
905
906 // Decode the first 3 bytes
907 redbits=(((FXuint)temp[4])<<16)|(((FXuint)temp[3])<<8)|((FXuint)temp[2]);
908 grnbits=(((FXuint)temp[12])<<16)|(((FXuint)temp[11])<<8)|((FXuint)temp[10]);
909 for(j=0; j<2; ++j){
910 for(i=0; i<4; ++i){
911 if(((x+i)<dds.header.dwWidth) && ((y+j)<dds.header.dwHeight)){
912 offset=((z*dds.header.dwHeight+y+j)*dds.header.dwWidth+x+i)<<2;
913 image[offset+1]=ty=grn[grnbits&7];
914 image[offset+2]=tx=red[redbits&7];
915 t=127*128-(tx-127)*(tx-128)-(ty-127)*(ty-128);
916 if(t>0){
917 image[offset+0]=(FXuchar)(isqrt(t)+128);
918 }
919 else{
920 image[offset+0]=127;
921 }
922 image[offset+3]=255;
923 }
924 redbits>>=3;
925 grnbits>>=3;
926 }
927 }
928
929 // Decode the last 3 bytes
930 redbits=(((FXuint)temp[7])<<16)|(((FXuint)temp[6])<<8)|((FXuint)temp[5]);
931 grnbits=(((FXuint)temp[15])<<16)|(((FXuint)temp[14])<<8)|((FXuint)temp[13]);
932 for(j=2; j<4; ++j){
933 for(i=0; i<4; ++i){
934 if(((x+i)<dds.header.dwWidth) && ((y+j)<dds.header.dwHeight)){
935 offset=((z*dds.header.dwHeight+y+j)*dds.header.dwWidth+x+i)<<2;
936 image[offset+2]=tx=red[redbits&7];
937 image[offset+1]=ty=grn[grnbits&7];
938 t=127*128-(tx-127)*(tx-128)-(ty-127)*(ty-128);
939 if(t>0){
940 image[offset+0]=(FXuchar)(isqrt(t)+128);
941 }
942 else{
943 image[offset+0]=127;
944 }
945 image[offset+3]=255;
946 }
947 redbits>>=3;
948 grnbits>>=3;
949 }
950 }
951 temp+=16;
952 }
953 }
954 }
955 return true;
956 }
957
958
959 // Compute shifts
getShifts(FXuint mask,FXuint & shift,FXuint & mul,FXuint & sc)960 static void getShifts(FXuint mask,FXuint& shift,FXuint& mul,FXuint& sc){
961 FXuint bits=0;
962 shift=0;
963 mul=1;
964 sc=0;
965 while(!(mask&1)){
966 mask>>=1;
967 shift++;
968 }
969 while(mask&(1<<bits)) bits++;
970 while((mask*mul)<255){
971 mul=(mul<<bits)+1;
972 }
973 mask*=mul;
974 while((mask&~0xff)!=0){
975 mask>>=1;
976 sc++;
977 }
978 }
979
980
981 // General decompress integer pixel
dds_decompress_RGB(const DDSImage & dds,FXuchar * image,FXuint bmask,FXuint gmask,FXuint rmask,FXuint s)982 static FXbool dds_decompress_RGB(const DDSImage& dds,FXuchar *image,FXuint bmask,FXuint gmask,FXuint rmask,FXuint s){
983 FXuint rshift=0,gshift=0,bshift=0,rmul=0,gmul=0,bmul=0,rs=0,gs=0,bs=0;
984 FXuint x,y,z,offset,pix,t;
985 FXuchar *temp=dds.data;
986 FXTRACE((150,"dds_decompress_RGBA\n"));
987 if(rmask){ getShifts(rmask,rshift,rmul,rs); }
988 if(gmask){ getShifts(gmask,gshift,gmul,gs); }
989 if(bmask){ getShifts(bmask,bshift,bmul,bs); }
990 FXTRACE((150,"rmask=0x%08x rshift=%2d rmul=%3d rs=%3d\n",rmask,rshift,rmul,rs));
991 FXTRACE((150,"gmask=0x%08x gshift=%2d gmul=%3d gs=%3d\n",gmask,gshift,gmul,gs));
992 FXTRACE((150,"bmask=0x%08x bshift=%2d bmul=%3d bs=%3d\n",bmask,bshift,bmul,bs));
993 for(z=offset=0; z<dds.header.dwDepth; ++z){
994 for(y=0; y<dds.header.dwHeight; ++y){
995 for(x=0; x<dds.header.dwWidth; ++x){
996 pix=(((FXuint)temp[3])<<24)|(((FXuint)temp[2])<<16)|(((FXuint)temp[1])<<8)|((FXuint)temp[0]);
997 t=(pix&bmask)>>bshift; image[offset+0]=(t*bmul)>>bs;
998 t=(pix&gmask)>>gshift; image[offset+1]=(t*gmul)>>gs;
999 t=(pix&rmask)>>rshift; image[offset+2]=(t*rmul)>>rs;
1000 image[offset+3]=255;
1001 offset+=4;
1002 temp+=s;
1003 }
1004 }
1005 }
1006 return true;
1007 }
1008
1009
1010 // General decompress integer pixel with alpha
dds_decompress_RGBA(const DDSImage & dds,FXuchar * image,FXuint bmask,FXuint gmask,FXuint rmask,FXuint amask,FXuint s)1011 static FXbool dds_decompress_RGBA(const DDSImage& dds,FXuchar *image,FXuint bmask,FXuint gmask,FXuint rmask,FXuint amask,FXuint s){
1012 FXuint rshift=0,gshift=0,bshift=0,ashift=0,rmul=0,gmul=0,bmul=0,amul=0,rs=0,gs=0,bs=0,as=0;
1013 FXuint x,y,z,offset,pix,t;
1014 FXuchar *temp=dds.data;
1015 FXTRACE((150,"dds_decompress_RGBA\n"));
1016 if(rmask){ getShifts(rmask,rshift,rmul,rs); }
1017 if(gmask){ getShifts(gmask,gshift,gmul,gs); }
1018 if(bmask){ getShifts(bmask,bshift,bmul,bs); }
1019 if(amask){ getShifts(amask,ashift,amul,as); }
1020 FXTRACE((150,"rmask=0x%08x rshift=%2d rmul=%3d rs=%3d\n",rmask,rshift,rmul,rs));
1021 FXTRACE((150,"gmask=0x%08x gshift=%2d gmul=%3d gs=%3d\n",gmask,gshift,gmul,gs));
1022 FXTRACE((150,"bmask=0x%08x bshift=%2d bmul=%3d bs=%3d\n",bmask,bshift,bmul,bs));
1023 FXTRACE((150,"amask=0x%08x ashift=%2d amul=%3d as=%3d\n",amask,ashift,amul,as));
1024 for(z=offset=0; z<dds.header.dwDepth; ++z){
1025 for(y=0; y<dds.header.dwHeight; ++y){
1026 for(x=0; x<dds.header.dwWidth; ++x){
1027 pix=(((FXuint)temp[3])<<24)|(((FXuint)temp[2])<<16)|(((FXuint)temp[1])<<8)|((FXuint)temp[0]);
1028 t=(pix&bmask)>>bshift; image[offset+0]=(t*bmul)>>bs;
1029 t=(pix&gmask)>>gshift; image[offset+1]=(t*gmul)>>gs;
1030 t=(pix&rmask)>>rshift; image[offset+2]=(t*rmul)>>rs;
1031 t=(pix&amask)>>ashift; image[offset+3]=(t*amul)>>as;
1032 offset+=4;
1033 temp+=s;
1034 }
1035 }
1036 }
1037 return true;
1038 }
1039
1040
1041 // Decompress Luminance
dds_decompress_LUM(const DDSImage & dds,FXuchar * image,FXuint cmask,FXuint s)1042 static FXbool dds_decompress_LUM(const DDSImage& dds,FXuchar *image,FXuint cmask,FXuint s){
1043 FXuint cshift=0,cmul=0,cs=0;
1044 FXuint x,y,z,offset,pix,t;
1045 FXuchar *temp=dds.data;
1046 FXTRACE((150,"dds_decompress_LUM\n"));
1047 if(cmask){ getShifts(cmask,cshift,cmul,cs); }
1048 FXTRACE((150,"cmask=0x%08x cshift=%2d cmul=%3d cs=%3d\n",cmask,cshift,cmul,cs));
1049 for(z=offset=0; z<dds.header.dwDepth; ++z){
1050 for(y=0; y<dds.header.dwHeight; ++y){
1051 for(x=0; x<dds.header.dwWidth; ++x){
1052 pix=(((FXuint)temp[3])<<24)|(((FXuint)temp[2])<<16)|(((FXuint)temp[1])<<8)|((FXuint)temp[0]);
1053 t=(pix&cmask)>>cshift; image[offset+0]=image[offset+1]=image[offset+2]=(t*cmul)>>cs; image[offset+3]=255;
1054 offset+=4;
1055 temp+=s;
1056 }
1057 }
1058 }
1059 return true;
1060 }
1061
1062
1063 // Decompress Luminance and alpha
dds_decompress_LUMA(const DDSImage & dds,FXuchar * image,FXuint cmask,FXuint amask,FXuint s)1064 static FXbool dds_decompress_LUMA(const DDSImage& dds,FXuchar *image,FXuint cmask,FXuint amask,FXuint s){
1065 FXuint cshift=0,ashift=0,cmul=0,amul=0,cs=0,as=0;
1066 FXuint x,y,z,offset,pix,t;
1067 FXuchar *temp=dds.data;
1068 FXTRACE((150,"dds_decompress_LUMA\n"));
1069 if(cmask){ getShifts(cmask,cshift,cmul,cs); }
1070 if(amask){ getShifts(amask,ashift,amul,as); }
1071 FXTRACE((150,"cmask=0x%08x cshift=%2d cmul=%3d cs=%3d\n",cmask,cshift,cmul,cs));
1072 FXTRACE((150,"amask=0x%08x ashift=%2d amul=%3d as=%3d\n",amask,ashift,amul,as));
1073 for(z=offset=0; z<dds.header.dwDepth; ++z){
1074 for(y=0; y<dds.header.dwHeight; ++y){
1075 for(x=0; x<dds.header.dwWidth; ++x){
1076 pix=(((FXuint)temp[3])<<24)|(((FXuint)temp[2])<<16)|(((FXuint)temp[1])<<8)|((FXuint)temp[0]);
1077 t=(pix&cmask)>>cshift; image[offset+0]=image[offset+1]=image[offset+2]=(t*cmul)>>cs;
1078 t=(pix&amask)>>ashift; image[offset+3]=(t*amul)>>as;
1079 offset+=4;
1080 temp+=s;
1081 }
1082 }
1083 }
1084 return true;
1085 }
1086
1087
1088 // Decompress R16F
dds_decompress_R16F(const DDSImage & dds,FXuchar * image)1089 static FXbool dds_decompress_R16F(const DDSImage& dds,FXuchar *image){
1090 FXuint count=dds.header.dwDepth*dds.header.dwHeight*dds.header.dwWidth*4;
1091 FXhalf *temp=(FXhalf*)dds.data;
1092 FXuint p=0;
1093 FXTRACE((150,"dds_decompress_R16F\n"));
1094 while(p<count){
1095 image[p+0]=0;
1096 image[p+1]=0;
1097 image[p+2]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1098 image[p+3]=255;
1099 p+=4;
1100 }
1101 return true;
1102 }
1103
1104
1105 // Decompress G16R16F
dds_decompress_G16R16F(const DDSImage & dds,FXuchar * image)1106 static FXbool dds_decompress_G16R16F(const DDSImage& dds,FXuchar *image){
1107 FXuint count=dds.header.dwDepth*dds.header.dwHeight*dds.header.dwWidth*4;
1108 FXhalf *temp=(FXhalf*)dds.data;
1109 FXuint p=0;
1110 FXTRACE((150,"dds_decompress_G16R16F\n"));
1111 while(p<count){
1112 image[p+0]=0;
1113 image[p+2]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1114 image[p+1]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1115 image[p+3]=255;
1116 p+=4;
1117 }
1118 return true;
1119 }
1120
1121
1122 // Decompress A16B16G16R16F
dds_decompress_A16B16G16R16F(const DDSImage & dds,FXuchar * image)1123 static FXbool dds_decompress_A16B16G16R16F(const DDSImage& dds,FXuchar *image){
1124 FXuint count=dds.header.dwDepth*dds.header.dwHeight*dds.header.dwWidth*4;
1125 FXhalf *temp=(FXhalf*)dds.data;
1126 FXuint p=0;
1127 FXTRACE((150,"dds_decompress_A16B16G16R16F\n"));
1128 while(p<count){
1129 image[p+2]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1130 image[p+1]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1131 image[p+0]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1132 image[p+3]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1133 p+=4;
1134 }
1135 return true;
1136 }
1137
1138
1139 // Decompress A16B16G16R16
dds_decompress_A16B16G16R16(const DDSImage & dds,FXuchar * image)1140 static FXbool dds_decompress_A16B16G16R16(const DDSImage& dds,FXuchar *image){
1141 FXuint count=dds.header.dwDepth*dds.header.dwHeight*dds.header.dwWidth*4;
1142 FXushort *temp=(FXushort*)dds.data;
1143 FXuint p=0;
1144 FXTRACE((150,"dds_decompress_A16B16G16R16\n"));
1145 while(p<count){
1146 image[p+2]=(FXuchar)(*temp++ / 257);
1147 image[p+1]=(FXuchar)(*temp++ / 257);
1148 image[p+0]=(FXuchar)(*temp++ / 257);
1149 image[p+3]=(FXuchar)(*temp++ / 257);
1150 p+=4;
1151 }
1152 return true;
1153 }
1154
1155
1156 // Decompress R32F
dds_decompress_R32F(const DDSImage & dds,FXuchar * image)1157 static FXbool dds_decompress_R32F(const DDSImage& dds,FXuchar *image){
1158 FXuint count=dds.header.dwDepth*dds.header.dwHeight*dds.header.dwWidth*4;
1159 FXfloat *temp=(FXfloat*)dds.data;
1160 FXuint p=0;
1161 FXTRACE((150,"dds_decompress_R32F\n"));
1162 while(p<count){
1163 image[p+0]=0;
1164 image[p+1]=0;
1165 image[p+2]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1166 image[p+3]=255;
1167 p+=4;
1168 }
1169 return true;
1170 }
1171
1172
1173 // Decompress G32R32F
dds_decompress_G32R32F(const DDSImage & dds,FXuchar * image)1174 static FXbool dds_decompress_G32R32F(const DDSImage& dds,FXuchar *image){
1175 FXuint count=dds.header.dwDepth*dds.header.dwHeight*dds.header.dwWidth*4;
1176 FXfloat *temp=(FXfloat*)dds.data;
1177 FXuint p=0;
1178 FXTRACE((150,"dds_decompress_G32R32F\n"));
1179 while(p<count){
1180 image[p+2]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1181 image[p+1]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1182 image[p+0]=0;
1183 image[p+3]=255;
1184 p+=4;
1185 }
1186 return true;
1187 }
1188
1189
1190 // Decompress A32B32G32R32F
dds_decompress_A32B32G32R32F(const DDSImage & dds,FXuchar * image)1191 static FXbool dds_decompress_A32B32G32R32F(const DDSImage& dds,FXuchar *image){
1192 FXuint count=dds.header.dwDepth*dds.header.dwHeight*dds.header.dwWidth*4;
1193 FXfloat *temp=(FXfloat*)dds.data;
1194 FXuint p=0;
1195 FXTRACE((150,"dds_decompress_A32B32G32R32F\n"));
1196 while(p<count){
1197 image[p+2]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1198 image[p+1]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1199 image[p+0]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1200 image[p+3]=(FXuchar)(*temp++ * 255.0f + 0.5f);
1201 p+=4;
1202 }
1203 return true;
1204 }
1205
1206
1207 // Decompress R8G8_B8G8
dds_decompress_RGBG(const DDSImage & dds,FXuchar * image)1208 static FXbool dds_decompress_RGBG(const DDSImage& dds,FXuchar *image){
1209 FXuint x,y,z,offset;
1210 FXuchar *temp=dds.data;
1211 FXTRACE((150,"dds_decompress_RGBG\n"));
1212 for(z=offset=0; z<dds.header.dwDepth; z+=1){
1213 for(y=0; y<dds.header.dwHeight; y+=1){
1214 for(x=0; x<dds.header.dwWidth; x+=2){
1215 image[offset+0]=temp[3];
1216 image[offset+1]=temp[0];
1217 image[offset+2]=temp[1];
1218 image[offset+3]=255;
1219 image[offset+4]=temp[3];
1220 image[offset+5]=temp[2];
1221 image[offset+6]=temp[1];
1222 image[offset+7]=255;
1223 offset+=8;
1224 temp+=4;
1225 }
1226 }
1227 }
1228 return true;
1229 }
1230
1231
1232 // Decompress G8R8_G8B8
dds_decompress_GRGB(const DDSImage & dds,FXuchar * image)1233 static FXbool dds_decompress_GRGB(const DDSImage& dds,FXuchar *image){
1234 FXuint x,y,z,offset;
1235 FXuchar *temp=dds.data;
1236 FXTRACE((150,"dds_decompress_GRGB\n"));
1237 for(z=offset=0; z<dds.header.dwDepth; z+=1){
1238 for(y=0; y<dds.header.dwHeight; y+=1){
1239 for(x=0; x<dds.header.dwWidth; x+=2){
1240 image[offset+0]=temp[2];
1241 image[offset+1]=temp[1];
1242 image[offset+2]=temp[0];
1243 image[offset+3]=255;
1244 image[offset+4]=temp[2];
1245 image[offset+5]=temp[3];
1246 image[offset+6]=temp[0];
1247 image[offset+7]=255;
1248 offset+=8;
1249 temp+=4;
1250 }
1251 }
1252 }
1253 return true;
1254 }
1255
1256
1257 // Check if stream contains a BMP
fxcheckDDS(FXStream & store)1258 FXbool fxcheckDDS(FXStream& store){
1259 FXuchar signature[4];
1260 store.load(signature,4);
1261 store.position(-4,FXFromCurrent);
1262 return signature[0]=='D' && signature[1]=='D' && signature[2]=='S' && signature[3]==' ';
1263 }
1264
1265
1266 // Load image from stream
fxloadDDS(FXStream & store,FXColor * & data,FXint & width,FXint & height,FXint & depth)1267 FXbool fxloadDDS(FXStream& store,FXColor*& data,FXint& width,FXint& height,FXint& depth){
1268 FXbool swap=store.swapBytes();
1269 FXbool ok=false;
1270 DDSImage dds;
1271
1272 // Null out
1273 data=NULL;
1274 width=0;
1275 height=0;
1276 depth=0;
1277
1278 // Bitmaps are little-endian
1279 store.setBigEndian(false);
1280
1281 // Check header
1282 store >> dds.magic;
1283 if(dds.magic==DDSD_MAGIC){
1284 store >> dds.header.dwSize;
1285 if(dds.header.dwSize!=124) goto x; // Unexpected size; bail!
1286 store >> dds.header.dwFlags;
1287 store >> dds.header.dwHeight;
1288 store >> dds.header.dwWidth;
1289 store >> dds.header.dwLinearSize;
1290 store >> dds.header.dwDepth;
1291 store >> dds.header.dwMipMapCount;
1292 store.load(dds.header.dwReserved1,11);
1293 store >> dds.header.ddpf.dwSize;
1294 store >> dds.header.ddpf.dwFlags;
1295 store >> dds.header.ddpf.dwFourCC;
1296 store >> dds.header.ddpf.dwRGBBitCount;
1297 store >> dds.header.ddpf.dwRBitMask;
1298 store >> dds.header.ddpf.dwGBitMask;
1299 store >> dds.header.ddpf.dwBBitMask;
1300 store >> dds.header.ddpf.dwABitMask;
1301 store >> dds.header.dwCaps;
1302 store >> dds.header.dwCaps2;
1303 store >> dds.header.dwCaps3;
1304 store >> dds.header.dwCaps4;
1305 store >> dds.header.dwReserved2;
1306
1307 // Load DX10 Header if present
1308 if(dds.header.ddpf.dwFourCC==D3DFMT_DX10){ // Parse over DX10 header
1309 store >> dds.xheader.dxgiFormat;
1310 store >> dds.xheader.resourceDimension;
1311 store >> dds.xheader.miscFlag;
1312 store >> dds.xheader.arraySize;
1313 store >> dds.xheader.reserved;
1314 }
1315 else{
1316 dds.xheader.dxgiFormat=DXGI_FORMAT_UNKNOWN;
1317 dds.xheader.resourceDimension=D3D10_RESOURCE_DIMENSION_UNKNOWN;
1318 dds.xheader.miscFlag=0;
1319 dds.xheader.arraySize=1;
1320 dds.xheader.reserved=0;
1321 }
1322
1323 FXTRACE((150,"dds.magic=0x%08x\n",dds.magic));
1324 FXTRACE((150,"dds.header.dwSize=%d\n",dds.header.dwSize));
1325 FXTRACE((150,"dds.header.dwFlags=0x%08x: %s%s%s%s%s%s%s%s\n",dds.header.dwFlags,(dds.header.dwFlags&DDSD_CAPS)?"DDSD_CAPS ":"",(dds.header.dwFlags&DDSD_HEIGHT)?"DDSD_HEIGHT ":"",(dds.header.dwFlags&DDSD_WIDTH)?"DDSD_WIDTH ":"",(dds.header.dwFlags&DDSD_PITCH)?"DDSD_PITCH ":"",(dds.header.dwFlags&DDSD_PIXELFORMAT)?"DDSD_PIXELFORMAT ":"",(dds.header.dwFlags&DDSD_MIPMAPCOUNT)?"DDSD_MIPMAPCOUNT ":"",(dds.header.dwFlags&DDSD_LINEARSIZE)?"DDSD_LINEARSIZE ":"",(dds.header.dwFlags&DDSD_DEPTH)?"DDSD_DEPTH":""));
1326 FXTRACE((150,"dds.header.dwHeight=%d\n",dds.header.dwHeight));
1327 FXTRACE((150,"dds.header.dwWidth=%d\n",dds.header.dwWidth));
1328 FXTRACE((150,"dds.header.dwDepth=%d\n",dds.header.dwDepth));
1329 FXTRACE((150,"dds.header.dwLinearSize=%d\n",dds.header.dwLinearSize));
1330 FXTRACE((150,"dds.header.dwMipMapCount=%d\n",dds.header.dwMipMapCount));
1331 FXTRACE((150,"dds.header.ddpf.dwSize=%d\n",dds.header.ddpf.dwSize));
1332 FXTRACE((150,"dds.header.ddpf.dwFlags=0x%08x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",dds.header.ddpf.dwFlags,(dds.header.ddpf.dwFlags&DDPF_ALPHAPIXELS)?"DDPF_ALPHAPIXELS ":"",(dds.header.ddpf.dwFlags&DDPF_ALPHA)?"DDPF_ALPHA ":"",(dds.header.ddpf.dwFlags&DDPF_FOURCC)?"DDPF_FOURCC ":"",(dds.header.ddpf.dwFlags&DDPF_PALETTEINDEXED4)?"DDPF_PALETTEINDEXED4 ":"",(dds.header.ddpf.dwFlags&DDPF_PALETTEINDEXED8)?"DDPF_PALETTEINDEXED8 ":"",(dds.header.ddpf.dwFlags&DDPF_RGB)?"DDPF_RGB ":"",(dds.header.ddpf.dwFlags&DDPF_COMPRESSED)?"DDPF_COMPRESSED ":"",(dds.header.ddpf.dwFlags&DDPF_RGBTOYUV)?"DDPF_RGBTOYUV ":"",(dds.header.ddpf.dwFlags&DDPF_YUV)?"DDPF_YUV ":"",(dds.header.ddpf.dwFlags&DDPF_ZBUFFER)?"DDPF_ZBUFFER ":"",(dds.header.ddpf.dwFlags&DDPF_PALETTEINDEXED1)?"DDPF_PALETTEINDEXED1 ":"",(dds.header.ddpf.dwFlags&DDPF_PALETTEINDEXED2)?"DDPF_PALETTEINDEXED2 ":"",(dds.header.ddpf.dwFlags&DDPF_ZPIXELS)?"DDPF_ZPIXELS ":"",(dds.header.ddpf.dwFlags&DDPF_STENCILBUFFER)?"DDPF_STENCILBUFFER ":"",(dds.header.ddpf.dwFlags&DDPF_ALPHAPREMULT)?"DDPF_ALPHAPREMULT ":"",(dds.header.ddpf.dwFlags&DDPF_LUMINANCE)?"DDPF_LUMINANCE ":"",(dds.header.ddpf.dwFlags&DDPF_BUMPLUMINANCE)?"DDPF_BUMPLUMINANCE ":"",(dds.header.ddpf.dwFlags&DDPF_NORMAL)?"DDPF_NORMAL":""));
1333 FXTRACE((150,"dds.header.ddpf.dwFourCC=0x%08x (%d) (%c%c%c%c)\n",dds.header.ddpf.dwFourCC,dds.header.ddpf.dwFourCC,dds.header.ddpf.dwFourCC&255,(dds.header.ddpf.dwFourCC>>8)&255,(dds.header.ddpf.dwFourCC>>16)&255,(dds.header.ddpf.dwFourCC>>24)&255));
1334 FXTRACE((150,"dds.header.ddpf.dwRGBBitCount=%d\n",dds.header.ddpf.dwRGBBitCount));
1335 FXTRACE((150,"dds.header.ddpf.dwRBitMask=0x%08x\n",dds.header.ddpf.dwRBitMask));
1336 FXTRACE((150,"dds.header.ddpf.dwGBitMask=0x%08x\n",dds.header.ddpf.dwGBitMask));
1337 FXTRACE((150,"dds.header.ddpf.dwBBitMask=0x%08x\n",dds.header.ddpf.dwBBitMask));
1338 FXTRACE((150,"dds.header.ddpf.dwABitMask=0x%08x\n",dds.header.ddpf.dwABitMask));
1339
1340 FXTRACE((150,"dds.header.dwCaps =0x%08x: %s%s%s\n",dds.header.dwCaps,(dds.header.dwCaps&DDSCAPS_COMPLEX)?"DDSCAPS_COMPLEX ":"",(dds.header.dwCaps&DDSCAPS_TEXTURE)?"DDSCAPS_TEXTURE ":"",(dds.header.dwCaps&DDSCAPS_MIPMAP)?"DDSCAPS_MIPMAP":""));
1341 FXTRACE((150,"dds.header.dwCaps2=0x%08x: %s%s%s%s%s%s%s%s\n",dds.header.dwCaps2,(dds.header.dwCaps2&DDSCAPS2_CUBEMAP)?"DDSCAPS2_CUBEMAP ":"",(dds.header.dwCaps2&DDSCAPS2_VOLUME)?"DDSCAPS2_VOLUME ":"",(dds.header.dwCaps2&DDSCAPS2_CUBEMAP_POSITIVEX)?"DDSCAPS2_CUBEMAP_POSITIVEX ":"",(dds.header.dwCaps2&DDSCAPS2_CUBEMAP_NEGATIVEX)?"DDSCAPS2_CUBEMAP_NEGATIVEX ":"",(dds.header.dwCaps2&DDSCAPS2_CUBEMAP_POSITIVEY)?"DDSCAPS2_CUBEMAP_POSITIVEY ":"",(dds.header.dwCaps2&DDSCAPS2_CUBEMAP_NEGATIVEY)?"DDSCAPS2_CUBEMAP_NEGATIVEY ":"",(dds.header.dwCaps2&DDSCAPS2_CUBEMAP_POSITIVEZ)?"DDSCAPS2_CUBEMAP_POSITIVEZ ":"",(dds.header.dwCaps2&DDSCAPS2_CUBEMAP_NEGATIVEZ)?"DDSCAPS2_CUBEMAP_NEGATIVEZ ":""));
1342 FXTRACE((150,"dds.header.dwCaps3=0x%08x\n",dds.header.dwCaps3));
1343 FXTRACE((150,"dds.header.dwCaps4=0x%08x\n",dds.header.dwCaps4));
1344
1345 FXTRACE((150,"dds.xheader.dxgiFormat=%d\n",dds.xheader.dxgiFormat));
1346 FXTRACE((150,"dds.xheader.resourceDimension=%d\n",dds.xheader.resourceDimension));
1347 FXTRACE((150,"dds.xheader.miscFlag=%d\n",dds.xheader.miscFlag));
1348 FXTRACE((150,"dds.xheader.arraySize=%d\n",dds.xheader.arraySize));
1349
1350 // Fix depth
1351 if(!(dds.header.dwFlags&DDSD_DEPTH) || (dds.header.dwDepth==0)) dds.header.dwDepth=1;
1352
1353 // Fix mipmap count
1354 if(!(dds.header.dwFlags&DDSD_MIPMAPCOUNT) || (dds.header.dwMipMapCount==0)) dds.header.dwMipMapCount=1;
1355
1356 // Set image size to return
1357 width=dds.header.dwWidth;
1358 height=dds.header.dwHeight;
1359 depth=dds.header.dwDepth;
1360
1361 // Perhaps broken format; assume DDPF_FOURCC
1362 if(dds.header.ddpf.dwFlags==0 && dds.header.ddpf.dwFourCC!=0){
1363 dds.header.ddpf.dwFlags=DDPF_FOURCC;
1364 }
1365
1366 // Figure out how much to allocate for compressed data
1367 if(dds.header.ddpf.dwFlags&DDPF_FOURCC){
1368 switch(dds.header.ddpf.dwFourCC){
1369 case D3DFMT_DXT1:
1370 case D3DFMT_ATI1:
1371 dds.size=((width+3)>>2)*((height+3)>>2)*depth*8;
1372 break;
1373 case D3DFMT_DXT2:
1374 case D3DFMT_DXT3:
1375 case D3DFMT_DXT4:
1376 case D3DFMT_DXT5:
1377 case D3DFMT_ATI2:
1378 case D3DFMT_RXGB:
1379 dds.size=((width+3)>>2)*((height+3)>>2)*depth*16;
1380 break;
1381 case D3DFMT_A1:
1382 dds.size=((width+7)>>3)*height*depth;
1383 break;
1384 case D3DFMT_A2XY:
1385 case D3DFMT_UYVY:
1386 case D3DFMT_YUY2:
1387 goto x; // Unsupported compression code
1388 case D3DFMT_R16F:
1389 case D3DFMT_R5G6B5:
1390 case D3DFMT_X1R5G5B5:
1391 case D3DFMT_A1R5G5B5:
1392 case D3DFMT_A4R4G4B4:
1393 case D3DFMT_A8R3G3B2:
1394 case D3DFMT_X4R4G4B4:
1395 case D3DFMT_R8G8_B8G8:
1396 case D3DFMT_G8R8_G8B8:
1397 case D3DFMT_L16:
1398 case D3DFMT_A8P8:
1399 case D3DFMT_A8L8:
1400 dds.size=width*height*depth*2;
1401 break;
1402 case D3DFMT_G16R16F:
1403 case D3DFMT_A8R8G8B8:
1404 case D3DFMT_X8R8G8B8:
1405 case D3DFMT_A8B8G8R8:
1406 case D3DFMT_X8B8G8R8:
1407 case D3DFMT_G16R16:
1408 case D3DFMT_A2R10G10B10:
1409 case D3DFMT_R32F:
1410 case D3DFMT_A2B10G10R10:
1411 case D3DFMT_A2B10G10R10_XR_BIAS:
1412 dds.size=width*height*depth*4;
1413 break;
1414 case D3DFMT_A32B32G32R32F:
1415 dds.size=width*height*depth*16;
1416 break;
1417 case D3DFMT_R8G8B8:
1418 dds.size=width*height*depth*3;
1419 break;
1420 case D3DFMT_R3G3B2:
1421 case D3DFMT_A8:
1422 case D3DFMT_P8:
1423 case D3DFMT_L8:
1424 case D3DFMT_A4L4:
1425 dds.size=width*height*depth;
1426 break;
1427 case D3DFMT_A16B16G16R16F:
1428 case D3DFMT_G32R32F:
1429 case D3DFMT_A16B16G16R16:
1430 dds.size=width*height*depth*8;
1431 break;
1432 default:
1433 goto x; // Unsupported compression code
1434 }
1435 }
1436
1437 // Figure out how much to allocate for RGB
1438 else if(dds.header.ddpf.dwFlags&DDPF_RGB){
1439 dds.size=width*height*depth*dds.header.ddpf.dwRGBBitCount/8;
1440 }
1441
1442 // Luminance
1443 else if(dds.header.ddpf.dwFlags&DDPF_LUMINANCE){
1444 dds.size=width*height*depth*dds.header.ddpf.dwRGBBitCount/8;
1445 }
1446
1447 // Unsupported format
1448 else{
1449 goto x; // Not supported
1450 }
1451
1452 FXTRACE((150,"dds.size=%d\n",dds.size));
1453
1454 // Allocate array for compressed data
1455 if(allocElms(dds.data,dds.size)){
1456
1457 // Allocate output image
1458 if(allocElms(data,width*height*depth)){
1459
1460 // Load temp array
1461 store.load(dds.data,dds.size);
1462
1463 // FOURCC format
1464 if(dds.header.ddpf.dwFlags&DDPF_FOURCC){
1465 switch(dds.header.ddpf.dwFourCC){
1466 case D3DFMT_DXT1:
1467 ok=dds_decompress_DXT1(dds,(FXuchar*)data);
1468 break;
1469 case D3DFMT_DXT2:
1470 ok=dds_decompress_DXT2(dds,(FXuchar*)data);
1471 break;
1472 case D3DFMT_DXT3:
1473 ok=dds_decompress_DXT3(dds,(FXuchar*)data);
1474 break;
1475 case D3DFMT_DXT4:
1476 ok=dds_decompress_DXT4(dds,(FXuchar*)data);
1477 break;
1478 case D3DFMT_DXT5:
1479 ok=dds_decompress_DXT5(dds,(FXuchar*)data);
1480 break;
1481 case D3DFMT_ATI1:
1482 ok=dds_decompress_BC4(dds,(FXuchar*)data);
1483 break;
1484 case D3DFMT_ATI2:
1485 ok=dds_decompress_3DC(dds,(FXuchar*)data);
1486 break;
1487 case D3DFMT_RXGB:
1488 ok=dds_decompress_RXGB(dds,(FXuchar*)data);
1489 break;
1490 case D3DFMT_A2XY:
1491 case D3DFMT_UYVY:
1492 case D3DFMT_YUY2:
1493 break;
1494 case D3DFMT_R8G8_B8G8:
1495 ok=dds_decompress_RGBG(dds,(FXuchar*)data);
1496 break;
1497 case D3DFMT_G8R8_G8B8:
1498 ok=dds_decompress_GRGB(dds,(FXuchar*)data);
1499 break;
1500 case D3DFMT_R16F:
1501 ok=dds_decompress_R16F(dds,(FXuchar*)data);
1502 break;
1503 case D3DFMT_G16R16F:
1504 ok=dds_decompress_G16R16F(dds,(FXuchar*)data);
1505 break;
1506 case D3DFMT_A16B16G16R16F:
1507 ok=dds_decompress_A16B16G16R16F(dds,(FXuchar*)data);
1508 break;
1509 case D3DFMT_R32F:
1510 ok=dds_decompress_R32F(dds,(FXuchar*)data);
1511 break;
1512 case D3DFMT_G32R32F:
1513 ok=dds_decompress_G32R32F(dds,(FXuchar*)data);
1514 break;
1515 case D3DFMT_A32B32G32R32F:
1516 ok=dds_decompress_A32B32G32R32F(dds,(FXuchar*)data);
1517 break;
1518 case D3DFMT_R8G8B8:
1519 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x0000FF,0x00FF00,0xFF0000,3);
1520 break;
1521 case D3DFMT_A8R8G8B8:
1522 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x000000FF,0x0000FF00,0x00FF0000,0xFF000000,4);
1523 break;
1524 case D3DFMT_X8R8G8B8:
1525 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x0000FF,0x00FF00,0xFF0000,4);
1526 break;
1527 case D3DFMT_R5G6B5:
1528 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x001F,0x07E0,0xF800,2);
1529 break;
1530 case D3DFMT_X1R5G5B5:
1531 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x001F,0x03E0,0x7C00,2);
1532 break;
1533 case D3DFMT_A1R5G5B5:
1534 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x001F,0x03E0,0x7C00,0x8000,2);
1535 break;
1536 case D3DFMT_A4R4G4B4:
1537 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x000F,0x00F0,0x0F00,0xF000,2);
1538 break;
1539 case D3DFMT_R3G3B2:
1540 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x07,0x38,0xC0,1);
1541 break;
1542 case D3DFMT_A8:
1543 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x00,0x00,0x00,0xFF,1);
1544 break;
1545 case D3DFMT_A8R3G3B2:
1546 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x0003,0x001C,0x00E0,0xFF00,2);
1547 break;
1548 case D3DFMT_X4R4G4B4:
1549 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x000F,0x00F0,0x0F00,2);
1550 break;
1551 case D3DFMT_A8B8G8R8:
1552 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x00FF0000,0x0000FF00,0x000000FF,0xFF000000,4);
1553 break;
1554 case D3DFMT_X8B8G8R8:
1555 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x00FF0000,0x0000FF00,0x000000FF,4);
1556 break;
1557 case D3DFMT_G16R16:
1558 ok=dds_decompress_RGB(dds,(FXuchar*)data,0x00000000,0xFFFF0000,0x0000FFFF,4);
1559 break;
1560 case D3DFMT_A2R10G10B10:
1561 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x000003FF,0x000FFC00,0x3FF00000,0xC0000000,2);
1562 break;
1563 case D3DFMT_A16B16G16R16:
1564 ok=dds_decompress_A16B16G16R16(dds,(FXuchar*)data);
1565 break;
1566 case D3DFMT_P8:
1567 case D3DFMT_L8:
1568 ok=dds_decompress_LUM(dds,(FXuchar*)data,0xFF,1);
1569 break;
1570 case D3DFMT_A8P8:
1571 case D3DFMT_A8L8:
1572 ok=dds_decompress_LUMA(dds,(FXuchar*)data,0x00FF,0xFF00,2);
1573 break;
1574 case D3DFMT_A4L4:
1575 ok=dds_decompress_LUMA(dds,(FXuchar*)data,0x0F,0xF0,1);
1576 break;
1577 case D3DFMT_L16:
1578 ok=dds_decompress_LUM(dds,(FXuchar*)data,0xFFFF,2);
1579 break;
1580 case D3DFMT_A1:
1581 break;
1582 case D3DFMT_A2B10G10R10:
1583 case D3DFMT_A2B10G10R10_XR_BIAS:
1584 ok=dds_decompress_RGBA(dds,(FXuchar*)data,0x3FF00000,0x000FFC00,0x000003FF,0xC0000000,2);
1585 break;
1586 }
1587 }
1588
1589 // RGB format
1590 else if(dds.header.ddpf.dwFlags&DDPF_RGB){
1591 if(dds.header.ddpf.dwFlags&DDPF_ALPHAPIXELS)
1592 ok=dds_decompress_RGBA(dds,(FXuchar*)data,dds.header.ddpf.dwBBitMask,dds.header.ddpf.dwGBitMask,dds.header.ddpf.dwRBitMask,dds.header.ddpf.dwABitMask,(dds.header.ddpf.dwRGBBitCount+7)>>3);
1593 else
1594 ok=dds_decompress_RGB(dds,(FXuchar*)data,dds.header.ddpf.dwBBitMask,dds.header.ddpf.dwGBitMask,dds.header.ddpf.dwRBitMask,(dds.header.ddpf.dwRGBBitCount+7)>>3);
1595 }
1596
1597 // Lumimance format
1598 else if(dds.header.ddpf.dwFlags&DDPF_LUMINANCE){
1599 if(dds.header.ddpf.dwFlags&DDPF_ALPHAPIXELS)
1600 ok=dds_decompress_LUMA(dds,(FXuchar*)data,dds.header.ddpf.dwRBitMask,dds.header.ddpf.dwABitMask,(dds.header.ddpf.dwRGBBitCount+7)/8);
1601 else
1602 ok=dds_decompress_LUM(dds,(FXuchar*)data,dds.header.ddpf.dwRBitMask,(dds.header.ddpf.dwRGBBitCount+7)/8);
1603 }
1604 }
1605
1606 // Free temp array of encoded pixels
1607 freeElms(dds.data);
1608 }
1609 }
1610
1611 // Restore original byte orientation
1612 x:store.swapBytes(swap);
1613
1614 // Done
1615 return ok;
1616 }
1617
1618
1619 // Save a dds file to a stream
fxsaveDDS(FXStream & store,FXColor * data,FXint width,FXint height,FXint depth)1620 FXbool fxsaveDDS(FXStream& store,FXColor* data,FXint width,FXint height,FXint depth){
1621 DDSImage dds;
1622 FXbool swap;
1623
1624 // Must make sense
1625 if(!data || width<=0 || height<=0 || depth<=0) return false;
1626
1627 // Switch byte order for the duration
1628 swap=store.swapBytes();
1629 store.setBigEndian(false);
1630
1631 // Initialize header
1632 dds.magic=DDSD_MAGIC;
1633 dds.header.dwSize=sizeof(DDSHeader);
1634 dds.header.dwFlags=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_MIPMAPCOUNT|DDSD_LINEARSIZE;
1635 dds.header.dwHeight=height;
1636 dds.header.dwWidth=width;
1637 dds.header.dwLinearSize=width*height*depth*4;
1638 dds.header.dwDepth=depth;
1639 dds.header.dwMipMapCount=1;
1640 memset(dds.header.dwReserved1,0,sizeof(dds.header.dwReserved1));
1641 dds.header.ddpf.dwSize=sizeof(DDSPixelFormat);
1642 dds.header.ddpf.dwFlags=DDPF_RGB;
1643 dds.header.ddpf.dwFourCC=0;
1644 dds.header.ddpf.dwRGBBitCount=32;
1645 dds.header.ddpf.dwBBitMask=0x000000ff;
1646 dds.header.ddpf.dwGBitMask=0x0000ff00;
1647 dds.header.ddpf.dwRBitMask=0x00ff0000;
1648 dds.header.ddpf.dwABitMask=0xff000000;
1649 if(1<depth){
1650 dds.header.dwCaps=DDSCAPS_COMPLEX|DDSCAPS_TEXTURE;
1651 dds.header.dwCaps2=DDSCAPS2_VOLUME;
1652 }
1653 else{
1654 dds.header.dwCaps=DDSCAPS_TEXTURE;
1655 dds.header.dwCaps2=0;
1656 }
1657 dds.header.dwCaps3=0;
1658 dds.header.dwCaps4=0;
1659 dds.header.dwReserved2=0;
1660
1661 // Start saving now
1662 store << dds.magic;
1663 store << dds.header.dwSize;
1664 store << dds.header.dwFlags;
1665 store << dds.header.dwHeight;
1666 store << dds.header.dwWidth;
1667 store << dds.header.dwLinearSize;
1668 store << dds.header.dwDepth;
1669 store << dds.header.dwMipMapCount;
1670 store.save(dds.header.dwReserved1,11);
1671 store << dds.header.ddpf.dwSize;
1672 store << dds.header.ddpf.dwFlags;
1673 store << dds.header.ddpf.dwFourCC;
1674 store << dds.header.ddpf.dwRGBBitCount;
1675 store << dds.header.ddpf.dwRBitMask;
1676 store << dds.header.ddpf.dwGBitMask;
1677 store << dds.header.ddpf.dwBBitMask;
1678 store << dds.header.ddpf.dwABitMask;
1679 store << dds.header.dwCaps;
1680 store << dds.header.dwCaps2;
1681 store << dds.header.dwCaps3;
1682 store << dds.header.dwCaps4;
1683 store << dds.header.dwReserved2;
1684
1685 // Data array
1686 store.save(data,width*height*depth);
1687
1688 store.swapBytes(swap);
1689 return true;
1690 }
1691
1692 }
1693