2 * Copyright 2020 Ziqing Hui
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.
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.
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
22 * For uncompressed formats, a block is equivalent to a pixel.
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.
37 #include "wincodecs_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
43 #define DDS_MAGIC 0x20534444
45 #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
46 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
47 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
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))
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
64 #define DDSCAPS2_CUBEMAP 0x00000200
65 #define DDSCAPS2_VOLUME 0x00200000
67 #define DDS_DIMENSION_TEXTURE1D 2
68 #define DDS_DIMENSION_TEXTURE2D 3
69 #define DDS_DIMENSION_TEXTURE3D 4
71 #define DDS_RESOURCE_MISC_TEXTURECUBE 0x00000004
73 #define DDS_BLOCK_WIDTH 4
74 #define DDS_BLOCK_HEIGHT 4
92 DWORD pitchOrLinearSize
;
96 DDS_PIXELFORMAT ddspf
;
106 DWORD resourceDimension
;
112 typedef struct dds_info
{
120 UINT bytes_per_block
; /* for uncompressed format, this means bytes per pixel*/
122 WICDdsDimension dimension
;
123 WICDdsAlphaMode alpha_mode
;
124 const GUID
*pixel_format
;
125 UINT pixel_format_bpp
;
128 typedef struct dds_frame_info
{
132 UINT bytes_per_block
; /* for uncompressed format, this means bytes per pixel*/
135 UINT width_in_blocks
;
136 UINT height_in_blocks
;
137 const GUID
*pixel_format
;
138 UINT pixel_format_bpp
;
141 typedef struct DdsDecoder
{
142 IWICBitmapDecoder IWICBitmapDecoder_iface
;
143 IWICDdsDecoder IWICDdsDecoder_iface
;
144 IWICWineDecoder IWICWineDecoder_iface
;
148 CRITICAL_SECTION lock
;
152 typedef struct DdsFrameDecode
{
153 IWICBitmapFrameDecode IWICBitmapFrameDecode_iface
;
154 IWICDdsFrameDecode IWICDdsFrameDecode_iface
;
158 CRITICAL_SECTION lock
;
162 typedef struct DdsEncoder
{
163 IWICBitmapEncoder IWICBitmapEncoder_iface
;
165 CRITICAL_SECTION lock
;
168 BOOL uncommitted_frame
;
172 static struct dds_format
{
173 DDS_PIXELFORMAT pixel_format
;
174 const GUID
*wic_format
;
176 DXGI_FORMAT dxgi_format
;
177 } dds_format_table
[] = {
178 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '1'), 0, 0, 0, 0, 0 },
179 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC1_UNORM
},
180 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0 },
181 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC2_UNORM
},
182 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '3'), 0, 0, 0, 0, 0 },
183 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC2_UNORM
},
184 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '4'), 0, 0, 0, 0, 0 },
185 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC3_UNORM
},
186 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '5'), 0, 0, 0, 0, 0 },
187 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC3_UNORM
},
188 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '4', 'U'), 0, 0, 0, 0, 0 },
189 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_UNORM
},
190 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '4', 'S'), 0, 0, 0, 0, 0 },
191 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_SNORM
},
192 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '5', 'U'), 0, 0, 0, 0, 0 },
193 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_UNORM
},
194 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '5', 'S'), 0, 0, 0, 0, 0 },
195 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_SNORM
},
196 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('A', 'T', 'I', '1'), 0, 0, 0, 0, 0 },
197 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_UNORM
},
198 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('A', 'T', 'I', '2'), 0, 0, 0, 0, 0 },
199 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_UNORM
},
200 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('R', 'G', 'B', 'G'), 0, 0, 0, 0, 0 },
201 &GUID_WICPixelFormat32bpp4Channels
, 32, DXGI_FORMAT_R8G8_B8G8_UNORM
},
202 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('G', 'R', 'G', 'B'), 0, 0, 0, 0, 0 },
203 &GUID_WICPixelFormat32bpp4Channels
, 32, DXGI_FORMAT_G8R8_G8B8_UNORM
},
204 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', '1', '0'), 0, 0, 0, 0, 0 },
205 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_UNKNOWN
},
206 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x24, 0, 0, 0, 0, 0 },
207 &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_UNORM
},
208 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x6E, 0, 0, 0, 0, 0 },
209 &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_SNORM
},
210 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x6F, 0, 0, 0, 0, 0 },
211 &GUID_WICPixelFormat16bppGrayHalf
, 16, DXGI_FORMAT_R16_FLOAT
},
212 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x70, 0, 0, 0, 0, 0 },
213 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R16G16_FLOAT
},
214 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x71, 0, 0, 0, 0, 0 },
215 &GUID_WICPixelFormat64bppRGBAHalf
, 64, DXGI_FORMAT_R16G16B16A16_FLOAT
},
216 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x72, 0, 0, 0, 0, 0 },
217 &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
218 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x73, 0, 0, 0, 0, 0 },
219 &GUID_WICPixelFormatUndefined
, 32, DXGI_FORMAT_R32G32_FLOAT
},
220 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x74, 0, 0, 0, 0, 0 },
221 &GUID_WICPixelFormat128bppRGBAFloat
, 128, DXGI_FORMAT_R32G32B32A32_FLOAT
},
222 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF,0xFF00,0xFF0000,0xFF000000 },
223 &GUID_WICPixelFormat32bppRGBA
, 32, DXGI_FORMAT_R8G8B8A8_UNORM
},
224 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF,0xFF00,0xFF0000,0 },
225 &GUID_WICPixelFormat32bppRGB
, 32, DXGI_FORMAT_UNKNOWN
},
226 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF0000,0xFF00,0xFF,0xFF000000 },
227 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_B8G8R8A8_UNORM
},
228 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF0000,0xFF00,0xFF,0 },
229 &GUID_WICPixelFormat32bppBGR
, 32, DXGI_FORMAT_B8G8R8X8_UNORM
},
230 /* The red and blue masks are swapped for DXGI_FORMAT_R10G10B10A2_UNORM.
231 * For "correct" one, the RGB masks should be 0x3FF,0xFFC00,0x3FF00000.
232 * see: https://walbourn.github.io/dds-update-and-1010102-problems */
233 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0x3FF00000,0xFFC00,0x3FF,0xC0000000 },
234 &GUID_WICPixelFormat32bppR10G10B10A2
, 32, DXGI_FORMAT_R10G10B10A2_UNORM
},
235 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0x3FF,0xFFC00,0x3FF00000,0xC0000000 },
236 &GUID_WICPixelFormat32bppRGBA1010102
, 32, DXGI_FORMAT_UNKNOWN
},
237 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFFFF,0xFFFF0000,0,0 },
238 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R16G16_UNORM
},
239 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFFFFFFFF,0,0,0 },
240 &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
241 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 24, 0xFF0000,0x00FF00,0x0000FF,0 },
242 &GUID_WICPixelFormat24bppBGR
, 24, DXGI_FORMAT_UNKNOWN
},
243 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 24, 0x0000FF,0x00FF00,0xFF0000,0 },
244 &GUID_WICPixelFormat24bppRGB
, 24, DXGI_FORMAT_UNKNOWN
},
245 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0xF800,0x7E0,0x1F,0 },
246 &GUID_WICPixelFormat16bppBGR565
, 16, DXGI_FORMAT_B5G6R5_UNORM
},
247 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0x7C00,0x3E0,0x1F,0 },
248 &GUID_WICPixelFormat16bppBGR555
, 16, DXGI_FORMAT_UNKNOWN
},
249 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0x7C00,0x3E0,0x1F,0x8000 },
250 &GUID_WICPixelFormat16bppBGRA5551
, 16, DXGI_FORMAT_B5G5R5A1_UNORM
},
251 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0xF00,0xF0,0xF,0xF000 },
252 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_B4G4R4A4_UNORM
},
253 { { sizeof(DDS_PIXELFORMAT
), DDPF_ALPHA
, 0, 8, 0,0,0,0xFF },
254 &GUID_WICPixelFormat8bppAlpha
, 8, DXGI_FORMAT_A8_UNORM
},
255 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 16, 0xFFFF,0,0,0 },
256 &GUID_WICPixelFormat16bppGray
, 16, DXGI_FORMAT_R16_UNORM
},
257 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 16, 0xFF,0,0,0xFF00 },
258 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R8G8_UNORM
},
259 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 8, 0xFF,0,0,0 },
260 &GUID_WICPixelFormat8bppGray
, 8, DXGI_FORMAT_R8_UNORM
},
261 { { 0 }, &GUID_WICPixelFormat8bppAlpha
, 8, DXGI_FORMAT_A8_UNORM
},
262 { { 0 }, &GUID_WICPixelFormat8bppGray
, 8, DXGI_FORMAT_R8_UNORM
},
263 { { 0 }, &GUID_WICPixelFormat16bppGray
, 16, DXGI_FORMAT_R16_UNORM
},
264 { { 0 }, &GUID_WICPixelFormat16bppGrayHalf
, 16, DXGI_FORMAT_R16_FLOAT
},
265 { { 0 }, &GUID_WICPixelFormat16bppBGR565
, 16, DXGI_FORMAT_B5G6R5_UNORM
},
266 { { 0 }, &GUID_WICPixelFormat16bppBGRA5551
, 16, DXGI_FORMAT_B5G5R5A1_UNORM
},
267 { { 0 }, &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
268 { { 0 }, &GUID_WICPixelFormat32bppRGBA
, 32, DXGI_FORMAT_R8G8B8A8_UNORM
},
269 { { 0 }, &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_B8G8R8A8_UNORM
},
270 { { 0 }, &GUID_WICPixelFormat32bppBGR
, 32, DXGI_FORMAT_B8G8R8X8_UNORM
},
271 { { 0 }, &GUID_WICPixelFormat32bppR10G10B10A2
, 32, DXGI_FORMAT_R10G10B10A2_UNORM
},
272 { { 0 }, &GUID_WICPixelFormat32bppRGBE
, 32, DXGI_FORMAT_R9G9B9E5_SHAREDEXP
},
273 { { 0 }, &GUID_WICPixelFormat32bppRGBA1010102XR
, 32, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
},
274 { { 0 }, &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_UNORM
},
275 { { 0 }, &GUID_WICPixelFormat64bppRGBAHalf
, 64, DXGI_FORMAT_R16G16B16A16_FLOAT
},
276 { { 0 }, &GUID_WICPixelFormat96bppRGBFloat
, 96, DXGI_FORMAT_R32G32B32_FLOAT
},
277 { { 0 }, &GUID_WICPixelFormat128bppRGBAFloat
, 128, DXGI_FORMAT_R32G32B32A32_FLOAT
},
278 { { 0 }, &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_UNKNOWN
}
281 static DXGI_FORMAT compressed_formats
[] = {
282 DXGI_FORMAT_BC1_TYPELESS
, DXGI_FORMAT_BC1_UNORM
, DXGI_FORMAT_BC1_UNORM_SRGB
,
283 DXGI_FORMAT_BC2_TYPELESS
, DXGI_FORMAT_BC2_UNORM
, DXGI_FORMAT_BC2_UNORM_SRGB
,
284 DXGI_FORMAT_BC3_TYPELESS
, DXGI_FORMAT_BC3_UNORM
, DXGI_FORMAT_BC3_UNORM_SRGB
,
285 DXGI_FORMAT_BC4_TYPELESS
, DXGI_FORMAT_BC4_UNORM
, DXGI_FORMAT_BC4_SNORM
,
286 DXGI_FORMAT_BC5_TYPELESS
, DXGI_FORMAT_BC5_UNORM
, DXGI_FORMAT_BC5_SNORM
,
287 DXGI_FORMAT_BC6H_TYPELESS
, DXGI_FORMAT_BC6H_UF16
, DXGI_FORMAT_BC6H_SF16
,
288 DXGI_FORMAT_BC7_TYPELESS
, DXGI_FORMAT_BC7_UNORM
, DXGI_FORMAT_BC7_UNORM_SRGB
291 static HRESULT WINAPI
DdsDecoder_Dds_GetFrame(IWICDdsDecoder
*, UINT
, UINT
, UINT
, IWICBitmapFrameDecode
**);
293 static DWORD
rgb565_to_argb(WORD color
, BYTE alpha
)
295 return MAKE_ARGB(alpha
, (GET_RGB565_R(color
) * 0xFF + 0x0F) / 0x1F,
296 (GET_RGB565_G(color
) * 0xFF + 0x1F) / 0x3F,
297 (GET_RGB565_B(color
) * 0xFF + 0x0F) / 0x1F);
300 static inline BOOL
has_extended_header(DDS_HEADER
*header
)
302 return (header
->ddspf
.flags
& DDPF_FOURCC
) &&
303 (header
->ddspf
.fourCC
== MAKEFOURCC('D', 'X', '1', '0'));
306 static WICDdsDimension
get_dimension(DDS_HEADER
*header
, DDS_HEADER_DXT10
*header_dxt10
)
309 if (header_dxt10
->miscFlag
& DDS_RESOURCE_MISC_TEXTURECUBE
) return WICDdsTextureCube
;
310 switch (header_dxt10
->resourceDimension
)
312 case DDS_DIMENSION_TEXTURE1D
: return WICDdsTexture1D
;
313 case DDS_DIMENSION_TEXTURE2D
: return WICDdsTexture2D
;
314 case DDS_DIMENSION_TEXTURE3D
: return WICDdsTexture3D
;
315 default: return WICDdsTexture2D
;
318 if (header
->caps2
& DDSCAPS2_CUBEMAP
) {
319 return WICDdsTextureCube
;
320 } else if (header
->caps2
& DDSCAPS2_VOLUME
) {
321 return WICDdsTexture3D
;
323 return WICDdsTexture2D
;
328 static struct dds_format
*get_dds_format(DDS_PIXELFORMAT
*pixel_format
)
332 for (i
= 0; i
< ARRAY_SIZE(dds_format_table
); i
++)
334 if ((pixel_format
->flags
& dds_format_table
[i
].pixel_format
.flags
) &&
335 (pixel_format
->fourCC
== dds_format_table
[i
].pixel_format
.fourCC
) &&
336 (pixel_format
->rgbBitCount
== dds_format_table
[i
].pixel_format
.rgbBitCount
) &&
337 (pixel_format
->rBitMask
== dds_format_table
[i
].pixel_format
.rBitMask
) &&
338 (pixel_format
->gBitMask
== dds_format_table
[i
].pixel_format
.gBitMask
) &&
339 (pixel_format
->bBitMask
== dds_format_table
[i
].pixel_format
.bBitMask
) &&
340 (pixel_format
->aBitMask
== dds_format_table
[i
].pixel_format
.aBitMask
))
341 return dds_format_table
+ i
;
344 return dds_format_table
+ ARRAY_SIZE(dds_format_table
) - 1;
347 static WICDdsAlphaMode
get_alpha_mode_from_fourcc(DWORD fourcc
)
351 case MAKEFOURCC('D', 'X', 'T', '1'):
352 case MAKEFOURCC('D', 'X', 'T', '2'):
353 case MAKEFOURCC('D', 'X', 'T', '4'):
354 return WICDdsAlphaModePremultiplied
;
356 return WICDdsAlphaModeUnknown
;
360 static UINT
get_bytes_per_block_from_format(DXGI_FORMAT format
)
362 /* for uncompressed format, return bytes per pixel*/
365 case DXGI_FORMAT_R8_TYPELESS
:
366 case DXGI_FORMAT_R8_UNORM
:
367 case DXGI_FORMAT_R8_UINT
:
368 case DXGI_FORMAT_R8_SNORM
:
369 case DXGI_FORMAT_R8_SINT
:
370 case DXGI_FORMAT_A8_UNORM
:
372 case DXGI_FORMAT_R8G8_TYPELESS
:
373 case DXGI_FORMAT_R8G8_UNORM
:
374 case DXGI_FORMAT_R8G8_UINT
:
375 case DXGI_FORMAT_R8G8_SNORM
:
376 case DXGI_FORMAT_R8G8_SINT
:
377 case DXGI_FORMAT_R16_TYPELESS
:
378 case DXGI_FORMAT_R16_FLOAT
:
379 case DXGI_FORMAT_D16_UNORM
:
380 case DXGI_FORMAT_R16_UNORM
:
381 case DXGI_FORMAT_R16_UINT
:
382 case DXGI_FORMAT_R16_SNORM
:
383 case DXGI_FORMAT_R16_SINT
:
384 case DXGI_FORMAT_B5G6R5_UNORM
:
385 case DXGI_FORMAT_B5G5R5A1_UNORM
:
386 case DXGI_FORMAT_B4G4R4A4_UNORM
:
388 case DXGI_FORMAT_R10G10B10A2_TYPELESS
:
389 case DXGI_FORMAT_R10G10B10A2_UNORM
:
390 case DXGI_FORMAT_R10G10B10A2_UINT
:
391 case DXGI_FORMAT_R11G11B10_FLOAT
:
392 case DXGI_FORMAT_R8G8B8A8_TYPELESS
:
393 case DXGI_FORMAT_R8G8B8A8_UNORM
:
394 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
:
395 case DXGI_FORMAT_R8G8B8A8_UINT
:
396 case DXGI_FORMAT_R8G8B8A8_SNORM
:
397 case DXGI_FORMAT_R8G8B8A8_SINT
:
398 case DXGI_FORMAT_R16G16_TYPELESS
:
399 case DXGI_FORMAT_R16G16_FLOAT
:
400 case DXGI_FORMAT_R16G16_UNORM
:
401 case DXGI_FORMAT_R16G16_UINT
:
402 case DXGI_FORMAT_R16G16_SNORM
:
403 case DXGI_FORMAT_R16G16_SINT
:
404 case DXGI_FORMAT_R32_TYPELESS
:
405 case DXGI_FORMAT_D32_FLOAT
:
406 case DXGI_FORMAT_R32_FLOAT
:
407 case DXGI_FORMAT_R32_UINT
:
408 case DXGI_FORMAT_R32_SINT
:
409 case DXGI_FORMAT_R24G8_TYPELESS
:
410 case DXGI_FORMAT_D24_UNORM_S8_UINT
:
411 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS
:
412 case DXGI_FORMAT_X24_TYPELESS_G8_UINT
:
413 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP
:
414 case DXGI_FORMAT_R8G8_B8G8_UNORM
:
415 case DXGI_FORMAT_G8R8_G8B8_UNORM
:
416 case DXGI_FORMAT_B8G8R8A8_UNORM
:
417 case DXGI_FORMAT_B8G8R8X8_UNORM
:
418 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
:
419 case DXGI_FORMAT_B8G8R8A8_TYPELESS
:
420 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
:
421 case DXGI_FORMAT_B8G8R8X8_TYPELESS
:
422 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
:
424 case DXGI_FORMAT_BC1_UNORM
:
425 case DXGI_FORMAT_BC1_TYPELESS
:
426 case DXGI_FORMAT_BC1_UNORM_SRGB
:
427 case DXGI_FORMAT_BC4_TYPELESS
:
428 case DXGI_FORMAT_BC4_UNORM
:
429 case DXGI_FORMAT_BC4_SNORM
:
430 case DXGI_FORMAT_R16G16B16A16_TYPELESS
:
431 case DXGI_FORMAT_R16G16B16A16_FLOAT
:
432 case DXGI_FORMAT_R16G16B16A16_UNORM
:
433 case DXGI_FORMAT_R16G16B16A16_UINT
:
434 case DXGI_FORMAT_R16G16B16A16_SNORM
:
435 case DXGI_FORMAT_R16G16B16A16_SINT
:
436 case DXGI_FORMAT_R32G32_TYPELESS
:
437 case DXGI_FORMAT_R32G32_FLOAT
:
438 case DXGI_FORMAT_R32G32_UINT
:
439 case DXGI_FORMAT_R32G32_SINT
:
440 case DXGI_FORMAT_R32G8X24_TYPELESS
:
441 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT
:
442 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS
:
443 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT
:
445 case DXGI_FORMAT_R32G32B32_TYPELESS
:
446 case DXGI_FORMAT_R32G32B32_FLOAT
:
447 case DXGI_FORMAT_R32G32B32_UINT
:
448 case DXGI_FORMAT_R32G32B32_SINT
:
450 case DXGI_FORMAT_BC2_UNORM
:
451 case DXGI_FORMAT_BC2_TYPELESS
:
452 case DXGI_FORMAT_BC2_UNORM_SRGB
:
453 case DXGI_FORMAT_BC3_UNORM
:
454 case DXGI_FORMAT_BC3_TYPELESS
:
455 case DXGI_FORMAT_BC3_UNORM_SRGB
:
456 case DXGI_FORMAT_BC5_TYPELESS
:
457 case DXGI_FORMAT_BC5_UNORM
:
458 case DXGI_FORMAT_BC5_SNORM
:
459 case DXGI_FORMAT_BC6H_TYPELESS
:
460 case DXGI_FORMAT_BC6H_UF16
:
461 case DXGI_FORMAT_BC6H_SF16
:
462 case DXGI_FORMAT_BC7_TYPELESS
:
463 case DXGI_FORMAT_BC7_UNORM
:
464 case DXGI_FORMAT_BC7_UNORM_SRGB
:
465 case DXGI_FORMAT_R32G32B32A32_TYPELESS
:
466 case DXGI_FORMAT_R32G32B32A32_FLOAT
:
467 case DXGI_FORMAT_R32G32B32A32_UINT
:
468 case DXGI_FORMAT_R32G32B32A32_SINT
:
471 WARN("DXGI format 0x%x is not supported in DDS decoder\n", format
);
476 static const GUID
*dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format
)
479 for (i
= 0; i
< ARRAY_SIZE(dds_format_table
); i
++)
481 if (dds_format_table
[i
].pixel_format
.size
== 0 &&
482 dds_format_table
[i
].dxgi_format
== dxgi_format
)
483 return dds_format_table
[i
].wic_format
;
485 return &GUID_WICPixelFormatUndefined
;
488 static BOOL
is_compressed(DXGI_FORMAT format
)
492 for (i
= 0; i
< ARRAY_SIZE(compressed_formats
); i
++)
494 if (format
== compressed_formats
[i
]) return TRUE
;
499 static void get_dds_info(dds_info
* info
, DDS_HEADER
*header
, DDS_HEADER_DXT10
*header_dxt10
)
503 struct dds_format
*format_info
;
505 info
->width
= header
->width
;
506 info
->height
= header
->height
;
508 info
->mip_levels
= 1;
509 info
->array_size
= 1;
510 if (header
->depth
) info
->depth
= header
->depth
;
511 if (header
->mipMapCount
) info
->mip_levels
= header
->mipMapCount
;
513 if (has_extended_header(header
)) {
514 if (header_dxt10
->arraySize
) info
->array_size
= header_dxt10
->arraySize
;
515 info
->format
= header_dxt10
->dxgiFormat
;
516 info
->dimension
= get_dimension(NULL
, header_dxt10
);
517 info
->alpha_mode
= header_dxt10
->miscFlags2
& 0x00000008;
518 info
->data_offset
= sizeof(DWORD
) + sizeof(*header
) + sizeof(*header_dxt10
);
519 if (is_compressed(info
->format
)) {
520 info
->pixel_format
= (info
->alpha_mode
== WICDdsAlphaModePremultiplied
) ?
521 &GUID_WICPixelFormat32bppPBGRA
: &GUID_WICPixelFormat32bppBGRA
;
522 info
->pixel_format_bpp
= 32;
524 info
->pixel_format
= dxgi_format_to_wic_format(info
->format
);
525 info
->pixel_format_bpp
= get_bytes_per_block_from_format(info
->format
) * 8;
528 format_info
= get_dds_format(&header
->ddspf
);
529 info
->format
= format_info
->dxgi_format
;
530 info
->dimension
= get_dimension(header
, NULL
);
531 info
->alpha_mode
= get_alpha_mode_from_fourcc(header
->ddspf
.fourCC
);
532 info
->data_offset
= sizeof(DWORD
) + sizeof(*header
);
533 info
->pixel_format
= format_info
->wic_format
;
534 info
->pixel_format_bpp
= format_info
->wic_format_bpp
;
537 if (header
->ddspf
.flags
& (DDPF_RGB
| DDPF_ALPHA
| DDPF_LUMINANCE
)) {
538 info
->bytes_per_block
= header
->ddspf
.rgbBitCount
/ 8;
540 info
->bytes_per_block
= get_bytes_per_block_from_format(info
->format
);
543 /* get frame count */
545 if (info
->depth
== 1) {
546 info
->frame_count
= info
->array_size
* info
->mip_levels
;
548 info
->frame_count
= 0;
550 for (i
= 0; i
< info
->mip_levels
; i
++)
552 info
->frame_count
+= depth
;
553 if (depth
> 1) depth
/= 2;
555 info
->frame_count
*= info
->array_size
;
557 if (info
->dimension
== WICDdsTextureCube
) info
->frame_count
*= 6;
560 static void decode_block(const BYTE
*block_data
, UINT block_count
, DXGI_FORMAT format
,
561 UINT width
, UINT height
, DWORD
*buffer
)
563 const BYTE
*block
, *color_indices
, *alpha_indices
, *alpha_table
;
564 int i
, j
, x
, y
, block_x
, block_y
, color_index
, alpha_index
;
565 int block_size
, color_offset
, color_indices_offset
;
566 WORD color
[4], color_value
= 0;
567 BYTE alpha
[8], alpha_value
= 0;
569 if (format
== DXGI_FORMAT_BC1_UNORM
) {
572 color_indices_offset
= 4;
576 color_indices_offset
= 12;
581 for (i
= 0; i
< block_count
; i
++)
583 block
= block_data
+ i
* block_size
;
585 color
[0] = *((WORD
*)(block
+ color_offset
));
586 color
[1] = *((WORD
*)(block
+ color_offset
+ 2));
587 color
[2] = MAKE_RGB565(((GET_RGB565_R(color
[0]) * 2 + GET_RGB565_R(color
[1]) + 1) / 3),
588 ((GET_RGB565_G(color
[0]) * 2 + GET_RGB565_G(color
[1]) + 1) / 3),
589 ((GET_RGB565_B(color
[0]) * 2 + GET_RGB565_B(color
[1]) + 1) / 3));
590 color
[3] = MAKE_RGB565(((GET_RGB565_R(color
[0]) + GET_RGB565_R(color
[1]) * 2 + 1) / 3),
591 ((GET_RGB565_G(color
[0]) + GET_RGB565_G(color
[1]) * 2 + 1) / 3),
592 ((GET_RGB565_B(color
[0]) + GET_RGB565_B(color
[1]) * 2 + 1) / 3));
596 case DXGI_FORMAT_BC1_UNORM
:
597 if (color
[0] <= color
[1]) {
598 color
[2] = MAKE_RGB565(((GET_RGB565_R(color
[0]) + GET_RGB565_R(color
[1]) + 1) / 2),
599 ((GET_RGB565_G(color
[0]) + GET_RGB565_G(color
[1]) + 1) / 2),
600 ((GET_RGB565_B(color
[0]) + GET_RGB565_B(color
[1]) + 1) / 2));
604 case DXGI_FORMAT_BC2_UNORM
:
607 case DXGI_FORMAT_BC3_UNORM
:
609 alpha
[1] = *(block
+ 1);
610 if (alpha
[0] > alpha
[1]) {
611 for (j
= 2; j
< 8; j
++)
613 alpha
[j
] = (BYTE
)((alpha
[0] * (8 - j
) + alpha
[1] * (j
- 1) + 3) / 7);
616 for (j
= 2; j
< 6; j
++)
618 alpha
[j
] = (BYTE
)((alpha
[0] * (6 - j
) + alpha
[1] * (j
- 1) + 2) / 5);
623 alpha_indices
= block
+ 2;
629 color_indices
= block
+ color_indices_offset
;
630 for (j
= 0; j
< 16; j
++)
634 if (x
>= width
|| y
>= height
) continue;
636 color_index
= (color_indices
[j
/ 4] >> ((j
% 4) * 2)) & 0x3;
637 color_value
= color
[color_index
];
641 case DXGI_FORMAT_BC1_UNORM
:
642 if ((color
[0] <= color
[1]) && !color_value
) {
649 case DXGI_FORMAT_BC2_UNORM
:
650 alpha_value
= (alpha_table
[j
/ 2] >> (j
% 2) * 4) & 0xF;
651 alpha_value
= (BYTE
)((alpha_value
* 0xFF + 0x7)/ 0xF);
653 case DXGI_FORMAT_BC3_UNORM
:
654 alpha_index
= (*((DWORD
*)(alpha_indices
+ (j
/ 8) * 3)) >> ((j
% 8) * 3)) & 0x7;
655 alpha_value
= alpha
[alpha_index
];
660 buffer
[x
+ y
* width
] = rgb565_to_argb(color_value
, alpha_value
);
663 block_x
+= DDS_BLOCK_WIDTH
;
664 if (block_x
>= width
) {
666 block_y
+= DDS_BLOCK_HEIGHT
;
671 static inline DdsDecoder
*impl_from_IWICBitmapDecoder(IWICBitmapDecoder
*iface
)
673 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICBitmapDecoder_iface
);
676 static inline DdsDecoder
*impl_from_IWICDdsDecoder(IWICDdsDecoder
*iface
)
678 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICDdsDecoder_iface
);
681 static inline DdsDecoder
*impl_from_IWICWineDecoder(IWICWineDecoder
*iface
)
683 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICWineDecoder_iface
);
686 static inline DdsFrameDecode
*impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface
)
688 return CONTAINING_RECORD(iface
, DdsFrameDecode
, IWICBitmapFrameDecode_iface
);
691 static inline DdsFrameDecode
*impl_from_IWICDdsFrameDecode(IWICDdsFrameDecode
*iface
)
693 return CONTAINING_RECORD(iface
, DdsFrameDecode
, IWICDdsFrameDecode_iface
);
696 static inline DdsEncoder
*impl_from_IWICBitmapEncoder(IWICBitmapEncoder
*iface
)
698 return CONTAINING_RECORD(iface
, DdsEncoder
, IWICBitmapEncoder_iface
);
701 static HRESULT WINAPI
DdsFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
704 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
705 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
707 if (!ppv
) return E_INVALIDARG
;
709 if (IsEqualIID(&IID_IUnknown
, iid
) ||
710 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
711 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
)) {
712 *ppv
= &This
->IWICBitmapFrameDecode_iface
;
713 } else if (IsEqualGUID(&IID_IWICDdsFrameDecode
, iid
)) {
714 *ppv
= &This
->IWICDdsFrameDecode_iface
;
717 return E_NOINTERFACE
;
720 IUnknown_AddRef((IUnknown
*)*ppv
);
724 static ULONG WINAPI
DdsFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
726 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
727 ULONG ref
= InterlockedIncrement(&This
->ref
);
729 TRACE("(%p) refcount=%u\n", iface
, ref
);
734 static ULONG WINAPI
DdsFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
736 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
737 ULONG ref
= InterlockedDecrement(&This
->ref
);
739 TRACE("(%p) refcount=%u\n", iface
, ref
);
742 if (This
->pixel_data
!= This
->block_data
) HeapFree(GetProcessHeap(), 0, This
->pixel_data
);
743 HeapFree(GetProcessHeap(), 0, This
->block_data
);
744 HeapFree(GetProcessHeap(), 0, This
);
750 static HRESULT WINAPI
DdsFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
751 UINT
*puiWidth
, UINT
*puiHeight
)
753 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
755 if (!puiWidth
|| !puiHeight
) return E_INVALIDARG
;
757 *puiWidth
= This
->info
.width
;
758 *puiHeight
= This
->info
.height
;
760 TRACE("(%p) -> (%d,%d)\n", iface
, *puiWidth
, *puiHeight
);
765 static HRESULT WINAPI
DdsFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
766 WICPixelFormatGUID
*pPixelFormat
)
768 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
770 if (!pPixelFormat
) return E_INVALIDARG
;
772 *pPixelFormat
= *This
->info
.pixel_format
;
774 TRACE("(%p) -> %s\n", iface
, debugstr_guid(pPixelFormat
));
779 static HRESULT WINAPI
DdsFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
780 double *pDpiX
, double *pDpiY
)
782 FIXME("(%p,%p,%p): stub.\n", iface
, pDpiX
, pDpiY
);
787 static HRESULT WINAPI
DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
788 IWICPalette
*pIPalette
)
790 FIXME("(%p,%p): stub.\n", iface
, pIPalette
);
795 static HRESULT WINAPI
DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
796 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
798 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
799 UINT bpp
, frame_stride
, frame_size
;
800 INT x
, y
, width
, height
;
803 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
805 if (!pbBuffer
) return E_INVALIDARG
;
807 bpp
= This
->info
.pixel_format_bpp
;
808 if (!bpp
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
810 frame_stride
= This
->info
.width
* bpp
/ 8;
811 frame_size
= frame_stride
* This
->info
.height
;
813 if (cbStride
< frame_stride
) return E_INVALIDARG
;
814 if (cbBufferSize
< frame_size
) return WINCODEC_ERR_INSUFFICIENTBUFFER
;
819 height
= prc
->Height
;
820 if (x
< 0 || y
< 0 || width
<= 0 || height
<= 0 ||
821 x
+ width
> This
->info
.width
||
822 y
+ height
> This
->info
.height
) {
825 if (cbStride
< width
* bpp
/ 8) return E_INVALIDARG
;
826 if (cbBufferSize
< cbStride
* height
) return WINCODEC_ERR_INSUFFICIENTBUFFER
;
829 EnterCriticalSection(&This
->lock
);
831 if (!This
->pixel_data
) {
832 if (is_compressed(This
->info
.format
)) {
833 This
->pixel_data
= HeapAlloc(GetProcessHeap(), 0, frame_size
);
834 if (!This
->pixel_data
) {
838 decode_block(This
->block_data
, This
->info
.width_in_blocks
* This
->info
.height_in_blocks
, This
->info
.format
,
839 This
->info
.width
, This
->info
.height
, (DWORD
*)This
->pixel_data
);
841 This
->pixel_data
= This
->block_data
;
845 hr
= copy_pixels(bpp
, This
->pixel_data
, This
->info
.width
, This
->info
.height
, frame_stride
,
846 prc
, cbStride
, cbBufferSize
, pbBuffer
);
849 LeaveCriticalSection(&This
->lock
);
854 static HRESULT WINAPI
DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
855 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
857 FIXME("(%p,%p): stub.\n", iface
, ppIMetadataQueryReader
);
862 static HRESULT WINAPI
DdsFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
863 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
865 FIXME("(%p,%u,%p,%p): stub.\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
870 static HRESULT WINAPI
DdsFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
871 IWICBitmapSource
**ppIThumbnail
)
873 FIXME("(%p,%p): stub.\n", iface
, ppIThumbnail
);
878 static const IWICBitmapFrameDecodeVtbl DdsFrameDecode_Vtbl
= {
879 DdsFrameDecode_QueryInterface
,
880 DdsFrameDecode_AddRef
,
881 DdsFrameDecode_Release
,
882 DdsFrameDecode_GetSize
,
883 DdsFrameDecode_GetPixelFormat
,
884 DdsFrameDecode_GetResolution
,
885 DdsFrameDecode_CopyPalette
,
886 DdsFrameDecode_CopyPixels
,
887 DdsFrameDecode_GetMetadataQueryReader
,
888 DdsFrameDecode_GetColorContexts
,
889 DdsFrameDecode_GetThumbnail
892 static HRESULT WINAPI
DdsFrameDecode_Dds_QueryInterface(IWICDdsFrameDecode
*iface
,
893 REFIID iid
, void **ppv
)
895 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
896 return DdsFrameDecode_QueryInterface(&This
->IWICBitmapFrameDecode_iface
, iid
, ppv
);
899 static ULONG WINAPI
DdsFrameDecode_Dds_AddRef(IWICDdsFrameDecode
*iface
)
901 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
902 return DdsFrameDecode_AddRef(&This
->IWICBitmapFrameDecode_iface
);
905 static ULONG WINAPI
DdsFrameDecode_Dds_Release(IWICDdsFrameDecode
*iface
)
907 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
908 return DdsFrameDecode_Release(&This
->IWICBitmapFrameDecode_iface
);
911 static HRESULT WINAPI
DdsFrameDecode_Dds_GetSizeInBlocks(IWICDdsFrameDecode
*iface
,
912 UINT
*widthInBlocks
, UINT
*heightInBlocks
)
914 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
916 if (!widthInBlocks
|| !heightInBlocks
) return E_INVALIDARG
;
918 *widthInBlocks
= This
->info
.width_in_blocks
;
919 *heightInBlocks
= This
->info
.height_in_blocks
;
921 TRACE("(%p,%p,%p) -> (%d,%d)\n", iface
, widthInBlocks
, heightInBlocks
, *widthInBlocks
, *heightInBlocks
);
926 static HRESULT WINAPI
DdsFrameDecode_Dds_GetFormatInfo(IWICDdsFrameDecode
*iface
,
927 WICDdsFormatInfo
*formatInfo
)
929 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
931 if (!formatInfo
) return E_INVALIDARG
;
933 formatInfo
->DxgiFormat
= This
->info
.format
;
934 formatInfo
->BytesPerBlock
= This
->info
.bytes_per_block
;
935 formatInfo
->BlockWidth
= This
->info
.block_width
;
936 formatInfo
->BlockHeight
= This
->info
.block_height
;
938 TRACE("(%p,%p) -> (0x%x,%d,%d,%d)\n", iface
, formatInfo
,
939 formatInfo
->DxgiFormat
, formatInfo
->BytesPerBlock
, formatInfo
->BlockWidth
, formatInfo
->BlockHeight
);
944 static HRESULT WINAPI
DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode
*iface
,
945 const WICRect
*boundsInBlocks
, UINT stride
, UINT bufferSize
,
948 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
949 int x
, y
, width
, height
;
950 UINT bytes_per_block
, frame_stride
, frame_size
;
952 TRACE("(%p,%p,%u,%u,%p)\n", iface
, boundsInBlocks
, stride
, bufferSize
, buffer
);
954 if (!buffer
) return E_INVALIDARG
;
956 bytes_per_block
= This
->info
.bytes_per_block
;
957 frame_stride
= This
->info
.width_in_blocks
* bytes_per_block
;
958 frame_size
= frame_stride
* This
->info
.height_in_blocks
;
960 if (!boundsInBlocks
) {
961 if (stride
< frame_stride
) return E_INVALIDARG
;
962 if (bufferSize
< frame_size
) return E_INVALIDARG
;
964 x
= boundsInBlocks
->X
;
965 y
= boundsInBlocks
->Y
;
966 width
= boundsInBlocks
->Width
;
967 height
= boundsInBlocks
->Height
;
968 if (x
< 0 || y
< 0 || width
<= 0 || height
<= 0 ||
969 x
+ width
> This
->info
.width_in_blocks
||
970 y
+ height
> This
->info
.height_in_blocks
) {
973 if (stride
< width
* bytes_per_block
) return E_INVALIDARG
;
974 if (bufferSize
< stride
* height
) return E_INVALIDARG
;
977 return copy_pixels(This
->info
.bytes_per_block
* 8, This
->block_data
, This
->info
.width_in_blocks
,
978 This
->info
.height_in_blocks
, frame_stride
, boundsInBlocks
, stride
, bufferSize
, buffer
);
981 static const IWICDdsFrameDecodeVtbl DdsFrameDecode_Dds_Vtbl
= {
982 DdsFrameDecode_Dds_QueryInterface
,
983 DdsFrameDecode_Dds_AddRef
,
984 DdsFrameDecode_Dds_Release
,
985 DdsFrameDecode_Dds_GetSizeInBlocks
,
986 DdsFrameDecode_Dds_GetFormatInfo
,
987 DdsFrameDecode_Dds_CopyBlocks
990 static HRESULT
DdsFrameDecode_CreateInstance(DdsFrameDecode
**frame_decode
)
992 DdsFrameDecode
*result
;
994 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(*result
));
995 if (!result
) return E_OUTOFMEMORY
;
997 result
->IWICBitmapFrameDecode_iface
.lpVtbl
= &DdsFrameDecode_Vtbl
;
998 result
->IWICDdsFrameDecode_iface
.lpVtbl
= &DdsFrameDecode_Dds_Vtbl
;
1000 InitializeCriticalSection(&result
->lock
);
1001 result
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsFrameDecode.lock");
1003 *frame_decode
= result
;
1007 static HRESULT WINAPI
DdsDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
1010 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1011 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1013 if (!ppv
) return E_INVALIDARG
;
1015 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1016 IsEqualIID(&IID_IWICBitmapDecoder
, iid
)) {
1017 *ppv
= &This
->IWICBitmapDecoder_iface
;
1018 } else if (IsEqualIID(&IID_IWICDdsDecoder
, iid
)) {
1019 *ppv
= &This
->IWICDdsDecoder_iface
;
1020 } else if (IsEqualIID(&IID_IWICWineDecoder
, iid
)) {
1021 *ppv
= &This
->IWICWineDecoder_iface
;
1024 return E_NOINTERFACE
;
1027 IUnknown_AddRef((IUnknown
*)*ppv
);
1031 static ULONG WINAPI
DdsDecoder_AddRef(IWICBitmapDecoder
*iface
)
1033 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1034 ULONG ref
= InterlockedIncrement(&This
->ref
);
1036 TRACE("(%p) refcount=%u\n", iface
, ref
);
1041 static ULONG WINAPI
DdsDecoder_Release(IWICBitmapDecoder
*iface
)
1043 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1044 ULONG ref
= InterlockedDecrement(&This
->ref
);
1046 TRACE("(%p) refcount=%u\n", iface
, ref
);
1050 This
->lock
.DebugInfo
->Spare
[0] = 0;
1051 DeleteCriticalSection(&This
->lock
);
1052 if (This
->stream
) IStream_Release(This
->stream
);
1053 HeapFree(GetProcessHeap(), 0, This
);
1059 static HRESULT WINAPI
DdsDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*stream
,
1062 FIXME("(%p,%p,%p): stub.\n", iface
, stream
, capability
);
1067 static HRESULT WINAPI
DdsDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
1068 WICDecodeOptions cacheOptions
)
1070 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1073 TRACE("(%p,%p,%x)\n", iface
, pIStream
, cacheOptions
);
1075 EnterCriticalSection(&This
->lock
);
1077 hr
= IWICWineDecoder_Initialize(&This
->IWICWineDecoder_iface
, pIStream
, cacheOptions
);
1078 if (FAILED(hr
)) goto end
;
1080 if (This
->info
.dimension
== WICDdsTextureCube
||
1081 (This
->info
.format
!= DXGI_FORMAT_BC1_UNORM
&&
1082 This
->info
.format
!= DXGI_FORMAT_BC2_UNORM
&&
1083 This
->info
.format
!= DXGI_FORMAT_BC3_UNORM
)) {
1084 IStream_Release(pIStream
);
1085 This
->stream
= NULL
;
1086 This
->initialized
= FALSE
;
1087 hr
= WINCODEC_ERR_BADHEADER
;
1091 LeaveCriticalSection(&This
->lock
);
1096 static HRESULT WINAPI
DdsDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
1097 GUID
*pguidContainerFormat
)
1099 TRACE("(%p,%p)\n", iface
, pguidContainerFormat
);
1101 memcpy(pguidContainerFormat
, &GUID_ContainerFormatDds
, sizeof(GUID
));
1106 static HRESULT WINAPI
DdsDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
1107 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
1109 TRACE("(%p,%p)\n", iface
, ppIDecoderInfo
);
1111 return get_decoder_info(&CLSID_WICDdsDecoder
, ppIDecoderInfo
);
1114 static HRESULT WINAPI
DdsDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
1115 IWICPalette
*pIPalette
)
1117 TRACE("(%p,%p)\n", iface
, pIPalette
);
1119 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
1122 static HRESULT WINAPI
DdsDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
1123 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
1125 if (!ppIMetadataQueryReader
) return E_INVALIDARG
;
1127 FIXME("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
1132 static HRESULT WINAPI
DdsDecoder_GetPreview(IWICBitmapDecoder
*iface
,
1133 IWICBitmapSource
**ppIBitmapSource
)
1135 TRACE("(%p,%p)\n", iface
, ppIBitmapSource
);
1137 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1140 static HRESULT WINAPI
DdsDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
1141 UINT cCount
, IWICColorContext
**ppDdslorContexts
, UINT
*pcActualCount
)
1143 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppDdslorContexts
, pcActualCount
);
1145 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1148 static HRESULT WINAPI
DdsDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
1149 IWICBitmapSource
**ppIThumbnail
)
1151 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
1153 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
1156 static HRESULT WINAPI
DdsDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
1159 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1161 if (!pCount
) return E_INVALIDARG
;
1162 if (!This
->initialized
) return WINCODEC_ERR_WRONGSTATE
;
1164 EnterCriticalSection(&This
->lock
);
1166 *pCount
= This
->info
.frame_count
;
1168 LeaveCriticalSection(&This
->lock
);
1170 TRACE("(%p) -> %d\n", iface
, *pCount
);
1175 static HRESULT WINAPI
DdsDecoder_GetFrame(IWICBitmapDecoder
*iface
,
1176 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
1178 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1179 UINT frame_per_texture
, array_index
, mip_level
, slice_index
, depth
;
1181 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
1183 if (!ppIBitmapFrame
) return E_INVALIDARG
;
1185 EnterCriticalSection(&This
->lock
);
1187 if (!This
->initialized
) {
1188 LeaveCriticalSection(&This
->lock
);
1189 return WINCODEC_ERR_WRONGSTATE
;
1192 if (This
->info
.dimension
== WICDdsTextureCube
) {
1193 frame_per_texture
= This
->info
.mip_levels
;
1195 frame_per_texture
= This
->info
.frame_count
/ This
->info
.array_size
;
1197 array_index
= index
/ frame_per_texture
;
1198 slice_index
= index
% frame_per_texture
;
1199 depth
= This
->info
.depth
;
1201 while (slice_index
>= depth
)
1203 slice_index
-= depth
;
1205 if (depth
> 1) depth
/= 2;
1208 LeaveCriticalSection(&This
->lock
);
1210 return DdsDecoder_Dds_GetFrame(&This
->IWICDdsDecoder_iface
, array_index
, mip_level
, slice_index
, ppIBitmapFrame
);
1213 static const IWICBitmapDecoderVtbl DdsDecoder_Vtbl
= {
1214 DdsDecoder_QueryInterface
,
1217 DdsDecoder_QueryCapability
,
1218 DdsDecoder_Initialize
,
1219 DdsDecoder_GetContainerFormat
,
1220 DdsDecoder_GetDecoderInfo
,
1221 DdsDecoder_CopyPalette
,
1222 DdsDecoder_GetMetadataQueryReader
,
1223 DdsDecoder_GetPreview
,
1224 DdsDecoder_GetColorContexts
,
1225 DdsDecoder_GetThumbnail
,
1226 DdsDecoder_GetFrameCount
,
1230 static HRESULT WINAPI
DdsDecoder_Dds_QueryInterface(IWICDdsDecoder
*iface
,
1231 REFIID iid
, void **ppv
)
1233 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1234 return DdsDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1237 static ULONG WINAPI
DdsDecoder_Dds_AddRef(IWICDdsDecoder
*iface
)
1239 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1240 return DdsDecoder_AddRef(&This
->IWICBitmapDecoder_iface
);
1243 static ULONG WINAPI
DdsDecoder_Dds_Release(IWICDdsDecoder
*iface
)
1245 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1246 return DdsDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1249 static HRESULT WINAPI
DdsDecoder_Dds_GetParameters(IWICDdsDecoder
*iface
,
1250 WICDdsParameters
*parameters
)
1252 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1255 if (!parameters
) return E_INVALIDARG
;
1257 EnterCriticalSection(&This
->lock
);
1259 if (!This
->initialized
) {
1260 hr
= WINCODEC_ERR_WRONGSTATE
;
1264 parameters
->Width
= This
->info
.width
;
1265 parameters
->Height
= This
->info
.height
;
1266 parameters
->Depth
= This
->info
.depth
;
1267 parameters
->MipLevels
= This
->info
.mip_levels
;
1268 parameters
->ArraySize
= This
->info
.array_size
;
1269 parameters
->DxgiFormat
= This
->info
.format
;
1270 parameters
->Dimension
= This
->info
.dimension
;
1271 parameters
->AlphaMode
= This
->info
.alpha_mode
;
1273 TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x dimension=0x%x alphaMode=0x%x)\n",
1274 iface
, parameters
->Width
, parameters
->Height
, parameters
->Depth
, parameters
->MipLevels
,
1275 parameters
->ArraySize
, parameters
->DxgiFormat
, parameters
->Dimension
, parameters
->AlphaMode
);
1280 LeaveCriticalSection(&This
->lock
);
1285 static HRESULT WINAPI
DdsDecoder_Dds_GetFrame(IWICDdsDecoder
*iface
,
1286 UINT arrayIndex
, UINT mipLevel
, UINT sliceIndex
,
1287 IWICBitmapFrameDecode
**bitmapFrame
)
1289 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1292 UINT width
, height
, depth
, block_width
, block_height
, width_in_blocks
, height_in_blocks
, size
;
1293 UINT frame_width
= 0, frame_height
= 0, frame_width_in_blocks
= 0, frame_height_in_blocks
= 0, frame_size
= 0;
1294 UINT bytes_per_block
, bytesread
, i
;
1295 DdsFrameDecode
*frame_decode
= NULL
;
1297 TRACE("(%p,%u,%u,%u,%p)\n", iface
, arrayIndex
, mipLevel
, sliceIndex
, bitmapFrame
);
1299 if (!bitmapFrame
) return E_INVALIDARG
;
1301 EnterCriticalSection(&This
->lock
);
1303 if (!This
->initialized
) {
1304 hr
= WINCODEC_ERR_WRONGSTATE
;
1308 if ((arrayIndex
>= This
->info
.array_size
&& This
->info
.dimension
!= WICDdsTextureCube
) ||
1309 (arrayIndex
>= This
->info
.array_size
* 6) ||
1310 (mipLevel
>= This
->info
.mip_levels
) ||
1311 (sliceIndex
>= This
->info
.depth
)) {
1316 if (is_compressed(This
->info
.format
)) {
1317 block_width
= DDS_BLOCK_WIDTH
;
1318 block_height
= DDS_BLOCK_HEIGHT
;
1323 bytes_per_block
= This
->info
.bytes_per_block
;
1324 seek
.QuadPart
= This
->info
.data_offset
;
1326 width
= This
->info
.width
;
1327 height
= This
->info
.height
;
1328 depth
= This
->info
.depth
;
1329 for (i
= 0; i
< This
->info
.mip_levels
; i
++)
1331 width_in_blocks
= (width
+ block_width
- 1) / block_width
;
1332 height_in_blocks
= (height
+ block_height
- 1) / block_height
;
1333 size
= width_in_blocks
* height_in_blocks
* bytes_per_block
;
1336 seek
.QuadPart
+= size
* depth
;
1337 } else if (i
== mipLevel
){
1338 seek
.QuadPart
+= size
* sliceIndex
;
1339 frame_width
= width
;
1340 frame_height
= height
;
1341 frame_width_in_blocks
= width_in_blocks
;
1342 frame_height_in_blocks
= height_in_blocks
;
1343 frame_size
= frame_width_in_blocks
* frame_height_in_blocks
* bytes_per_block
;
1344 if (arrayIndex
== 0) break;
1346 seek
.QuadPart
+= arrayIndex
* size
* depth
;
1348 if (width
> 1) width
/= 2;
1349 if (height
> 1) height
/= 2;
1350 if (depth
> 1) depth
/= 2;
1353 hr
= DdsFrameDecode_CreateInstance(&frame_decode
);
1354 if (hr
!= S_OK
) goto end
;
1355 frame_decode
->info
.width
= frame_width
;
1356 frame_decode
->info
.height
= frame_height
;
1357 frame_decode
->info
.format
= This
->info
.format
;
1358 frame_decode
->info
.bytes_per_block
= bytes_per_block
;
1359 frame_decode
->info
.block_width
= block_width
;
1360 frame_decode
->info
.block_height
= block_height
;
1361 frame_decode
->info
.width_in_blocks
= frame_width_in_blocks
;
1362 frame_decode
->info
.height_in_blocks
= frame_height_in_blocks
;
1363 frame_decode
->info
.pixel_format
= This
->info
.pixel_format
;
1364 frame_decode
->info
.pixel_format_bpp
= This
->info
.pixel_format_bpp
;
1365 frame_decode
->block_data
= HeapAlloc(GetProcessHeap(), 0, frame_size
);
1366 frame_decode
->pixel_data
= NULL
;
1367 hr
= IStream_Seek(This
->stream
, seek
, SEEK_SET
, NULL
);
1368 if (hr
!= S_OK
) goto end
;
1369 hr
= IStream_Read(This
->stream
, frame_decode
->block_data
, frame_size
, &bytesread
);
1370 if (hr
!= S_OK
|| bytesread
!= frame_size
) {
1371 hr
= WINCODEC_ERR_STREAMREAD
;
1374 *bitmapFrame
= &frame_decode
->IWICBitmapFrameDecode_iface
;
1379 LeaveCriticalSection(&This
->lock
);
1381 if (hr
!= S_OK
&& frame_decode
) DdsFrameDecode_Release(&frame_decode
->IWICBitmapFrameDecode_iface
);
1386 static const IWICDdsDecoderVtbl DdsDecoder_Dds_Vtbl
= {
1387 DdsDecoder_Dds_QueryInterface
,
1388 DdsDecoder_Dds_AddRef
,
1389 DdsDecoder_Dds_Release
,
1390 DdsDecoder_Dds_GetParameters
,
1391 DdsDecoder_Dds_GetFrame
1394 static HRESULT WINAPI
DdsDecoder_Wine_QueryInterface(IWICWineDecoder
*iface
, REFIID iid
, void **ppv
)
1396 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1397 return DdsDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1400 static ULONG WINAPI
DdsDecoder_Wine_AddRef(IWICWineDecoder
*iface
)
1402 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1403 return DdsDecoder_AddRef(&This
->IWICBitmapDecoder_iface
);
1406 static ULONG WINAPI
DdsDecoder_Wine_Release(IWICWineDecoder
*iface
)
1408 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1409 return DdsDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1412 static HRESULT WINAPI
DdsDecoder_Wine_Initialize(IWICWineDecoder
*iface
, IStream
*stream
, WICDecodeOptions options
)
1414 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1415 DDS_HEADER_DXT10 header_dxt10
;
1422 TRACE("(This %p, stream %p, options %#x)\n", iface
, stream
, options
);
1424 EnterCriticalSection(&This
->lock
);
1426 if (This
->initialized
) {
1427 hr
= WINCODEC_ERR_WRONGSTATE
;
1432 hr
= IStream_Seek(stream
, seek
, SEEK_SET
, NULL
);
1433 if (FAILED(hr
)) goto end
;
1435 hr
= IStream_Read(stream
, &magic
, sizeof(magic
), &bytesread
);
1436 if (FAILED(hr
)) goto end
;
1437 if (bytesread
!= sizeof(magic
)) {
1438 hr
= WINCODEC_ERR_STREAMREAD
;
1441 if (magic
!= DDS_MAGIC
) {
1442 hr
= WINCODEC_ERR_UNKNOWNIMAGEFORMAT
;
1446 hr
= IStream_Read(stream
, &header
, sizeof(header
), &bytesread
);
1447 if (FAILED(hr
)) goto end
;
1448 if (bytesread
!= sizeof(header
)) {
1449 hr
= WINCODEC_ERR_STREAMREAD
;
1452 if (header
.size
!= sizeof(header
)) {
1453 hr
= WINCODEC_ERR_BADHEADER
;
1457 if (has_extended_header(&header
)) {
1458 hr
= IStream_Read(stream
, &header_dxt10
, sizeof(header_dxt10
), &bytesread
);
1459 if (FAILED(hr
)) goto end
;
1460 if (bytesread
!= sizeof(header_dxt10
)) {
1461 hr
= WINCODEC_ERR_STREAMREAD
;
1466 get_dds_info(&This
->info
, &header
, &header_dxt10
);
1468 This
->initialized
= TRUE
;
1469 This
->stream
= stream
;
1470 IStream_AddRef(stream
);
1473 LeaveCriticalSection(&This
->lock
);
1478 static const IWICWineDecoderVtbl DdsDecoder_Wine_Vtbl
= {
1479 DdsDecoder_Wine_QueryInterface
,
1480 DdsDecoder_Wine_AddRef
,
1481 DdsDecoder_Wine_Release
,
1482 DdsDecoder_Wine_Initialize
1485 HRESULT
DdsDecoder_CreateInstance(REFIID iid
, void** ppv
)
1490 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1494 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(DdsDecoder
));
1495 if (!This
) return E_OUTOFMEMORY
;
1497 This
->IWICBitmapDecoder_iface
.lpVtbl
= &DdsDecoder_Vtbl
;
1498 This
->IWICDdsDecoder_iface
.lpVtbl
= &DdsDecoder_Dds_Vtbl
;
1499 This
->IWICWineDecoder_iface
.lpVtbl
= &DdsDecoder_Wine_Vtbl
;
1501 This
->initialized
= FALSE
;
1502 This
->stream
= NULL
;
1503 InitializeCriticalSection(&This
->lock
);
1504 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsDecoder.lock");
1506 ret
= IWICBitmapDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1507 IWICBitmapDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1512 static HRESULT WINAPI
DdsEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
1515 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1516 FIXME("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1518 if (!ppv
) return E_INVALIDARG
;
1520 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1521 IsEqualIID(&IID_IWICBitmapEncoder
, iid
)) {
1522 *ppv
= &This
->IWICBitmapEncoder_iface
;
1526 return E_NOINTERFACE
;
1529 IUnknown_AddRef((IUnknown
*)*ppv
);
1533 static ULONG WINAPI
DdsEncoder_AddRef(IWICBitmapEncoder
*iface
)
1535 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1536 ULONG ref
= InterlockedIncrement(&This
->ref
);
1538 TRACE("(%p) refcount=%u\n", iface
, ref
);
1543 static ULONG WINAPI
DdsEncoder_Release(IWICBitmapEncoder
*iface
)
1545 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1546 ULONG ref
= InterlockedDecrement(&This
->ref
);
1548 TRACE("(%p) refcount=%u\n", iface
, ref
);
1551 This
->lock
.DebugInfo
->Spare
[0] = 0;
1552 DeleteCriticalSection(&This
->lock
);
1553 if (This
->stream
) IStream_Release(This
->stream
);
1554 HeapFree(GetProcessHeap(), 0, This
);
1560 static HRESULT WINAPI
DdsEncoder_Initialize(IWICBitmapEncoder
*iface
,
1561 IStream
*pIStream
, WICBitmapEncoderCacheOption cacheOption
)
1563 FIXME("(%p,%p,%u): stub\n", iface
, pIStream
, cacheOption
);
1567 static HRESULT WINAPI
DdsEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
, GUID
*format
)
1569 TRACE("(%p,%p)\n", iface
, format
);
1572 return E_INVALIDARG
;
1574 memcpy(format
, &GUID_ContainerFormatDds
, sizeof(*format
));
1578 static HRESULT WINAPI
DdsEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
, IWICBitmapEncoderInfo
**info
)
1580 IWICComponentInfo
*comp_info
;
1583 TRACE("%p,%p\n", iface
, info
);
1585 if (!info
) return E_INVALIDARG
;
1587 hr
= CreateComponentInfo(&CLSID_WICDdsEncoder
, &comp_info
);
1589 hr
= IWICComponentInfo_QueryInterface(comp_info
, &IID_IWICBitmapEncoderInfo
, (void **)info
);
1590 IWICComponentInfo_Release(comp_info
);
1595 static HRESULT WINAPI
DdsEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
1596 UINT cCount
, IWICColorContext
**ppIColorContext
)
1598 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
1602 static HRESULT WINAPI
DdsEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*palette
)
1604 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1607 TRACE("(%p,%p)\n", iface
, palette
);
1609 EnterCriticalSection(&This
->lock
);
1611 hr
= This
->stream
? WINCODEC_ERR_UNSUPPORTEDOPERATION
: WINCODEC_ERR_NOTINITIALIZED
;
1613 LeaveCriticalSection(&This
->lock
);
1618 static HRESULT WINAPI
DdsEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
1620 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
1621 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1624 static HRESULT WINAPI
DdsEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
1626 TRACE("(%p,%p)\n", iface
, pIPreview
);
1627 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1630 static HRESULT WINAPI
DdsEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
1631 IWICBitmapFrameEncode
**ppIFrameEncode
, IPropertyBag2
**ppIEncoderOptions
)
1633 FIXME("(%p,%p,%p): stub\n", iface
, ppIFrameEncode
, ppIEncoderOptions
);
1637 static HRESULT WINAPI
DdsEncoder_Commit(IWICBitmapEncoder
*iface
)
1639 FIXME("(%p): stub\n", iface
);
1643 static HRESULT WINAPI
DdsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
1644 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
1646 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
1650 static const IWICBitmapEncoderVtbl DdsEncoder_Vtbl
= {
1651 DdsEncoder_QueryInterface
,
1654 DdsEncoder_Initialize
,
1655 DdsEncoder_GetContainerFormat
,
1656 DdsEncoder_GetEncoderInfo
,
1657 DdsEncoder_SetColorContexts
,
1658 DdsEncoder_SetPalette
,
1659 DdsEncoder_SetThumbnail
,
1660 DdsEncoder_SetPreview
,
1661 DdsEncoder_CreateNewFrame
,
1663 DdsEncoder_GetMetadataQueryWriter
1666 HRESULT
DdsEncoder_CreateInstance( REFIID iid
, void **ppv
)
1671 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1675 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(DdsEncoder
));
1676 if (!This
) return E_OUTOFMEMORY
;
1678 This
->IWICBitmapEncoder_iface
.lpVtbl
= &DdsEncoder_Vtbl
;
1680 This
->stream
= NULL
;
1681 This
->frame_count
= 0;
1682 This
->uncommitted_frame
= FALSE
;
1683 This
->committed
= FALSE
;
1684 InitializeCriticalSection(&This
->lock
);
1685 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsEncoder.lock");
1687 ret
= IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
1688 IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);