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
;
164 IWICDdsEncoder IWICDdsEncoder_iface
;
166 CRITICAL_SECTION lock
;
169 BOOL uncommitted_frame
;
173 typedef struct DdsFrameEncode
{
174 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface
;
185 static struct dds_format
{
186 DDS_PIXELFORMAT pixel_format
;
187 const GUID
*wic_format
;
189 DXGI_FORMAT dxgi_format
;
190 } dds_format_table
[] = {
191 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '1'), 0, 0, 0, 0, 0 },
192 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC1_UNORM
},
193 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0 },
194 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC2_UNORM
},
195 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '3'), 0, 0, 0, 0, 0 },
196 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC2_UNORM
},
197 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '4'), 0, 0, 0, 0, 0 },
198 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC3_UNORM
},
199 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '5'), 0, 0, 0, 0, 0 },
200 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC3_UNORM
},
201 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '4', 'U'), 0, 0, 0, 0, 0 },
202 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_UNORM
},
203 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '4', 'S'), 0, 0, 0, 0, 0 },
204 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_SNORM
},
205 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '5', 'U'), 0, 0, 0, 0, 0 },
206 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_UNORM
},
207 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '5', 'S'), 0, 0, 0, 0, 0 },
208 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_SNORM
},
209 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('A', 'T', 'I', '1'), 0, 0, 0, 0, 0 },
210 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_UNORM
},
211 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('A', 'T', 'I', '2'), 0, 0, 0, 0, 0 },
212 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_UNORM
},
213 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('R', 'G', 'B', 'G'), 0, 0, 0, 0, 0 },
214 &GUID_WICPixelFormat32bpp4Channels
, 32, DXGI_FORMAT_R8G8_B8G8_UNORM
},
215 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('G', 'R', 'G', 'B'), 0, 0, 0, 0, 0 },
216 &GUID_WICPixelFormat32bpp4Channels
, 32, DXGI_FORMAT_G8R8_G8B8_UNORM
},
217 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', '1', '0'), 0, 0, 0, 0, 0 },
218 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_UNKNOWN
},
219 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x24, 0, 0, 0, 0, 0 },
220 &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_UNORM
},
221 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x6E, 0, 0, 0, 0, 0 },
222 &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_SNORM
},
223 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x6F, 0, 0, 0, 0, 0 },
224 &GUID_WICPixelFormat16bppGrayHalf
, 16, DXGI_FORMAT_R16_FLOAT
},
225 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x70, 0, 0, 0, 0, 0 },
226 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R16G16_FLOAT
},
227 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x71, 0, 0, 0, 0, 0 },
228 &GUID_WICPixelFormat64bppRGBAHalf
, 64, DXGI_FORMAT_R16G16B16A16_FLOAT
},
229 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x72, 0, 0, 0, 0, 0 },
230 &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
231 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x73, 0, 0, 0, 0, 0 },
232 &GUID_WICPixelFormatUndefined
, 32, DXGI_FORMAT_R32G32_FLOAT
},
233 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x74, 0, 0, 0, 0, 0 },
234 &GUID_WICPixelFormat128bppRGBAFloat
, 128, DXGI_FORMAT_R32G32B32A32_FLOAT
},
235 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF,0xFF00,0xFF0000,0xFF000000 },
236 &GUID_WICPixelFormat32bppRGBA
, 32, DXGI_FORMAT_R8G8B8A8_UNORM
},
237 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF,0xFF00,0xFF0000,0 },
238 &GUID_WICPixelFormat32bppRGB
, 32, DXGI_FORMAT_UNKNOWN
},
239 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF0000,0xFF00,0xFF,0xFF000000 },
240 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_B8G8R8A8_UNORM
},
241 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF0000,0xFF00,0xFF,0 },
242 &GUID_WICPixelFormat32bppBGR
, 32, DXGI_FORMAT_B8G8R8X8_UNORM
},
243 /* The red and blue masks are swapped for DXGI_FORMAT_R10G10B10A2_UNORM.
244 * For "correct" one, the RGB masks should be 0x3FF,0xFFC00,0x3FF00000.
245 * see: https://walbourn.github.io/dds-update-and-1010102-problems */
246 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0x3FF00000,0xFFC00,0x3FF,0xC0000000 },
247 &GUID_WICPixelFormat32bppR10G10B10A2
, 32, DXGI_FORMAT_R10G10B10A2_UNORM
},
248 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0x3FF,0xFFC00,0x3FF00000,0xC0000000 },
249 &GUID_WICPixelFormat32bppRGBA1010102
, 32, DXGI_FORMAT_UNKNOWN
},
250 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFFFF,0xFFFF0000,0,0 },
251 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R16G16_UNORM
},
252 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFFFFFFFF,0,0,0 },
253 &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
254 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 24, 0xFF0000,0x00FF00,0x0000FF,0 },
255 &GUID_WICPixelFormat24bppBGR
, 24, DXGI_FORMAT_UNKNOWN
},
256 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 24, 0x0000FF,0x00FF00,0xFF0000,0 },
257 &GUID_WICPixelFormat24bppRGB
, 24, DXGI_FORMAT_UNKNOWN
},
258 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0xF800,0x7E0,0x1F,0 },
259 &GUID_WICPixelFormat16bppBGR565
, 16, DXGI_FORMAT_B5G6R5_UNORM
},
260 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0x7C00,0x3E0,0x1F,0 },
261 &GUID_WICPixelFormat16bppBGR555
, 16, DXGI_FORMAT_UNKNOWN
},
262 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0x7C00,0x3E0,0x1F,0x8000 },
263 &GUID_WICPixelFormat16bppBGRA5551
, 16, DXGI_FORMAT_B5G5R5A1_UNORM
},
264 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0xF00,0xF0,0xF,0xF000 },
265 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_B4G4R4A4_UNORM
},
266 { { sizeof(DDS_PIXELFORMAT
), DDPF_ALPHA
, 0, 8, 0,0,0,0xFF },
267 &GUID_WICPixelFormat8bppAlpha
, 8, DXGI_FORMAT_A8_UNORM
},
268 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 16, 0xFFFF,0,0,0 },
269 &GUID_WICPixelFormat16bppGray
, 16, DXGI_FORMAT_R16_UNORM
},
270 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 16, 0xFF,0,0,0xFF00 },
271 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R8G8_UNORM
},
272 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 8, 0xFF,0,0,0 },
273 &GUID_WICPixelFormat8bppGray
, 8, DXGI_FORMAT_R8_UNORM
},
274 { { 0 }, &GUID_WICPixelFormat8bppAlpha
, 8, DXGI_FORMAT_A8_UNORM
},
275 { { 0 }, &GUID_WICPixelFormat8bppGray
, 8, DXGI_FORMAT_R8_UNORM
},
276 { { 0 }, &GUID_WICPixelFormat16bppGray
, 16, DXGI_FORMAT_R16_UNORM
},
277 { { 0 }, &GUID_WICPixelFormat16bppGrayHalf
, 16, DXGI_FORMAT_R16_FLOAT
},
278 { { 0 }, &GUID_WICPixelFormat16bppBGR565
, 16, DXGI_FORMAT_B5G6R5_UNORM
},
279 { { 0 }, &GUID_WICPixelFormat16bppBGRA5551
, 16, DXGI_FORMAT_B5G5R5A1_UNORM
},
280 { { 0 }, &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
281 { { 0 }, &GUID_WICPixelFormat32bppRGBA
, 32, DXGI_FORMAT_R8G8B8A8_UNORM
},
282 { { 0 }, &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_B8G8R8A8_UNORM
},
283 { { 0 }, &GUID_WICPixelFormat32bppBGR
, 32, DXGI_FORMAT_B8G8R8X8_UNORM
},
284 { { 0 }, &GUID_WICPixelFormat32bppR10G10B10A2
, 32, DXGI_FORMAT_R10G10B10A2_UNORM
},
285 { { 0 }, &GUID_WICPixelFormat32bppRGBE
, 32, DXGI_FORMAT_R9G9B9E5_SHAREDEXP
},
286 { { 0 }, &GUID_WICPixelFormat32bppRGBA1010102XR
, 32, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
},
287 { { 0 }, &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_UNORM
},
288 { { 0 }, &GUID_WICPixelFormat64bppRGBAHalf
, 64, DXGI_FORMAT_R16G16B16A16_FLOAT
},
289 { { 0 }, &GUID_WICPixelFormat96bppRGBFloat
, 96, DXGI_FORMAT_R32G32B32_FLOAT
},
290 { { 0 }, &GUID_WICPixelFormat128bppRGBAFloat
, 128, DXGI_FORMAT_R32G32B32A32_FLOAT
},
291 { { 0 }, &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_UNKNOWN
}
294 static DXGI_FORMAT compressed_formats
[] = {
295 DXGI_FORMAT_BC1_TYPELESS
, DXGI_FORMAT_BC1_UNORM
, DXGI_FORMAT_BC1_UNORM_SRGB
,
296 DXGI_FORMAT_BC2_TYPELESS
, DXGI_FORMAT_BC2_UNORM
, DXGI_FORMAT_BC2_UNORM_SRGB
,
297 DXGI_FORMAT_BC3_TYPELESS
, DXGI_FORMAT_BC3_UNORM
, DXGI_FORMAT_BC3_UNORM_SRGB
,
298 DXGI_FORMAT_BC4_TYPELESS
, DXGI_FORMAT_BC4_UNORM
, DXGI_FORMAT_BC4_SNORM
,
299 DXGI_FORMAT_BC5_TYPELESS
, DXGI_FORMAT_BC5_UNORM
, DXGI_FORMAT_BC5_SNORM
,
300 DXGI_FORMAT_BC6H_TYPELESS
, DXGI_FORMAT_BC6H_UF16
, DXGI_FORMAT_BC6H_SF16
,
301 DXGI_FORMAT_BC7_TYPELESS
, DXGI_FORMAT_BC7_UNORM
, DXGI_FORMAT_BC7_UNORM_SRGB
304 static HRESULT WINAPI
DdsDecoder_Dds_GetFrame(IWICDdsDecoder
*, UINT
, UINT
, UINT
, IWICBitmapFrameDecode
**);
306 static DWORD
rgb565_to_argb(WORD color
, BYTE alpha
)
308 return MAKE_ARGB(alpha
, (GET_RGB565_R(color
) * 0xFF + 0x0F) / 0x1F,
309 (GET_RGB565_G(color
) * 0xFF + 0x1F) / 0x3F,
310 (GET_RGB565_B(color
) * 0xFF + 0x0F) / 0x1F);
313 static inline BOOL
has_extended_header(DDS_HEADER
*header
)
315 return (header
->ddspf
.flags
& DDPF_FOURCC
) &&
316 (header
->ddspf
.fourCC
== MAKEFOURCC('D', 'X', '1', '0'));
319 static WICDdsDimension
get_dimension(DDS_HEADER
*header
, DDS_HEADER_DXT10
*header_dxt10
)
322 if (header_dxt10
->miscFlag
& DDS_RESOURCE_MISC_TEXTURECUBE
) return WICDdsTextureCube
;
323 switch (header_dxt10
->resourceDimension
)
325 case DDS_DIMENSION_TEXTURE1D
: return WICDdsTexture1D
;
326 case DDS_DIMENSION_TEXTURE2D
: return WICDdsTexture2D
;
327 case DDS_DIMENSION_TEXTURE3D
: return WICDdsTexture3D
;
328 default: return WICDdsTexture2D
;
331 if (header
->caps2
& DDSCAPS2_CUBEMAP
) {
332 return WICDdsTextureCube
;
333 } else if (header
->caps2
& DDSCAPS2_VOLUME
) {
334 return WICDdsTexture3D
;
336 return WICDdsTexture2D
;
341 static struct dds_format
*get_dds_format(DDS_PIXELFORMAT
*pixel_format
)
345 for (i
= 0; i
< ARRAY_SIZE(dds_format_table
); i
++)
347 if ((pixel_format
->flags
& dds_format_table
[i
].pixel_format
.flags
) &&
348 (pixel_format
->fourCC
== dds_format_table
[i
].pixel_format
.fourCC
) &&
349 (pixel_format
->rgbBitCount
== dds_format_table
[i
].pixel_format
.rgbBitCount
) &&
350 (pixel_format
->rBitMask
== dds_format_table
[i
].pixel_format
.rBitMask
) &&
351 (pixel_format
->gBitMask
== dds_format_table
[i
].pixel_format
.gBitMask
) &&
352 (pixel_format
->bBitMask
== dds_format_table
[i
].pixel_format
.bBitMask
) &&
353 (pixel_format
->aBitMask
== dds_format_table
[i
].pixel_format
.aBitMask
))
354 return dds_format_table
+ i
;
357 return dds_format_table
+ ARRAY_SIZE(dds_format_table
) - 1;
360 static WICDdsAlphaMode
get_alpha_mode_from_fourcc(DWORD fourcc
)
364 case MAKEFOURCC('D', 'X', 'T', '1'):
365 case MAKEFOURCC('D', 'X', 'T', '2'):
366 case MAKEFOURCC('D', 'X', 'T', '4'):
367 return WICDdsAlphaModePremultiplied
;
369 return WICDdsAlphaModeUnknown
;
373 static UINT
get_bytes_per_block_from_format(DXGI_FORMAT format
)
375 /* for uncompressed format, return bytes per pixel*/
378 case DXGI_FORMAT_R8_TYPELESS
:
379 case DXGI_FORMAT_R8_UNORM
:
380 case DXGI_FORMAT_R8_UINT
:
381 case DXGI_FORMAT_R8_SNORM
:
382 case DXGI_FORMAT_R8_SINT
:
383 case DXGI_FORMAT_A8_UNORM
:
385 case DXGI_FORMAT_R8G8_TYPELESS
:
386 case DXGI_FORMAT_R8G8_UNORM
:
387 case DXGI_FORMAT_R8G8_UINT
:
388 case DXGI_FORMAT_R8G8_SNORM
:
389 case DXGI_FORMAT_R8G8_SINT
:
390 case DXGI_FORMAT_R16_TYPELESS
:
391 case DXGI_FORMAT_R16_FLOAT
:
392 case DXGI_FORMAT_D16_UNORM
:
393 case DXGI_FORMAT_R16_UNORM
:
394 case DXGI_FORMAT_R16_UINT
:
395 case DXGI_FORMAT_R16_SNORM
:
396 case DXGI_FORMAT_R16_SINT
:
397 case DXGI_FORMAT_B5G6R5_UNORM
:
398 case DXGI_FORMAT_B5G5R5A1_UNORM
:
399 case DXGI_FORMAT_B4G4R4A4_UNORM
:
401 case DXGI_FORMAT_R10G10B10A2_TYPELESS
:
402 case DXGI_FORMAT_R10G10B10A2_UNORM
:
403 case DXGI_FORMAT_R10G10B10A2_UINT
:
404 case DXGI_FORMAT_R11G11B10_FLOAT
:
405 case DXGI_FORMAT_R8G8B8A8_TYPELESS
:
406 case DXGI_FORMAT_R8G8B8A8_UNORM
:
407 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
:
408 case DXGI_FORMAT_R8G8B8A8_UINT
:
409 case DXGI_FORMAT_R8G8B8A8_SNORM
:
410 case DXGI_FORMAT_R8G8B8A8_SINT
:
411 case DXGI_FORMAT_R16G16_TYPELESS
:
412 case DXGI_FORMAT_R16G16_FLOAT
:
413 case DXGI_FORMAT_R16G16_UNORM
:
414 case DXGI_FORMAT_R16G16_UINT
:
415 case DXGI_FORMAT_R16G16_SNORM
:
416 case DXGI_FORMAT_R16G16_SINT
:
417 case DXGI_FORMAT_R32_TYPELESS
:
418 case DXGI_FORMAT_D32_FLOAT
:
419 case DXGI_FORMAT_R32_FLOAT
:
420 case DXGI_FORMAT_R32_UINT
:
421 case DXGI_FORMAT_R32_SINT
:
422 case DXGI_FORMAT_R24G8_TYPELESS
:
423 case DXGI_FORMAT_D24_UNORM_S8_UINT
:
424 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS
:
425 case DXGI_FORMAT_X24_TYPELESS_G8_UINT
:
426 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP
:
427 case DXGI_FORMAT_R8G8_B8G8_UNORM
:
428 case DXGI_FORMAT_G8R8_G8B8_UNORM
:
429 case DXGI_FORMAT_B8G8R8A8_UNORM
:
430 case DXGI_FORMAT_B8G8R8X8_UNORM
:
431 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
:
432 case DXGI_FORMAT_B8G8R8A8_TYPELESS
:
433 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
:
434 case DXGI_FORMAT_B8G8R8X8_TYPELESS
:
435 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
:
437 case DXGI_FORMAT_BC1_UNORM
:
438 case DXGI_FORMAT_BC1_TYPELESS
:
439 case DXGI_FORMAT_BC1_UNORM_SRGB
:
440 case DXGI_FORMAT_BC4_TYPELESS
:
441 case DXGI_FORMAT_BC4_UNORM
:
442 case DXGI_FORMAT_BC4_SNORM
:
443 case DXGI_FORMAT_R16G16B16A16_TYPELESS
:
444 case DXGI_FORMAT_R16G16B16A16_FLOAT
:
445 case DXGI_FORMAT_R16G16B16A16_UNORM
:
446 case DXGI_FORMAT_R16G16B16A16_UINT
:
447 case DXGI_FORMAT_R16G16B16A16_SNORM
:
448 case DXGI_FORMAT_R16G16B16A16_SINT
:
449 case DXGI_FORMAT_R32G32_TYPELESS
:
450 case DXGI_FORMAT_R32G32_FLOAT
:
451 case DXGI_FORMAT_R32G32_UINT
:
452 case DXGI_FORMAT_R32G32_SINT
:
453 case DXGI_FORMAT_R32G8X24_TYPELESS
:
454 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT
:
455 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS
:
456 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT
:
458 case DXGI_FORMAT_R32G32B32_TYPELESS
:
459 case DXGI_FORMAT_R32G32B32_FLOAT
:
460 case DXGI_FORMAT_R32G32B32_UINT
:
461 case DXGI_FORMAT_R32G32B32_SINT
:
463 case DXGI_FORMAT_BC2_UNORM
:
464 case DXGI_FORMAT_BC2_TYPELESS
:
465 case DXGI_FORMAT_BC2_UNORM_SRGB
:
466 case DXGI_FORMAT_BC3_UNORM
:
467 case DXGI_FORMAT_BC3_TYPELESS
:
468 case DXGI_FORMAT_BC3_UNORM_SRGB
:
469 case DXGI_FORMAT_BC5_TYPELESS
:
470 case DXGI_FORMAT_BC5_UNORM
:
471 case DXGI_FORMAT_BC5_SNORM
:
472 case DXGI_FORMAT_BC6H_TYPELESS
:
473 case DXGI_FORMAT_BC6H_UF16
:
474 case DXGI_FORMAT_BC6H_SF16
:
475 case DXGI_FORMAT_BC7_TYPELESS
:
476 case DXGI_FORMAT_BC7_UNORM
:
477 case DXGI_FORMAT_BC7_UNORM_SRGB
:
478 case DXGI_FORMAT_R32G32B32A32_TYPELESS
:
479 case DXGI_FORMAT_R32G32B32A32_FLOAT
:
480 case DXGI_FORMAT_R32G32B32A32_UINT
:
481 case DXGI_FORMAT_R32G32B32A32_SINT
:
484 WARN("DXGI format 0x%x is not supported in DDS decoder\n", format
);
489 static const GUID
*dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format
)
492 for (i
= 0; i
< ARRAY_SIZE(dds_format_table
); i
++)
494 if (dds_format_table
[i
].pixel_format
.size
== 0 &&
495 dds_format_table
[i
].dxgi_format
== dxgi_format
)
496 return dds_format_table
[i
].wic_format
;
498 return &GUID_WICPixelFormatUndefined
;
501 static BOOL
is_compressed(DXGI_FORMAT format
)
505 for (i
= 0; i
< ARRAY_SIZE(compressed_formats
); i
++)
507 if (format
== compressed_formats
[i
]) return TRUE
;
512 static void get_dds_info(dds_info
* info
, DDS_HEADER
*header
, DDS_HEADER_DXT10
*header_dxt10
)
516 struct dds_format
*format_info
;
518 info
->width
= header
->width
;
519 info
->height
= header
->height
;
521 info
->mip_levels
= 1;
522 info
->array_size
= 1;
523 if (header
->depth
) info
->depth
= header
->depth
;
524 if (header
->mipMapCount
) info
->mip_levels
= header
->mipMapCount
;
526 if (has_extended_header(header
)) {
527 if (header_dxt10
->arraySize
) info
->array_size
= header_dxt10
->arraySize
;
528 info
->format
= header_dxt10
->dxgiFormat
;
529 info
->dimension
= get_dimension(NULL
, header_dxt10
);
530 info
->alpha_mode
= header_dxt10
->miscFlags2
& 0x00000008;
531 info
->data_offset
= sizeof(DWORD
) + sizeof(*header
) + sizeof(*header_dxt10
);
532 if (is_compressed(info
->format
)) {
533 info
->pixel_format
= (info
->alpha_mode
== WICDdsAlphaModePremultiplied
) ?
534 &GUID_WICPixelFormat32bppPBGRA
: &GUID_WICPixelFormat32bppBGRA
;
535 info
->pixel_format_bpp
= 32;
537 info
->pixel_format
= dxgi_format_to_wic_format(info
->format
);
538 info
->pixel_format_bpp
= get_bytes_per_block_from_format(info
->format
) * 8;
541 format_info
= get_dds_format(&header
->ddspf
);
542 info
->format
= format_info
->dxgi_format
;
543 info
->dimension
= get_dimension(header
, NULL
);
544 info
->alpha_mode
= get_alpha_mode_from_fourcc(header
->ddspf
.fourCC
);
545 info
->data_offset
= sizeof(DWORD
) + sizeof(*header
);
546 info
->pixel_format
= format_info
->wic_format
;
547 info
->pixel_format_bpp
= format_info
->wic_format_bpp
;
550 if (header
->ddspf
.flags
& (DDPF_RGB
| DDPF_ALPHA
| DDPF_LUMINANCE
)) {
551 info
->bytes_per_block
= header
->ddspf
.rgbBitCount
/ 8;
553 info
->bytes_per_block
= get_bytes_per_block_from_format(info
->format
);
556 /* get frame count */
558 if (info
->depth
== 1) {
559 info
->frame_count
= info
->array_size
* info
->mip_levels
;
561 info
->frame_count
= 0;
563 for (i
= 0; i
< info
->mip_levels
; i
++)
565 info
->frame_count
+= depth
;
566 if (depth
> 1) depth
/= 2;
568 info
->frame_count
*= info
->array_size
;
570 if (info
->dimension
== WICDdsTextureCube
) info
->frame_count
*= 6;
573 static void decode_block(const BYTE
*block_data
, UINT block_count
, DXGI_FORMAT format
,
574 UINT width
, UINT height
, DWORD
*buffer
)
576 const BYTE
*block
, *color_indices
, *alpha_indices
, *alpha_table
;
577 int i
, j
, x
, y
, block_x
, block_y
, color_index
, alpha_index
;
578 int block_size
, color_offset
, color_indices_offset
;
579 WORD color
[4], color_value
= 0;
580 BYTE alpha
[8], alpha_value
= 0;
582 if (format
== DXGI_FORMAT_BC1_UNORM
) {
585 color_indices_offset
= 4;
589 color_indices_offset
= 12;
594 for (i
= 0; i
< block_count
; i
++)
596 block
= block_data
+ i
* block_size
;
598 color
[0] = *((WORD
*)(block
+ color_offset
));
599 color
[1] = *((WORD
*)(block
+ color_offset
+ 2));
600 color
[2] = MAKE_RGB565(((GET_RGB565_R(color
[0]) * 2 + GET_RGB565_R(color
[1]) + 1) / 3),
601 ((GET_RGB565_G(color
[0]) * 2 + GET_RGB565_G(color
[1]) + 1) / 3),
602 ((GET_RGB565_B(color
[0]) * 2 + GET_RGB565_B(color
[1]) + 1) / 3));
603 color
[3] = MAKE_RGB565(((GET_RGB565_R(color
[0]) + GET_RGB565_R(color
[1]) * 2 + 1) / 3),
604 ((GET_RGB565_G(color
[0]) + GET_RGB565_G(color
[1]) * 2 + 1) / 3),
605 ((GET_RGB565_B(color
[0]) + GET_RGB565_B(color
[1]) * 2 + 1) / 3));
609 case DXGI_FORMAT_BC1_UNORM
:
610 if (color
[0] <= color
[1]) {
611 color
[2] = MAKE_RGB565(((GET_RGB565_R(color
[0]) + GET_RGB565_R(color
[1]) + 1) / 2),
612 ((GET_RGB565_G(color
[0]) + GET_RGB565_G(color
[1]) + 1) / 2),
613 ((GET_RGB565_B(color
[0]) + GET_RGB565_B(color
[1]) + 1) / 2));
617 case DXGI_FORMAT_BC2_UNORM
:
620 case DXGI_FORMAT_BC3_UNORM
:
622 alpha
[1] = *(block
+ 1);
623 if (alpha
[0] > alpha
[1]) {
624 for (j
= 2; j
< 8; j
++)
626 alpha
[j
] = (BYTE
)((alpha
[0] * (8 - j
) + alpha
[1] * (j
- 1) + 3) / 7);
629 for (j
= 2; j
< 6; j
++)
631 alpha
[j
] = (BYTE
)((alpha
[0] * (6 - j
) + alpha
[1] * (j
- 1) + 2) / 5);
636 alpha_indices
= block
+ 2;
642 color_indices
= block
+ color_indices_offset
;
643 for (j
= 0; j
< 16; j
++)
647 if (x
>= width
|| y
>= height
) continue;
649 color_index
= (color_indices
[j
/ 4] >> ((j
% 4) * 2)) & 0x3;
650 color_value
= color
[color_index
];
654 case DXGI_FORMAT_BC1_UNORM
:
655 if ((color
[0] <= color
[1]) && !color_value
) {
662 case DXGI_FORMAT_BC2_UNORM
:
663 alpha_value
= (alpha_table
[j
/ 2] >> (j
% 2) * 4) & 0xF;
664 alpha_value
= (BYTE
)((alpha_value
* 0xFF + 0x7)/ 0xF);
666 case DXGI_FORMAT_BC3_UNORM
:
667 alpha_index
= (*((DWORD
*)(alpha_indices
+ (j
/ 8) * 3)) >> ((j
% 8) * 3)) & 0x7;
668 alpha_value
= alpha
[alpha_index
];
673 buffer
[x
+ y
* width
] = rgb565_to_argb(color_value
, alpha_value
);
676 block_x
+= DDS_BLOCK_WIDTH
;
677 if (block_x
>= width
) {
679 block_y
+= DDS_BLOCK_HEIGHT
;
684 static inline DdsDecoder
*impl_from_IWICBitmapDecoder(IWICBitmapDecoder
*iface
)
686 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICBitmapDecoder_iface
);
689 static inline DdsDecoder
*impl_from_IWICDdsDecoder(IWICDdsDecoder
*iface
)
691 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICDdsDecoder_iface
);
694 static inline DdsDecoder
*impl_from_IWICWineDecoder(IWICWineDecoder
*iface
)
696 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICWineDecoder_iface
);
699 static inline DdsFrameDecode
*impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface
)
701 return CONTAINING_RECORD(iface
, DdsFrameDecode
, IWICBitmapFrameDecode_iface
);
704 static inline DdsFrameDecode
*impl_from_IWICDdsFrameDecode(IWICDdsFrameDecode
*iface
)
706 return CONTAINING_RECORD(iface
, DdsFrameDecode
, IWICDdsFrameDecode_iface
);
709 static inline DdsEncoder
*impl_from_IWICBitmapEncoder(IWICBitmapEncoder
*iface
)
711 return CONTAINING_RECORD(iface
, DdsEncoder
, IWICBitmapEncoder_iface
);
714 static inline DdsEncoder
*impl_from_IWICDdsEncoder(IWICDdsEncoder
*iface
)
716 return CONTAINING_RECORD(iface
, DdsEncoder
, IWICDdsEncoder_iface
);
719 static inline DdsFrameEncode
*impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface
)
721 return CONTAINING_RECORD(iface
, DdsFrameEncode
, IWICBitmapFrameEncode_iface
);
724 static HRESULT WINAPI
DdsFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
727 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
728 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
730 if (!ppv
) return E_INVALIDARG
;
732 if (IsEqualIID(&IID_IUnknown
, iid
) ||
733 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
734 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
)) {
735 *ppv
= &This
->IWICBitmapFrameDecode_iface
;
736 } else if (IsEqualGUID(&IID_IWICDdsFrameDecode
, iid
)) {
737 *ppv
= &This
->IWICDdsFrameDecode_iface
;
740 return E_NOINTERFACE
;
743 IUnknown_AddRef((IUnknown
*)*ppv
);
747 static ULONG WINAPI
DdsFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
749 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
750 ULONG ref
= InterlockedIncrement(&This
->ref
);
752 TRACE("(%p) refcount=%u\n", iface
, ref
);
757 static ULONG WINAPI
DdsFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
759 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
760 ULONG ref
= InterlockedDecrement(&This
->ref
);
762 TRACE("(%p) refcount=%u\n", iface
, ref
);
765 if (This
->pixel_data
!= This
->block_data
) HeapFree(GetProcessHeap(), 0, This
->pixel_data
);
766 HeapFree(GetProcessHeap(), 0, This
->block_data
);
767 HeapFree(GetProcessHeap(), 0, This
);
773 static HRESULT WINAPI
DdsFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
774 UINT
*puiWidth
, UINT
*puiHeight
)
776 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
778 if (!puiWidth
|| !puiHeight
) return E_INVALIDARG
;
780 *puiWidth
= This
->info
.width
;
781 *puiHeight
= This
->info
.height
;
783 TRACE("(%p) -> (%d,%d)\n", iface
, *puiWidth
, *puiHeight
);
788 static HRESULT WINAPI
DdsFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
789 WICPixelFormatGUID
*pPixelFormat
)
791 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
793 if (!pPixelFormat
) return E_INVALIDARG
;
795 *pPixelFormat
= *This
->info
.pixel_format
;
797 TRACE("(%p) -> %s\n", iface
, debugstr_guid(pPixelFormat
));
802 static HRESULT WINAPI
DdsFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
803 double *pDpiX
, double *pDpiY
)
805 FIXME("(%p,%p,%p): stub.\n", iface
, pDpiX
, pDpiY
);
810 static HRESULT WINAPI
DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
811 IWICPalette
*pIPalette
)
813 FIXME("(%p,%p): stub.\n", iface
, pIPalette
);
818 static HRESULT WINAPI
DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
819 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
821 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
822 UINT bpp
, frame_stride
, frame_size
;
823 INT x
, y
, width
, height
;
826 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
828 if (!pbBuffer
) return E_INVALIDARG
;
830 bpp
= This
->info
.pixel_format_bpp
;
831 if (!bpp
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
833 frame_stride
= This
->info
.width
* bpp
/ 8;
834 frame_size
= frame_stride
* This
->info
.height
;
836 if (cbStride
< frame_stride
) return E_INVALIDARG
;
837 if (cbBufferSize
< frame_size
) return WINCODEC_ERR_INSUFFICIENTBUFFER
;
842 height
= prc
->Height
;
843 if (x
< 0 || y
< 0 || width
<= 0 || height
<= 0 ||
844 x
+ width
> This
->info
.width
||
845 y
+ height
> This
->info
.height
) {
848 if (cbStride
< width
* bpp
/ 8) return E_INVALIDARG
;
849 if (cbBufferSize
< cbStride
* height
) return WINCODEC_ERR_INSUFFICIENTBUFFER
;
852 EnterCriticalSection(&This
->lock
);
854 if (!This
->pixel_data
) {
855 if (is_compressed(This
->info
.format
)) {
856 This
->pixel_data
= HeapAlloc(GetProcessHeap(), 0, frame_size
);
857 if (!This
->pixel_data
) {
861 decode_block(This
->block_data
, This
->info
.width_in_blocks
* This
->info
.height_in_blocks
, This
->info
.format
,
862 This
->info
.width
, This
->info
.height
, (DWORD
*)This
->pixel_data
);
864 This
->pixel_data
= This
->block_data
;
868 hr
= copy_pixels(bpp
, This
->pixel_data
, This
->info
.width
, This
->info
.height
, frame_stride
,
869 prc
, cbStride
, cbBufferSize
, pbBuffer
);
872 LeaveCriticalSection(&This
->lock
);
877 static HRESULT WINAPI
DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
878 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
880 FIXME("(%p,%p): stub.\n", iface
, ppIMetadataQueryReader
);
885 static HRESULT WINAPI
DdsFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
886 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
888 FIXME("(%p,%u,%p,%p): stub.\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
893 static HRESULT WINAPI
DdsFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
894 IWICBitmapSource
**ppIThumbnail
)
896 FIXME("(%p,%p): stub.\n", iface
, ppIThumbnail
);
901 static const IWICBitmapFrameDecodeVtbl DdsFrameDecode_Vtbl
= {
902 DdsFrameDecode_QueryInterface
,
903 DdsFrameDecode_AddRef
,
904 DdsFrameDecode_Release
,
905 DdsFrameDecode_GetSize
,
906 DdsFrameDecode_GetPixelFormat
,
907 DdsFrameDecode_GetResolution
,
908 DdsFrameDecode_CopyPalette
,
909 DdsFrameDecode_CopyPixels
,
910 DdsFrameDecode_GetMetadataQueryReader
,
911 DdsFrameDecode_GetColorContexts
,
912 DdsFrameDecode_GetThumbnail
915 static HRESULT WINAPI
DdsFrameDecode_Dds_QueryInterface(IWICDdsFrameDecode
*iface
,
916 REFIID iid
, void **ppv
)
918 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
919 return DdsFrameDecode_QueryInterface(&This
->IWICBitmapFrameDecode_iface
, iid
, ppv
);
922 static ULONG WINAPI
DdsFrameDecode_Dds_AddRef(IWICDdsFrameDecode
*iface
)
924 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
925 return DdsFrameDecode_AddRef(&This
->IWICBitmapFrameDecode_iface
);
928 static ULONG WINAPI
DdsFrameDecode_Dds_Release(IWICDdsFrameDecode
*iface
)
930 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
931 return DdsFrameDecode_Release(&This
->IWICBitmapFrameDecode_iface
);
934 static HRESULT WINAPI
DdsFrameDecode_Dds_GetSizeInBlocks(IWICDdsFrameDecode
*iface
,
935 UINT
*widthInBlocks
, UINT
*heightInBlocks
)
937 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
939 if (!widthInBlocks
|| !heightInBlocks
) return E_INVALIDARG
;
941 *widthInBlocks
= This
->info
.width_in_blocks
;
942 *heightInBlocks
= This
->info
.height_in_blocks
;
944 TRACE("(%p,%p,%p) -> (%d,%d)\n", iface
, widthInBlocks
, heightInBlocks
, *widthInBlocks
, *heightInBlocks
);
949 static HRESULT WINAPI
DdsFrameDecode_Dds_GetFormatInfo(IWICDdsFrameDecode
*iface
,
950 WICDdsFormatInfo
*formatInfo
)
952 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
954 if (!formatInfo
) return E_INVALIDARG
;
956 formatInfo
->DxgiFormat
= This
->info
.format
;
957 formatInfo
->BytesPerBlock
= This
->info
.bytes_per_block
;
958 formatInfo
->BlockWidth
= This
->info
.block_width
;
959 formatInfo
->BlockHeight
= This
->info
.block_height
;
961 TRACE("(%p,%p) -> (0x%x,%d,%d,%d)\n", iface
, formatInfo
,
962 formatInfo
->DxgiFormat
, formatInfo
->BytesPerBlock
, formatInfo
->BlockWidth
, formatInfo
->BlockHeight
);
967 static HRESULT WINAPI
DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode
*iface
,
968 const WICRect
*boundsInBlocks
, UINT stride
, UINT bufferSize
,
971 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
972 int x
, y
, width
, height
;
973 UINT bytes_per_block
, frame_stride
, frame_size
;
975 TRACE("(%p,%p,%u,%u,%p)\n", iface
, boundsInBlocks
, stride
, bufferSize
, buffer
);
977 if (!buffer
) return E_INVALIDARG
;
979 bytes_per_block
= This
->info
.bytes_per_block
;
980 frame_stride
= This
->info
.width_in_blocks
* bytes_per_block
;
981 frame_size
= frame_stride
* This
->info
.height_in_blocks
;
983 if (!boundsInBlocks
) {
984 if (stride
< frame_stride
) return E_INVALIDARG
;
985 if (bufferSize
< frame_size
) return E_INVALIDARG
;
987 x
= boundsInBlocks
->X
;
988 y
= boundsInBlocks
->Y
;
989 width
= boundsInBlocks
->Width
;
990 height
= boundsInBlocks
->Height
;
991 if (x
< 0 || y
< 0 || width
<= 0 || height
<= 0 ||
992 x
+ width
> This
->info
.width_in_blocks
||
993 y
+ height
> This
->info
.height_in_blocks
) {
996 if (stride
< width
* bytes_per_block
) return E_INVALIDARG
;
997 if (bufferSize
< stride
* height
) return E_INVALIDARG
;
1000 return copy_pixels(This
->info
.bytes_per_block
* 8, This
->block_data
, This
->info
.width_in_blocks
,
1001 This
->info
.height_in_blocks
, frame_stride
, boundsInBlocks
, stride
, bufferSize
, buffer
);
1004 static const IWICDdsFrameDecodeVtbl DdsFrameDecode_Dds_Vtbl
= {
1005 DdsFrameDecode_Dds_QueryInterface
,
1006 DdsFrameDecode_Dds_AddRef
,
1007 DdsFrameDecode_Dds_Release
,
1008 DdsFrameDecode_Dds_GetSizeInBlocks
,
1009 DdsFrameDecode_Dds_GetFormatInfo
,
1010 DdsFrameDecode_Dds_CopyBlocks
1013 static HRESULT
DdsFrameDecode_CreateInstance(DdsFrameDecode
**frame_decode
)
1015 DdsFrameDecode
*result
;
1017 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(*result
));
1018 if (!result
) return E_OUTOFMEMORY
;
1020 result
->IWICBitmapFrameDecode_iface
.lpVtbl
= &DdsFrameDecode_Vtbl
;
1021 result
->IWICDdsFrameDecode_iface
.lpVtbl
= &DdsFrameDecode_Dds_Vtbl
;
1023 InitializeCriticalSection(&result
->lock
);
1024 result
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsFrameDecode.lock");
1026 *frame_decode
= result
;
1030 static HRESULT WINAPI
DdsDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
1033 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1034 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1036 if (!ppv
) return E_INVALIDARG
;
1038 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1039 IsEqualIID(&IID_IWICBitmapDecoder
, iid
)) {
1040 *ppv
= &This
->IWICBitmapDecoder_iface
;
1041 } else if (IsEqualIID(&IID_IWICDdsDecoder
, iid
)) {
1042 *ppv
= &This
->IWICDdsDecoder_iface
;
1043 } else if (IsEqualIID(&IID_IWICWineDecoder
, iid
)) {
1044 *ppv
= &This
->IWICWineDecoder_iface
;
1047 return E_NOINTERFACE
;
1050 IUnknown_AddRef((IUnknown
*)*ppv
);
1054 static ULONG WINAPI
DdsDecoder_AddRef(IWICBitmapDecoder
*iface
)
1056 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1057 ULONG ref
= InterlockedIncrement(&This
->ref
);
1059 TRACE("(%p) refcount=%u\n", iface
, ref
);
1064 static ULONG WINAPI
DdsDecoder_Release(IWICBitmapDecoder
*iface
)
1066 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1067 ULONG ref
= InterlockedDecrement(&This
->ref
);
1069 TRACE("(%p) refcount=%u\n", iface
, ref
);
1073 This
->lock
.DebugInfo
->Spare
[0] = 0;
1074 DeleteCriticalSection(&This
->lock
);
1075 if (This
->stream
) IStream_Release(This
->stream
);
1076 HeapFree(GetProcessHeap(), 0, This
);
1082 static HRESULT WINAPI
DdsDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*stream
,
1085 FIXME("(%p,%p,%p): stub.\n", iface
, stream
, capability
);
1090 static HRESULT WINAPI
DdsDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
1091 WICDecodeOptions cacheOptions
)
1093 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1096 TRACE("(%p,%p,%x)\n", iface
, pIStream
, cacheOptions
);
1098 EnterCriticalSection(&This
->lock
);
1100 hr
= IWICWineDecoder_Initialize(&This
->IWICWineDecoder_iface
, pIStream
, cacheOptions
);
1101 if (FAILED(hr
)) goto end
;
1103 if (This
->info
.dimension
== WICDdsTextureCube
||
1104 (This
->info
.format
!= DXGI_FORMAT_BC1_UNORM
&&
1105 This
->info
.format
!= DXGI_FORMAT_BC2_UNORM
&&
1106 This
->info
.format
!= DXGI_FORMAT_BC3_UNORM
)) {
1107 IStream_Release(pIStream
);
1108 This
->stream
= NULL
;
1109 This
->initialized
= FALSE
;
1110 hr
= WINCODEC_ERR_BADHEADER
;
1114 LeaveCriticalSection(&This
->lock
);
1119 static HRESULT WINAPI
DdsDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
1120 GUID
*pguidContainerFormat
)
1122 TRACE("(%p,%p)\n", iface
, pguidContainerFormat
);
1124 memcpy(pguidContainerFormat
, &GUID_ContainerFormatDds
, sizeof(GUID
));
1129 static HRESULT WINAPI
DdsDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
1130 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
1132 TRACE("(%p,%p)\n", iface
, ppIDecoderInfo
);
1134 return get_decoder_info(&CLSID_WICDdsDecoder
, ppIDecoderInfo
);
1137 static HRESULT WINAPI
DdsDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
1138 IWICPalette
*pIPalette
)
1140 TRACE("(%p,%p)\n", iface
, pIPalette
);
1142 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
1145 static HRESULT WINAPI
DdsDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
1146 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
1148 if (!ppIMetadataQueryReader
) return E_INVALIDARG
;
1150 FIXME("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
1155 static HRESULT WINAPI
DdsDecoder_GetPreview(IWICBitmapDecoder
*iface
,
1156 IWICBitmapSource
**ppIBitmapSource
)
1158 TRACE("(%p,%p)\n", iface
, ppIBitmapSource
);
1160 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1163 static HRESULT WINAPI
DdsDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
1164 UINT cCount
, IWICColorContext
**ppDdslorContexts
, UINT
*pcActualCount
)
1166 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppDdslorContexts
, pcActualCount
);
1168 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1171 static HRESULT WINAPI
DdsDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
1172 IWICBitmapSource
**ppIThumbnail
)
1174 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
1176 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
1179 static HRESULT WINAPI
DdsDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
1182 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1184 if (!pCount
) return E_INVALIDARG
;
1185 if (!This
->initialized
) return WINCODEC_ERR_WRONGSTATE
;
1187 EnterCriticalSection(&This
->lock
);
1189 *pCount
= This
->info
.frame_count
;
1191 LeaveCriticalSection(&This
->lock
);
1193 TRACE("(%p) -> %d\n", iface
, *pCount
);
1198 static HRESULT WINAPI
DdsDecoder_GetFrame(IWICBitmapDecoder
*iface
,
1199 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
1201 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1202 UINT frame_per_texture
, array_index
, mip_level
, slice_index
, depth
;
1204 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
1206 if (!ppIBitmapFrame
) return E_INVALIDARG
;
1208 EnterCriticalSection(&This
->lock
);
1210 if (!This
->initialized
) {
1211 LeaveCriticalSection(&This
->lock
);
1212 return WINCODEC_ERR_WRONGSTATE
;
1215 if (This
->info
.dimension
== WICDdsTextureCube
) {
1216 frame_per_texture
= This
->info
.mip_levels
;
1218 frame_per_texture
= This
->info
.frame_count
/ This
->info
.array_size
;
1220 array_index
= index
/ frame_per_texture
;
1221 slice_index
= index
% frame_per_texture
;
1222 depth
= This
->info
.depth
;
1224 while (slice_index
>= depth
)
1226 slice_index
-= depth
;
1228 if (depth
> 1) depth
/= 2;
1231 LeaveCriticalSection(&This
->lock
);
1233 return DdsDecoder_Dds_GetFrame(&This
->IWICDdsDecoder_iface
, array_index
, mip_level
, slice_index
, ppIBitmapFrame
);
1236 static const IWICBitmapDecoderVtbl DdsDecoder_Vtbl
= {
1237 DdsDecoder_QueryInterface
,
1240 DdsDecoder_QueryCapability
,
1241 DdsDecoder_Initialize
,
1242 DdsDecoder_GetContainerFormat
,
1243 DdsDecoder_GetDecoderInfo
,
1244 DdsDecoder_CopyPalette
,
1245 DdsDecoder_GetMetadataQueryReader
,
1246 DdsDecoder_GetPreview
,
1247 DdsDecoder_GetColorContexts
,
1248 DdsDecoder_GetThumbnail
,
1249 DdsDecoder_GetFrameCount
,
1253 static HRESULT WINAPI
DdsDecoder_Dds_QueryInterface(IWICDdsDecoder
*iface
,
1254 REFIID iid
, void **ppv
)
1256 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1257 return DdsDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1260 static ULONG WINAPI
DdsDecoder_Dds_AddRef(IWICDdsDecoder
*iface
)
1262 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1263 return DdsDecoder_AddRef(&This
->IWICBitmapDecoder_iface
);
1266 static ULONG WINAPI
DdsDecoder_Dds_Release(IWICDdsDecoder
*iface
)
1268 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1269 return DdsDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1272 static HRESULT WINAPI
DdsDecoder_Dds_GetParameters(IWICDdsDecoder
*iface
,
1273 WICDdsParameters
*parameters
)
1275 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1278 if (!parameters
) return E_INVALIDARG
;
1280 EnterCriticalSection(&This
->lock
);
1282 if (!This
->initialized
) {
1283 hr
= WINCODEC_ERR_WRONGSTATE
;
1287 parameters
->Width
= This
->info
.width
;
1288 parameters
->Height
= This
->info
.height
;
1289 parameters
->Depth
= This
->info
.depth
;
1290 parameters
->MipLevels
= This
->info
.mip_levels
;
1291 parameters
->ArraySize
= This
->info
.array_size
;
1292 parameters
->DxgiFormat
= This
->info
.format
;
1293 parameters
->Dimension
= This
->info
.dimension
;
1294 parameters
->AlphaMode
= This
->info
.alpha_mode
;
1296 TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x dimension=0x%x alphaMode=0x%x)\n",
1297 iface
, parameters
->Width
, parameters
->Height
, parameters
->Depth
, parameters
->MipLevels
,
1298 parameters
->ArraySize
, parameters
->DxgiFormat
, parameters
->Dimension
, parameters
->AlphaMode
);
1303 LeaveCriticalSection(&This
->lock
);
1308 static HRESULT WINAPI
DdsDecoder_Dds_GetFrame(IWICDdsDecoder
*iface
,
1309 UINT arrayIndex
, UINT mipLevel
, UINT sliceIndex
,
1310 IWICBitmapFrameDecode
**bitmapFrame
)
1312 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1315 UINT width
, height
, depth
, block_width
, block_height
, width_in_blocks
, height_in_blocks
, size
;
1316 UINT frame_width
= 0, frame_height
= 0, frame_width_in_blocks
= 0, frame_height_in_blocks
= 0, frame_size
= 0;
1317 UINT bytes_per_block
, bytesread
, i
;
1318 DdsFrameDecode
*frame_decode
= NULL
;
1320 TRACE("(%p,%u,%u,%u,%p)\n", iface
, arrayIndex
, mipLevel
, sliceIndex
, bitmapFrame
);
1322 if (!bitmapFrame
) return E_INVALIDARG
;
1324 EnterCriticalSection(&This
->lock
);
1326 if (!This
->initialized
) {
1327 hr
= WINCODEC_ERR_WRONGSTATE
;
1331 if ((arrayIndex
>= This
->info
.array_size
&& This
->info
.dimension
!= WICDdsTextureCube
) ||
1332 (arrayIndex
>= This
->info
.array_size
* 6) ||
1333 (mipLevel
>= This
->info
.mip_levels
) ||
1334 (sliceIndex
>= This
->info
.depth
)) {
1339 if (is_compressed(This
->info
.format
)) {
1340 block_width
= DDS_BLOCK_WIDTH
;
1341 block_height
= DDS_BLOCK_HEIGHT
;
1346 bytes_per_block
= This
->info
.bytes_per_block
;
1347 seek
.QuadPart
= This
->info
.data_offset
;
1349 width
= This
->info
.width
;
1350 height
= This
->info
.height
;
1351 depth
= This
->info
.depth
;
1352 for (i
= 0; i
< This
->info
.mip_levels
; i
++)
1354 width_in_blocks
= (width
+ block_width
- 1) / block_width
;
1355 height_in_blocks
= (height
+ block_height
- 1) / block_height
;
1356 size
= width_in_blocks
* height_in_blocks
* bytes_per_block
;
1359 seek
.QuadPart
+= size
* depth
;
1360 } else if (i
== mipLevel
){
1361 seek
.QuadPart
+= size
* sliceIndex
;
1362 frame_width
= width
;
1363 frame_height
= height
;
1364 frame_width_in_blocks
= width_in_blocks
;
1365 frame_height_in_blocks
= height_in_blocks
;
1366 frame_size
= frame_width_in_blocks
* frame_height_in_blocks
* bytes_per_block
;
1367 if (arrayIndex
== 0) break;
1369 seek
.QuadPart
+= arrayIndex
* size
* depth
;
1371 if (width
> 1) width
/= 2;
1372 if (height
> 1) height
/= 2;
1373 if (depth
> 1) depth
/= 2;
1376 hr
= DdsFrameDecode_CreateInstance(&frame_decode
);
1377 if (hr
!= S_OK
) goto end
;
1378 frame_decode
->info
.width
= frame_width
;
1379 frame_decode
->info
.height
= frame_height
;
1380 frame_decode
->info
.format
= This
->info
.format
;
1381 frame_decode
->info
.bytes_per_block
= bytes_per_block
;
1382 frame_decode
->info
.block_width
= block_width
;
1383 frame_decode
->info
.block_height
= block_height
;
1384 frame_decode
->info
.width_in_blocks
= frame_width_in_blocks
;
1385 frame_decode
->info
.height_in_blocks
= frame_height_in_blocks
;
1386 frame_decode
->info
.pixel_format
= This
->info
.pixel_format
;
1387 frame_decode
->info
.pixel_format_bpp
= This
->info
.pixel_format_bpp
;
1388 frame_decode
->block_data
= HeapAlloc(GetProcessHeap(), 0, frame_size
);
1389 frame_decode
->pixel_data
= NULL
;
1390 hr
= IStream_Seek(This
->stream
, seek
, SEEK_SET
, NULL
);
1391 if (hr
!= S_OK
) goto end
;
1392 hr
= IStream_Read(This
->stream
, frame_decode
->block_data
, frame_size
, &bytesread
);
1393 if (hr
!= S_OK
|| bytesread
!= frame_size
) {
1394 hr
= WINCODEC_ERR_STREAMREAD
;
1397 *bitmapFrame
= &frame_decode
->IWICBitmapFrameDecode_iface
;
1402 LeaveCriticalSection(&This
->lock
);
1404 if (hr
!= S_OK
&& frame_decode
) DdsFrameDecode_Release(&frame_decode
->IWICBitmapFrameDecode_iface
);
1409 static const IWICDdsDecoderVtbl DdsDecoder_Dds_Vtbl
= {
1410 DdsDecoder_Dds_QueryInterface
,
1411 DdsDecoder_Dds_AddRef
,
1412 DdsDecoder_Dds_Release
,
1413 DdsDecoder_Dds_GetParameters
,
1414 DdsDecoder_Dds_GetFrame
1417 static HRESULT WINAPI
DdsDecoder_Wine_QueryInterface(IWICWineDecoder
*iface
, REFIID iid
, void **ppv
)
1419 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1420 return DdsDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1423 static ULONG WINAPI
DdsDecoder_Wine_AddRef(IWICWineDecoder
*iface
)
1425 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1426 return DdsDecoder_AddRef(&This
->IWICBitmapDecoder_iface
);
1429 static ULONG WINAPI
DdsDecoder_Wine_Release(IWICWineDecoder
*iface
)
1431 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1432 return DdsDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1435 static HRESULT WINAPI
DdsDecoder_Wine_Initialize(IWICWineDecoder
*iface
, IStream
*stream
, WICDecodeOptions options
)
1437 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1438 DDS_HEADER_DXT10 header_dxt10
;
1445 TRACE("(This %p, stream %p, options %#x)\n", iface
, stream
, options
);
1447 EnterCriticalSection(&This
->lock
);
1449 if (This
->initialized
) {
1450 hr
= WINCODEC_ERR_WRONGSTATE
;
1455 hr
= IStream_Seek(stream
, seek
, SEEK_SET
, NULL
);
1456 if (FAILED(hr
)) goto end
;
1458 hr
= IStream_Read(stream
, &magic
, sizeof(magic
), &bytesread
);
1459 if (FAILED(hr
)) goto end
;
1460 if (bytesread
!= sizeof(magic
)) {
1461 hr
= WINCODEC_ERR_STREAMREAD
;
1464 if (magic
!= DDS_MAGIC
) {
1465 hr
= WINCODEC_ERR_UNKNOWNIMAGEFORMAT
;
1469 hr
= IStream_Read(stream
, &header
, sizeof(header
), &bytesread
);
1470 if (FAILED(hr
)) goto end
;
1471 if (bytesread
!= sizeof(header
)) {
1472 hr
= WINCODEC_ERR_STREAMREAD
;
1475 if (header
.size
!= sizeof(header
)) {
1476 hr
= WINCODEC_ERR_BADHEADER
;
1480 if (has_extended_header(&header
)) {
1481 hr
= IStream_Read(stream
, &header_dxt10
, sizeof(header_dxt10
), &bytesread
);
1482 if (FAILED(hr
)) goto end
;
1483 if (bytesread
!= sizeof(header_dxt10
)) {
1484 hr
= WINCODEC_ERR_STREAMREAD
;
1489 get_dds_info(&This
->info
, &header
, &header_dxt10
);
1491 This
->initialized
= TRUE
;
1492 This
->stream
= stream
;
1493 IStream_AddRef(stream
);
1496 LeaveCriticalSection(&This
->lock
);
1501 static const IWICWineDecoderVtbl DdsDecoder_Wine_Vtbl
= {
1502 DdsDecoder_Wine_QueryInterface
,
1503 DdsDecoder_Wine_AddRef
,
1504 DdsDecoder_Wine_Release
,
1505 DdsDecoder_Wine_Initialize
1508 static HRESULT WINAPI
DdsFrameEncode_QueryInterface(IWICBitmapFrameEncode
*iface
, REFIID iid
, void **ppv
)
1510 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1511 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1513 if (!ppv
) return E_INVALIDARG
;
1515 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1516 IsEqualIID(&IID_IWICBitmapFrameEncode
, iid
))
1518 *ppv
= &This
->IWICBitmapFrameEncode_iface
;
1523 return E_NOINTERFACE
;
1526 IUnknown_AddRef((IUnknown
*)*ppv
);
1530 static ULONG WINAPI
DdsFrameEncode_AddRef(IWICBitmapFrameEncode
*iface
)
1532 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1533 ULONG ref
= InterlockedIncrement(&This
->ref
);
1535 TRACE("(%p) refcount=%u\n", iface
, ref
);
1540 static ULONG WINAPI
DdsFrameEncode_Release(IWICBitmapFrameEncode
*iface
)
1542 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1543 ULONG ref
= InterlockedDecrement(&This
->ref
);
1545 TRACE("(%p) refcount=%u\n", iface
, ref
);
1549 IWICBitmapEncoder_Release(&This
->parent
->IWICBitmapEncoder_iface
);
1550 HeapFree(GetProcessHeap(), 0, This
);
1556 static HRESULT WINAPI
DdsFrameEncode_Initialize(IWICBitmapFrameEncode
*iface
,
1557 IPropertyBag2
*encoderOptions
)
1559 FIXME("(%p,%p): stub\n", iface
, encoderOptions
);
1563 static HRESULT WINAPI
DdsFrameEncode_SetSize(IWICBitmapFrameEncode
*iface
,
1564 UINT width
, UINT height
)
1566 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1569 TRACE("(%p,%u,%u)\n", iface
, width
, height
);
1571 EnterCriticalSection(&This
->parent
->lock
);
1573 if (!This
->initialized
|| This
->frame_created
)
1575 hr
= WINCODEC_ERR_WRONGSTATE
;
1579 This
->width
= width
;
1580 This
->height
= height
;
1584 LeaveCriticalSection(&This
->parent
->lock
);
1589 static HRESULT WINAPI
DdsFrameEncode_SetResolution(IWICBitmapFrameEncode
*iface
,
1590 double dpiX
, double dpiY
)
1592 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1595 TRACE("(%p,%0.2f,%0.2f)\n", iface
, dpiX
, dpiY
);
1597 EnterCriticalSection(&This
->parent
->lock
);
1599 if (!This
->initialized
|| This
->frame_created
)
1601 hr
= WINCODEC_ERR_WRONGSTATE
;
1610 LeaveCriticalSection(&This
->parent
->lock
);
1615 static HRESULT WINAPI
DdsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode
*iface
,
1616 WICPixelFormatGUID
*pixelFormat
)
1618 FIXME("(%p,%s): stub\n", iface
, debugstr_guid(pixelFormat
));
1622 static HRESULT WINAPI
DdsFrameEncode_SetColorContexts(IWICBitmapFrameEncode
*iface
,
1623 UINT count
, IWICColorContext
**colorContext
)
1625 FIXME("(%p,%u,%p): stub\n", iface
, count
, colorContext
);
1629 static HRESULT WINAPI
DdsFrameEncode_SetPalette(IWICBitmapFrameEncode
*iface
,
1630 IWICPalette
*palette
)
1632 FIXME("(%p,%p): stub\n", iface
, palette
);
1636 static HRESULT WINAPI
DdsFrameEncode_SetThumbnail(IWICBitmapFrameEncode
*iface
,
1637 IWICBitmapSource
*thumbnail
)
1639 TRACE("(%p,%p)\n", iface
, thumbnail
);
1640 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1643 static HRESULT WINAPI
DdsFrameEncode_WritePixels(IWICBitmapFrameEncode
*iface
,
1644 UINT lineCount
, UINT stride
, UINT bufferSize
, BYTE
*pixels
)
1646 FIXME("(%p,%u,%u,%u,%p): stub\n", iface
, lineCount
, stride
, bufferSize
, pixels
);
1650 static HRESULT WINAPI
DdsFrameEncode_WriteSource(IWICBitmapFrameEncode
*iface
,
1651 IWICBitmapSource
*bitmapSource
, WICRect
*rc
)
1653 FIXME("(%p,%p,%s): stub\n", iface
, bitmapSource
, debug_wic_rect(rc
));
1657 static HRESULT WINAPI
DdsFrameEncode_Commit(IWICBitmapFrameEncode
*iface
)
1659 FIXME("(%p): stub\n", iface
);
1663 static HRESULT WINAPI
DdsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface
,
1664 IWICMetadataQueryWriter
**metadataQueryWriter
)
1666 FIXME("(%p,%p): stub\n", iface
, metadataQueryWriter
);
1670 static const IWICBitmapFrameEncodeVtbl DdsFrameEncode_Vtbl
= {
1671 DdsFrameEncode_QueryInterface
,
1672 DdsFrameEncode_AddRef
,
1673 DdsFrameEncode_Release
,
1674 DdsFrameEncode_Initialize
,
1675 DdsFrameEncode_SetSize
,
1676 DdsFrameEncode_SetResolution
,
1677 DdsFrameEncode_SetPixelFormat
,
1678 DdsFrameEncode_SetColorContexts
,
1679 DdsFrameEncode_SetPalette
,
1680 DdsFrameEncode_SetThumbnail
,
1681 DdsFrameEncode_WritePixels
,
1682 DdsFrameEncode_WriteSource
,
1683 DdsFrameEncode_Commit
,
1684 DdsFrameEncode_GetMetadataQueryWriter
1687 HRESULT
DdsDecoder_CreateInstance(REFIID iid
, void** ppv
)
1692 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1696 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(DdsDecoder
));
1697 if (!This
) return E_OUTOFMEMORY
;
1699 This
->IWICBitmapDecoder_iface
.lpVtbl
= &DdsDecoder_Vtbl
;
1700 This
->IWICDdsDecoder_iface
.lpVtbl
= &DdsDecoder_Dds_Vtbl
;
1701 This
->IWICWineDecoder_iface
.lpVtbl
= &DdsDecoder_Wine_Vtbl
;
1703 This
->initialized
= FALSE
;
1704 This
->stream
= NULL
;
1705 InitializeCriticalSection(&This
->lock
);
1706 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsDecoder.lock");
1708 ret
= IWICBitmapDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1709 IWICBitmapDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1714 static HRESULT WINAPI
DdsEncoder_Dds_QueryInterface(IWICDdsEncoder
*iface
, REFIID iid
,
1717 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1718 return IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
1721 static ULONG WINAPI
DdsEncoder_Dds_AddRef(IWICDdsEncoder
*iface
)
1723 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1724 return IWICBitmapEncoder_AddRef(&This
->IWICBitmapEncoder_iface
);
1727 static ULONG WINAPI
DdsEncoder_Dds_Release(IWICDdsEncoder
*iface
)
1729 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1730 return IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);
1733 static HRESULT WINAPI
DdsEncoder_Dds_SetParameters(IWICDdsEncoder
*iface
,
1734 WICDdsParameters
*parameters
)
1736 FIXME("(%p,%p): stub.\n", iface
, parameters
);
1740 static HRESULT WINAPI
DdsEncoder_Dds_GetParameters(IWICDdsEncoder
*iface
,
1741 WICDdsParameters
*parameters
)
1743 FIXME("(%p,%p): stub.\n", iface
, parameters
);
1747 static HRESULT WINAPI
DdsEncoder_Dds_CreateNewFrame(IWICDdsEncoder
*iface
,
1748 IWICBitmapFrameEncode
**frameEncode
,
1749 UINT
*arrayIndex
, UINT
*mipLevel
, UINT
*sliceIndex
)
1751 FIXME("(%p,%p,%p,%p,%p): stub.\n", iface
, frameEncode
, arrayIndex
, mipLevel
, sliceIndex
);
1755 static const IWICDdsEncoderVtbl DdsEncoder_Dds_Vtbl
=
1757 DdsEncoder_Dds_QueryInterface
,
1758 DdsEncoder_Dds_AddRef
,
1759 DdsEncoder_Dds_Release
,
1760 DdsEncoder_Dds_SetParameters
,
1761 DdsEncoder_Dds_GetParameters
,
1762 DdsEncoder_Dds_CreateNewFrame
1765 static HRESULT WINAPI
DdsEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
1768 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1769 FIXME("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1771 if (!ppv
) return E_INVALIDARG
;
1773 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1774 IsEqualIID(&IID_IWICBitmapEncoder
, iid
)) {
1775 *ppv
= &This
->IWICBitmapEncoder_iface
;
1776 } else if (IsEqualIID(&IID_IWICDdsEncoder
, iid
)) {
1777 *ppv
= &This
->IWICDdsEncoder_iface
;
1780 return E_NOINTERFACE
;
1783 IUnknown_AddRef((IUnknown
*)*ppv
);
1787 static ULONG WINAPI
DdsEncoder_AddRef(IWICBitmapEncoder
*iface
)
1789 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1790 ULONG ref
= InterlockedIncrement(&This
->ref
);
1792 TRACE("(%p) refcount=%u\n", iface
, ref
);
1797 static ULONG WINAPI
DdsEncoder_Release(IWICBitmapEncoder
*iface
)
1799 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1800 ULONG ref
= InterlockedDecrement(&This
->ref
);
1802 TRACE("(%p) refcount=%u\n", iface
, ref
);
1805 This
->lock
.DebugInfo
->Spare
[0] = 0;
1806 DeleteCriticalSection(&This
->lock
);
1807 if (This
->stream
) IStream_Release(This
->stream
);
1808 HeapFree(GetProcessHeap(), 0, This
);
1814 static HRESULT WINAPI
DdsEncoder_Initialize(IWICBitmapEncoder
*iface
,
1815 IStream
*stream
, WICBitmapEncoderCacheOption cacheOption
)
1817 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1820 TRACE("(%p,%p,%u)\n", iface
, stream
, cacheOption
);
1822 if (cacheOption
!= WICBitmapEncoderNoCache
)
1823 FIXME("Cache option %#x is not supported.\n", cacheOption
);
1825 if (!stream
) return E_INVALIDARG
;
1827 EnterCriticalSection(&This
->lock
);
1831 hr
= WINCODEC_ERR_WRONGSTATE
;
1835 This
->stream
= stream
;
1836 IStream_AddRef(stream
);
1841 LeaveCriticalSection(&This
->lock
);
1846 static HRESULT WINAPI
DdsEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
, GUID
*format
)
1848 TRACE("(%p,%p)\n", iface
, format
);
1851 return E_INVALIDARG
;
1853 memcpy(format
, &GUID_ContainerFormatDds
, sizeof(*format
));
1857 static HRESULT WINAPI
DdsEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
, IWICBitmapEncoderInfo
**info
)
1859 IWICComponentInfo
*comp_info
;
1862 TRACE("%p,%p\n", iface
, info
);
1864 if (!info
) return E_INVALIDARG
;
1866 hr
= CreateComponentInfo(&CLSID_WICDdsEncoder
, &comp_info
);
1868 hr
= IWICComponentInfo_QueryInterface(comp_info
, &IID_IWICBitmapEncoderInfo
, (void **)info
);
1869 IWICComponentInfo_Release(comp_info
);
1874 static HRESULT WINAPI
DdsEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
1875 UINT cCount
, IWICColorContext
**ppIColorContext
)
1877 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
1881 static HRESULT WINAPI
DdsEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*palette
)
1883 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1886 TRACE("(%p,%p)\n", iface
, palette
);
1888 EnterCriticalSection(&This
->lock
);
1890 hr
= This
->stream
? WINCODEC_ERR_UNSUPPORTEDOPERATION
: WINCODEC_ERR_NOTINITIALIZED
;
1892 LeaveCriticalSection(&This
->lock
);
1897 static HRESULT WINAPI
DdsEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
1899 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
1900 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1903 static HRESULT WINAPI
DdsEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
1905 TRACE("(%p,%p)\n", iface
, pIPreview
);
1906 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1909 static HRESULT WINAPI
DdsEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
1910 IWICBitmapFrameEncode
**frameEncode
, IPropertyBag2
**encoderOptions
)
1912 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1913 DdsFrameEncode
*result
;
1916 TRACE("(%p,%p,%p)\n", iface
, frameEncode
, encoderOptions
);
1918 EnterCriticalSection(&This
->lock
);
1922 hr
= WINCODEC_ERR_WRONGSTATE
;
1926 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(*result
));
1933 result
->IWICBitmapFrameEncode_iface
.lpVtbl
= &DdsFrameEncode_Vtbl
;
1935 result
->parent
= This
;
1936 result
->initialized
= FALSE
;
1937 result
->frame_created
= FALSE
;
1938 IWICBitmapEncoder_AddRef(iface
);
1940 *frameEncode
= &result
->IWICBitmapFrameEncode_iface
;
1944 LeaveCriticalSection(&This
->lock
);
1948 static HRESULT WINAPI
DdsEncoder_Commit(IWICBitmapEncoder
*iface
)
1950 FIXME("(%p): stub\n", iface
);
1954 static HRESULT WINAPI
DdsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
1955 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
1957 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
1961 static const IWICBitmapEncoderVtbl DdsEncoder_Vtbl
= {
1962 DdsEncoder_QueryInterface
,
1965 DdsEncoder_Initialize
,
1966 DdsEncoder_GetContainerFormat
,
1967 DdsEncoder_GetEncoderInfo
,
1968 DdsEncoder_SetColorContexts
,
1969 DdsEncoder_SetPalette
,
1970 DdsEncoder_SetThumbnail
,
1971 DdsEncoder_SetPreview
,
1972 DdsEncoder_CreateNewFrame
,
1974 DdsEncoder_GetMetadataQueryWriter
1977 HRESULT
DdsEncoder_CreateInstance( REFIID iid
, void **ppv
)
1982 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1986 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(DdsEncoder
));
1987 if (!This
) return E_OUTOFMEMORY
;
1989 This
->IWICBitmapEncoder_iface
.lpVtbl
= &DdsEncoder_Vtbl
;
1990 This
->IWICDdsEncoder_iface
.lpVtbl
= &DdsEncoder_Dds_Vtbl
;
1992 This
->stream
= NULL
;
1993 This
->frame_count
= 0;
1994 This
->uncommitted_frame
= FALSE
;
1995 This
->committed
= FALSE
;
1996 InitializeCriticalSection(&This
->lock
);
1997 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsEncoder.lock");
1999 ret
= IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
2000 IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);