xref: /reactos/dll/win32/windowscodecs/ddsformat.c (revision 197ed01e)
1 /*
2  * Copyright 2020 Ziqing Hui
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  *
19  * Note:
20  *
21  * Uncompressed image:
22  *     For uncompressed formats, a block is equivalent to a pixel.
23  *
24  * Cube map:
25  *     A cube map is equivalent to a 2D texture array which has 6 textures.
26  *     A cube map array is equivalent to a 2D texture array which has cubeCount*6 textures.
27  */
28 
29 #include <stdarg.h>
30 
31 #define COBJMACROS
32 
33 #include "windef.h"
34 #include "winbase.h"
35 #include "objbase.h"
36 
37 #include "wincodecs_private.h"
38 
39 #include "wine/debug.h"
40 
41 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
42 
43 #define DDS_MAGIC 0x20534444
44 #ifndef MAKEFOURCC
45 #define MAKEFOURCC(ch0, ch1, ch2, ch3)  \
46     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) |  \
47     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
48 #endif
49 
50 #define GET_RGB565_R(color)   ((BYTE)(((color) >> 11) & 0x1F))
51 #define GET_RGB565_G(color)   ((BYTE)(((color) >> 5)  & 0x3F))
52 #define GET_RGB565_B(color)   ((BYTE)(((color) >> 0)  & 0x1F))
53 #define MAKE_RGB565(r, g, b)  ((WORD)(((BYTE)(r) << 11) | ((BYTE)(g) << 5) | (BYTE)(b)))
54 #define MAKE_ARGB(a, r, g, b) (((DWORD)(a) << 24) | ((DWORD)(r) << 16) | ((DWORD)(g) << 8) | (DWORD)(b))
55 
56 #define DDPF_ALPHAPIXELS     0x00000001
57 #define DDPF_ALPHA           0x00000002
58 #define DDPF_FOURCC          0x00000004
59 #define DDPF_PALETTEINDEXED8 0x00000020
60 #define DDPF_RGB             0x00000040
61 #define DDPF_LUMINANCE       0x00020000
62 #define DDPF_BUMPDUDV        0x00080000
63 
64 #define DDSCAPS2_CUBEMAP 0x00000200
65 #define DDSCAPS2_VOLUME  0x00200000
66 
67 #define DDS_DIMENSION_TEXTURE1D 2
68 #define DDS_DIMENSION_TEXTURE2D 3
69 #define DDS_DIMENSION_TEXTURE3D 4
70 
71 #define DDS_RESOURCE_MISC_TEXTURECUBE 0x00000004
72 
73 #define DDS_BLOCK_WIDTH  4
74 #define DDS_BLOCK_HEIGHT 4
75 
76 typedef struct {
77     DWORD size;
78     DWORD flags;
79     DWORD fourCC;
80     DWORD rgbBitCount;
81     DWORD rBitMask;
82     DWORD gBitMask;
83     DWORD bBitMask;
84     DWORD aBitMask;
85 } DDS_PIXELFORMAT;
86 
87 typedef struct {
88     DWORD size;
89     DWORD flags;
90     DWORD height;
91     DWORD width;
92     DWORD pitchOrLinearSize;
93     DWORD depth;
94     DWORD mipMapCount;
95     DWORD reserved1[11];
96     DDS_PIXELFORMAT ddspf;
97     DWORD caps;
98     DWORD caps2;
99     DWORD caps3;
100     DWORD caps4;
101     DWORD reserved2;
102 } DDS_HEADER;
103 
104 typedef struct {
105     DWORD dxgiFormat;
106     DWORD resourceDimension;
107     DWORD miscFlag;
108     DWORD arraySize;
109     DWORD miscFlags2;
110 } DDS_HEADER_DXT10;
111 
112 typedef struct dds_info {
113     UINT width;
114     UINT height;
115     UINT depth;
116     UINT mip_levels;
117     UINT array_size;
118     UINT frame_count;
119     UINT data_offset;
120     UINT bytes_per_block; /* for uncompressed format, this means bytes per pixel*/
121     DXGI_FORMAT format;
122     WICDdsDimension dimension;
123     WICDdsAlphaMode alpha_mode;
124     const GUID *pixel_format;
125     UINT pixel_format_bpp;
126 } dds_info;
127 
128 typedef struct dds_frame_info {
129     UINT width;
130     UINT height;
131     DXGI_FORMAT format;
132     UINT bytes_per_block; /* for uncompressed format, this means bytes per pixel*/
133     UINT block_width;
134     UINT block_height;
135     UINT width_in_blocks;
136     UINT height_in_blocks;
137     const GUID *pixel_format;
138     UINT pixel_format_bpp;
139 } dds_frame_info;
140 
141 typedef struct DdsDecoder {
142     IWICBitmapDecoder IWICBitmapDecoder_iface;
143     IWICDdsDecoder IWICDdsDecoder_iface;
144     IWICWineDecoder IWICWineDecoder_iface;
145     LONG ref;
146     BOOL initialized;
147     IStream *stream;
148     CRITICAL_SECTION lock;
149     dds_info info;
150 } DdsDecoder;
151 
152 typedef struct DdsFrameDecode {
153     IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
154     IWICDdsFrameDecode IWICDdsFrameDecode_iface;
155     LONG ref;
156     BYTE *block_data;
157     BYTE *pixel_data;
158     CRITICAL_SECTION lock;
159     dds_frame_info info;
160 } DdsFrameDecode;
161 
162 typedef struct DdsEncoder {
163     IWICBitmapEncoder IWICBitmapEncoder_iface;
164     IWICDdsEncoder IWICDdsEncoder_iface;
165     LONG ref;
166     CRITICAL_SECTION lock;
167     IStream *stream;
168     UINT frame_count;
169     UINT frame_index;
170     BOOL uncommitted_frame;
171     BOOL committed;
172     dds_info info;
173 } DdsEncoder;
174 
175 typedef struct DdsFrameEncode {
176     IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
177     LONG ref;
178     DdsEncoder *parent;
179     BOOL initialized;
180     BOOL frame_created;
181     UINT width;
182     UINT height;
183     double dpi_x;
184     double dpi_y;
185 } DdsFrameEncode;
186 
187 static struct dds_format {
188     DDS_PIXELFORMAT pixel_format;
189     const GUID *wic_format;
190     UINT wic_format_bpp;
191     DXGI_FORMAT dxgi_format;
192 } dds_format_table[] = {
193     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'), 0, 0, 0, 0, 0 },
194       &GUID_WICPixelFormat32bppPBGRA, 32,       DXGI_FORMAT_BC1_UNORM },
195     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0 },
196       &GUID_WICPixelFormat32bppPBGRA, 32,       DXGI_FORMAT_BC2_UNORM },
197     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'), 0, 0, 0, 0, 0 },
198       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC2_UNORM },
199     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '4'), 0, 0, 0, 0, 0 },
200       &GUID_WICPixelFormat32bppPBGRA, 32,       DXGI_FORMAT_BC3_UNORM },
201     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '5'), 0, 0, 0, 0, 0 },
202       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC3_UNORM },
203     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '4', 'U'), 0, 0, 0, 0, 0 },
204       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC4_UNORM },
205     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '4', 'S'), 0, 0, 0, 0, 0 },
206       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC4_SNORM },
207     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '5', 'U'), 0, 0, 0, 0, 0 },
208       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC5_UNORM },
209     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '5', 'S'), 0, 0, 0, 0, 0 },
210       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC5_SNORM },
211     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('A', 'T', 'I', '1'), 0, 0, 0, 0, 0 },
212       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC4_UNORM },
213     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('A', 'T', 'I', '2'), 0, 0, 0, 0, 0 },
214       &GUID_WICPixelFormat32bppBGRA,  32,       DXGI_FORMAT_BC5_UNORM },
215     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('R', 'G', 'B', 'G'), 0, 0, 0, 0, 0 },
216       &GUID_WICPixelFormat32bpp4Channels, 32,   DXGI_FORMAT_R8G8_B8G8_UNORM },
217     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('G', 'R', 'G', 'B'), 0, 0, 0, 0, 0 },
218       &GUID_WICPixelFormat32bpp4Channels, 32,   DXGI_FORMAT_G8R8_G8B8_UNORM },
219     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', '1', '0'), 0, 0, 0, 0, 0 },
220       &GUID_WICPixelFormatUndefined,       0,   DXGI_FORMAT_UNKNOWN },
221     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x24, 0, 0, 0, 0, 0 },
222       &GUID_WICPixelFormat64bppRGBA,       64,  DXGI_FORMAT_R16G16B16A16_UNORM },
223     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x6E, 0, 0, 0, 0, 0 },
224       &GUID_WICPixelFormat64bppRGBA,       64,  DXGI_FORMAT_R16G16B16A16_SNORM },
225     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x6F, 0, 0, 0, 0, 0 },
226       &GUID_WICPixelFormat16bppGrayHalf,   16,  DXGI_FORMAT_R16_FLOAT },
227     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x70, 0, 0, 0, 0, 0 },
228       &GUID_WICPixelFormatUndefined,       0,   DXGI_FORMAT_R16G16_FLOAT },
229     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x71, 0, 0, 0, 0, 0 },
230       &GUID_WICPixelFormat64bppRGBAHalf,   64,  DXGI_FORMAT_R16G16B16A16_FLOAT },
231     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x72, 0, 0, 0, 0, 0 },
232       &GUID_WICPixelFormat32bppGrayFloat,  32,  DXGI_FORMAT_R32_FLOAT },
233     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x73, 0, 0, 0, 0, 0 },
234       &GUID_WICPixelFormatUndefined,       32,  DXGI_FORMAT_R32G32_FLOAT },
235     { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x74, 0, 0, 0, 0, 0 },
236       &GUID_WICPixelFormat128bppRGBAFloat, 128, DXGI_FORMAT_R32G32B32A32_FLOAT },
237     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 32, 0xFF,0xFF00,0xFF0000,0xFF000000 },
238       &GUID_WICPixelFormat32bppRGBA,        32, DXGI_FORMAT_R8G8B8A8_UNORM },
239     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 32, 0xFF,0xFF00,0xFF0000,0 },
240       &GUID_WICPixelFormat32bppRGB,         32, DXGI_FORMAT_UNKNOWN },
241     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 32, 0xFF0000,0xFF00,0xFF,0xFF000000 },
242       &GUID_WICPixelFormat32bppBGRA,        32, DXGI_FORMAT_B8G8R8A8_UNORM },
243     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 32, 0xFF0000,0xFF00,0xFF,0 },
244       &GUID_WICPixelFormat32bppBGR,         32, DXGI_FORMAT_B8G8R8X8_UNORM },
245     /* The red and blue masks are swapped for DXGI_FORMAT_R10G10B10A2_UNORM.
246      * For "correct" one, the RGB masks should be 0x3FF,0xFFC00,0x3FF00000.
247      * see: https://walbourn.github.io/dds-update-and-1010102-problems */
248     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 32, 0x3FF00000,0xFFC00,0x3FF,0xC0000000 },
249       &GUID_WICPixelFormat32bppR10G10B10A2, 32, DXGI_FORMAT_R10G10B10A2_UNORM },
250     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 32, 0x3FF,0xFFC00,0x3FF00000,0xC0000000 },
251       &GUID_WICPixelFormat32bppRGBA1010102, 32, DXGI_FORMAT_R10G10B10A2_UNORM },
252     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB ,      0, 32, 0xFFFF,0xFFFF0000,0,0 },
253       &GUID_WICPixelFormatUndefined,        0,  DXGI_FORMAT_R16G16_UNORM },
254     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB ,      0, 32, 0xFFFFFFFF,0,0,0 },
255       &GUID_WICPixelFormat32bppGrayFloat,   32, DXGI_FORMAT_R32_FLOAT },
256     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB ,      0, 24, 0xFF0000,0x00FF00,0x0000FF,0 },
257       &GUID_WICPixelFormat24bppBGR,         24, DXGI_FORMAT_UNKNOWN },
258     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB ,      0, 24, 0x0000FF,0x00FF00,0xFF0000,0 },
259       &GUID_WICPixelFormat24bppRGB,         24, DXGI_FORMAT_UNKNOWN },
260     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 16, 0xF800,0x7E0,0x1F,0 },
261       &GUID_WICPixelFormat16bppBGR565,      16, DXGI_FORMAT_B5G6R5_UNORM },
262     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 16, 0x7C00,0x3E0,0x1F,0 },
263       &GUID_WICPixelFormat16bppBGR555,      16, DXGI_FORMAT_UNKNOWN },
264     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 16, 0x7C00,0x3E0,0x1F,0x8000 },
265       &GUID_WICPixelFormat16bppBGRA5551,    16, DXGI_FORMAT_B5G5R5A1_UNORM },
266     { { sizeof(DDS_PIXELFORMAT), DDPF_RGB,       0, 16, 0xF00,0xF0,0xF,0xF000 },
267       &GUID_WICPixelFormatUndefined,        0,  DXGI_FORMAT_B4G4R4A4_UNORM },
268     { { sizeof(DDS_PIXELFORMAT), DDPF_ALPHA,     0, 8,  0,0,0,0xFF },
269       &GUID_WICPixelFormat8bppAlpha,        8,  DXGI_FORMAT_A8_UNORM },
270     { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 16, 0xFFFF,0,0,0 },
271       &GUID_WICPixelFormat16bppGray,        16, DXGI_FORMAT_R16_UNORM },
272     { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 16, 0xFF,0,0,0xFF00 },
273       &GUID_WICPixelFormatUndefined,        0,  DXGI_FORMAT_R8G8_UNORM },
274     { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 8,  0xFF,0,0,0 },
275       &GUID_WICPixelFormat8bppGray,         8,  DXGI_FORMAT_R8_UNORM },
276     { { 0 }, &GUID_WICPixelFormat8bppAlpha,          8,   DXGI_FORMAT_A8_UNORM },
277     { { 0 }, &GUID_WICPixelFormat8bppGray,           8,   DXGI_FORMAT_R8_UNORM },
278     { { 0 }, &GUID_WICPixelFormat16bppGray,          16,  DXGI_FORMAT_R16_UNORM },
279     { { 0 }, &GUID_WICPixelFormat16bppGrayHalf,      16,  DXGI_FORMAT_R16_FLOAT },
280     { { 0 }, &GUID_WICPixelFormat16bppBGR565,        16,  DXGI_FORMAT_B5G6R5_UNORM },
281     { { 0 }, &GUID_WICPixelFormat16bppBGRA5551,      16,  DXGI_FORMAT_B5G5R5A1_UNORM },
282     { { 0 }, &GUID_WICPixelFormat32bppGrayFloat,     32,  DXGI_FORMAT_R32_FLOAT },
283     { { 0 }, &GUID_WICPixelFormat32bppRGBA,          32,  DXGI_FORMAT_R8G8B8A8_UNORM },
284     { { 0 }, &GUID_WICPixelFormat32bppBGRA,          32,  DXGI_FORMAT_B8G8R8A8_UNORM },
285     { { 0 }, &GUID_WICPixelFormat32bppBGR,           32,  DXGI_FORMAT_B8G8R8X8_UNORM },
286     { { 0 }, &GUID_WICPixelFormat32bppR10G10B10A2,   32,  DXGI_FORMAT_R10G10B10A2_UNORM },
287     { { 0 }, &GUID_WICPixelFormat32bppRGBE,          32,  DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
288     { { 0 }, &GUID_WICPixelFormat32bppRGBA1010102XR, 32,  DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM },
289     { { 0 }, &GUID_WICPixelFormat64bppRGBA,          64,  DXGI_FORMAT_R16G16B16A16_UNORM },
290     { { 0 }, &GUID_WICPixelFormat64bppRGBAHalf,      64,  DXGI_FORMAT_R16G16B16A16_FLOAT },
291     { { 0 }, &GUID_WICPixelFormat96bppRGBFloat,      96,  DXGI_FORMAT_R32G32B32_FLOAT },
292     { { 0 }, &GUID_WICPixelFormat128bppRGBAFloat,    128, DXGI_FORMAT_R32G32B32A32_FLOAT },
293     { { 0 }, &GUID_WICPixelFormatUndefined,          0,   DXGI_FORMAT_UNKNOWN }
294 };
295 
296 static DXGI_FORMAT compressed_formats[] = {
297     DXGI_FORMAT_BC1_TYPELESS,  DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB,
298     DXGI_FORMAT_BC2_TYPELESS,  DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB,
299     DXGI_FORMAT_BC3_TYPELESS,  DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB,
300     DXGI_FORMAT_BC4_TYPELESS,  DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM,
301     DXGI_FORMAT_BC5_TYPELESS,  DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM,
302     DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16,
303     DXGI_FORMAT_BC7_TYPELESS,  DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB
304 };
305 
306 static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *, UINT, UINT, UINT, IWICBitmapFrameDecode **);
307 
rgb565_to_argb(WORD color,BYTE alpha)308 static DWORD rgb565_to_argb(WORD color, BYTE alpha)
309 {
310     return MAKE_ARGB(alpha, (GET_RGB565_R(color) * 0xFF + 0x0F) / 0x1F,
311                             (GET_RGB565_G(color) * 0xFF + 0x1F) / 0x3F,
312                             (GET_RGB565_B(color) * 0xFF + 0x0F) / 0x1F);
313 }
314 
has_extended_header(DDS_HEADER * header)315 static inline BOOL has_extended_header(DDS_HEADER *header)
316 {
317     return (header->ddspf.flags & DDPF_FOURCC) &&
318            (header->ddspf.fourCC == MAKEFOURCC('D', 'X', '1', '0'));
319 }
320 
get_dimension(DDS_HEADER * header,DDS_HEADER_DXT10 * header_dxt10)321 static WICDdsDimension get_dimension(DDS_HEADER *header, DDS_HEADER_DXT10 *header_dxt10)
322 {
323     if (header_dxt10) {
324         if (header_dxt10->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) return WICDdsTextureCube;
325         switch (header_dxt10->resourceDimension)
326         {
327         case DDS_DIMENSION_TEXTURE1D: return WICDdsTexture1D;
328         case DDS_DIMENSION_TEXTURE2D: return WICDdsTexture2D;
329         case DDS_DIMENSION_TEXTURE3D: return WICDdsTexture3D;
330         default: return WICDdsTexture2D;
331         }
332     } else {
333         if (header->caps2 & DDSCAPS2_CUBEMAP) {
334             return WICDdsTextureCube;
335         } else if (header->caps2 & DDSCAPS2_VOLUME) {
336             return WICDdsTexture3D;
337         } else {
338             return WICDdsTexture2D;
339         }
340     }
341 }
342 
get_dds_format(DDS_PIXELFORMAT * pixel_format)343 static struct dds_format *get_dds_format(DDS_PIXELFORMAT *pixel_format)
344 {
345     UINT i;
346 
347     for (i = 0; i < ARRAY_SIZE(dds_format_table); i++)
348     {
349         if ((pixel_format->flags & dds_format_table[i].pixel_format.flags) &&
350             (pixel_format->fourCC == dds_format_table[i].pixel_format.fourCC) &&
351             (pixel_format->rgbBitCount == dds_format_table[i].pixel_format.rgbBitCount) &&
352             (pixel_format->rBitMask == dds_format_table[i].pixel_format.rBitMask) &&
353             (pixel_format->gBitMask == dds_format_table[i].pixel_format.gBitMask) &&
354             (pixel_format->bBitMask == dds_format_table[i].pixel_format.bBitMask) &&
355             (pixel_format->aBitMask == dds_format_table[i].pixel_format.aBitMask))
356             return dds_format_table + i;
357     }
358 
359     return dds_format_table + ARRAY_SIZE(dds_format_table) - 1;
360 }
361 
get_alpha_mode_from_fourcc(DWORD fourcc)362 static WICDdsAlphaMode get_alpha_mode_from_fourcc(DWORD fourcc)
363 {
364     switch (fourcc)
365     {
366         case MAKEFOURCC('D', 'X', 'T', '1'):
367         case MAKEFOURCC('D', 'X', 'T', '2'):
368         case MAKEFOURCC('D', 'X', 'T', '4'):
369             return WICDdsAlphaModePremultiplied;
370         default:
371             return WICDdsAlphaModeUnknown;
372     }
373 }
374 
get_bytes_per_block_from_format(DXGI_FORMAT format)375 static UINT get_bytes_per_block_from_format(DXGI_FORMAT format)
376 {
377     /* for uncompressed format, return bytes per pixel*/
378     switch (format)
379     {
380         case DXGI_FORMAT_R8_TYPELESS:
381         case DXGI_FORMAT_R8_UNORM:
382         case DXGI_FORMAT_R8_UINT:
383         case DXGI_FORMAT_R8_SNORM:
384         case DXGI_FORMAT_R8_SINT:
385         case DXGI_FORMAT_A8_UNORM:
386             return 1;
387         case DXGI_FORMAT_R8G8_TYPELESS:
388         case DXGI_FORMAT_R8G8_UNORM:
389         case DXGI_FORMAT_R8G8_UINT:
390         case DXGI_FORMAT_R8G8_SNORM:
391         case DXGI_FORMAT_R8G8_SINT:
392         case DXGI_FORMAT_R16_TYPELESS:
393         case DXGI_FORMAT_R16_FLOAT:
394         case DXGI_FORMAT_D16_UNORM:
395         case DXGI_FORMAT_R16_UNORM:
396         case DXGI_FORMAT_R16_UINT:
397         case DXGI_FORMAT_R16_SNORM:
398         case DXGI_FORMAT_R16_SINT:
399         case DXGI_FORMAT_B5G6R5_UNORM:
400         case DXGI_FORMAT_B5G5R5A1_UNORM:
401         case DXGI_FORMAT_B4G4R4A4_UNORM:
402             return 2;
403         case DXGI_FORMAT_R10G10B10A2_TYPELESS:
404         case DXGI_FORMAT_R10G10B10A2_UNORM:
405         case DXGI_FORMAT_R10G10B10A2_UINT:
406         case DXGI_FORMAT_R11G11B10_FLOAT:
407         case DXGI_FORMAT_R8G8B8A8_TYPELESS:
408         case DXGI_FORMAT_R8G8B8A8_UNORM:
409         case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
410         case DXGI_FORMAT_R8G8B8A8_UINT:
411         case DXGI_FORMAT_R8G8B8A8_SNORM:
412         case DXGI_FORMAT_R8G8B8A8_SINT:
413         case DXGI_FORMAT_R16G16_TYPELESS:
414         case DXGI_FORMAT_R16G16_FLOAT:
415         case DXGI_FORMAT_R16G16_UNORM:
416         case DXGI_FORMAT_R16G16_UINT:
417         case DXGI_FORMAT_R16G16_SNORM:
418         case DXGI_FORMAT_R16G16_SINT:
419         case DXGI_FORMAT_R32_TYPELESS:
420         case DXGI_FORMAT_D32_FLOAT:
421         case DXGI_FORMAT_R32_FLOAT:
422         case DXGI_FORMAT_R32_UINT:
423         case DXGI_FORMAT_R32_SINT:
424         case DXGI_FORMAT_R24G8_TYPELESS:
425         case DXGI_FORMAT_D24_UNORM_S8_UINT:
426         case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
427         case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
428         case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
429         case DXGI_FORMAT_R8G8_B8G8_UNORM:
430         case DXGI_FORMAT_G8R8_G8B8_UNORM:
431         case DXGI_FORMAT_B8G8R8A8_UNORM:
432         case DXGI_FORMAT_B8G8R8X8_UNORM:
433         case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
434         case DXGI_FORMAT_B8G8R8A8_TYPELESS:
435         case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
436         case DXGI_FORMAT_B8G8R8X8_TYPELESS:
437         case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
438             return 4;
439         case DXGI_FORMAT_BC1_UNORM:
440         case DXGI_FORMAT_BC1_TYPELESS:
441         case DXGI_FORMAT_BC1_UNORM_SRGB:
442         case DXGI_FORMAT_BC4_TYPELESS:
443         case DXGI_FORMAT_BC4_UNORM:
444         case DXGI_FORMAT_BC4_SNORM:
445         case DXGI_FORMAT_R16G16B16A16_TYPELESS:
446         case DXGI_FORMAT_R16G16B16A16_FLOAT:
447         case DXGI_FORMAT_R16G16B16A16_UNORM:
448         case DXGI_FORMAT_R16G16B16A16_UINT:
449         case DXGI_FORMAT_R16G16B16A16_SNORM:
450         case DXGI_FORMAT_R16G16B16A16_SINT:
451         case DXGI_FORMAT_R32G32_TYPELESS:
452         case DXGI_FORMAT_R32G32_FLOAT:
453         case DXGI_FORMAT_R32G32_UINT:
454         case DXGI_FORMAT_R32G32_SINT:
455         case DXGI_FORMAT_R32G8X24_TYPELESS:
456         case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
457         case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
458         case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
459             return 8;
460         case DXGI_FORMAT_R32G32B32_TYPELESS:
461         case DXGI_FORMAT_R32G32B32_FLOAT:
462         case DXGI_FORMAT_R32G32B32_UINT:
463         case DXGI_FORMAT_R32G32B32_SINT:
464             return 12;
465         case DXGI_FORMAT_BC2_UNORM:
466         case DXGI_FORMAT_BC2_TYPELESS:
467         case DXGI_FORMAT_BC2_UNORM_SRGB:
468         case DXGI_FORMAT_BC3_UNORM:
469         case DXGI_FORMAT_BC3_TYPELESS:
470         case DXGI_FORMAT_BC3_UNORM_SRGB:
471         case DXGI_FORMAT_BC5_TYPELESS:
472         case DXGI_FORMAT_BC5_UNORM:
473         case DXGI_FORMAT_BC5_SNORM:
474         case DXGI_FORMAT_BC6H_TYPELESS:
475         case DXGI_FORMAT_BC6H_UF16:
476         case DXGI_FORMAT_BC6H_SF16:
477         case DXGI_FORMAT_BC7_TYPELESS:
478         case DXGI_FORMAT_BC7_UNORM:
479         case DXGI_FORMAT_BC7_UNORM_SRGB:
480         case DXGI_FORMAT_R32G32B32A32_TYPELESS:
481         case DXGI_FORMAT_R32G32B32A32_FLOAT:
482         case DXGI_FORMAT_R32G32B32A32_UINT:
483         case DXGI_FORMAT_R32G32B32A32_SINT:
484             return 16;
485         default:
486             WARN("DXGI format 0x%x is not supported in DDS decoder\n", format);
487             return 0;
488     }
489 }
490 
get_frame_count(UINT depth,UINT mip_levels,UINT array_size,WICDdsDimension dimension)491 static UINT get_frame_count(UINT depth, UINT mip_levels, UINT array_size, WICDdsDimension dimension)
492 {
493     UINT frame_count, i;
494 
495     if (depth == 1)
496     {
497         frame_count = mip_levels;
498     }
499     else
500     {
501         frame_count = 0;
502         for (i = 0; i < mip_levels; i++)
503         {
504             frame_count += depth;
505             if (depth > 1) depth /= 2;
506         }
507     }
508 
509     frame_count *= array_size;
510     if (dimension == WICDdsTextureCube) frame_count *= 6;
511 
512     return frame_count;
513 }
514 
get_frame_dds_index(UINT index,dds_info * info,UINT * array_index,UINT * mip_level,UINT * slice_index)515 static void get_frame_dds_index(UINT index, dds_info *info, UINT *array_index, UINT *mip_level, UINT *slice_index)
516 {
517     UINT frame_per_texture, depth;
518 
519     if (info->dimension == WICDdsTextureCube)
520         frame_per_texture = info->mip_levels;
521     else
522         frame_per_texture = info->frame_count / info->array_size;
523 
524     *array_index = index / frame_per_texture;
525     *slice_index = index % frame_per_texture;
526     depth = info->depth;
527     *mip_level = 0;
528     while (*slice_index >= depth)
529     {
530         *slice_index -= depth;
531         (*mip_level)++;
532         if (depth > 1) depth /= 2;
533     }
534 }
535 
dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format)536 static const GUID *dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format)
537 {
538     UINT i;
539     for (i = 0; i < ARRAY_SIZE(dds_format_table); i++)
540     {
541         if (dds_format_table[i].pixel_format.size == 0 &&
542             dds_format_table[i].dxgi_format == dxgi_format)
543             return dds_format_table[i].wic_format;
544     }
545     return &GUID_WICPixelFormatUndefined;
546 }
547 
is_compressed(DXGI_FORMAT format)548 static BOOL is_compressed(DXGI_FORMAT format)
549 {
550     UINT i;
551 
552     for (i = 0; i < ARRAY_SIZE(compressed_formats); i++)
553     {
554         if (format == compressed_formats[i]) return TRUE;
555     }
556     return FALSE;
557 }
558 
get_dds_info(dds_info * info,DDS_HEADER * header,DDS_HEADER_DXT10 * header_dxt10)559 static void get_dds_info(dds_info* info, DDS_HEADER *header, DDS_HEADER_DXT10 *header_dxt10)
560 {
561     struct dds_format *format_info;
562 
563     info->width = header->width;
564     info->height = header->height;
565     info->depth = 1;
566     info->mip_levels = 1;
567     info->array_size = 1;
568     if (header->depth) info->depth = header->depth;
569     if (header->mipMapCount) info->mip_levels = header->mipMapCount;
570 
571     if (has_extended_header(header)) {
572         if (header_dxt10->arraySize) info->array_size = header_dxt10->arraySize;
573         info->format = header_dxt10->dxgiFormat;
574         info->dimension = get_dimension(NULL, header_dxt10);
575         info->alpha_mode = header_dxt10->miscFlags2 & 0x00000008;
576         info->data_offset = sizeof(DWORD) + sizeof(*header) + sizeof(*header_dxt10);
577         if (is_compressed(info->format)) {
578             info->pixel_format = (info->alpha_mode == WICDdsAlphaModePremultiplied) ?
579                                  &GUID_WICPixelFormat32bppPBGRA : &GUID_WICPixelFormat32bppBGRA;
580             info->pixel_format_bpp = 32;
581         } else {
582             info->pixel_format = dxgi_format_to_wic_format(info->format);
583             info->pixel_format_bpp = get_bytes_per_block_from_format(info->format) * 8;
584         }
585     } else {
586         format_info = get_dds_format(&header->ddspf);
587         info->format = format_info->dxgi_format;
588         info->dimension = get_dimension(header, NULL);
589         info->alpha_mode = get_alpha_mode_from_fourcc(header->ddspf.fourCC);
590         info->data_offset = sizeof(DWORD) + sizeof(*header);
591         info->pixel_format = format_info->wic_format;
592         info->pixel_format_bpp = format_info->wic_format_bpp;
593     }
594 
595     if (header->ddspf.flags & (DDPF_RGB | DDPF_ALPHA | DDPF_LUMINANCE)) {
596         info->bytes_per_block = header->ddspf.rgbBitCount / 8;
597     } else {
598         info->bytes_per_block = get_bytes_per_block_from_format(info->format);
599     }
600 
601     info->frame_count = get_frame_count(info->depth, info->mip_levels, info->array_size, info->dimension);
602 }
603 
decode_block(const BYTE * block_data,UINT block_count,DXGI_FORMAT format,UINT width,UINT height,DWORD * buffer)604 static void decode_block(const BYTE *block_data, UINT block_count, DXGI_FORMAT format,
605                          UINT width, UINT height, DWORD *buffer)
606 {
607     const BYTE *block, *color_indices, *alpha_indices, *alpha_table;
608     int i, j, x, y, block_x, block_y, color_index, alpha_index;
609     int block_size, color_offset, color_indices_offset;
610     WORD color[4], color_value = 0;
611     BYTE alpha[8], alpha_value = 0;
612 
613     if (format == DXGI_FORMAT_BC1_UNORM) {
614         block_size = 8;
615         color_offset = 0;
616         color_indices_offset = 4;
617     } else {
618         block_size = 16;
619         color_offset = 8;
620         color_indices_offset = 12;
621     }
622     block_x = 0;
623     block_y = 0;
624 
625     for (i = 0; i < block_count; i++)
626     {
627         block = block_data + i * block_size;
628 
629         color[0] = *((WORD *)(block + color_offset));
630         color[1] = *((WORD *)(block + color_offset + 2));
631         color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) * 2 + GET_RGB565_R(color[1]) + 1) / 3),
632                                ((GET_RGB565_G(color[0]) * 2 + GET_RGB565_G(color[1]) + 1) / 3),
633                                ((GET_RGB565_B(color[0]) * 2 + GET_RGB565_B(color[1]) + 1) / 3));
634         color[3] = MAKE_RGB565(((GET_RGB565_R(color[0]) + GET_RGB565_R(color[1]) * 2 + 1) / 3),
635                                ((GET_RGB565_G(color[0]) + GET_RGB565_G(color[1]) * 2 + 1) / 3),
636                                ((GET_RGB565_B(color[0]) + GET_RGB565_B(color[1]) * 2 + 1) / 3));
637 
638         switch (format)
639         {
640             case DXGI_FORMAT_BC1_UNORM:
641                 if (color[0] <= color[1]) {
642                     color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) + GET_RGB565_R(color[1]) + 1) / 2),
643                                            ((GET_RGB565_G(color[0]) + GET_RGB565_G(color[1]) + 1) / 2),
644                                            ((GET_RGB565_B(color[0]) + GET_RGB565_B(color[1]) + 1) / 2));
645                     color[3] = 0;
646                 }
647                 break;
648             case DXGI_FORMAT_BC2_UNORM:
649                 alpha_table = block;
650                 break;
651             case DXGI_FORMAT_BC3_UNORM:
652                 alpha[0] = *block;
653                 alpha[1] = *(block + 1);
654                 if (alpha[0] > alpha[1]) {
655                     for (j = 2; j < 8; j++)
656                     {
657                         alpha[j] = (BYTE)((alpha[0] * (8 - j) + alpha[1] * (j - 1) + 3) / 7);
658                     }
659                 } else {
660                     for (j = 2; j < 6; j++)
661                     {
662                         alpha[j] = (BYTE)((alpha[0] * (6 - j) + alpha[1] * (j - 1) + 2) / 5);
663                     }
664                     alpha[6] = 0;
665                     alpha[7] = 0xFF;
666                 }
667                 alpha_indices = block + 2;
668                 break;
669             default:
670                 break;
671         }
672 
673         color_indices = block + color_indices_offset;
674         for (j = 0; j < 16; j++)
675         {
676             x = block_x + j % 4;
677             y = block_y + j / 4;
678             if (x >= width || y >= height) continue;
679 
680             color_index = (color_indices[j / 4] >> ((j % 4) * 2)) & 0x3;
681             color_value = color[color_index];
682 
683             switch (format)
684             {
685                 case DXGI_FORMAT_BC1_UNORM:
686                     if ((color[0] <= color[1]) && !color_value) {
687                         color_value = 0;
688                         alpha_value = 0;
689                     } else {
690                         alpha_value = 0xFF;
691                     }
692                     break;
693                 case DXGI_FORMAT_BC2_UNORM:
694                     alpha_value = (alpha_table[j / 2] >> (j % 2) * 4) & 0xF;
695                     alpha_value = (BYTE)((alpha_value * 0xFF + 0x7)/ 0xF);
696                     break;
697                 case DXGI_FORMAT_BC3_UNORM:
698                     alpha_index = (*((DWORD *)(alpha_indices + (j / 8) * 3)) >> ((j % 8) * 3)) & 0x7;
699                     alpha_value = alpha[alpha_index];
700                     break;
701                 default:
702                     break;
703             }
704             buffer[x + y * width] = rgb565_to_argb(color_value, alpha_value);
705         }
706 
707         block_x += DDS_BLOCK_WIDTH;
708         if (block_x >= width) {
709             block_x = 0;
710             block_y += DDS_BLOCK_HEIGHT;
711         }
712     }
713 }
714 
impl_from_IWICBitmapDecoder(IWICBitmapDecoder * iface)715 static inline DdsDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
716 {
717     return CONTAINING_RECORD(iface, DdsDecoder, IWICBitmapDecoder_iface);
718 }
719 
impl_from_IWICDdsDecoder(IWICDdsDecoder * iface)720 static inline DdsDecoder *impl_from_IWICDdsDecoder(IWICDdsDecoder *iface)
721 {
722     return CONTAINING_RECORD(iface, DdsDecoder, IWICDdsDecoder_iface);
723 }
724 
impl_from_IWICWineDecoder(IWICWineDecoder * iface)725 static inline DdsDecoder *impl_from_IWICWineDecoder(IWICWineDecoder *iface)
726 {
727     return CONTAINING_RECORD(iface, DdsDecoder, IWICWineDecoder_iface);
728 }
729 
impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode * iface)730 static inline DdsFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
731 {
732     return CONTAINING_RECORD(iface, DdsFrameDecode, IWICBitmapFrameDecode_iface);
733 }
734 
impl_from_IWICDdsFrameDecode(IWICDdsFrameDecode * iface)735 static inline DdsFrameDecode *impl_from_IWICDdsFrameDecode(IWICDdsFrameDecode *iface)
736 {
737     return CONTAINING_RECORD(iface, DdsFrameDecode, IWICDdsFrameDecode_iface);
738 }
739 
impl_from_IWICBitmapEncoder(IWICBitmapEncoder * iface)740 static inline DdsEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
741 {
742     return CONTAINING_RECORD(iface, DdsEncoder, IWICBitmapEncoder_iface);
743 }
744 
impl_from_IWICDdsEncoder(IWICDdsEncoder * iface)745 static inline DdsEncoder *impl_from_IWICDdsEncoder(IWICDdsEncoder *iface)
746 {
747     return CONTAINING_RECORD(iface, DdsEncoder, IWICDdsEncoder_iface);
748 }
749 
impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode * iface)750 static inline DdsFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
751 {
752     return CONTAINING_RECORD(iface, DdsFrameEncode, IWICBitmapFrameEncode_iface);
753 }
754 
DdsFrameDecode_QueryInterface(IWICBitmapFrameDecode * iface,REFIID iid,void ** ppv)755 static HRESULT WINAPI DdsFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
756                                                     void **ppv)
757 {
758     DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
759     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
760 
761     if (!ppv) return E_INVALIDARG;
762 
763     if (IsEqualIID(&IID_IUnknown, iid) ||
764         IsEqualIID(&IID_IWICBitmapSource, iid) ||
765         IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) {
766         *ppv = &This->IWICBitmapFrameDecode_iface;
767     } else if (IsEqualGUID(&IID_IWICDdsFrameDecode, iid)) {
768         *ppv = &This->IWICDdsFrameDecode_iface;
769     } else {
770         *ppv = NULL;
771         return E_NOINTERFACE;
772     }
773 
774     IUnknown_AddRef((IUnknown*)*ppv);
775     return S_OK;
776 }
777 
DdsFrameDecode_AddRef(IWICBitmapFrameDecode * iface)778 static ULONG WINAPI DdsFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
779 {
780     DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
781     ULONG ref = InterlockedIncrement(&This->ref);
782 
783     TRACE("(%p) refcount=%lu\n", iface, ref);
784 
785     return ref;
786 }
787 
DdsFrameDecode_Release(IWICBitmapFrameDecode * iface)788 static ULONG WINAPI DdsFrameDecode_Release(IWICBitmapFrameDecode *iface)
789 {
790     DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
791     ULONG ref = InterlockedDecrement(&This->ref);
792 
793     TRACE("(%p) refcount=%lu\n", iface, ref);
794 
795     if (ref == 0) {
796         if (This->pixel_data != This->block_data) free(This->pixel_data);
797         free(This->block_data);
798         free(This);
799     }
800 
801     return ref;
802 }
803 
DdsFrameDecode_GetSize(IWICBitmapFrameDecode * iface,UINT * puiWidth,UINT * puiHeight)804 static HRESULT WINAPI DdsFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
805                                              UINT *puiWidth, UINT *puiHeight)
806 {
807     DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
808 
809     if (!puiWidth || !puiHeight) return E_INVALIDARG;
810 
811     *puiWidth = This->info.width;
812     *puiHeight = This->info.height;
813 
814     TRACE("(%p) -> (%d,%d)\n", iface, *puiWidth, *puiHeight);
815 
816     return S_OK;
817 }
818 
DdsFrameDecode_GetPixelFormat(IWICBitmapFrameDecode * iface,WICPixelFormatGUID * pPixelFormat)819 static HRESULT WINAPI DdsFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
820                                                     WICPixelFormatGUID *pPixelFormat)
821 {
822     DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
823 
824     if (!pPixelFormat) return E_INVALIDARG;
825 
826     *pPixelFormat = *This->info.pixel_format;
827 
828     TRACE("(%p) -> %s\n", iface, debugstr_guid(pPixelFormat));
829 
830     return S_OK;
831 }
832 
DdsFrameDecode_GetResolution(IWICBitmapFrameDecode * iface,double * pDpiX,double * pDpiY)833 static HRESULT WINAPI DdsFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
834                                                    double *pDpiX, double *pDpiY)
835 {
836     FIXME("(%p,%p,%p): stub.\n", iface, pDpiX, pDpiY);
837 
838     return E_NOTIMPL;
839 }
840 
DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode * iface,IWICPalette * pIPalette)841 static HRESULT WINAPI DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
842                                                  IWICPalette *pIPalette)
843 {
844     FIXME("(%p,%p): stub.\n", iface, pIPalette);
845 
846     return E_NOTIMPL;
847 }
848 
DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode * iface,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer)849 static HRESULT WINAPI DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
850                                                 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
851 {
852     DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
853     UINT bpp, frame_stride, frame_size;
854     INT x, y, width, height;
855     HRESULT hr;
856 
857     TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
858 
859     if (!pbBuffer) return E_INVALIDARG;
860 
861     bpp = This->info.pixel_format_bpp;
862     if (!bpp) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
863 
864     frame_stride = This->info.width * bpp / 8;
865     frame_size = frame_stride * This->info.height;
866     if (!prc) {
867         if (cbStride < frame_stride) return E_INVALIDARG;
868         if (cbBufferSize < frame_size) return WINCODEC_ERR_INSUFFICIENTBUFFER;
869     } else {
870         x = prc->X;
871         y = prc->Y;
872         width = prc->Width;
873         height = prc->Height;
874         if (x < 0 || y < 0 || width <= 0 || height <= 0 ||
875             x + width > This->info.width ||
876             y + height > This->info.height) {
877             return E_INVALIDARG;
878         }
879         if (cbStride < width * bpp / 8) return E_INVALIDARG;
880         if (cbBufferSize < cbStride * height) return WINCODEC_ERR_INSUFFICIENTBUFFER;
881     }
882 
883     EnterCriticalSection(&This->lock);
884 
885     if (!This->pixel_data) {
886         if (is_compressed(This->info.format)) {
887             This->pixel_data = malloc(frame_size);
888             if (!This->pixel_data) {
889                 hr = E_OUTOFMEMORY;
890                 goto end;
891             }
892             decode_block(This->block_data, This->info.width_in_blocks * This->info.height_in_blocks, This->info.format,
893                          This->info.width, This->info.height, (DWORD *)This->pixel_data);
894         } else {
895             This->pixel_data = This->block_data;
896         }
897     }
898 
899     hr = copy_pixels(bpp, This->pixel_data, This->info.width, This->info.height, frame_stride,
900                      prc, cbStride, cbBufferSize, pbBuffer);
901 
902 end:
903     LeaveCriticalSection(&This->lock);
904 
905     return hr;
906 }
907 
DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode * iface,IWICMetadataQueryReader ** ppIMetadataQueryReader)908 static HRESULT WINAPI DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
909                                                             IWICMetadataQueryReader **ppIMetadataQueryReader)
910 {
911     FIXME("(%p,%p): stub.\n", iface, ppIMetadataQueryReader);
912 
913     return E_NOTIMPL;
914 }
915 
DdsFrameDecode_GetColorContexts(IWICBitmapFrameDecode * iface,UINT cCount,IWICColorContext ** ppIColorContexts,UINT * pcActualCount)916 static HRESULT WINAPI DdsFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
917                                                       UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
918 {
919     FIXME("(%p,%u,%p,%p): stub.\n", iface, cCount, ppIColorContexts, pcActualCount);
920 
921     return E_NOTIMPL;
922 }
923 
DdsFrameDecode_GetThumbnail(IWICBitmapFrameDecode * iface,IWICBitmapSource ** ppIThumbnail)924 static HRESULT WINAPI DdsFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
925                                                   IWICBitmapSource **ppIThumbnail)
926 {
927     FIXME("(%p,%p): stub.\n", iface, ppIThumbnail);
928 
929     return E_NOTIMPL;
930 }
931 
932 static const IWICBitmapFrameDecodeVtbl DdsFrameDecode_Vtbl = {
933     DdsFrameDecode_QueryInterface,
934     DdsFrameDecode_AddRef,
935     DdsFrameDecode_Release,
936     DdsFrameDecode_GetSize,
937     DdsFrameDecode_GetPixelFormat,
938     DdsFrameDecode_GetResolution,
939     DdsFrameDecode_CopyPalette,
940     DdsFrameDecode_CopyPixels,
941     DdsFrameDecode_GetMetadataQueryReader,
942     DdsFrameDecode_GetColorContexts,
943     DdsFrameDecode_GetThumbnail
944 };
945 
DdsFrameDecode_Dds_QueryInterface(IWICDdsFrameDecode * iface,REFIID iid,void ** ppv)946 static HRESULT WINAPI DdsFrameDecode_Dds_QueryInterface(IWICDdsFrameDecode *iface,
947                                                         REFIID iid, void **ppv)
948 {
949     DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
950     return DdsFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
951 }
952 
DdsFrameDecode_Dds_AddRef(IWICDdsFrameDecode * iface)953 static ULONG WINAPI DdsFrameDecode_Dds_AddRef(IWICDdsFrameDecode *iface)
954 {
955     DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
956     return DdsFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
957 }
958 
DdsFrameDecode_Dds_Release(IWICDdsFrameDecode * iface)959 static ULONG WINAPI DdsFrameDecode_Dds_Release(IWICDdsFrameDecode *iface)
960 {
961     DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
962     return DdsFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
963 }
964 
DdsFrameDecode_Dds_GetSizeInBlocks(IWICDdsFrameDecode * iface,UINT * widthInBlocks,UINT * heightInBlocks)965 static HRESULT WINAPI DdsFrameDecode_Dds_GetSizeInBlocks(IWICDdsFrameDecode *iface,
966                                                          UINT *widthInBlocks, UINT *heightInBlocks)
967 {
968     DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
969 
970     if (!widthInBlocks || !heightInBlocks) return E_INVALIDARG;
971 
972     *widthInBlocks = This->info.width_in_blocks;
973     *heightInBlocks = This->info.height_in_blocks;
974 
975     TRACE("(%p,%p,%p) -> (%d,%d)\n", iface, widthInBlocks, heightInBlocks, *widthInBlocks, *heightInBlocks);
976 
977     return S_OK;
978 }
979 
DdsFrameDecode_Dds_GetFormatInfo(IWICDdsFrameDecode * iface,WICDdsFormatInfo * formatInfo)980 static HRESULT WINAPI DdsFrameDecode_Dds_GetFormatInfo(IWICDdsFrameDecode *iface,
981                                                        WICDdsFormatInfo *formatInfo)
982 {
983     DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
984 
985     if (!formatInfo) return E_INVALIDARG;
986 
987     formatInfo->DxgiFormat = This->info.format;
988     formatInfo->BytesPerBlock = This->info.bytes_per_block;
989     formatInfo->BlockWidth = This->info.block_width;
990     formatInfo->BlockHeight = This->info.block_height;
991 
992     TRACE("(%p,%p) -> (0x%x,%d,%d,%d)\n", iface, formatInfo,
993           formatInfo->DxgiFormat, formatInfo->BytesPerBlock, formatInfo->BlockWidth, formatInfo->BlockHeight);
994 
995     return S_OK;
996 }
997 
DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode * iface,const WICRect * boundsInBlocks,UINT stride,UINT bufferSize,BYTE * buffer)998 static HRESULT WINAPI DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode *iface,
999                                                     const WICRect *boundsInBlocks, UINT stride, UINT bufferSize,
1000                                                     BYTE *buffer)
1001 {
1002     DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
1003     int x, y, width, height;
1004     UINT bytes_per_block, frame_stride, frame_size;
1005 
1006     TRACE("(%p,%p,%u,%u,%p)\n", iface, boundsInBlocks, stride, bufferSize, buffer);
1007 
1008     if (!buffer) return E_INVALIDARG;
1009 
1010     bytes_per_block = This->info.bytes_per_block;
1011     frame_stride = This->info.width_in_blocks * bytes_per_block;
1012     frame_size = frame_stride * This->info.height_in_blocks;
1013 
1014     if (!boundsInBlocks) {
1015         if (stride < frame_stride) return E_INVALIDARG;
1016         if (bufferSize < frame_size) return E_INVALIDARG;
1017     } else {
1018         x = boundsInBlocks->X;
1019         y = boundsInBlocks->Y;
1020         width = boundsInBlocks->Width;
1021         height = boundsInBlocks->Height;
1022         if (x < 0 || y < 0 || width <= 0 || height <= 0 ||
1023             x + width > This->info.width_in_blocks ||
1024             y + height > This->info.height_in_blocks) {
1025             return E_INVALIDARG;
1026         }
1027         if (stride < width * bytes_per_block) return E_INVALIDARG;
1028         if (bufferSize < stride * height) return E_INVALIDARG;
1029     }
1030 
1031     return copy_pixels(This->info.bytes_per_block * 8, This->block_data, This->info.width_in_blocks,
1032                        This->info.height_in_blocks, frame_stride, boundsInBlocks, stride, bufferSize, buffer);
1033 }
1034 
1035 static const IWICDdsFrameDecodeVtbl DdsFrameDecode_Dds_Vtbl = {
1036     DdsFrameDecode_Dds_QueryInterface,
1037     DdsFrameDecode_Dds_AddRef,
1038     DdsFrameDecode_Dds_Release,
1039     DdsFrameDecode_Dds_GetSizeInBlocks,
1040     DdsFrameDecode_Dds_GetFormatInfo,
1041     DdsFrameDecode_Dds_CopyBlocks
1042 };
1043 
DdsFrameDecode_CreateInstance(DdsFrameDecode ** frame_decode)1044 static HRESULT DdsFrameDecode_CreateInstance(DdsFrameDecode **frame_decode)
1045 {
1046     DdsFrameDecode *result;
1047 
1048     result = malloc(sizeof(*result));
1049     if (!result) return E_OUTOFMEMORY;
1050 
1051     result->IWICBitmapFrameDecode_iface.lpVtbl = &DdsFrameDecode_Vtbl;
1052     result->IWICDdsFrameDecode_iface.lpVtbl = &DdsFrameDecode_Dds_Vtbl;
1053     result->ref = 1;
1054 #ifdef __REACTOS__
1055     InitializeCriticalSection(&result->lock);
1056 #else
1057     InitializeCriticalSectionEx(&result->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
1058 #endif
1059     result->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DdsFrameDecode.lock");
1060 
1061     *frame_decode = result;
1062     return S_OK;
1063 }
1064 
DdsDecoder_QueryInterface(IWICBitmapDecoder * iface,REFIID iid,void ** ppv)1065 static HRESULT WINAPI DdsDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
1066                                                 void **ppv)
1067 {
1068     DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
1069     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1070 
1071     if (!ppv) return E_INVALIDARG;
1072 
1073     if (IsEqualIID(&IID_IUnknown, iid) ||
1074         IsEqualIID(&IID_IWICBitmapDecoder, iid)) {
1075         *ppv = &This->IWICBitmapDecoder_iface;
1076     } else if (IsEqualIID(&IID_IWICDdsDecoder, iid)) {
1077         *ppv = &This->IWICDdsDecoder_iface;
1078     } else if (IsEqualIID(&IID_IWICWineDecoder, iid)) {
1079         *ppv = &This->IWICWineDecoder_iface;
1080     } else {
1081         *ppv = NULL;
1082         return E_NOINTERFACE;
1083     }
1084 
1085     IUnknown_AddRef((IUnknown*)*ppv);
1086     return S_OK;
1087 }
1088 
DdsDecoder_AddRef(IWICBitmapDecoder * iface)1089 static ULONG WINAPI DdsDecoder_AddRef(IWICBitmapDecoder *iface)
1090 {
1091     DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
1092     ULONG ref = InterlockedIncrement(&This->ref);
1093 
1094     TRACE("(%p) refcount=%lu\n", iface, ref);
1095 
1096     return ref;
1097 }
1098 
DdsDecoder_Release(IWICBitmapDecoder * iface)1099 static ULONG WINAPI DdsDecoder_Release(IWICBitmapDecoder *iface)
1100 {
1101     DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
1102     ULONG ref = InterlockedDecrement(&This->ref);
1103 
1104     TRACE("(%p) refcount=%lu\n", iface, ref);
1105 
1106     if (ref == 0)
1107     {
1108         This->lock.DebugInfo->Spare[0] = 0;
1109         DeleteCriticalSection(&This->lock);
1110         if (This->stream) IStream_Release(This->stream);
1111         free(This);
1112     }
1113 
1114     return ref;
1115 }
1116 
DdsDecoder_QueryCapability(IWICBitmapDecoder * iface,IStream * stream,DWORD * capability)1117 static HRESULT WINAPI DdsDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
1118                                                  DWORD *capability)
1119 {
1120     FIXME("(%p,%p,%p): stub.\n", iface, stream, capability);
1121 
1122     return E_NOTIMPL;
1123 }
1124 
DdsDecoder_Initialize(IWICBitmapDecoder * iface,IStream * pIStream,WICDecodeOptions cacheOptions)1125 static HRESULT WINAPI DdsDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
1126                                             WICDecodeOptions cacheOptions)
1127 {
1128     DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
1129     HRESULT hr;
1130 
1131     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
1132 
1133     EnterCriticalSection(&This->lock);
1134 
1135     hr = IWICWineDecoder_Initialize(&This->IWICWineDecoder_iface, pIStream, cacheOptions);
1136     if (FAILED(hr)) goto end;
1137 
1138     if (This->info.dimension == WICDdsTextureCube ||
1139         (This->info.format != DXGI_FORMAT_BC1_UNORM &&
1140          This->info.format != DXGI_FORMAT_BC2_UNORM &&
1141          This->info.format != DXGI_FORMAT_BC3_UNORM)) {
1142         IStream_Release(pIStream);
1143         This->stream = NULL;
1144         This->initialized = FALSE;
1145         hr = WINCODEC_ERR_BADHEADER;
1146     }
1147 
1148 end:
1149     LeaveCriticalSection(&This->lock);
1150 
1151     return hr;
1152 }
1153 
DdsDecoder_GetContainerFormat(IWICBitmapDecoder * iface,GUID * pguidContainerFormat)1154 static HRESULT WINAPI DdsDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
1155                                                     GUID *pguidContainerFormat)
1156 {
1157     TRACE("(%p,%p)\n", iface, pguidContainerFormat);
1158 
1159     memcpy(pguidContainerFormat, &GUID_ContainerFormatDds, sizeof(GUID));
1160 
1161     return S_OK;
1162 }
1163 
DdsDecoder_GetDecoderInfo(IWICBitmapDecoder * iface,IWICBitmapDecoderInfo ** ppIDecoderInfo)1164 static HRESULT WINAPI DdsDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
1165                                                 IWICBitmapDecoderInfo **ppIDecoderInfo)
1166 {
1167     TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
1168 
1169     return get_decoder_info(&CLSID_WICDdsDecoder, ppIDecoderInfo);
1170 }
1171 
DdsDecoder_CopyPalette(IWICBitmapDecoder * iface,IWICPalette * pIPalette)1172 static HRESULT WINAPI DdsDecoder_CopyPalette(IWICBitmapDecoder *iface,
1173                                              IWICPalette *pIPalette)
1174 {
1175     TRACE("(%p,%p)\n", iface, pIPalette);
1176 
1177     return WINCODEC_ERR_PALETTEUNAVAILABLE;
1178 }
1179 
DdsDecoder_GetMetadataQueryReader(IWICBitmapDecoder * iface,IWICMetadataQueryReader ** ppIMetadataQueryReader)1180 static HRESULT WINAPI DdsDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
1181                                                         IWICMetadataQueryReader **ppIMetadataQueryReader)
1182 {
1183     if (!ppIMetadataQueryReader) return E_INVALIDARG;
1184 
1185     FIXME("(%p,%p)\n", iface, ppIMetadataQueryReader);
1186 
1187     return E_NOTIMPL;
1188 }
1189 
DdsDecoder_GetPreview(IWICBitmapDecoder * iface,IWICBitmapSource ** ppIBitmapSource)1190 static HRESULT WINAPI DdsDecoder_GetPreview(IWICBitmapDecoder *iface,
1191                                             IWICBitmapSource **ppIBitmapSource)
1192 {
1193     TRACE("(%p,%p)\n", iface, ppIBitmapSource);
1194 
1195     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1196 }
1197 
DdsDecoder_GetColorContexts(IWICBitmapDecoder * iface,UINT cCount,IWICColorContext ** ppDdslorContexts,UINT * pcActualCount)1198 static HRESULT WINAPI DdsDecoder_GetColorContexts(IWICBitmapDecoder *iface,
1199                                                   UINT cCount, IWICColorContext **ppDdslorContexts, UINT *pcActualCount)
1200 {
1201     TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppDdslorContexts, pcActualCount);
1202 
1203     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1204 }
1205 
DdsDecoder_GetThumbnail(IWICBitmapDecoder * iface,IWICBitmapSource ** ppIThumbnail)1206 static HRESULT WINAPI DdsDecoder_GetThumbnail(IWICBitmapDecoder *iface,
1207                                               IWICBitmapSource **ppIThumbnail)
1208 {
1209     TRACE("(%p,%p)\n", iface, ppIThumbnail);
1210 
1211     return WINCODEC_ERR_CODECNOTHUMBNAIL;
1212 }
1213 
DdsDecoder_GetFrameCount(IWICBitmapDecoder * iface,UINT * pCount)1214 static HRESULT WINAPI DdsDecoder_GetFrameCount(IWICBitmapDecoder *iface,
1215                                                UINT *pCount)
1216 {
1217     DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
1218 
1219     if (!pCount) return E_INVALIDARG;
1220     if (!This->initialized) return WINCODEC_ERR_WRONGSTATE;
1221 
1222     EnterCriticalSection(&This->lock);
1223 
1224     *pCount = This->info.frame_count;
1225 
1226     LeaveCriticalSection(&This->lock);
1227 
1228     TRACE("(%p) -> %d\n", iface, *pCount);
1229 
1230     return S_OK;
1231 }
1232 
DdsDecoder_GetFrame(IWICBitmapDecoder * iface,UINT index,IWICBitmapFrameDecode ** ppIBitmapFrame)1233 static HRESULT WINAPI DdsDecoder_GetFrame(IWICBitmapDecoder *iface,
1234                                           UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
1235 {
1236     DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
1237     UINT array_index, mip_level, slice_index;
1238 
1239     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
1240 
1241     if (!ppIBitmapFrame) return E_INVALIDARG;
1242 
1243     EnterCriticalSection(&This->lock);
1244 
1245     if (!This->initialized) {
1246         LeaveCriticalSection(&This->lock);
1247         return WINCODEC_ERR_WRONGSTATE;
1248     }
1249 
1250     get_frame_dds_index(index, &This->info, &array_index, &mip_level, &slice_index);
1251 
1252     LeaveCriticalSection(&This->lock);
1253 
1254     return DdsDecoder_Dds_GetFrame(&This->IWICDdsDecoder_iface, array_index, mip_level, slice_index, ppIBitmapFrame);
1255 }
1256 
1257 static const IWICBitmapDecoderVtbl DdsDecoder_Vtbl = {
1258         DdsDecoder_QueryInterface,
1259         DdsDecoder_AddRef,
1260         DdsDecoder_Release,
1261         DdsDecoder_QueryCapability,
1262         DdsDecoder_Initialize,
1263         DdsDecoder_GetContainerFormat,
1264         DdsDecoder_GetDecoderInfo,
1265         DdsDecoder_CopyPalette,
1266         DdsDecoder_GetMetadataQueryReader,
1267         DdsDecoder_GetPreview,
1268         DdsDecoder_GetColorContexts,
1269         DdsDecoder_GetThumbnail,
1270         DdsDecoder_GetFrameCount,
1271         DdsDecoder_GetFrame
1272 };
1273 
DdsDecoder_Dds_QueryInterface(IWICDdsDecoder * iface,REFIID iid,void ** ppv)1274 static HRESULT WINAPI DdsDecoder_Dds_QueryInterface(IWICDdsDecoder *iface,
1275                                                     REFIID iid, void **ppv)
1276 {
1277     DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
1278     return DdsDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
1279 }
1280 
DdsDecoder_Dds_AddRef(IWICDdsDecoder * iface)1281 static ULONG WINAPI DdsDecoder_Dds_AddRef(IWICDdsDecoder *iface)
1282 {
1283     DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
1284     return DdsDecoder_AddRef(&This->IWICBitmapDecoder_iface);
1285 }
1286 
DdsDecoder_Dds_Release(IWICDdsDecoder * iface)1287 static ULONG WINAPI DdsDecoder_Dds_Release(IWICDdsDecoder *iface)
1288 {
1289     DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
1290     return DdsDecoder_Release(&This->IWICBitmapDecoder_iface);
1291 }
1292 
DdsDecoder_Dds_GetParameters(IWICDdsDecoder * iface,WICDdsParameters * parameters)1293 static HRESULT WINAPI DdsDecoder_Dds_GetParameters(IWICDdsDecoder *iface,
1294                                                    WICDdsParameters *parameters)
1295 {
1296     DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
1297     HRESULT hr;
1298 
1299     if (!parameters) return E_INVALIDARG;
1300 
1301     EnterCriticalSection(&This->lock);
1302 
1303     if (!This->initialized) {
1304         hr = WINCODEC_ERR_WRONGSTATE;
1305         goto end;
1306     }
1307 
1308     parameters->Width = This->info.width;
1309     parameters->Height = This->info.height;
1310     parameters->Depth = This->info.depth;
1311     parameters->MipLevels = This->info.mip_levels;
1312     parameters->ArraySize = This->info.array_size;
1313     parameters->DxgiFormat = This->info.format;
1314     parameters->Dimension = This->info.dimension;
1315     parameters->AlphaMode = This->info.alpha_mode;
1316 
1317     TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x dimension=0x%x alphaMode=0x%x)\n",
1318           iface, parameters->Width, parameters->Height, parameters->Depth, parameters->MipLevels,
1319           parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension, parameters->AlphaMode);
1320 
1321     hr = S_OK;
1322 
1323 end:
1324     LeaveCriticalSection(&This->lock);
1325 
1326     return hr;
1327 }
1328 
DdsDecoder_Dds_GetFrame(IWICDdsDecoder * iface,UINT arrayIndex,UINT mipLevel,UINT sliceIndex,IWICBitmapFrameDecode ** bitmapFrame)1329 static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface,
1330                                               UINT arrayIndex, UINT mipLevel, UINT sliceIndex,
1331                                               IWICBitmapFrameDecode **bitmapFrame)
1332 {
1333     DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
1334     HRESULT hr;
1335     LARGE_INTEGER seek;
1336     UINT width, height, depth, block_width, block_height, width_in_blocks, height_in_blocks, size;
1337     UINT frame_width = 0, frame_height = 0, frame_width_in_blocks = 0, frame_height_in_blocks = 0, frame_size = 0;
1338     UINT bytes_per_block, i;
1339     DWORD bytesread;
1340     DdsFrameDecode *frame_decode = NULL;
1341 
1342     TRACE("(%p,%u,%u,%u,%p)\n", iface, arrayIndex, mipLevel, sliceIndex, bitmapFrame);
1343 
1344     if (!bitmapFrame) return E_INVALIDARG;
1345 
1346     EnterCriticalSection(&This->lock);
1347 
1348     if (!This->initialized) {
1349         hr = WINCODEC_ERR_WRONGSTATE;
1350         goto end;
1351     }
1352 
1353     if ((arrayIndex >= This->info.array_size && This->info.dimension != WICDdsTextureCube) ||
1354         (arrayIndex >= This->info.array_size * 6) ||
1355         (mipLevel   >= This->info.mip_levels) ||
1356         (sliceIndex >= This->info.depth)) {
1357         hr = E_INVALIDARG;
1358         goto end;
1359     }
1360 
1361     if (is_compressed(This->info.format)) {
1362         block_width = DDS_BLOCK_WIDTH;
1363         block_height = DDS_BLOCK_HEIGHT;
1364     } else {
1365         block_width = 1;
1366         block_height = 1;
1367     }
1368     bytes_per_block = This->info.bytes_per_block;
1369     seek.QuadPart = This->info.data_offset;
1370 
1371     width = This->info.width;
1372     height = This->info.height;
1373     depth = This->info.depth;
1374     for (i = 0; i < This->info.mip_levels; i++)
1375     {
1376         width_in_blocks = (width + block_width - 1) / block_width;
1377         height_in_blocks = (height + block_height - 1) / block_height;
1378         size = width_in_blocks * height_in_blocks * bytes_per_block;
1379 
1380         if (i < mipLevel)  {
1381             seek.QuadPart += size * depth;
1382         } else if (i == mipLevel){
1383             seek.QuadPart += size * sliceIndex;
1384             frame_width = width;
1385             frame_height = height;
1386             frame_width_in_blocks = width_in_blocks;
1387             frame_height_in_blocks = height_in_blocks;
1388             frame_size = frame_width_in_blocks * frame_height_in_blocks * bytes_per_block;
1389             if (arrayIndex == 0) break;
1390         }
1391         seek.QuadPart += arrayIndex * size * depth;
1392 
1393         if (width > 1) width /= 2;
1394         if (height > 1) height /= 2;
1395         if (depth > 1) depth /= 2;
1396     }
1397 
1398     hr = DdsFrameDecode_CreateInstance(&frame_decode);
1399     if (hr != S_OK) goto end;
1400     frame_decode->info.width = frame_width;
1401     frame_decode->info.height = frame_height;
1402     frame_decode->info.format = This->info.format;
1403     frame_decode->info.bytes_per_block = bytes_per_block;
1404     frame_decode->info.block_width = block_width;
1405     frame_decode->info.block_height = block_height;
1406     frame_decode->info.width_in_blocks = frame_width_in_blocks;
1407     frame_decode->info.height_in_blocks = frame_height_in_blocks;
1408     frame_decode->info.pixel_format = This->info.pixel_format;
1409     frame_decode->info.pixel_format_bpp = This->info.pixel_format_bpp;
1410     frame_decode->block_data = malloc(frame_size);
1411     frame_decode->pixel_data = NULL;
1412     hr = IStream_Seek(This->stream, seek, SEEK_SET, NULL);
1413     if (hr != S_OK) goto end;
1414     hr = IStream_Read(This->stream, frame_decode->block_data, frame_size, &bytesread);
1415     if (hr != S_OK || bytesread != frame_size) {
1416         hr = WINCODEC_ERR_STREAMREAD;
1417         goto end;
1418     }
1419     *bitmapFrame = &frame_decode->IWICBitmapFrameDecode_iface;
1420 
1421     hr = S_OK;
1422 
1423 end:
1424     LeaveCriticalSection(&This->lock);
1425 
1426     if (hr != S_OK && frame_decode) DdsFrameDecode_Release(&frame_decode->IWICBitmapFrameDecode_iface);
1427 
1428     return hr;
1429 }
1430 
1431 static const IWICDdsDecoderVtbl DdsDecoder_Dds_Vtbl = {
1432     DdsDecoder_Dds_QueryInterface,
1433     DdsDecoder_Dds_AddRef,
1434     DdsDecoder_Dds_Release,
1435     DdsDecoder_Dds_GetParameters,
1436     DdsDecoder_Dds_GetFrame
1437 };
1438 
DdsDecoder_Wine_QueryInterface(IWICWineDecoder * iface,REFIID iid,void ** ppv)1439 static HRESULT WINAPI DdsDecoder_Wine_QueryInterface(IWICWineDecoder *iface, REFIID iid, void **ppv)
1440 {
1441     DdsDecoder *This = impl_from_IWICWineDecoder(iface);
1442     return DdsDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
1443 }
1444 
DdsDecoder_Wine_AddRef(IWICWineDecoder * iface)1445 static ULONG WINAPI DdsDecoder_Wine_AddRef(IWICWineDecoder *iface)
1446 {
1447     DdsDecoder *This = impl_from_IWICWineDecoder(iface);
1448     return DdsDecoder_AddRef(&This->IWICBitmapDecoder_iface);
1449 }
1450 
DdsDecoder_Wine_Release(IWICWineDecoder * iface)1451 static ULONG WINAPI DdsDecoder_Wine_Release(IWICWineDecoder *iface)
1452 {
1453     DdsDecoder *This = impl_from_IWICWineDecoder(iface);
1454     return DdsDecoder_Release(&This->IWICBitmapDecoder_iface);
1455 }
1456 
DdsDecoder_Wine_Initialize(IWICWineDecoder * iface,IStream * stream,WICDecodeOptions options)1457 static HRESULT WINAPI DdsDecoder_Wine_Initialize(IWICWineDecoder *iface, IStream *stream, WICDecodeOptions options)
1458 {
1459     DdsDecoder *This = impl_from_IWICWineDecoder(iface);
1460     DDS_HEADER_DXT10 header_dxt10;
1461     LARGE_INTEGER seek;
1462     DDS_HEADER header;
1463     ULONG bytesread;
1464     DWORD magic;
1465     HRESULT hr;
1466 
1467     TRACE("(This %p, stream %p, options %#x)\n", iface, stream, options);
1468 
1469     EnterCriticalSection(&This->lock);
1470 
1471     if (This->initialized) {
1472         hr = WINCODEC_ERR_WRONGSTATE;
1473         goto end;
1474     }
1475 
1476     seek.QuadPart = 0;
1477     hr = IStream_Seek(stream, seek, SEEK_SET, NULL);
1478     if (FAILED(hr)) goto end;
1479 
1480     hr = IStream_Read(stream, &magic, sizeof(magic), &bytesread);
1481     if (FAILED(hr)) goto end;
1482     if (bytesread != sizeof(magic)) {
1483         hr = WINCODEC_ERR_STREAMREAD;
1484         goto end;
1485     }
1486     if (magic != DDS_MAGIC) {
1487         hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT;
1488         goto end;
1489     }
1490 
1491     hr = IStream_Read(stream, &header, sizeof(header), &bytesread);
1492     if (FAILED(hr)) goto end;
1493     if (bytesread != sizeof(header)) {
1494         hr = WINCODEC_ERR_STREAMREAD;
1495         goto end;
1496     }
1497     if (header.size != sizeof(header)) {
1498         hr = WINCODEC_ERR_BADHEADER;
1499         goto end;
1500     }
1501 
1502     if (has_extended_header(&header)) {
1503         hr = IStream_Read(stream, &header_dxt10, sizeof(header_dxt10), &bytesread);
1504         if (FAILED(hr)) goto end;
1505         if (bytesread != sizeof(header_dxt10)) {
1506             hr = WINCODEC_ERR_STREAMREAD;
1507             goto end;
1508         }
1509     }
1510 
1511     get_dds_info(&This->info, &header, &header_dxt10);
1512 
1513     This->initialized = TRUE;
1514     This->stream = stream;
1515     IStream_AddRef(stream);
1516 
1517 end:
1518     LeaveCriticalSection(&This->lock);
1519 
1520     return hr;
1521 }
1522 
1523 static const IWICWineDecoderVtbl DdsDecoder_Wine_Vtbl = {
1524     DdsDecoder_Wine_QueryInterface,
1525     DdsDecoder_Wine_AddRef,
1526     DdsDecoder_Wine_Release,
1527     DdsDecoder_Wine_Initialize
1528 };
1529 
DdsFrameEncode_QueryInterface(IWICBitmapFrameEncode * iface,REFIID iid,void ** ppv)1530 static HRESULT WINAPI DdsFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid, void **ppv)
1531 {
1532     DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1533     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1534 
1535     if (!ppv) return E_INVALIDARG;
1536 
1537     if (IsEqualIID(&IID_IUnknown, iid) ||
1538         IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
1539     {
1540         *ppv = &This->IWICBitmapFrameEncode_iface;
1541     }
1542     else
1543     {
1544         *ppv = NULL;
1545         return E_NOINTERFACE;
1546     }
1547 
1548     IUnknown_AddRef((IUnknown*)*ppv);
1549     return S_OK;
1550 }
1551 
DdsFrameEncode_AddRef(IWICBitmapFrameEncode * iface)1552 static ULONG WINAPI DdsFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
1553 {
1554     DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1555     ULONG ref = InterlockedIncrement(&This->ref);
1556 
1557     TRACE("(%p) refcount=%lu\n", iface, ref);
1558 
1559     return ref;
1560 }
1561 
DdsFrameEncode_Release(IWICBitmapFrameEncode * iface)1562 static ULONG WINAPI DdsFrameEncode_Release(IWICBitmapFrameEncode *iface)
1563 {
1564     DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1565     ULONG ref = InterlockedDecrement(&This->ref);
1566 
1567     TRACE("(%p) refcount=%lu\n", iface, ref);
1568 
1569     if (ref == 0)
1570     {
1571         IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface);
1572         free(This);
1573     }
1574 
1575     return ref;
1576 }
1577 
DdsFrameEncode_Initialize(IWICBitmapFrameEncode * iface,IPropertyBag2 * encoderOptions)1578 static HRESULT WINAPI DdsFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
1579                                                 IPropertyBag2 *encoderOptions)
1580 {
1581     DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1582     HRESULT hr;
1583 
1584     TRACE("(%p,%p)\n", iface, encoderOptions);
1585     if (encoderOptions) FIXME("encoder options are not supported for DDS.\n");
1586 
1587     EnterCriticalSection(&This->parent->lock);
1588 
1589     if (This->initialized)
1590     {
1591         hr = WINCODEC_ERR_WRONGSTATE;
1592     }
1593     else
1594     {
1595         This->initialized = TRUE;
1596         hr = S_OK;
1597     }
1598 
1599     LeaveCriticalSection(&This->parent->lock);
1600 
1601     return hr;
1602 }
1603 
DdsFrameEncode_SetSize(IWICBitmapFrameEncode * iface,UINT width,UINT height)1604 static HRESULT WINAPI DdsFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
1605                                              UINT width, UINT height)
1606 {
1607     DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1608     HRESULT hr;
1609 
1610     TRACE("(%p,%u,%u)\n", iface, width, height);
1611 
1612     EnterCriticalSection(&This->parent->lock);
1613 
1614     if (!This->initialized || This->frame_created)
1615     {
1616         hr = WINCODEC_ERR_WRONGSTATE;
1617     }
1618     else
1619     {
1620         This->width = width;
1621         This->height = height;
1622         hr = S_OK;
1623     }
1624 
1625     LeaveCriticalSection(&This->parent->lock);
1626 
1627     return hr;
1628 }
1629 
DdsFrameEncode_SetResolution(IWICBitmapFrameEncode * iface,double dpiX,double dpiY)1630 static HRESULT WINAPI DdsFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
1631                                                    double dpiX, double dpiY)
1632 {
1633     DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1634     HRESULT hr;
1635 
1636     TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
1637 
1638     EnterCriticalSection(&This->parent->lock);
1639 
1640     if (!This->initialized || This->frame_created)
1641     {
1642         hr = WINCODEC_ERR_WRONGSTATE;
1643     }
1644     else
1645     {
1646         This->dpi_x = dpiX;
1647         This->dpi_y = dpiY;
1648         hr = S_OK;
1649     }
1650 
1651     LeaveCriticalSection(&This->parent->lock);
1652 
1653     return hr;
1654 }
1655 
DdsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode * iface,WICPixelFormatGUID * pixelFormat)1656 static HRESULT WINAPI DdsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
1657                                                     WICPixelFormatGUID *pixelFormat)
1658 {
1659     DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1660     HRESULT hr;
1661 
1662     TRACE("(%p,%s)\n", iface, debugstr_guid(pixelFormat));
1663 
1664     EnterCriticalSection(&This->parent->lock);
1665 
1666     if (!This->initialized)
1667     {
1668         hr = WINCODEC_ERR_NOTINITIALIZED;
1669     }
1670     else if (This->frame_created)
1671     {
1672         hr = WINCODEC_ERR_WRONGSTATE;
1673     }
1674     else
1675     {
1676         *pixelFormat = GUID_WICPixelFormat32bppBGRA;
1677         hr = S_OK;
1678     }
1679 
1680     LeaveCriticalSection(&This->parent->lock);
1681 
1682     return hr;
1683 }
1684 
DdsFrameEncode_SetColorContexts(IWICBitmapFrameEncode * iface,UINT count,IWICColorContext ** colorContext)1685 static HRESULT WINAPI DdsFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
1686                                                       UINT count, IWICColorContext **colorContext)
1687 {
1688     FIXME("(%p,%u,%p): stub\n", iface, count, colorContext);
1689     return E_NOTIMPL;
1690 }
1691 
DdsFrameEncode_SetPalette(IWICBitmapFrameEncode * iface,IWICPalette * palette)1692 static HRESULT WINAPI DdsFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
1693                                                 IWICPalette *palette)
1694 {
1695     FIXME("(%p,%p): stub\n", iface, palette);
1696     return E_NOTIMPL;
1697 }
1698 
DdsFrameEncode_SetThumbnail(IWICBitmapFrameEncode * iface,IWICBitmapSource * thumbnail)1699 static HRESULT WINAPI DdsFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
1700                                                   IWICBitmapSource *thumbnail)
1701 {
1702     TRACE("(%p,%p)\n", iface, thumbnail);
1703     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1704 }
1705 
DdsFrameEncode_WritePixels(IWICBitmapFrameEncode * iface,UINT lineCount,UINT stride,UINT bufferSize,BYTE * pixels)1706 static HRESULT WINAPI DdsFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
1707                                                  UINT lineCount, UINT stride, UINT bufferSize, BYTE *pixels)
1708 {
1709     FIXME("(%p,%u,%u,%u,%p): stub\n", iface, lineCount, stride, bufferSize, pixels);
1710     return E_NOTIMPL;
1711 }
1712 
DdsFrameEncode_WriteSource(IWICBitmapFrameEncode * iface,IWICBitmapSource * bitmapSource,WICRect * rc)1713 static HRESULT WINAPI DdsFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
1714                                                  IWICBitmapSource *bitmapSource, WICRect *rc)
1715 {
1716     FIXME("(%p,%p,%s): stub\n", iface, bitmapSource, debug_wic_rect(rc));
1717     return E_NOTIMPL;
1718 }
1719 
DdsFrameEncode_Commit(IWICBitmapFrameEncode * iface)1720 static HRESULT WINAPI DdsFrameEncode_Commit(IWICBitmapFrameEncode *iface)
1721 {
1722     FIXME("(%p): stub\n", iface);
1723     return E_NOTIMPL;
1724 }
1725 
DdsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode * iface,IWICMetadataQueryWriter ** metadataQueryWriter)1726 static HRESULT WINAPI DdsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
1727                                                             IWICMetadataQueryWriter **metadataQueryWriter)
1728 {
1729     FIXME("(%p,%p): stub\n", iface, metadataQueryWriter);
1730     return E_NOTIMPL;
1731 }
1732 
1733 static const IWICBitmapFrameEncodeVtbl DdsFrameEncode_Vtbl = {
1734     DdsFrameEncode_QueryInterface,
1735     DdsFrameEncode_AddRef,
1736     DdsFrameEncode_Release,
1737     DdsFrameEncode_Initialize,
1738     DdsFrameEncode_SetSize,
1739     DdsFrameEncode_SetResolution,
1740     DdsFrameEncode_SetPixelFormat,
1741     DdsFrameEncode_SetColorContexts,
1742     DdsFrameEncode_SetPalette,
1743     DdsFrameEncode_SetThumbnail,
1744     DdsFrameEncode_WritePixels,
1745     DdsFrameEncode_WriteSource,
1746     DdsFrameEncode_Commit,
1747     DdsFrameEncode_GetMetadataQueryWriter
1748 };
1749 
DdsDecoder_CreateInstance(REFIID iid,void ** ppv)1750 HRESULT DdsDecoder_CreateInstance(REFIID iid, void** ppv)
1751 {
1752     DdsDecoder *This;
1753     HRESULT ret;
1754 
1755     TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
1756 
1757     *ppv = NULL;
1758 
1759     This = malloc(sizeof(DdsDecoder));
1760     if (!This) return E_OUTOFMEMORY;
1761 
1762     This->IWICBitmapDecoder_iface.lpVtbl = &DdsDecoder_Vtbl;
1763     This->IWICDdsDecoder_iface.lpVtbl = &DdsDecoder_Dds_Vtbl;
1764     This->IWICWineDecoder_iface.lpVtbl = &DdsDecoder_Wine_Vtbl;
1765     This->ref = 1;
1766     This->initialized = FALSE;
1767     This->stream = NULL;
1768 #ifdef __REACTOS__
1769     InitializeCriticalSection(&This->lock);
1770 #else
1771     InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
1772 #endif
1773     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DdsDecoder.lock");
1774 
1775     ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
1776     IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
1777 
1778     return ret;
1779 }
1780 
DdsEncoder_Dds_QueryInterface(IWICDdsEncoder * iface,REFIID iid,void ** ppv)1781 static HRESULT WINAPI DdsEncoder_Dds_QueryInterface(IWICDdsEncoder *iface, REFIID iid,
1782                                                     void **ppv)
1783 {
1784     DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
1785     return IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
1786 }
1787 
DdsEncoder_Dds_AddRef(IWICDdsEncoder * iface)1788 static ULONG WINAPI DdsEncoder_Dds_AddRef(IWICDdsEncoder *iface)
1789 {
1790     DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
1791     return IWICBitmapEncoder_AddRef(&This->IWICBitmapEncoder_iface);
1792 }
1793 
DdsEncoder_Dds_Release(IWICDdsEncoder * iface)1794 static ULONG WINAPI DdsEncoder_Dds_Release(IWICDdsEncoder *iface)
1795 {
1796     DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
1797     return IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
1798 }
1799 
DdsEncoder_Dds_SetParameters(IWICDdsEncoder * iface,WICDdsParameters * parameters)1800 static HRESULT WINAPI DdsEncoder_Dds_SetParameters(IWICDdsEncoder *iface,
1801                                                    WICDdsParameters *parameters)
1802 {
1803     DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
1804     HRESULT hr;
1805 
1806     TRACE("(%p,%p)\n", iface, parameters);
1807 
1808     if (!parameters) return E_INVALIDARG;
1809 
1810     EnterCriticalSection(&This->lock);
1811 
1812     if (!This->stream)
1813     {
1814         hr = WINCODEC_ERR_WRONGSTATE;
1815         goto end;
1816     }
1817 
1818     This->info.width      = parameters->Width;
1819     This->info.height     = parameters->Height;
1820     This->info.depth      = parameters->Depth;
1821     This->info.mip_levels = parameters->MipLevels;
1822     This->info.array_size = parameters->ArraySize;
1823     This->info.format     = parameters->DxgiFormat;
1824     This->info.dimension  = parameters->Dimension;
1825     This->info.alpha_mode = parameters->AlphaMode;
1826 
1827     This->info.bytes_per_block = get_bytes_per_block_from_format(This->info.format);
1828     This->info.frame_count = get_frame_count(This->info.depth, This->info.mip_levels,
1829                                              This->info.array_size, This->info.dimension);
1830 
1831     hr = S_OK;
1832 
1833 end:
1834     LeaveCriticalSection(&This->lock);
1835     return hr;
1836 }
1837 
DdsEncoder_Dds_GetParameters(IWICDdsEncoder * iface,WICDdsParameters * parameters)1838 static HRESULT WINAPI DdsEncoder_Dds_GetParameters(IWICDdsEncoder *iface,
1839                                                    WICDdsParameters *parameters)
1840 {
1841     DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
1842     HRESULT hr;
1843 
1844     TRACE("(%p,%p)\n", iface, parameters);
1845 
1846     if (!parameters) return E_INVALIDARG;
1847 
1848     EnterCriticalSection(&This->lock);
1849 
1850     if (!This->stream)
1851     {
1852         hr = WINCODEC_ERR_WRONGSTATE;
1853         goto end;
1854     }
1855 
1856     parameters->Width      = This->info.width;
1857     parameters->Height     = This->info.height;
1858     parameters->Depth      = This->info.depth;
1859     parameters->MipLevels  = This->info.mip_levels;
1860     parameters->ArraySize  = This->info.array_size;
1861     parameters->DxgiFormat = This->info.format;
1862     parameters->Dimension  = This->info.dimension;
1863     parameters->AlphaMode  = This->info.alpha_mode;
1864 
1865     TRACE("(%p,%p) -> (%dx%d depth=%u mipLevels=%u arraySize=%u dxgiFormat=%#x dimension=%#x alphaMode=%#x)\n",
1866           iface, parameters, parameters->Width, parameters->Height, parameters->Depth, parameters->MipLevels,
1867           parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension, parameters->AlphaMode);
1868 
1869     hr = S_OK;
1870 
1871 end:
1872     LeaveCriticalSection(&This->lock);
1873     return hr;
1874 }
1875 
DdsEncoder_Dds_CreateNewFrame(IWICDdsEncoder * iface,IWICBitmapFrameEncode ** frameEncode,UINT * arrayIndex,UINT * mipLevel,UINT * sliceIndex)1876 static HRESULT WINAPI DdsEncoder_Dds_CreateNewFrame(IWICDdsEncoder *iface,
1877                                                     IWICBitmapFrameEncode **frameEncode,
1878                                                     UINT *arrayIndex, UINT *mipLevel, UINT *sliceIndex)
1879 {
1880     DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
1881     UINT array_index, mip_level, slice_index;
1882     DdsFrameEncode *result;
1883     HRESULT hr;
1884 
1885     TRACE("(%p,%p,%p,%p,%p)\n", iface, frameEncode, arrayIndex, mipLevel, sliceIndex);
1886 
1887     EnterCriticalSection(&This->lock);
1888 
1889     if (!This->stream || This->committed || This->uncommitted_frame)
1890     {
1891         hr = WINCODEC_ERR_WRONGSTATE;
1892         goto end;
1893     }
1894 
1895     result = malloc(sizeof(*result));
1896     if (!result)
1897     {
1898         hr = E_OUTOFMEMORY;
1899         goto end;
1900     }
1901 
1902     get_frame_dds_index(This->frame_index, &This->info, &array_index, &mip_level, &slice_index);
1903     if (arrayIndex) *arrayIndex = array_index;
1904     if (mipLevel)   *mipLevel   = mip_level;
1905     if (sliceIndex) *sliceIndex = slice_index;
1906 
1907     This->frame_index++;
1908     result->IWICBitmapFrameEncode_iface.lpVtbl = &DdsFrameEncode_Vtbl;
1909     result->ref = 1;
1910     result->parent = This;
1911     result->parent->uncommitted_frame = TRUE;
1912     result->initialized = FALSE;
1913     result->frame_created = FALSE;
1914     IWICDdsEncoder_AddRef(iface);
1915 
1916     *frameEncode = &result->IWICBitmapFrameEncode_iface;
1917     hr = S_OK;
1918 
1919 end:
1920     LeaveCriticalSection(&This->lock);
1921     return hr;
1922 }
1923 
1924 static const IWICDdsEncoderVtbl DdsEncoder_Dds_Vtbl =
1925 {
1926     DdsEncoder_Dds_QueryInterface,
1927     DdsEncoder_Dds_AddRef,
1928     DdsEncoder_Dds_Release,
1929     DdsEncoder_Dds_SetParameters,
1930     DdsEncoder_Dds_GetParameters,
1931     DdsEncoder_Dds_CreateNewFrame
1932 };
1933 
DdsEncoder_QueryInterface(IWICBitmapEncoder * iface,REFIID iid,void ** ppv)1934 static HRESULT WINAPI DdsEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
1935                                                    void **ppv)
1936 {
1937     DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
1938     FIXME("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1939 
1940     if (!ppv) return E_INVALIDARG;
1941 
1942     if (IsEqualIID(&IID_IUnknown, iid) ||
1943         IsEqualIID(&IID_IWICBitmapEncoder, iid)) {
1944         *ppv = &This->IWICBitmapEncoder_iface;
1945     } else if (IsEqualIID(&IID_IWICDdsEncoder, iid)) {
1946         *ppv = &This->IWICDdsEncoder_iface;
1947     } else {
1948         *ppv = NULL;
1949         return E_NOINTERFACE;
1950     }
1951 
1952     IUnknown_AddRef((IUnknown*)*ppv);
1953     return S_OK;
1954 }
1955 
DdsEncoder_AddRef(IWICBitmapEncoder * iface)1956 static ULONG WINAPI DdsEncoder_AddRef(IWICBitmapEncoder *iface)
1957 {
1958     DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
1959     ULONG ref = InterlockedIncrement(&This->ref);
1960 
1961     TRACE("(%p) refcount=%lu\n", iface, ref);
1962 
1963     return ref;
1964 }
1965 
DdsEncoder_Release(IWICBitmapEncoder * iface)1966 static ULONG WINAPI DdsEncoder_Release(IWICBitmapEncoder *iface)
1967 {
1968     DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
1969     ULONG ref = InterlockedDecrement(&This->ref);
1970 
1971     TRACE("(%p) refcount=%lu\n", iface, ref);
1972 
1973     if (ref == 0) {
1974         This->lock.DebugInfo->Spare[0] = 0;
1975         DeleteCriticalSection(&This->lock);
1976         if (This->stream) IStream_Release(This->stream);
1977         free(This);
1978     }
1979 
1980     return ref;
1981 }
1982 
DdsEncoder_Initialize(IWICBitmapEncoder * iface,IStream * stream,WICBitmapEncoderCacheOption cacheOption)1983 static HRESULT WINAPI DdsEncoder_Initialize(IWICBitmapEncoder *iface,
1984                                             IStream *stream, WICBitmapEncoderCacheOption cacheOption)
1985 {
1986     DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
1987     HRESULT hr;
1988 
1989     TRACE("(%p,%p,%u)\n", iface, stream, cacheOption);
1990 
1991     if (cacheOption != WICBitmapEncoderNoCache)
1992         FIXME("Cache option %#x is not supported.\n", cacheOption);
1993 
1994     if (!stream) return E_INVALIDARG;
1995 
1996     EnterCriticalSection(&This->lock);
1997 
1998     if (This->stream)
1999     {
2000         hr = WINCODEC_ERR_WRONGSTATE;
2001         goto end;
2002     }
2003 
2004     This->stream = stream;
2005     IStream_AddRef(stream);
2006 
2007     This->info.width = 1;
2008     This->info.height = 1;
2009     This->info.depth = 1;
2010     This->info.mip_levels = 1;
2011     This->info.array_size = 1;
2012     This->info.frame_count = 1;
2013     This->info.data_offset = 0;
2014     This->info.bytes_per_block = get_bytes_per_block_from_format(DXGI_FORMAT_BC3_UNORM);
2015     This->info.format = DXGI_FORMAT_BC3_UNORM;
2016     This->info.dimension = WICDdsTexture2D;
2017     This->info.alpha_mode = WICDdsAlphaModeUnknown;
2018     This->info.pixel_format = &GUID_WICPixelFormatUndefined;
2019     This->info.pixel_format_bpp = 0;
2020 
2021     hr = S_OK;
2022 
2023 end:
2024     LeaveCriticalSection(&This->lock);
2025 
2026     return hr;
2027 }
2028 
DdsEncoder_GetContainerFormat(IWICBitmapEncoder * iface,GUID * format)2029 static HRESULT WINAPI DdsEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format)
2030 {
2031     TRACE("(%p,%p)\n", iface, format);
2032 
2033     if (!format)
2034         return E_INVALIDARG;
2035 
2036     memcpy(format, &GUID_ContainerFormatDds, sizeof(*format));
2037     return S_OK;
2038 }
2039 
DdsEncoder_GetEncoderInfo(IWICBitmapEncoder * iface,IWICBitmapEncoderInfo ** info)2040 static HRESULT WINAPI DdsEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
2041 {
2042     IWICComponentInfo *comp_info;
2043     HRESULT hr;
2044 
2045     TRACE("%p,%p\n", iface, info);
2046 
2047     if (!info) return E_INVALIDARG;
2048 
2049     hr = CreateComponentInfo(&CLSID_WICDdsEncoder, &comp_info);
2050     if (hr == S_OK) {
2051         hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
2052         IWICComponentInfo_Release(comp_info);
2053     }
2054     return hr;
2055 }
2056 
DdsEncoder_SetColorContexts(IWICBitmapEncoder * iface,UINT cCount,IWICColorContext ** ppIColorContext)2057 static HRESULT WINAPI DdsEncoder_SetColorContexts(IWICBitmapEncoder *iface,
2058                                                      UINT cCount, IWICColorContext **ppIColorContext)
2059 {
2060     FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
2061     return E_NOTIMPL;
2062 }
2063 
DdsEncoder_SetPalette(IWICBitmapEncoder * iface,IWICPalette * palette)2064 static HRESULT WINAPI DdsEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
2065 {
2066     DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
2067     HRESULT hr;
2068 
2069     TRACE("(%p,%p)\n", iface, palette);
2070 
2071     EnterCriticalSection(&This->lock);
2072 
2073     hr = This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
2074 
2075     LeaveCriticalSection(&This->lock);
2076 
2077     return hr;
2078 }
2079 
DdsEncoder_SetThumbnail(IWICBitmapEncoder * iface,IWICBitmapSource * pIThumbnail)2080 static HRESULT WINAPI DdsEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
2081 {
2082     TRACE("(%p,%p)\n", iface, pIThumbnail);
2083     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
2084 }
2085 
DdsEncoder_SetPreview(IWICBitmapEncoder * iface,IWICBitmapSource * pIPreview)2086 static HRESULT WINAPI DdsEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
2087 {
2088     TRACE("(%p,%p)\n", iface, pIPreview);
2089     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
2090 }
2091 
DdsEncoder_CreateNewFrame(IWICBitmapEncoder * iface,IWICBitmapFrameEncode ** frameEncode,IPropertyBag2 ** encoderOptions)2092 static HRESULT WINAPI DdsEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
2093                                                 IWICBitmapFrameEncode **frameEncode, IPropertyBag2 **encoderOptions)
2094 {
2095     DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
2096 
2097     TRACE("(%p,%p,%p)\n", iface, frameEncode, encoderOptions);
2098 
2099     return IWICDdsEncoder_CreateNewFrame(&This->IWICDdsEncoder_iface, frameEncode, NULL, NULL, NULL);
2100 }
2101 
DdsEncoder_Commit(IWICBitmapEncoder * iface)2102 static HRESULT WINAPI DdsEncoder_Commit(IWICBitmapEncoder *iface)
2103 {
2104     FIXME("(%p): stub\n", iface);
2105     return E_NOTIMPL;
2106 }
2107 
DdsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder * iface,IWICMetadataQueryWriter ** ppIMetadataQueryWriter)2108 static HRESULT WINAPI DdsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
2109                                                            IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2110 {
2111     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
2112     return E_NOTIMPL;
2113 }
2114 
2115 static const IWICBitmapEncoderVtbl DdsEncoder_Vtbl = {
2116     DdsEncoder_QueryInterface,
2117     DdsEncoder_AddRef,
2118     DdsEncoder_Release,
2119     DdsEncoder_Initialize,
2120     DdsEncoder_GetContainerFormat,
2121     DdsEncoder_GetEncoderInfo,
2122     DdsEncoder_SetColorContexts,
2123     DdsEncoder_SetPalette,
2124     DdsEncoder_SetThumbnail,
2125     DdsEncoder_SetPreview,
2126     DdsEncoder_CreateNewFrame,
2127     DdsEncoder_Commit,
2128     DdsEncoder_GetMetadataQueryWriter
2129 };
2130 
DdsEncoder_CreateInstance(REFIID iid,void ** ppv)2131 HRESULT DdsEncoder_CreateInstance( REFIID iid, void **ppv)
2132 {
2133     DdsEncoder *This;
2134     HRESULT ret;
2135 
2136     TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
2137 
2138     *ppv = NULL;
2139 
2140     This = malloc(sizeof(DdsEncoder));
2141     if (!This) return E_OUTOFMEMORY;
2142 
2143     This->IWICBitmapEncoder_iface.lpVtbl = &DdsEncoder_Vtbl;
2144     This->IWICDdsEncoder_iface.lpVtbl = &DdsEncoder_Dds_Vtbl;
2145     This->ref = 1;
2146     This->stream = NULL;
2147     This->frame_count = 0;
2148     This->frame_index = 0;
2149     This->uncommitted_frame = FALSE;
2150     This->committed = FALSE;
2151 #ifdef __REACTOS__
2152     InitializeCriticalSection(&This->lock);
2153 #else
2154     InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
2155 #endif
2156     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DdsEncoder.lock");
2157 
2158     ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
2159     IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
2160 
2161     return ret;
2162 }
2163