From bd609f5ed4f12dc6ca07bc64e47a071a48fa5a9e Mon Sep 17 00:00:00 2001 From: Ziqing Hui Date: Wed, 26 May 2021 09:54:04 +0800 Subject: [PATCH] windowscodecs: Implement IWICDdsEncoder_CreateNewFrame. Signed-off-by: Ziqing Hui Signed-off-by: Esme Povirk Signed-off-by: Alexandre Julliard --- dlls/windowscodecs/ddsformat.c | 85 ++++++++++++++++++++++------ dlls/windowscodecs/tests/ddsformat.c | 6 +- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/dlls/windowscodecs/ddsformat.c b/dlls/windowscodecs/ddsformat.c index af062de06f2..790fe72b8c9 100644 --- a/dlls/windowscodecs/ddsformat.c +++ b/dlls/windowscodecs/ddsformat.c @@ -166,6 +166,7 @@ typedef struct DdsEncoder { CRITICAL_SECTION lock; IStream *stream; UINT frame_count; + UINT frame_index; BOOL uncommitted_frame; BOOL committed; dds_info info; @@ -511,6 +512,27 @@ static UINT get_frame_count(UINT depth, UINT mip_levels, UINT array_size, WICDds return frame_count; } +static void get_frame_dds_index(UINT index, dds_info *info, UINT *array_index, UINT *mip_level, UINT *slice_index) +{ + UINT frame_per_texture, depth; + + if (info->dimension == WICDdsTextureCube) + frame_per_texture = info->mip_levels; + else + frame_per_texture = info->frame_count / info->array_size; + + *array_index = index / frame_per_texture; + *slice_index = index % frame_per_texture; + depth = info->depth; + *mip_level = 0; + while (*slice_index >= depth) + { + *slice_index -= depth; + (*mip_level)++; + if (depth > 1) depth /= 2; + } +} + static const GUID *dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format) { UINT i; @@ -1208,7 +1230,7 @@ static HRESULT WINAPI DdsDecoder_GetFrame(IWICBitmapDecoder *iface, UINT index, IWICBitmapFrameDecode **ppIBitmapFrame) { DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); - UINT frame_per_texture, array_index, mip_level, slice_index, depth; + UINT array_index, mip_level, slice_index; TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame); @@ -1221,21 +1243,7 @@ static HRESULT WINAPI DdsDecoder_GetFrame(IWICBitmapDecoder *iface, return WINCODEC_ERR_WRONGSTATE; } - if (This->info.dimension == WICDdsTextureCube) { - frame_per_texture = This->info.mip_levels; - } else { - frame_per_texture = This->info.frame_count / This->info.array_size; - } - array_index = index / frame_per_texture; - slice_index = index % frame_per_texture; - depth = This->info.depth; - mip_level = 0; - while (slice_index >= depth) - { - slice_index -= depth; - mip_level++; - if (depth > 1) depth /= 2; - } + get_frame_dds_index(index, &This->info, &array_index, &mip_level, &slice_index); LeaveCriticalSection(&This->lock); @@ -1819,8 +1827,48 @@ static HRESULT WINAPI DdsEncoder_Dds_CreateNewFrame(IWICDdsEncoder *iface, IWICBitmapFrameEncode **frameEncode, UINT *arrayIndex, UINT *mipLevel, UINT *sliceIndex) { - FIXME("(%p,%p,%p,%p,%p): stub.\n", iface, frameEncode, arrayIndex, mipLevel, sliceIndex); - return E_NOTIMPL; + DdsEncoder *This = impl_from_IWICDdsEncoder(iface); + UINT array_index, mip_level, slice_index; + DdsFrameEncode *result; + HRESULT hr; + + TRACE("(%p,%p,%p,%p,%p)\n", iface, frameEncode, arrayIndex, mipLevel, sliceIndex); + + EnterCriticalSection(&This->lock); + + if (!This->stream || This->committed || This->uncommitted_frame) + { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + result = HeapAlloc(GetProcessHeap(), 0, sizeof(*result)); + if (!result) + { + hr = E_OUTOFMEMORY; + goto end; + } + + get_frame_dds_index(This->frame_index, &This->info, &array_index, &mip_level, &slice_index); + if (arrayIndex) *arrayIndex = array_index; + if (mipLevel) *mipLevel = mip_level; + if (sliceIndex) *sliceIndex = slice_index; + + This->frame_index++; + result->IWICBitmapFrameEncode_iface.lpVtbl = &DdsFrameEncode_Vtbl; + result->ref = 1; + result->parent = This; + result->parent->uncommitted_frame = TRUE; + result->initialized = FALSE; + result->frame_created = FALSE; + IWICDdsEncoder_AddRef(iface); + + *frameEncode = &result->IWICBitmapFrameEncode_iface; + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + return hr; } static const IWICDdsEncoderVtbl DdsEncoder_Dds_Vtbl = @@ -2076,6 +2124,7 @@ HRESULT DdsEncoder_CreateInstance( REFIID iid, void **ppv) This->ref = 1; This->stream = NULL; This->frame_count = 0; + This->frame_index = 0; This->uncommitted_frame = FALSE; This->committed = FALSE; InitializeCriticalSection(&This->lock); diff --git a/dlls/windowscodecs/tests/ddsformat.c b/dlls/windowscodecs/tests/ddsformat.c index ecc5d0ec00d..8900b7699f8 100644 --- a/dlls/windowscodecs/tests/ddsformat.c +++ b/dlls/windowscodecs/tests/ddsformat.c @@ -1446,17 +1446,15 @@ static void test_dds_encoder_create_frame(void) create_and_init_encoder(buffer, sizeof(buffer), &encoder, &dds_encoder, &stream); IWICDdsEncoder_SetParameters(dds_encoder, ¶ms); hr = IWICDdsEncoder_CreateNewFrame(dds_encoder, &frame0, &array_index, &mip_level, &slice_index); - todo_wine ok(hr == S_OK, "CreateNewFrame failed, hr %#x\n", hr); - if (hr == S_OK) IWICBitmapFrameEncode_Release(frame0); + IWICBitmapFrameEncode_Release(frame0); release_encoder(encoder, dds_encoder, stream); create_and_init_encoder(buffer, sizeof(buffer), &encoder, &dds_encoder, &stream); IWICDdsEncoder_SetParameters(dds_encoder, ¶ms); hr = IWICDdsEncoder_CreateNewFrame(dds_encoder, &frame0, NULL, NULL, NULL); - todo_wine ok(hr == S_OK, "CreateNewFrame failed, hr %#x\n", hr); - if (hr == S_OK) IWICBitmapFrameEncode_Release(frame0); + IWICBitmapFrameEncode_Release(frame0); end: release_encoder(encoder, dds_encoder, stream);