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
;
170 BOOL uncommitted_frame
;
175 typedef struct DdsFrameEncode
{
176 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface
;
187 static struct dds_format
{
188 DDS_PIXELFORMAT pixel_format
;
189 const GUID
*wic_format
;
191 DXGI_FORMAT dxgi_format
;
192 } dds_format_table
[] = {
193 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '1'), 0, 0, 0, 0, 0 },
194 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC1_UNORM
},
195 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0 },
196 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC2_UNORM
},
197 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '3'), 0, 0, 0, 0, 0 },
198 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC2_UNORM
},
199 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '4'), 0, 0, 0, 0, 0 },
200 &GUID_WICPixelFormat32bppPBGRA
, 32, DXGI_FORMAT_BC3_UNORM
},
201 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', 'T', '5'), 0, 0, 0, 0, 0 },
202 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC3_UNORM
},
203 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '4', 'U'), 0, 0, 0, 0, 0 },
204 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_UNORM
},
205 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '4', 'S'), 0, 0, 0, 0, 0 },
206 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_SNORM
},
207 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '5', 'U'), 0, 0, 0, 0, 0 },
208 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_UNORM
},
209 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('B', 'C', '5', 'S'), 0, 0, 0, 0, 0 },
210 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_SNORM
},
211 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('A', 'T', 'I', '1'), 0, 0, 0, 0, 0 },
212 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC4_UNORM
},
213 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('A', 'T', 'I', '2'), 0, 0, 0, 0, 0 },
214 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_BC5_UNORM
},
215 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('R', 'G', 'B', 'G'), 0, 0, 0, 0, 0 },
216 &GUID_WICPixelFormat32bpp4Channels
, 32, DXGI_FORMAT_R8G8_B8G8_UNORM
},
217 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('G', 'R', 'G', 'B'), 0, 0, 0, 0, 0 },
218 &GUID_WICPixelFormat32bpp4Channels
, 32, DXGI_FORMAT_G8R8_G8B8_UNORM
},
219 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, MAKEFOURCC('D', 'X', '1', '0'), 0, 0, 0, 0, 0 },
220 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_UNKNOWN
},
221 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x24, 0, 0, 0, 0, 0 },
222 &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_UNORM
},
223 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x6E, 0, 0, 0, 0, 0 },
224 &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_SNORM
},
225 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x6F, 0, 0, 0, 0, 0 },
226 &GUID_WICPixelFormat16bppGrayHalf
, 16, DXGI_FORMAT_R16_FLOAT
},
227 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x70, 0, 0, 0, 0, 0 },
228 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R16G16_FLOAT
},
229 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x71, 0, 0, 0, 0, 0 },
230 &GUID_WICPixelFormat64bppRGBAHalf
, 64, DXGI_FORMAT_R16G16B16A16_FLOAT
},
231 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x72, 0, 0, 0, 0, 0 },
232 &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
233 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x73, 0, 0, 0, 0, 0 },
234 &GUID_WICPixelFormatUndefined
, 32, DXGI_FORMAT_R32G32_FLOAT
},
235 { { sizeof(DDS_PIXELFORMAT
), DDPF_FOURCC
, 0x74, 0, 0, 0, 0, 0 },
236 &GUID_WICPixelFormat128bppRGBAFloat
, 128, DXGI_FORMAT_R32G32B32A32_FLOAT
},
237 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF,0xFF00,0xFF0000,0xFF000000 },
238 &GUID_WICPixelFormat32bppRGBA
, 32, DXGI_FORMAT_R8G8B8A8_UNORM
},
239 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF,0xFF00,0xFF0000,0 },
240 &GUID_WICPixelFormat32bppRGB
, 32, DXGI_FORMAT_UNKNOWN
},
241 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF0000,0xFF00,0xFF,0xFF000000 },
242 &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_B8G8R8A8_UNORM
},
243 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFF0000,0xFF00,0xFF,0 },
244 &GUID_WICPixelFormat32bppBGR
, 32, DXGI_FORMAT_B8G8R8X8_UNORM
},
245 /* The red and blue masks are swapped for DXGI_FORMAT_R10G10B10A2_UNORM.
246 * For "correct" one, the RGB masks should be 0x3FF,0xFFC00,0x3FF00000.
247 * see: https://walbourn.github.io/dds-update-and-1010102-problems */
248 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0x3FF00000,0xFFC00,0x3FF,0xC0000000 },
249 &GUID_WICPixelFormat32bppR10G10B10A2
, 32, DXGI_FORMAT_R10G10B10A2_UNORM
},
250 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0x3FF,0xFFC00,0x3FF00000,0xC0000000 },
251 &GUID_WICPixelFormat32bppRGBA1010102
, 32, DXGI_FORMAT_R10G10B10A2_UNORM
},
252 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFFFF,0xFFFF0000,0,0 },
253 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R16G16_UNORM
},
254 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 32, 0xFFFFFFFF,0,0,0 },
255 &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
256 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 24, 0xFF0000,0x00FF00,0x0000FF,0 },
257 &GUID_WICPixelFormat24bppBGR
, 24, DXGI_FORMAT_UNKNOWN
},
258 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 24, 0x0000FF,0x00FF00,0xFF0000,0 },
259 &GUID_WICPixelFormat24bppRGB
, 24, DXGI_FORMAT_UNKNOWN
},
260 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0xF800,0x7E0,0x1F,0 },
261 &GUID_WICPixelFormat16bppBGR565
, 16, DXGI_FORMAT_B5G6R5_UNORM
},
262 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0x7C00,0x3E0,0x1F,0 },
263 &GUID_WICPixelFormat16bppBGR555
, 16, DXGI_FORMAT_UNKNOWN
},
264 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0x7C00,0x3E0,0x1F,0x8000 },
265 &GUID_WICPixelFormat16bppBGRA5551
, 16, DXGI_FORMAT_B5G5R5A1_UNORM
},
266 { { sizeof(DDS_PIXELFORMAT
), DDPF_RGB
, 0, 16, 0xF00,0xF0,0xF,0xF000 },
267 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_B4G4R4A4_UNORM
},
268 { { sizeof(DDS_PIXELFORMAT
), DDPF_ALPHA
, 0, 8, 0,0,0,0xFF },
269 &GUID_WICPixelFormat8bppAlpha
, 8, DXGI_FORMAT_A8_UNORM
},
270 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 16, 0xFFFF,0,0,0 },
271 &GUID_WICPixelFormat16bppGray
, 16, DXGI_FORMAT_R16_UNORM
},
272 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 16, 0xFF,0,0,0xFF00 },
273 &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_R8G8_UNORM
},
274 { { sizeof(DDS_PIXELFORMAT
), DDPF_LUMINANCE
, 0, 8, 0xFF,0,0,0 },
275 &GUID_WICPixelFormat8bppGray
, 8, DXGI_FORMAT_R8_UNORM
},
276 { { 0 }, &GUID_WICPixelFormat8bppAlpha
, 8, DXGI_FORMAT_A8_UNORM
},
277 { { 0 }, &GUID_WICPixelFormat8bppGray
, 8, DXGI_FORMAT_R8_UNORM
},
278 { { 0 }, &GUID_WICPixelFormat16bppGray
, 16, DXGI_FORMAT_R16_UNORM
},
279 { { 0 }, &GUID_WICPixelFormat16bppGrayHalf
, 16, DXGI_FORMAT_R16_FLOAT
},
280 { { 0 }, &GUID_WICPixelFormat16bppBGR565
, 16, DXGI_FORMAT_B5G6R5_UNORM
},
281 { { 0 }, &GUID_WICPixelFormat16bppBGRA5551
, 16, DXGI_FORMAT_B5G5R5A1_UNORM
},
282 { { 0 }, &GUID_WICPixelFormat32bppGrayFloat
, 32, DXGI_FORMAT_R32_FLOAT
},
283 { { 0 }, &GUID_WICPixelFormat32bppRGBA
, 32, DXGI_FORMAT_R8G8B8A8_UNORM
},
284 { { 0 }, &GUID_WICPixelFormat32bppBGRA
, 32, DXGI_FORMAT_B8G8R8A8_UNORM
},
285 { { 0 }, &GUID_WICPixelFormat32bppBGR
, 32, DXGI_FORMAT_B8G8R8X8_UNORM
},
286 { { 0 }, &GUID_WICPixelFormat32bppR10G10B10A2
, 32, DXGI_FORMAT_R10G10B10A2_UNORM
},
287 { { 0 }, &GUID_WICPixelFormat32bppRGBE
, 32, DXGI_FORMAT_R9G9B9E5_SHAREDEXP
},
288 { { 0 }, &GUID_WICPixelFormat32bppRGBA1010102XR
, 32, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
},
289 { { 0 }, &GUID_WICPixelFormat64bppRGBA
, 64, DXGI_FORMAT_R16G16B16A16_UNORM
},
290 { { 0 }, &GUID_WICPixelFormat64bppRGBAHalf
, 64, DXGI_FORMAT_R16G16B16A16_FLOAT
},
291 { { 0 }, &GUID_WICPixelFormat96bppRGBFloat
, 96, DXGI_FORMAT_R32G32B32_FLOAT
},
292 { { 0 }, &GUID_WICPixelFormat128bppRGBAFloat
, 128, DXGI_FORMAT_R32G32B32A32_FLOAT
},
293 { { 0 }, &GUID_WICPixelFormatUndefined
, 0, DXGI_FORMAT_UNKNOWN
}
296 static DXGI_FORMAT compressed_formats
[] = {
297 DXGI_FORMAT_BC1_TYPELESS
, DXGI_FORMAT_BC1_UNORM
, DXGI_FORMAT_BC1_UNORM_SRGB
,
298 DXGI_FORMAT_BC2_TYPELESS
, DXGI_FORMAT_BC2_UNORM
, DXGI_FORMAT_BC2_UNORM_SRGB
,
299 DXGI_FORMAT_BC3_TYPELESS
, DXGI_FORMAT_BC3_UNORM
, DXGI_FORMAT_BC3_UNORM_SRGB
,
300 DXGI_FORMAT_BC4_TYPELESS
, DXGI_FORMAT_BC4_UNORM
, DXGI_FORMAT_BC4_SNORM
,
301 DXGI_FORMAT_BC5_TYPELESS
, DXGI_FORMAT_BC5_UNORM
, DXGI_FORMAT_BC5_SNORM
,
302 DXGI_FORMAT_BC6H_TYPELESS
, DXGI_FORMAT_BC6H_UF16
, DXGI_FORMAT_BC6H_SF16
,
303 DXGI_FORMAT_BC7_TYPELESS
, DXGI_FORMAT_BC7_UNORM
, DXGI_FORMAT_BC7_UNORM_SRGB
306 static HRESULT WINAPI
DdsDecoder_Dds_GetFrame(IWICDdsDecoder
*, UINT
, UINT
, UINT
, IWICBitmapFrameDecode
**);
308 static DWORD
rgb565_to_argb(WORD color
, BYTE alpha
)
310 return MAKE_ARGB(alpha
, (GET_RGB565_R(color
) * 0xFF + 0x0F) / 0x1F,
311 (GET_RGB565_G(color
) * 0xFF + 0x1F) / 0x3F,
312 (GET_RGB565_B(color
) * 0xFF + 0x0F) / 0x1F);
315 static inline BOOL
has_extended_header(DDS_HEADER
*header
)
317 return (header
->ddspf
.flags
& DDPF_FOURCC
) &&
318 (header
->ddspf
.fourCC
== MAKEFOURCC('D', 'X', '1', '0'));
321 static WICDdsDimension
get_dimension(DDS_HEADER
*header
, DDS_HEADER_DXT10
*header_dxt10
)
324 if (header_dxt10
->miscFlag
& DDS_RESOURCE_MISC_TEXTURECUBE
) return WICDdsTextureCube
;
325 switch (header_dxt10
->resourceDimension
)
327 case DDS_DIMENSION_TEXTURE1D
: return WICDdsTexture1D
;
328 case DDS_DIMENSION_TEXTURE2D
: return WICDdsTexture2D
;
329 case DDS_DIMENSION_TEXTURE3D
: return WICDdsTexture3D
;
330 default: return WICDdsTexture2D
;
333 if (header
->caps2
& DDSCAPS2_CUBEMAP
) {
334 return WICDdsTextureCube
;
335 } else if (header
->caps2
& DDSCAPS2_VOLUME
) {
336 return WICDdsTexture3D
;
338 return WICDdsTexture2D
;
343 static struct dds_format
*get_dds_format(DDS_PIXELFORMAT
*pixel_format
)
347 for (i
= 0; i
< ARRAY_SIZE(dds_format_table
); i
++)
349 if ((pixel_format
->flags
& dds_format_table
[i
].pixel_format
.flags
) &&
350 (pixel_format
->fourCC
== dds_format_table
[i
].pixel_format
.fourCC
) &&
351 (pixel_format
->rgbBitCount
== dds_format_table
[i
].pixel_format
.rgbBitCount
) &&
352 (pixel_format
->rBitMask
== dds_format_table
[i
].pixel_format
.rBitMask
) &&
353 (pixel_format
->gBitMask
== dds_format_table
[i
].pixel_format
.gBitMask
) &&
354 (pixel_format
->bBitMask
== dds_format_table
[i
].pixel_format
.bBitMask
) &&
355 (pixel_format
->aBitMask
== dds_format_table
[i
].pixel_format
.aBitMask
))
356 return dds_format_table
+ i
;
359 return dds_format_table
+ ARRAY_SIZE(dds_format_table
) - 1;
362 static WICDdsAlphaMode
get_alpha_mode_from_fourcc(DWORD fourcc
)
366 case MAKEFOURCC('D', 'X', 'T', '1'):
367 case MAKEFOURCC('D', 'X', 'T', '2'):
368 case MAKEFOURCC('D', 'X', 'T', '4'):
369 return WICDdsAlphaModePremultiplied
;
371 return WICDdsAlphaModeUnknown
;
375 static UINT
get_bytes_per_block_from_format(DXGI_FORMAT format
)
377 /* for uncompressed format, return bytes per pixel*/
380 case DXGI_FORMAT_R8_TYPELESS
:
381 case DXGI_FORMAT_R8_UNORM
:
382 case DXGI_FORMAT_R8_UINT
:
383 case DXGI_FORMAT_R8_SNORM
:
384 case DXGI_FORMAT_R8_SINT
:
385 case DXGI_FORMAT_A8_UNORM
:
387 case DXGI_FORMAT_R8G8_TYPELESS
:
388 case DXGI_FORMAT_R8G8_UNORM
:
389 case DXGI_FORMAT_R8G8_UINT
:
390 case DXGI_FORMAT_R8G8_SNORM
:
391 case DXGI_FORMAT_R8G8_SINT
:
392 case DXGI_FORMAT_R16_TYPELESS
:
393 case DXGI_FORMAT_R16_FLOAT
:
394 case DXGI_FORMAT_D16_UNORM
:
395 case DXGI_FORMAT_R16_UNORM
:
396 case DXGI_FORMAT_R16_UINT
:
397 case DXGI_FORMAT_R16_SNORM
:
398 case DXGI_FORMAT_R16_SINT
:
399 case DXGI_FORMAT_B5G6R5_UNORM
:
400 case DXGI_FORMAT_B5G5R5A1_UNORM
:
401 case DXGI_FORMAT_B4G4R4A4_UNORM
:
403 case DXGI_FORMAT_R10G10B10A2_TYPELESS
:
404 case DXGI_FORMAT_R10G10B10A2_UNORM
:
405 case DXGI_FORMAT_R10G10B10A2_UINT
:
406 case DXGI_FORMAT_R11G11B10_FLOAT
:
407 case DXGI_FORMAT_R8G8B8A8_TYPELESS
:
408 case DXGI_FORMAT_R8G8B8A8_UNORM
:
409 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
:
410 case DXGI_FORMAT_R8G8B8A8_UINT
:
411 case DXGI_FORMAT_R8G8B8A8_SNORM
:
412 case DXGI_FORMAT_R8G8B8A8_SINT
:
413 case DXGI_FORMAT_R16G16_TYPELESS
:
414 case DXGI_FORMAT_R16G16_FLOAT
:
415 case DXGI_FORMAT_R16G16_UNORM
:
416 case DXGI_FORMAT_R16G16_UINT
:
417 case DXGI_FORMAT_R16G16_SNORM
:
418 case DXGI_FORMAT_R16G16_SINT
:
419 case DXGI_FORMAT_R32_TYPELESS
:
420 case DXGI_FORMAT_D32_FLOAT
:
421 case DXGI_FORMAT_R32_FLOAT
:
422 case DXGI_FORMAT_R32_UINT
:
423 case DXGI_FORMAT_R32_SINT
:
424 case DXGI_FORMAT_R24G8_TYPELESS
:
425 case DXGI_FORMAT_D24_UNORM_S8_UINT
:
426 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS
:
427 case DXGI_FORMAT_X24_TYPELESS_G8_UINT
:
428 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP
:
429 case DXGI_FORMAT_R8G8_B8G8_UNORM
:
430 case DXGI_FORMAT_G8R8_G8B8_UNORM
:
431 case DXGI_FORMAT_B8G8R8A8_UNORM
:
432 case DXGI_FORMAT_B8G8R8X8_UNORM
:
433 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
:
434 case DXGI_FORMAT_B8G8R8A8_TYPELESS
:
435 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
:
436 case DXGI_FORMAT_B8G8R8X8_TYPELESS
:
437 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
:
439 case DXGI_FORMAT_BC1_UNORM
:
440 case DXGI_FORMAT_BC1_TYPELESS
:
441 case DXGI_FORMAT_BC1_UNORM_SRGB
:
442 case DXGI_FORMAT_BC4_TYPELESS
:
443 case DXGI_FORMAT_BC4_UNORM
:
444 case DXGI_FORMAT_BC4_SNORM
:
445 case DXGI_FORMAT_R16G16B16A16_TYPELESS
:
446 case DXGI_FORMAT_R16G16B16A16_FLOAT
:
447 case DXGI_FORMAT_R16G16B16A16_UNORM
:
448 case DXGI_FORMAT_R16G16B16A16_UINT
:
449 case DXGI_FORMAT_R16G16B16A16_SNORM
:
450 case DXGI_FORMAT_R16G16B16A16_SINT
:
451 case DXGI_FORMAT_R32G32_TYPELESS
:
452 case DXGI_FORMAT_R32G32_FLOAT
:
453 case DXGI_FORMAT_R32G32_UINT
:
454 case DXGI_FORMAT_R32G32_SINT
:
455 case DXGI_FORMAT_R32G8X24_TYPELESS
:
456 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT
:
457 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS
:
458 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT
:
460 case DXGI_FORMAT_R32G32B32_TYPELESS
:
461 case DXGI_FORMAT_R32G32B32_FLOAT
:
462 case DXGI_FORMAT_R32G32B32_UINT
:
463 case DXGI_FORMAT_R32G32B32_SINT
:
465 case DXGI_FORMAT_BC2_UNORM
:
466 case DXGI_FORMAT_BC2_TYPELESS
:
467 case DXGI_FORMAT_BC2_UNORM_SRGB
:
468 case DXGI_FORMAT_BC3_UNORM
:
469 case DXGI_FORMAT_BC3_TYPELESS
:
470 case DXGI_FORMAT_BC3_UNORM_SRGB
:
471 case DXGI_FORMAT_BC5_TYPELESS
:
472 case DXGI_FORMAT_BC5_UNORM
:
473 case DXGI_FORMAT_BC5_SNORM
:
474 case DXGI_FORMAT_BC6H_TYPELESS
:
475 case DXGI_FORMAT_BC6H_UF16
:
476 case DXGI_FORMAT_BC6H_SF16
:
477 case DXGI_FORMAT_BC7_TYPELESS
:
478 case DXGI_FORMAT_BC7_UNORM
:
479 case DXGI_FORMAT_BC7_UNORM_SRGB
:
480 case DXGI_FORMAT_R32G32B32A32_TYPELESS
:
481 case DXGI_FORMAT_R32G32B32A32_FLOAT
:
482 case DXGI_FORMAT_R32G32B32A32_UINT
:
483 case DXGI_FORMAT_R32G32B32A32_SINT
:
486 WARN("DXGI format 0x%x is not supported in DDS decoder\n", format
);
491 static UINT
get_frame_count(UINT depth
, UINT mip_levels
, UINT array_size
, WICDdsDimension dimension
)
497 frame_count
= mip_levels
;
502 for (i
= 0; i
< mip_levels
; i
++)
504 frame_count
+= depth
;
505 if (depth
> 1) depth
/= 2;
509 frame_count
*= array_size
;
510 if (dimension
== WICDdsTextureCube
) frame_count
*= 6;
515 static void get_frame_dds_index(UINT index
, dds_info
*info
, UINT
*array_index
, UINT
*mip_level
, UINT
*slice_index
)
517 UINT frame_per_texture
, depth
;
519 if (info
->dimension
== WICDdsTextureCube
)
520 frame_per_texture
= info
->mip_levels
;
522 frame_per_texture
= info
->frame_count
/ info
->array_size
;
524 *array_index
= index
/ frame_per_texture
;
525 *slice_index
= index
% frame_per_texture
;
528 while (*slice_index
>= depth
)
530 *slice_index
-= depth
;
532 if (depth
> 1) depth
/= 2;
536 static const GUID
*dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format
)
539 for (i
= 0; i
< ARRAY_SIZE(dds_format_table
); i
++)
541 if (dds_format_table
[i
].pixel_format
.size
== 0 &&
542 dds_format_table
[i
].dxgi_format
== dxgi_format
)
543 return dds_format_table
[i
].wic_format
;
545 return &GUID_WICPixelFormatUndefined
;
548 static BOOL
is_compressed(DXGI_FORMAT format
)
552 for (i
= 0; i
< ARRAY_SIZE(compressed_formats
); i
++)
554 if (format
== compressed_formats
[i
]) return TRUE
;
559 static void get_dds_info(dds_info
* info
, DDS_HEADER
*header
, DDS_HEADER_DXT10
*header_dxt10
)
561 struct dds_format
*format_info
;
563 info
->width
= header
->width
;
564 info
->height
= header
->height
;
566 info
->mip_levels
= 1;
567 info
->array_size
= 1;
568 if (header
->depth
) info
->depth
= header
->depth
;
569 if (header
->mipMapCount
) info
->mip_levels
= header
->mipMapCount
;
571 if (has_extended_header(header
)) {
572 if (header_dxt10
->arraySize
) info
->array_size
= header_dxt10
->arraySize
;
573 info
->format
= header_dxt10
->dxgiFormat
;
574 info
->dimension
= get_dimension(NULL
, header_dxt10
);
575 info
->alpha_mode
= header_dxt10
->miscFlags2
& 0x00000008;
576 info
->data_offset
= sizeof(DWORD
) + sizeof(*header
) + sizeof(*header_dxt10
);
577 if (is_compressed(info
->format
)) {
578 info
->pixel_format
= (info
->alpha_mode
== WICDdsAlphaModePremultiplied
) ?
579 &GUID_WICPixelFormat32bppPBGRA
: &GUID_WICPixelFormat32bppBGRA
;
580 info
->pixel_format_bpp
= 32;
582 info
->pixel_format
= dxgi_format_to_wic_format(info
->format
);
583 info
->pixel_format_bpp
= get_bytes_per_block_from_format(info
->format
) * 8;
586 format_info
= get_dds_format(&header
->ddspf
);
587 info
->format
= format_info
->dxgi_format
;
588 info
->dimension
= get_dimension(header
, NULL
);
589 info
->alpha_mode
= get_alpha_mode_from_fourcc(header
->ddspf
.fourCC
);
590 info
->data_offset
= sizeof(DWORD
) + sizeof(*header
);
591 info
->pixel_format
= format_info
->wic_format
;
592 info
->pixel_format_bpp
= format_info
->wic_format_bpp
;
595 if (header
->ddspf
.flags
& (DDPF_RGB
| DDPF_ALPHA
| DDPF_LUMINANCE
)) {
596 info
->bytes_per_block
= header
->ddspf
.rgbBitCount
/ 8;
598 info
->bytes_per_block
= get_bytes_per_block_from_format(info
->format
);
601 info
->frame_count
= get_frame_count(info
->depth
, info
->mip_levels
, info
->array_size
, info
->dimension
);
604 static void decode_block(const BYTE
*block_data
, UINT block_count
, DXGI_FORMAT format
,
605 UINT width
, UINT height
, DWORD
*buffer
)
607 const BYTE
*block
, *color_indices
, *alpha_indices
, *alpha_table
;
608 int i
, j
, x
, y
, block_x
, block_y
, color_index
, alpha_index
;
609 int block_size
, color_offset
, color_indices_offset
;
610 WORD color
[4], color_value
= 0;
611 BYTE alpha
[8], alpha_value
= 0;
613 if (format
== DXGI_FORMAT_BC1_UNORM
) {
616 color_indices_offset
= 4;
620 color_indices_offset
= 12;
625 for (i
= 0; i
< block_count
; i
++)
627 block
= block_data
+ i
* block_size
;
629 color
[0] = *((WORD
*)(block
+ color_offset
));
630 color
[1] = *((WORD
*)(block
+ color_offset
+ 2));
631 color
[2] = MAKE_RGB565(((GET_RGB565_R(color
[0]) * 2 + GET_RGB565_R(color
[1]) + 1) / 3),
632 ((GET_RGB565_G(color
[0]) * 2 + GET_RGB565_G(color
[1]) + 1) / 3),
633 ((GET_RGB565_B(color
[0]) * 2 + GET_RGB565_B(color
[1]) + 1) / 3));
634 color
[3] = MAKE_RGB565(((GET_RGB565_R(color
[0]) + GET_RGB565_R(color
[1]) * 2 + 1) / 3),
635 ((GET_RGB565_G(color
[0]) + GET_RGB565_G(color
[1]) * 2 + 1) / 3),
636 ((GET_RGB565_B(color
[0]) + GET_RGB565_B(color
[1]) * 2 + 1) / 3));
640 case DXGI_FORMAT_BC1_UNORM
:
641 if (color
[0] <= color
[1]) {
642 color
[2] = MAKE_RGB565(((GET_RGB565_R(color
[0]) + GET_RGB565_R(color
[1]) + 1) / 2),
643 ((GET_RGB565_G(color
[0]) + GET_RGB565_G(color
[1]) + 1) / 2),
644 ((GET_RGB565_B(color
[0]) + GET_RGB565_B(color
[1]) + 1) / 2));
648 case DXGI_FORMAT_BC2_UNORM
:
651 case DXGI_FORMAT_BC3_UNORM
:
653 alpha
[1] = *(block
+ 1);
654 if (alpha
[0] > alpha
[1]) {
655 for (j
= 2; j
< 8; j
++)
657 alpha
[j
] = (BYTE
)((alpha
[0] * (8 - j
) + alpha
[1] * (j
- 1) + 3) / 7);
660 for (j
= 2; j
< 6; j
++)
662 alpha
[j
] = (BYTE
)((alpha
[0] * (6 - j
) + alpha
[1] * (j
- 1) + 2) / 5);
667 alpha_indices
= block
+ 2;
673 color_indices
= block
+ color_indices_offset
;
674 for (j
= 0; j
< 16; j
++)
678 if (x
>= width
|| y
>= height
) continue;
680 color_index
= (color_indices
[j
/ 4] >> ((j
% 4) * 2)) & 0x3;
681 color_value
= color
[color_index
];
685 case DXGI_FORMAT_BC1_UNORM
:
686 if ((color
[0] <= color
[1]) && !color_value
) {
693 case DXGI_FORMAT_BC2_UNORM
:
694 alpha_value
= (alpha_table
[j
/ 2] >> (j
% 2) * 4) & 0xF;
695 alpha_value
= (BYTE
)((alpha_value
* 0xFF + 0x7)/ 0xF);
697 case DXGI_FORMAT_BC3_UNORM
:
698 alpha_index
= (*((DWORD
*)(alpha_indices
+ (j
/ 8) * 3)) >> ((j
% 8) * 3)) & 0x7;
699 alpha_value
= alpha
[alpha_index
];
704 buffer
[x
+ y
* width
] = rgb565_to_argb(color_value
, alpha_value
);
707 block_x
+= DDS_BLOCK_WIDTH
;
708 if (block_x
>= width
) {
710 block_y
+= DDS_BLOCK_HEIGHT
;
715 static inline DdsDecoder
*impl_from_IWICBitmapDecoder(IWICBitmapDecoder
*iface
)
717 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICBitmapDecoder_iface
);
720 static inline DdsDecoder
*impl_from_IWICDdsDecoder(IWICDdsDecoder
*iface
)
722 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICDdsDecoder_iface
);
725 static inline DdsDecoder
*impl_from_IWICWineDecoder(IWICWineDecoder
*iface
)
727 return CONTAINING_RECORD(iface
, DdsDecoder
, IWICWineDecoder_iface
);
730 static inline DdsFrameDecode
*impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface
)
732 return CONTAINING_RECORD(iface
, DdsFrameDecode
, IWICBitmapFrameDecode_iface
);
735 static inline DdsFrameDecode
*impl_from_IWICDdsFrameDecode(IWICDdsFrameDecode
*iface
)
737 return CONTAINING_RECORD(iface
, DdsFrameDecode
, IWICDdsFrameDecode_iface
);
740 static inline DdsEncoder
*impl_from_IWICBitmapEncoder(IWICBitmapEncoder
*iface
)
742 return CONTAINING_RECORD(iface
, DdsEncoder
, IWICBitmapEncoder_iface
);
745 static inline DdsEncoder
*impl_from_IWICDdsEncoder(IWICDdsEncoder
*iface
)
747 return CONTAINING_RECORD(iface
, DdsEncoder
, IWICDdsEncoder_iface
);
750 static inline DdsFrameEncode
*impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface
)
752 return CONTAINING_RECORD(iface
, DdsFrameEncode
, IWICBitmapFrameEncode_iface
);
755 static HRESULT WINAPI
DdsFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
758 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
759 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
761 if (!ppv
) return E_INVALIDARG
;
763 if (IsEqualIID(&IID_IUnknown
, iid
) ||
764 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
765 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
)) {
766 *ppv
= &This
->IWICBitmapFrameDecode_iface
;
767 } else if (IsEqualGUID(&IID_IWICDdsFrameDecode
, iid
)) {
768 *ppv
= &This
->IWICDdsFrameDecode_iface
;
771 return E_NOINTERFACE
;
774 IUnknown_AddRef((IUnknown
*)*ppv
);
778 static ULONG WINAPI
DdsFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
780 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
781 ULONG ref
= InterlockedIncrement(&This
->ref
);
783 TRACE("(%p) refcount=%lu\n", iface
, ref
);
788 static ULONG WINAPI
DdsFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
790 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
791 ULONG ref
= InterlockedDecrement(&This
->ref
);
793 TRACE("(%p) refcount=%lu\n", iface
, ref
);
796 if (This
->pixel_data
!= This
->block_data
) free(This
->pixel_data
);
797 free(This
->block_data
);
804 static HRESULT WINAPI
DdsFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
805 UINT
*puiWidth
, UINT
*puiHeight
)
807 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
809 if (!puiWidth
|| !puiHeight
) return E_INVALIDARG
;
811 *puiWidth
= This
->info
.width
;
812 *puiHeight
= This
->info
.height
;
814 TRACE("(%p) -> (%d,%d)\n", iface
, *puiWidth
, *puiHeight
);
819 static HRESULT WINAPI
DdsFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
820 WICPixelFormatGUID
*pPixelFormat
)
822 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
824 if (!pPixelFormat
) return E_INVALIDARG
;
826 *pPixelFormat
= *This
->info
.pixel_format
;
828 TRACE("(%p) -> %s\n", iface
, debugstr_guid(pPixelFormat
));
833 static HRESULT WINAPI
DdsFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
834 double *pDpiX
, double *pDpiY
)
836 FIXME("(%p,%p,%p): stub.\n", iface
, pDpiX
, pDpiY
);
841 static HRESULT WINAPI
DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
842 IWICPalette
*pIPalette
)
844 FIXME("(%p,%p): stub.\n", iface
, pIPalette
);
849 static HRESULT WINAPI
DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
850 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
852 DdsFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
853 UINT bpp
, frame_stride
, frame_size
;
854 INT x
, y
, width
, height
;
857 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
859 if (!pbBuffer
) return E_INVALIDARG
;
861 bpp
= This
->info
.pixel_format_bpp
;
862 if (!bpp
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
864 frame_stride
= This
->info
.width
* bpp
/ 8;
865 frame_size
= frame_stride
* This
->info
.height
;
867 if (cbStride
< frame_stride
) return E_INVALIDARG
;
868 if (cbBufferSize
< frame_size
) return WINCODEC_ERR_INSUFFICIENTBUFFER
;
873 height
= prc
->Height
;
874 if (x
< 0 || y
< 0 || width
<= 0 || height
<= 0 ||
875 x
+ width
> This
->info
.width
||
876 y
+ height
> This
->info
.height
) {
879 if (cbStride
< width
* bpp
/ 8) return E_INVALIDARG
;
880 if (cbBufferSize
< cbStride
* height
) return WINCODEC_ERR_INSUFFICIENTBUFFER
;
883 EnterCriticalSection(&This
->lock
);
885 if (!This
->pixel_data
) {
886 if (is_compressed(This
->info
.format
)) {
887 This
->pixel_data
= malloc(frame_size
);
888 if (!This
->pixel_data
) {
892 decode_block(This
->block_data
, This
->info
.width_in_blocks
* This
->info
.height_in_blocks
, This
->info
.format
,
893 This
->info
.width
, This
->info
.height
, (DWORD
*)This
->pixel_data
);
895 This
->pixel_data
= This
->block_data
;
899 hr
= copy_pixels(bpp
, This
->pixel_data
, This
->info
.width
, This
->info
.height
, frame_stride
,
900 prc
, cbStride
, cbBufferSize
, pbBuffer
);
903 LeaveCriticalSection(&This
->lock
);
908 static HRESULT WINAPI
DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
909 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
911 FIXME("(%p,%p): stub.\n", iface
, ppIMetadataQueryReader
);
916 static HRESULT WINAPI
DdsFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
917 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
919 FIXME("(%p,%u,%p,%p): stub.\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
924 static HRESULT WINAPI
DdsFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
925 IWICBitmapSource
**ppIThumbnail
)
927 FIXME("(%p,%p): stub.\n", iface
, ppIThumbnail
);
932 static const IWICBitmapFrameDecodeVtbl DdsFrameDecode_Vtbl
= {
933 DdsFrameDecode_QueryInterface
,
934 DdsFrameDecode_AddRef
,
935 DdsFrameDecode_Release
,
936 DdsFrameDecode_GetSize
,
937 DdsFrameDecode_GetPixelFormat
,
938 DdsFrameDecode_GetResolution
,
939 DdsFrameDecode_CopyPalette
,
940 DdsFrameDecode_CopyPixels
,
941 DdsFrameDecode_GetMetadataQueryReader
,
942 DdsFrameDecode_GetColorContexts
,
943 DdsFrameDecode_GetThumbnail
946 static HRESULT WINAPI
DdsFrameDecode_Dds_QueryInterface(IWICDdsFrameDecode
*iface
,
947 REFIID iid
, void **ppv
)
949 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
950 return DdsFrameDecode_QueryInterface(&This
->IWICBitmapFrameDecode_iface
, iid
, ppv
);
953 static ULONG WINAPI
DdsFrameDecode_Dds_AddRef(IWICDdsFrameDecode
*iface
)
955 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
956 return DdsFrameDecode_AddRef(&This
->IWICBitmapFrameDecode_iface
);
959 static ULONG WINAPI
DdsFrameDecode_Dds_Release(IWICDdsFrameDecode
*iface
)
961 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
962 return DdsFrameDecode_Release(&This
->IWICBitmapFrameDecode_iface
);
965 static HRESULT WINAPI
DdsFrameDecode_Dds_GetSizeInBlocks(IWICDdsFrameDecode
*iface
,
966 UINT
*widthInBlocks
, UINT
*heightInBlocks
)
968 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
970 if (!widthInBlocks
|| !heightInBlocks
) return E_INVALIDARG
;
972 *widthInBlocks
= This
->info
.width_in_blocks
;
973 *heightInBlocks
= This
->info
.height_in_blocks
;
975 TRACE("(%p,%p,%p) -> (%d,%d)\n", iface
, widthInBlocks
, heightInBlocks
, *widthInBlocks
, *heightInBlocks
);
980 static HRESULT WINAPI
DdsFrameDecode_Dds_GetFormatInfo(IWICDdsFrameDecode
*iface
,
981 WICDdsFormatInfo
*formatInfo
)
983 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
985 if (!formatInfo
) return E_INVALIDARG
;
987 formatInfo
->DxgiFormat
= This
->info
.format
;
988 formatInfo
->BytesPerBlock
= This
->info
.bytes_per_block
;
989 formatInfo
->BlockWidth
= This
->info
.block_width
;
990 formatInfo
->BlockHeight
= This
->info
.block_height
;
992 TRACE("(%p,%p) -> (0x%x,%d,%d,%d)\n", iface
, formatInfo
,
993 formatInfo
->DxgiFormat
, formatInfo
->BytesPerBlock
, formatInfo
->BlockWidth
, formatInfo
->BlockHeight
);
998 static HRESULT WINAPI
DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode
*iface
,
999 const WICRect
*boundsInBlocks
, UINT stride
, UINT bufferSize
,
1002 DdsFrameDecode
*This
= impl_from_IWICDdsFrameDecode(iface
);
1003 int x
, y
, width
, height
;
1004 UINT bytes_per_block
, frame_stride
, frame_size
;
1006 TRACE("(%p,%p,%u,%u,%p)\n", iface
, boundsInBlocks
, stride
, bufferSize
, buffer
);
1008 if (!buffer
) return E_INVALIDARG
;
1010 bytes_per_block
= This
->info
.bytes_per_block
;
1011 frame_stride
= This
->info
.width_in_blocks
* bytes_per_block
;
1012 frame_size
= frame_stride
* This
->info
.height_in_blocks
;
1014 if (!boundsInBlocks
) {
1015 if (stride
< frame_stride
) return E_INVALIDARG
;
1016 if (bufferSize
< frame_size
) return E_INVALIDARG
;
1018 x
= boundsInBlocks
->X
;
1019 y
= boundsInBlocks
->Y
;
1020 width
= boundsInBlocks
->Width
;
1021 height
= boundsInBlocks
->Height
;
1022 if (x
< 0 || y
< 0 || width
<= 0 || height
<= 0 ||
1023 x
+ width
> This
->info
.width_in_blocks
||
1024 y
+ height
> This
->info
.height_in_blocks
) {
1025 return E_INVALIDARG
;
1027 if (stride
< width
* bytes_per_block
) return E_INVALIDARG
;
1028 if (bufferSize
< stride
* height
) return E_INVALIDARG
;
1031 return copy_pixels(This
->info
.bytes_per_block
* 8, This
->block_data
, This
->info
.width_in_blocks
,
1032 This
->info
.height_in_blocks
, frame_stride
, boundsInBlocks
, stride
, bufferSize
, buffer
);
1035 static const IWICDdsFrameDecodeVtbl DdsFrameDecode_Dds_Vtbl
= {
1036 DdsFrameDecode_Dds_QueryInterface
,
1037 DdsFrameDecode_Dds_AddRef
,
1038 DdsFrameDecode_Dds_Release
,
1039 DdsFrameDecode_Dds_GetSizeInBlocks
,
1040 DdsFrameDecode_Dds_GetFormatInfo
,
1041 DdsFrameDecode_Dds_CopyBlocks
1044 static HRESULT
DdsFrameDecode_CreateInstance(DdsFrameDecode
**frame_decode
)
1046 DdsFrameDecode
*result
;
1048 result
= malloc(sizeof(*result
));
1049 if (!result
) return E_OUTOFMEMORY
;
1051 result
->IWICBitmapFrameDecode_iface
.lpVtbl
= &DdsFrameDecode_Vtbl
;
1052 result
->IWICDdsFrameDecode_iface
.lpVtbl
= &DdsFrameDecode_Dds_Vtbl
;
1054 InitializeCriticalSection(&result
->lock
);
1055 result
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsFrameDecode.lock");
1057 *frame_decode
= result
;
1061 static HRESULT WINAPI
DdsDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
1064 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1065 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1067 if (!ppv
) return E_INVALIDARG
;
1069 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1070 IsEqualIID(&IID_IWICBitmapDecoder
, iid
)) {
1071 *ppv
= &This
->IWICBitmapDecoder_iface
;
1072 } else if (IsEqualIID(&IID_IWICDdsDecoder
, iid
)) {
1073 *ppv
= &This
->IWICDdsDecoder_iface
;
1074 } else if (IsEqualIID(&IID_IWICWineDecoder
, iid
)) {
1075 *ppv
= &This
->IWICWineDecoder_iface
;
1078 return E_NOINTERFACE
;
1081 IUnknown_AddRef((IUnknown
*)*ppv
);
1085 static ULONG WINAPI
DdsDecoder_AddRef(IWICBitmapDecoder
*iface
)
1087 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1088 ULONG ref
= InterlockedIncrement(&This
->ref
);
1090 TRACE("(%p) refcount=%lu\n", iface
, ref
);
1095 static ULONG WINAPI
DdsDecoder_Release(IWICBitmapDecoder
*iface
)
1097 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1098 ULONG ref
= InterlockedDecrement(&This
->ref
);
1100 TRACE("(%p) refcount=%lu\n", iface
, ref
);
1104 This
->lock
.DebugInfo
->Spare
[0] = 0;
1105 DeleteCriticalSection(&This
->lock
);
1106 if (This
->stream
) IStream_Release(This
->stream
);
1113 static HRESULT WINAPI
DdsDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*stream
,
1116 FIXME("(%p,%p,%p): stub.\n", iface
, stream
, capability
);
1121 static HRESULT WINAPI
DdsDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
1122 WICDecodeOptions cacheOptions
)
1124 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1127 TRACE("(%p,%p,%x)\n", iface
, pIStream
, cacheOptions
);
1129 EnterCriticalSection(&This
->lock
);
1131 hr
= IWICWineDecoder_Initialize(&This
->IWICWineDecoder_iface
, pIStream
, cacheOptions
);
1132 if (FAILED(hr
)) goto end
;
1134 if (This
->info
.dimension
== WICDdsTextureCube
||
1135 (This
->info
.format
!= DXGI_FORMAT_BC1_UNORM
&&
1136 This
->info
.format
!= DXGI_FORMAT_BC2_UNORM
&&
1137 This
->info
.format
!= DXGI_FORMAT_BC3_UNORM
)) {
1138 IStream_Release(pIStream
);
1139 This
->stream
= NULL
;
1140 This
->initialized
= FALSE
;
1141 hr
= WINCODEC_ERR_BADHEADER
;
1145 LeaveCriticalSection(&This
->lock
);
1150 static HRESULT WINAPI
DdsDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
1151 GUID
*pguidContainerFormat
)
1153 TRACE("(%p,%p)\n", iface
, pguidContainerFormat
);
1155 memcpy(pguidContainerFormat
, &GUID_ContainerFormatDds
, sizeof(GUID
));
1160 static HRESULT WINAPI
DdsDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
1161 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
1163 TRACE("(%p,%p)\n", iface
, ppIDecoderInfo
);
1165 return get_decoder_info(&CLSID_WICDdsDecoder
, ppIDecoderInfo
);
1168 static HRESULT WINAPI
DdsDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
1169 IWICPalette
*pIPalette
)
1171 TRACE("(%p,%p)\n", iface
, pIPalette
);
1173 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
1176 static HRESULT WINAPI
DdsDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
1177 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
1179 if (!ppIMetadataQueryReader
) return E_INVALIDARG
;
1181 FIXME("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
1186 static HRESULT WINAPI
DdsDecoder_GetPreview(IWICBitmapDecoder
*iface
,
1187 IWICBitmapSource
**ppIBitmapSource
)
1189 TRACE("(%p,%p)\n", iface
, ppIBitmapSource
);
1191 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1194 static HRESULT WINAPI
DdsDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
1195 UINT cCount
, IWICColorContext
**ppDdslorContexts
, UINT
*pcActualCount
)
1197 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppDdslorContexts
, pcActualCount
);
1199 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1202 static HRESULT WINAPI
DdsDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
1203 IWICBitmapSource
**ppIThumbnail
)
1205 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
1207 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
1210 static HRESULT WINAPI
DdsDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
1213 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1215 if (!pCount
) return E_INVALIDARG
;
1216 if (!This
->initialized
) return WINCODEC_ERR_WRONGSTATE
;
1218 EnterCriticalSection(&This
->lock
);
1220 *pCount
= This
->info
.frame_count
;
1222 LeaveCriticalSection(&This
->lock
);
1224 TRACE("(%p) -> %d\n", iface
, *pCount
);
1229 static HRESULT WINAPI
DdsDecoder_GetFrame(IWICBitmapDecoder
*iface
,
1230 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
1232 DdsDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
1233 UINT array_index
, mip_level
, slice_index
;
1235 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
1237 if (!ppIBitmapFrame
) return E_INVALIDARG
;
1239 EnterCriticalSection(&This
->lock
);
1241 if (!This
->initialized
) {
1242 LeaveCriticalSection(&This
->lock
);
1243 return WINCODEC_ERR_WRONGSTATE
;
1246 get_frame_dds_index(index
, &This
->info
, &array_index
, &mip_level
, &slice_index
);
1248 LeaveCriticalSection(&This
->lock
);
1250 return DdsDecoder_Dds_GetFrame(&This
->IWICDdsDecoder_iface
, array_index
, mip_level
, slice_index
, ppIBitmapFrame
);
1253 static const IWICBitmapDecoderVtbl DdsDecoder_Vtbl
= {
1254 DdsDecoder_QueryInterface
,
1257 DdsDecoder_QueryCapability
,
1258 DdsDecoder_Initialize
,
1259 DdsDecoder_GetContainerFormat
,
1260 DdsDecoder_GetDecoderInfo
,
1261 DdsDecoder_CopyPalette
,
1262 DdsDecoder_GetMetadataQueryReader
,
1263 DdsDecoder_GetPreview
,
1264 DdsDecoder_GetColorContexts
,
1265 DdsDecoder_GetThumbnail
,
1266 DdsDecoder_GetFrameCount
,
1270 static HRESULT WINAPI
DdsDecoder_Dds_QueryInterface(IWICDdsDecoder
*iface
,
1271 REFIID iid
, void **ppv
)
1273 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1274 return DdsDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1277 static ULONG WINAPI
DdsDecoder_Dds_AddRef(IWICDdsDecoder
*iface
)
1279 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1280 return DdsDecoder_AddRef(&This
->IWICBitmapDecoder_iface
);
1283 static ULONG WINAPI
DdsDecoder_Dds_Release(IWICDdsDecoder
*iface
)
1285 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1286 return DdsDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1289 static HRESULT WINAPI
DdsDecoder_Dds_GetParameters(IWICDdsDecoder
*iface
,
1290 WICDdsParameters
*parameters
)
1292 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1295 if (!parameters
) return E_INVALIDARG
;
1297 EnterCriticalSection(&This
->lock
);
1299 if (!This
->initialized
) {
1300 hr
= WINCODEC_ERR_WRONGSTATE
;
1304 parameters
->Width
= This
->info
.width
;
1305 parameters
->Height
= This
->info
.height
;
1306 parameters
->Depth
= This
->info
.depth
;
1307 parameters
->MipLevels
= This
->info
.mip_levels
;
1308 parameters
->ArraySize
= This
->info
.array_size
;
1309 parameters
->DxgiFormat
= This
->info
.format
;
1310 parameters
->Dimension
= This
->info
.dimension
;
1311 parameters
->AlphaMode
= This
->info
.alpha_mode
;
1313 TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x dimension=0x%x alphaMode=0x%x)\n",
1314 iface
, parameters
->Width
, parameters
->Height
, parameters
->Depth
, parameters
->MipLevels
,
1315 parameters
->ArraySize
, parameters
->DxgiFormat
, parameters
->Dimension
, parameters
->AlphaMode
);
1320 LeaveCriticalSection(&This
->lock
);
1325 static HRESULT WINAPI
DdsDecoder_Dds_GetFrame(IWICDdsDecoder
*iface
,
1326 UINT arrayIndex
, UINT mipLevel
, UINT sliceIndex
,
1327 IWICBitmapFrameDecode
**bitmapFrame
)
1329 DdsDecoder
*This
= impl_from_IWICDdsDecoder(iface
);
1332 UINT width
, height
, depth
, block_width
, block_height
, width_in_blocks
, height_in_blocks
, size
;
1333 UINT frame_width
= 0, frame_height
= 0, frame_width_in_blocks
= 0, frame_height_in_blocks
= 0, frame_size
= 0;
1334 UINT bytes_per_block
, i
;
1336 DdsFrameDecode
*frame_decode
= NULL
;
1338 TRACE("(%p,%u,%u,%u,%p)\n", iface
, arrayIndex
, mipLevel
, sliceIndex
, bitmapFrame
);
1340 if (!bitmapFrame
) return E_INVALIDARG
;
1342 EnterCriticalSection(&This
->lock
);
1344 if (!This
->initialized
) {
1345 hr
= WINCODEC_ERR_WRONGSTATE
;
1349 if ((arrayIndex
>= This
->info
.array_size
&& This
->info
.dimension
!= WICDdsTextureCube
) ||
1350 (arrayIndex
>= This
->info
.array_size
* 6) ||
1351 (mipLevel
>= This
->info
.mip_levels
) ||
1352 (sliceIndex
>= This
->info
.depth
)) {
1357 if (is_compressed(This
->info
.format
)) {
1358 block_width
= DDS_BLOCK_WIDTH
;
1359 block_height
= DDS_BLOCK_HEIGHT
;
1364 bytes_per_block
= This
->info
.bytes_per_block
;
1365 seek
.QuadPart
= This
->info
.data_offset
;
1367 width
= This
->info
.width
;
1368 height
= This
->info
.height
;
1369 depth
= This
->info
.depth
;
1370 for (i
= 0; i
< This
->info
.mip_levels
; i
++)
1372 width_in_blocks
= (width
+ block_width
- 1) / block_width
;
1373 height_in_blocks
= (height
+ block_height
- 1) / block_height
;
1374 size
= width_in_blocks
* height_in_blocks
* bytes_per_block
;
1377 seek
.QuadPart
+= size
* depth
;
1378 } else if (i
== mipLevel
){
1379 seek
.QuadPart
+= size
* sliceIndex
;
1380 frame_width
= width
;
1381 frame_height
= height
;
1382 frame_width_in_blocks
= width_in_blocks
;
1383 frame_height_in_blocks
= height_in_blocks
;
1384 frame_size
= frame_width_in_blocks
* frame_height_in_blocks
* bytes_per_block
;
1385 if (arrayIndex
== 0) break;
1387 seek
.QuadPart
+= arrayIndex
* size
* depth
;
1389 if (width
> 1) width
/= 2;
1390 if (height
> 1) height
/= 2;
1391 if (depth
> 1) depth
/= 2;
1394 hr
= DdsFrameDecode_CreateInstance(&frame_decode
);
1395 if (hr
!= S_OK
) goto end
;
1396 frame_decode
->info
.width
= frame_width
;
1397 frame_decode
->info
.height
= frame_height
;
1398 frame_decode
->info
.format
= This
->info
.format
;
1399 frame_decode
->info
.bytes_per_block
= bytes_per_block
;
1400 frame_decode
->info
.block_width
= block_width
;
1401 frame_decode
->info
.block_height
= block_height
;
1402 frame_decode
->info
.width_in_blocks
= frame_width_in_blocks
;
1403 frame_decode
->info
.height_in_blocks
= frame_height_in_blocks
;
1404 frame_decode
->info
.pixel_format
= This
->info
.pixel_format
;
1405 frame_decode
->info
.pixel_format_bpp
= This
->info
.pixel_format_bpp
;
1406 frame_decode
->block_data
= malloc(frame_size
);
1407 frame_decode
->pixel_data
= NULL
;
1408 hr
= IStream_Seek(This
->stream
, seek
, SEEK_SET
, NULL
);
1409 if (hr
!= S_OK
) goto end
;
1410 hr
= IStream_Read(This
->stream
, frame_decode
->block_data
, frame_size
, &bytesread
);
1411 if (hr
!= S_OK
|| bytesread
!= frame_size
) {
1412 hr
= WINCODEC_ERR_STREAMREAD
;
1415 *bitmapFrame
= &frame_decode
->IWICBitmapFrameDecode_iface
;
1420 LeaveCriticalSection(&This
->lock
);
1422 if (hr
!= S_OK
&& frame_decode
) DdsFrameDecode_Release(&frame_decode
->IWICBitmapFrameDecode_iface
);
1427 static const IWICDdsDecoderVtbl DdsDecoder_Dds_Vtbl
= {
1428 DdsDecoder_Dds_QueryInterface
,
1429 DdsDecoder_Dds_AddRef
,
1430 DdsDecoder_Dds_Release
,
1431 DdsDecoder_Dds_GetParameters
,
1432 DdsDecoder_Dds_GetFrame
1435 static HRESULT WINAPI
DdsDecoder_Wine_QueryInterface(IWICWineDecoder
*iface
, REFIID iid
, void **ppv
)
1437 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1438 return DdsDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1441 static ULONG WINAPI
DdsDecoder_Wine_AddRef(IWICWineDecoder
*iface
)
1443 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1444 return DdsDecoder_AddRef(&This
->IWICBitmapDecoder_iface
);
1447 static ULONG WINAPI
DdsDecoder_Wine_Release(IWICWineDecoder
*iface
)
1449 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1450 return DdsDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1453 static HRESULT WINAPI
DdsDecoder_Wine_Initialize(IWICWineDecoder
*iface
, IStream
*stream
, WICDecodeOptions options
)
1455 DdsDecoder
*This
= impl_from_IWICWineDecoder(iface
);
1456 DDS_HEADER_DXT10 header_dxt10
;
1463 TRACE("(This %p, stream %p, options %#x)\n", iface
, stream
, options
);
1465 EnterCriticalSection(&This
->lock
);
1467 if (This
->initialized
) {
1468 hr
= WINCODEC_ERR_WRONGSTATE
;
1473 hr
= IStream_Seek(stream
, seek
, SEEK_SET
, NULL
);
1474 if (FAILED(hr
)) goto end
;
1476 hr
= IStream_Read(stream
, &magic
, sizeof(magic
), &bytesread
);
1477 if (FAILED(hr
)) goto end
;
1478 if (bytesread
!= sizeof(magic
)) {
1479 hr
= WINCODEC_ERR_STREAMREAD
;
1482 if (magic
!= DDS_MAGIC
) {
1483 hr
= WINCODEC_ERR_UNKNOWNIMAGEFORMAT
;
1487 hr
= IStream_Read(stream
, &header
, sizeof(header
), &bytesread
);
1488 if (FAILED(hr
)) goto end
;
1489 if (bytesread
!= sizeof(header
)) {
1490 hr
= WINCODEC_ERR_STREAMREAD
;
1493 if (header
.size
!= sizeof(header
)) {
1494 hr
= WINCODEC_ERR_BADHEADER
;
1498 if (has_extended_header(&header
)) {
1499 hr
= IStream_Read(stream
, &header_dxt10
, sizeof(header_dxt10
), &bytesread
);
1500 if (FAILED(hr
)) goto end
;
1501 if (bytesread
!= sizeof(header_dxt10
)) {
1502 hr
= WINCODEC_ERR_STREAMREAD
;
1507 get_dds_info(&This
->info
, &header
, &header_dxt10
);
1509 This
->initialized
= TRUE
;
1510 This
->stream
= stream
;
1511 IStream_AddRef(stream
);
1514 LeaveCriticalSection(&This
->lock
);
1519 static const IWICWineDecoderVtbl DdsDecoder_Wine_Vtbl
= {
1520 DdsDecoder_Wine_QueryInterface
,
1521 DdsDecoder_Wine_AddRef
,
1522 DdsDecoder_Wine_Release
,
1523 DdsDecoder_Wine_Initialize
1526 static HRESULT WINAPI
DdsFrameEncode_QueryInterface(IWICBitmapFrameEncode
*iface
, REFIID iid
, void **ppv
)
1528 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1529 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1531 if (!ppv
) return E_INVALIDARG
;
1533 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1534 IsEqualIID(&IID_IWICBitmapFrameEncode
, iid
))
1536 *ppv
= &This
->IWICBitmapFrameEncode_iface
;
1541 return E_NOINTERFACE
;
1544 IUnknown_AddRef((IUnknown
*)*ppv
);
1548 static ULONG WINAPI
DdsFrameEncode_AddRef(IWICBitmapFrameEncode
*iface
)
1550 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1551 ULONG ref
= InterlockedIncrement(&This
->ref
);
1553 TRACE("(%p) refcount=%lu\n", iface
, ref
);
1558 static ULONG WINAPI
DdsFrameEncode_Release(IWICBitmapFrameEncode
*iface
)
1560 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1561 ULONG ref
= InterlockedDecrement(&This
->ref
);
1563 TRACE("(%p) refcount=%lu\n", iface
, ref
);
1567 IWICBitmapEncoder_Release(&This
->parent
->IWICBitmapEncoder_iface
);
1574 static HRESULT WINAPI
DdsFrameEncode_Initialize(IWICBitmapFrameEncode
*iface
,
1575 IPropertyBag2
*encoderOptions
)
1577 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1580 TRACE("(%p,%p)\n", iface
, encoderOptions
);
1581 if (encoderOptions
) FIXME("encoder options are not supported for DDS.\n");
1583 EnterCriticalSection(&This
->parent
->lock
);
1585 if (This
->initialized
)
1587 hr
= WINCODEC_ERR_WRONGSTATE
;
1591 This
->initialized
= TRUE
;
1595 LeaveCriticalSection(&This
->parent
->lock
);
1600 static HRESULT WINAPI
DdsFrameEncode_SetSize(IWICBitmapFrameEncode
*iface
,
1601 UINT width
, UINT height
)
1603 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1606 TRACE("(%p,%u,%u)\n", iface
, width
, height
);
1608 EnterCriticalSection(&This
->parent
->lock
);
1610 if (!This
->initialized
|| This
->frame_created
)
1612 hr
= WINCODEC_ERR_WRONGSTATE
;
1616 This
->width
= width
;
1617 This
->height
= height
;
1621 LeaveCriticalSection(&This
->parent
->lock
);
1626 static HRESULT WINAPI
DdsFrameEncode_SetResolution(IWICBitmapFrameEncode
*iface
,
1627 double dpiX
, double dpiY
)
1629 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1632 TRACE("(%p,%0.2f,%0.2f)\n", iface
, dpiX
, dpiY
);
1634 EnterCriticalSection(&This
->parent
->lock
);
1636 if (!This
->initialized
|| This
->frame_created
)
1638 hr
= WINCODEC_ERR_WRONGSTATE
;
1647 LeaveCriticalSection(&This
->parent
->lock
);
1652 static HRESULT WINAPI
DdsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode
*iface
,
1653 WICPixelFormatGUID
*pixelFormat
)
1655 DdsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1658 TRACE("(%p,%s)\n", iface
, debugstr_guid(pixelFormat
));
1660 EnterCriticalSection(&This
->parent
->lock
);
1662 if (!This
->initialized
)
1664 hr
= WINCODEC_ERR_NOTINITIALIZED
;
1666 else if (This
->frame_created
)
1668 hr
= WINCODEC_ERR_WRONGSTATE
;
1672 *pixelFormat
= GUID_WICPixelFormat32bppBGRA
;
1676 LeaveCriticalSection(&This
->parent
->lock
);
1681 static HRESULT WINAPI
DdsFrameEncode_SetColorContexts(IWICBitmapFrameEncode
*iface
,
1682 UINT count
, IWICColorContext
**colorContext
)
1684 FIXME("(%p,%u,%p): stub\n", iface
, count
, colorContext
);
1688 static HRESULT WINAPI
DdsFrameEncode_SetPalette(IWICBitmapFrameEncode
*iface
,
1689 IWICPalette
*palette
)
1691 FIXME("(%p,%p): stub\n", iface
, palette
);
1695 static HRESULT WINAPI
DdsFrameEncode_SetThumbnail(IWICBitmapFrameEncode
*iface
,
1696 IWICBitmapSource
*thumbnail
)
1698 TRACE("(%p,%p)\n", iface
, thumbnail
);
1699 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1702 static HRESULT WINAPI
DdsFrameEncode_WritePixels(IWICBitmapFrameEncode
*iface
,
1703 UINT lineCount
, UINT stride
, UINT bufferSize
, BYTE
*pixels
)
1705 FIXME("(%p,%u,%u,%u,%p): stub\n", iface
, lineCount
, stride
, bufferSize
, pixels
);
1709 static HRESULT WINAPI
DdsFrameEncode_WriteSource(IWICBitmapFrameEncode
*iface
,
1710 IWICBitmapSource
*bitmapSource
, WICRect
*rc
)
1712 FIXME("(%p,%p,%s): stub\n", iface
, bitmapSource
, debug_wic_rect(rc
));
1716 static HRESULT WINAPI
DdsFrameEncode_Commit(IWICBitmapFrameEncode
*iface
)
1718 FIXME("(%p): stub\n", iface
);
1722 static HRESULT WINAPI
DdsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface
,
1723 IWICMetadataQueryWriter
**metadataQueryWriter
)
1725 FIXME("(%p,%p): stub\n", iface
, metadataQueryWriter
);
1729 static const IWICBitmapFrameEncodeVtbl DdsFrameEncode_Vtbl
= {
1730 DdsFrameEncode_QueryInterface
,
1731 DdsFrameEncode_AddRef
,
1732 DdsFrameEncode_Release
,
1733 DdsFrameEncode_Initialize
,
1734 DdsFrameEncode_SetSize
,
1735 DdsFrameEncode_SetResolution
,
1736 DdsFrameEncode_SetPixelFormat
,
1737 DdsFrameEncode_SetColorContexts
,
1738 DdsFrameEncode_SetPalette
,
1739 DdsFrameEncode_SetThumbnail
,
1740 DdsFrameEncode_WritePixels
,
1741 DdsFrameEncode_WriteSource
,
1742 DdsFrameEncode_Commit
,
1743 DdsFrameEncode_GetMetadataQueryWriter
1746 HRESULT
DdsDecoder_CreateInstance(REFIID iid
, void** ppv
)
1751 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1755 This
= malloc(sizeof(DdsDecoder
));
1756 if (!This
) return E_OUTOFMEMORY
;
1758 This
->IWICBitmapDecoder_iface
.lpVtbl
= &DdsDecoder_Vtbl
;
1759 This
->IWICDdsDecoder_iface
.lpVtbl
= &DdsDecoder_Dds_Vtbl
;
1760 This
->IWICWineDecoder_iface
.lpVtbl
= &DdsDecoder_Wine_Vtbl
;
1762 This
->initialized
= FALSE
;
1763 This
->stream
= NULL
;
1764 InitializeCriticalSection(&This
->lock
);
1765 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsDecoder.lock");
1767 ret
= IWICBitmapDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
1768 IWICBitmapDecoder_Release(&This
->IWICBitmapDecoder_iface
);
1773 static HRESULT WINAPI
DdsEncoder_Dds_QueryInterface(IWICDdsEncoder
*iface
, REFIID iid
,
1776 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1777 return IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
1780 static ULONG WINAPI
DdsEncoder_Dds_AddRef(IWICDdsEncoder
*iface
)
1782 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1783 return IWICBitmapEncoder_AddRef(&This
->IWICBitmapEncoder_iface
);
1786 static ULONG WINAPI
DdsEncoder_Dds_Release(IWICDdsEncoder
*iface
)
1788 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1789 return IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);
1792 static HRESULT WINAPI
DdsEncoder_Dds_SetParameters(IWICDdsEncoder
*iface
,
1793 WICDdsParameters
*parameters
)
1795 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1798 TRACE("(%p,%p)\n", iface
, parameters
);
1800 if (!parameters
) return E_INVALIDARG
;
1802 EnterCriticalSection(&This
->lock
);
1806 hr
= WINCODEC_ERR_WRONGSTATE
;
1810 This
->info
.width
= parameters
->Width
;
1811 This
->info
.height
= parameters
->Height
;
1812 This
->info
.depth
= parameters
->Depth
;
1813 This
->info
.mip_levels
= parameters
->MipLevels
;
1814 This
->info
.array_size
= parameters
->ArraySize
;
1815 This
->info
.format
= parameters
->DxgiFormat
;
1816 This
->info
.dimension
= parameters
->Dimension
;
1817 This
->info
.alpha_mode
= parameters
->AlphaMode
;
1819 This
->info
.bytes_per_block
= get_bytes_per_block_from_format(This
->info
.format
);
1820 This
->info
.frame_count
= get_frame_count(This
->info
.depth
, This
->info
.mip_levels
,
1821 This
->info
.array_size
, This
->info
.dimension
);
1826 LeaveCriticalSection(&This
->lock
);
1830 static HRESULT WINAPI
DdsEncoder_Dds_GetParameters(IWICDdsEncoder
*iface
,
1831 WICDdsParameters
*parameters
)
1833 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1836 TRACE("(%p,%p)\n", iface
, parameters
);
1838 if (!parameters
) return E_INVALIDARG
;
1840 EnterCriticalSection(&This
->lock
);
1844 hr
= WINCODEC_ERR_WRONGSTATE
;
1848 parameters
->Width
= This
->info
.width
;
1849 parameters
->Height
= This
->info
.height
;
1850 parameters
->Depth
= This
->info
.depth
;
1851 parameters
->MipLevels
= This
->info
.mip_levels
;
1852 parameters
->ArraySize
= This
->info
.array_size
;
1853 parameters
->DxgiFormat
= This
->info
.format
;
1854 parameters
->Dimension
= This
->info
.dimension
;
1855 parameters
->AlphaMode
= This
->info
.alpha_mode
;
1857 TRACE("(%p,%p) -> (%dx%d depth=%u mipLevels=%u arraySize=%u dxgiFormat=%#x dimension=%#x alphaMode=%#x)\n",
1858 iface
, parameters
, parameters
->Width
, parameters
->Height
, parameters
->Depth
, parameters
->MipLevels
,
1859 parameters
->ArraySize
, parameters
->DxgiFormat
, parameters
->Dimension
, parameters
->AlphaMode
);
1864 LeaveCriticalSection(&This
->lock
);
1868 static HRESULT WINAPI
DdsEncoder_Dds_CreateNewFrame(IWICDdsEncoder
*iface
,
1869 IWICBitmapFrameEncode
**frameEncode
,
1870 UINT
*arrayIndex
, UINT
*mipLevel
, UINT
*sliceIndex
)
1872 DdsEncoder
*This
= impl_from_IWICDdsEncoder(iface
);
1873 UINT array_index
, mip_level
, slice_index
;
1874 DdsFrameEncode
*result
;
1877 TRACE("(%p,%p,%p,%p,%p)\n", iface
, frameEncode
, arrayIndex
, mipLevel
, sliceIndex
);
1879 EnterCriticalSection(&This
->lock
);
1881 if (!This
->stream
|| This
->committed
|| This
->uncommitted_frame
)
1883 hr
= WINCODEC_ERR_WRONGSTATE
;
1887 result
= malloc(sizeof(*result
));
1894 get_frame_dds_index(This
->frame_index
, &This
->info
, &array_index
, &mip_level
, &slice_index
);
1895 if (arrayIndex
) *arrayIndex
= array_index
;
1896 if (mipLevel
) *mipLevel
= mip_level
;
1897 if (sliceIndex
) *sliceIndex
= slice_index
;
1899 This
->frame_index
++;
1900 result
->IWICBitmapFrameEncode_iface
.lpVtbl
= &DdsFrameEncode_Vtbl
;
1902 result
->parent
= This
;
1903 result
->parent
->uncommitted_frame
= TRUE
;
1904 result
->initialized
= FALSE
;
1905 result
->frame_created
= FALSE
;
1906 IWICDdsEncoder_AddRef(iface
);
1908 *frameEncode
= &result
->IWICBitmapFrameEncode_iface
;
1912 LeaveCriticalSection(&This
->lock
);
1916 static const IWICDdsEncoderVtbl DdsEncoder_Dds_Vtbl
=
1918 DdsEncoder_Dds_QueryInterface
,
1919 DdsEncoder_Dds_AddRef
,
1920 DdsEncoder_Dds_Release
,
1921 DdsEncoder_Dds_SetParameters
,
1922 DdsEncoder_Dds_GetParameters
,
1923 DdsEncoder_Dds_CreateNewFrame
1926 static HRESULT WINAPI
DdsEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
1929 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1930 FIXME("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1932 if (!ppv
) return E_INVALIDARG
;
1934 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1935 IsEqualIID(&IID_IWICBitmapEncoder
, iid
)) {
1936 *ppv
= &This
->IWICBitmapEncoder_iface
;
1937 } else if (IsEqualIID(&IID_IWICDdsEncoder
, iid
)) {
1938 *ppv
= &This
->IWICDdsEncoder_iface
;
1941 return E_NOINTERFACE
;
1944 IUnknown_AddRef((IUnknown
*)*ppv
);
1948 static ULONG WINAPI
DdsEncoder_AddRef(IWICBitmapEncoder
*iface
)
1950 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1951 ULONG ref
= InterlockedIncrement(&This
->ref
);
1953 TRACE("(%p) refcount=%lu\n", iface
, ref
);
1958 static ULONG WINAPI
DdsEncoder_Release(IWICBitmapEncoder
*iface
)
1960 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1961 ULONG ref
= InterlockedDecrement(&This
->ref
);
1963 TRACE("(%p) refcount=%lu\n", iface
, ref
);
1966 This
->lock
.DebugInfo
->Spare
[0] = 0;
1967 DeleteCriticalSection(&This
->lock
);
1968 if (This
->stream
) IStream_Release(This
->stream
);
1975 static HRESULT WINAPI
DdsEncoder_Initialize(IWICBitmapEncoder
*iface
,
1976 IStream
*stream
, WICBitmapEncoderCacheOption cacheOption
)
1978 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1981 TRACE("(%p,%p,%u)\n", iface
, stream
, cacheOption
);
1983 if (cacheOption
!= WICBitmapEncoderNoCache
)
1984 FIXME("Cache option %#x is not supported.\n", cacheOption
);
1986 if (!stream
) return E_INVALIDARG
;
1988 EnterCriticalSection(&This
->lock
);
1992 hr
= WINCODEC_ERR_WRONGSTATE
;
1996 This
->stream
= stream
;
1997 IStream_AddRef(stream
);
1999 This
->info
.width
= 1;
2000 This
->info
.height
= 1;
2001 This
->info
.depth
= 1;
2002 This
->info
.mip_levels
= 1;
2003 This
->info
.array_size
= 1;
2004 This
->info
.frame_count
= 1;
2005 This
->info
.data_offset
= 0;
2006 This
->info
.bytes_per_block
= get_bytes_per_block_from_format(DXGI_FORMAT_BC3_UNORM
);
2007 This
->info
.format
= DXGI_FORMAT_BC3_UNORM
;
2008 This
->info
.dimension
= WICDdsTexture2D
;
2009 This
->info
.alpha_mode
= WICDdsAlphaModeUnknown
;
2010 This
->info
.pixel_format
= &GUID_WICPixelFormatUndefined
;
2011 This
->info
.pixel_format_bpp
= 0;
2016 LeaveCriticalSection(&This
->lock
);
2021 static HRESULT WINAPI
DdsEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
, GUID
*format
)
2023 TRACE("(%p,%p)\n", iface
, format
);
2026 return E_INVALIDARG
;
2028 memcpy(format
, &GUID_ContainerFormatDds
, sizeof(*format
));
2032 static HRESULT WINAPI
DdsEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
, IWICBitmapEncoderInfo
**info
)
2034 IWICComponentInfo
*comp_info
;
2037 TRACE("%p,%p\n", iface
, info
);
2039 if (!info
) return E_INVALIDARG
;
2041 hr
= CreateComponentInfo(&CLSID_WICDdsEncoder
, &comp_info
);
2043 hr
= IWICComponentInfo_QueryInterface(comp_info
, &IID_IWICBitmapEncoderInfo
, (void **)info
);
2044 IWICComponentInfo_Release(comp_info
);
2049 static HRESULT WINAPI
DdsEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
2050 UINT cCount
, IWICColorContext
**ppIColorContext
)
2052 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
2056 static HRESULT WINAPI
DdsEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*palette
)
2058 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
2061 TRACE("(%p,%p)\n", iface
, palette
);
2063 EnterCriticalSection(&This
->lock
);
2065 hr
= This
->stream
? WINCODEC_ERR_UNSUPPORTEDOPERATION
: WINCODEC_ERR_NOTINITIALIZED
;
2067 LeaveCriticalSection(&This
->lock
);
2072 static HRESULT WINAPI
DdsEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
2074 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
2075 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
2078 static HRESULT WINAPI
DdsEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
2080 TRACE("(%p,%p)\n", iface
, pIPreview
);
2081 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
2084 static HRESULT WINAPI
DdsEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
2085 IWICBitmapFrameEncode
**frameEncode
, IPropertyBag2
**encoderOptions
)
2087 DdsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
2089 TRACE("(%p,%p,%p)\n", iface
, frameEncode
, encoderOptions
);
2091 return IWICDdsEncoder_CreateNewFrame(&This
->IWICDdsEncoder_iface
, frameEncode
, NULL
, NULL
, NULL
);
2094 static HRESULT WINAPI
DdsEncoder_Commit(IWICBitmapEncoder
*iface
)
2096 FIXME("(%p): stub\n", iface
);
2100 static HRESULT WINAPI
DdsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
2101 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
2103 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
2107 static const IWICBitmapEncoderVtbl DdsEncoder_Vtbl
= {
2108 DdsEncoder_QueryInterface
,
2111 DdsEncoder_Initialize
,
2112 DdsEncoder_GetContainerFormat
,
2113 DdsEncoder_GetEncoderInfo
,
2114 DdsEncoder_SetColorContexts
,
2115 DdsEncoder_SetPalette
,
2116 DdsEncoder_SetThumbnail
,
2117 DdsEncoder_SetPreview
,
2118 DdsEncoder_CreateNewFrame
,
2120 DdsEncoder_GetMetadataQueryWriter
2123 HRESULT
DdsEncoder_CreateInstance( REFIID iid
, void **ppv
)
2128 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
2132 This
= malloc(sizeof(DdsEncoder
));
2133 if (!This
) return E_OUTOFMEMORY
;
2135 This
->IWICBitmapEncoder_iface
.lpVtbl
= &DdsEncoder_Vtbl
;
2136 This
->IWICDdsEncoder_iface
.lpVtbl
= &DdsEncoder_Dds_Vtbl
;
2138 This
->stream
= NULL
;
2139 This
->frame_count
= 0;
2140 This
->frame_index
= 0;
2141 This
->uncommitted_frame
= FALSE
;
2142 This
->committed
= FALSE
;
2143 InitializeCriticalSection(&This
->lock
);
2144 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DdsEncoder.lock");
2146 ret
= IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
2147 IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);