diff --git a/dlls/windowscodecs/ddsformat.c b/dlls/windowscodecs/ddsformat.c index 04914ead3a4..19d5dd5a3f0 100644 --- a/dlls/windowscodecs/ddsformat.c +++ b/dlls/windowscodecs/ddsformat.c @@ -94,6 +94,12 @@ typedef struct DdsDecoder { DDS_HEADER_DXT10 header_dxt10; } DdsDecoder; +static inline BOOL has_extended_header(DDS_HEADER *header) +{ + return (header->ddspf.flags & DDPF_FOURCC) && + (header->ddspf.fourCC == MAKEFOURCC('D', 'X', '1', '0')); +} + static inline DdsDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) { return CONTAINING_RECORD(iface, DdsDecoder, IWICBitmapDecoder_iface); @@ -202,8 +208,7 @@ static HRESULT WINAPI DdsDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p goto end; } - if (This->header.ddspf.flags & DDPF_FOURCC && - This->header.ddspf.fourCC == MAKEFOURCC('D', 'X', '1', '0')) { + if (has_extended_header(&This->header)) { hr = IStream_Read(pIStream, &This->header_dxt10, sizeof(This->header_dxt10), &bytesread); if (FAILED(hr)) goto end; if (bytesread != sizeof(This->header_dxt10)) { @@ -285,9 +290,36 @@ static HRESULT WINAPI DdsDecoder_GetThumbnail(IWICBitmapDecoder *iface, static HRESULT WINAPI DdsDecoder_GetFrameCount(IWICBitmapDecoder *iface, UINT *pCount) { - FIXME("(%p) <-- %d: stub.\n", iface, *pCount); + DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); + UINT arraySize = 1, mipMapCount = 1, depth = 1; + int i; - return E_NOTIMPL; + if (!pCount) return E_INVALIDARG; + if (!This->initialized) return WINCODEC_ERR_WRONGSTATE; + + EnterCriticalSection(&This->lock); + + if (This->header.mipMapCount) mipMapCount = This->header.mipMapCount; + if (This->header.depth) depth = This->header.depth; + if (has_extended_header(&This->header) && This->header_dxt10.arraySize) arraySize = This->header_dxt10.arraySize; + + if (depth == 1) { + *pCount = arraySize * mipMapCount; + } else { + *pCount = 0; + for (i = 0; i < mipMapCount; i++) + { + *pCount += depth; + if (depth > 1) depth /= 2; + } + *pCount *= arraySize; + } + + LeaveCriticalSection(&This->lock); + + TRACE("(%p) <-- %d\n", iface, *pCount); + + return S_OK; } static HRESULT WINAPI DdsDecoder_GetFrame(IWICBitmapDecoder *iface, diff --git a/dlls/windowscodecs/tests/ddsformat.c b/dlls/windowscodecs/tests/ddsformat.c index 99f19eb1751..e548ee9655b 100644 --- a/dlls/windowscodecs/tests/ddsformat.c +++ b/dlls/windowscodecs/tests/ddsformat.c @@ -304,17 +304,22 @@ static void test_dds_decoder_frame_count(void) decoder = create_decoder(); if (!decoder) goto next; + hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); + ok (hr == WINCODEC_ERR_WRONGSTATE, "%d: Expected hr=WINCODEC_ERR_WRONGSTATE, got %x\n", i, hr); + hr = IWICBitmapDecoder_GetFrameCount(decoder, NULL); + ok (hr == E_INVALIDARG, "%d: Expected hr=E_INVALIDARG, got %x\n", i, hr); + hr = init_decoder(decoder, stream, S_OK, -1); if (hr != S_OK) goto next; - todo_wine { hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); - ok (hr == S_OK, "GetFrameCount failed, hr=%x\n", hr); + ok (hr == S_OK, "%d: GetFrameCount failed, hr=%x\n", i, hr); if (hr == S_OK) { ok (frame_count == test_data[i].expected, "%d: expected frame count %d, got %d\n", i, test_data[i].expected, frame_count); } - }; + hr = IWICBitmapDecoder_GetFrameCount(decoder, NULL); + ok (hr == E_INVALIDARG, "%d: Expected hr=S_OK, got %x\n", i, hr); next: if (decoder) IWICBitmapDecoder_Release(decoder);