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