diff --git a/dlls/windowscodecs/ddsformat.c b/dlls/windowscodecs/ddsformat.c index bbd30a90d27..527da1d6b35 100644 --- a/dlls/windowscodecs/ddsformat.c +++ b/dlls/windowscodecs/ddsformat.c @@ -104,6 +104,7 @@ typedef struct dds_info { UINT array_size; UINT frame_count; UINT data_offset; + UINT bytes_per_block; BOOL compressed; DXGI_FORMAT format; WICDdsDimension dimension; @@ -209,6 +210,27 @@ static WICDdsAlphaMode get_alpha_mode_from_fourcc(DWORD fourcc) } } +static UINT get_bytes_per_block_from_format(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM_SRGB: + return 8; + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM_SRGB: + return 16; + default: + WARN("DXGI format 0x%x is not supported in DDS decoder\n", format); + return 0; + } +} + static void get_dds_info(dds_info* info, DDS_HEADER *header, DDS_HEADER_DXT10 *header_dxt10) { int i; @@ -231,7 +253,11 @@ static void get_dds_info(dds_info* info, DDS_HEADER *header, DDS_HEADER_DXT10 *h info->alpha_mode = header_dxt10->miscFlags2 & 0x00000008; info->data_offset = sizeof(DWORD) + sizeof(*header) + sizeof(*header_dxt10); } else { - info->format = get_format_from_fourcc(header->ddspf.fourCC); + if (info->compressed) { + info->format = get_format_from_fourcc(header->ddspf.fourCC); + } else { + info->format = DXGI_FORMAT_R8G8B8A8_UNORM; + } info->dimension = get_dimension(header, NULL); info->alpha_mode = get_alpha_mode_from_fourcc(header->ddspf.fourCC); info->data_offset = sizeof(DWORD) + sizeof(*header); @@ -239,7 +265,14 @@ static void get_dds_info(dds_info* info, DDS_HEADER *header, DDS_HEADER_DXT10 *h info->pixel_format = (info->alpha_mode == WICDdsAlphaModePremultiplied) ? &GUID_WICPixelFormat32bppPBGRA : &GUID_WICPixelFormat32bppBGRA; + if (info->compressed) { + info->bytes_per_block = get_bytes_per_block_from_format(info->format); + } else { + info->bytes_per_block = header->ddspf.rgbBitCount / 8; + } + /* get frame count */ + if (info->depth == 1) { info->frame_count = info->array_size * info->mip_levels; } else { @@ -254,27 +287,6 @@ static void get_dds_info(dds_info* info, DDS_HEADER *header, DDS_HEADER_DXT10 *h } } -static UINT get_bytes_per_block(DXGI_FORMAT format) -{ - switch(format) - { - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM_SRGB: - return 8; - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM_SRGB: - return 16; - default: - WARN("DXGI format 0x%x is not supported in DDS decoder\n", format); - return 0; - } -} - static inline DdsDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) { return CONTAINING_RECORD(iface, DdsDecoder, IWICBitmapDecoder_iface); @@ -840,7 +852,7 @@ static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface, DdsDecoder *This = impl_from_IWICDdsDecoder(iface); HRESULT hr; LARGE_INTEGER seek; - UINT width, height, depth, width_in_blocks, height_in_blocks, size; + UINT width, height, depth, block_width, block_height, width_in_blocks, height_in_blocks, size; UINT frame_width = 0, frame_height = 0, frame_width_in_blocks = 0, frame_height_in_blocks = 0, frame_size = 0; UINT bytes_per_block, bytesread, i; DdsFrameDecode *frame_decode = NULL; @@ -860,7 +872,14 @@ static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface, goto end; } - bytes_per_block = get_bytes_per_block(This->info.format); + bytes_per_block = This->info.bytes_per_block; + if (This->info.compressed) { + block_width = DDS_BLOCK_WIDTH; + block_height = DDS_BLOCK_HEIGHT; + } else { + block_width = 1; + block_height = 1; + } seek.QuadPart = This->info.data_offset; width = This->info.width; @@ -868,8 +887,8 @@ static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface, depth = This->info.depth; for (i = 0; i < This->info.mip_levels; i++) { - width_in_blocks = (width + DDS_BLOCK_WIDTH - 1) / DDS_BLOCK_WIDTH; - height_in_blocks = (height + DDS_BLOCK_HEIGHT - 1) / DDS_BLOCK_HEIGHT; + width_in_blocks = (width + block_width - 1) / block_width; + height_in_blocks = (height + block_height - 1) / block_height; size = width_in_blocks * height_in_blocks * bytes_per_block; if (i < mipLevel) { @@ -896,8 +915,8 @@ static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface, frame_decode->info.height = frame_height; frame_decode->info.format = This->info.format; frame_decode->info.bytes_per_block = bytes_per_block; - frame_decode->info.block_width = DDS_BLOCK_WIDTH; - frame_decode->info.block_height = DDS_BLOCK_HEIGHT; + frame_decode->info.block_width = block_width; + frame_decode->info.block_height = block_height; frame_decode->info.width_in_blocks = frame_width_in_blocks; frame_decode->info.height_in_blocks = frame_height_in_blocks; frame_decode->info.pixel_format = This->info.pixel_format; diff --git a/dlls/windowscodecs/tests/ddsformat.c b/dlls/windowscodecs/tests/ddsformat.c index 61dcbd6d9ce..4f53242d95a 100644 --- a/dlls/windowscodecs/tests/ddsformat.c +++ b/dlls/windowscodecs/tests/ddsformat.c @@ -431,7 +431,6 @@ static void test_dds_decoder_image_parameters(void) "Test %u: Expected MipLevels %u, got %u\n", i, test_data[i].expected_parameters.MipLevels, parameters.MipLevels); ok(parameters.ArraySize == test_data[i].expected_parameters.ArraySize, "Test %u: Expected ArraySize %u, got %u\n", i, test_data[i].expected_parameters.ArraySize, parameters.ArraySize); - todo_wine_if(test_data[i].expected_parameters.DxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) ok(parameters.DxgiFormat == test_data[i].expected_parameters.DxgiFormat, "Test %u: Expected DxgiFormat %#x, got %#x\n", i, test_data[i].expected_parameters.DxgiFormat, parameters.DxgiFormat); ok(parameters.Dimension == test_data[i].expected_parameters.Dimension, @@ -502,7 +501,6 @@ static void test_dds_decoder_frame_properties(IWICBitmapFrameDecode *frame_decod ok(hr == S_OK, "Test %u, frame %u: GetFormatInfo failed, hr %#x\n", i, frame_index, hr); if (hr != S_OK) return; - todo_wine_if(test_data[i].expected_parameters.DxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) { ok(format_info.DxgiFormat == test_data[i].expected_parameters.DxgiFormat, "Test %u, frame %u: Expected DXGI format %#x, got %#x\n", i, frame_index, test_data[i].expected_parameters.DxgiFormat, format_info.DxgiFormat); @@ -515,7 +513,6 @@ static void test_dds_decoder_frame_properties(IWICBitmapFrameDecode *frame_decod ok(format_info.BlockHeight == expected_block_height, "Test %u, frame %u: Expected block height %u, got %u\n", i, frame_index, expected_block_height, format_info.BlockHeight); - } /* size in blocks tests */ @@ -531,12 +528,10 @@ static void test_dds_decoder_frame_properties(IWICBitmapFrameDecode *frame_decod expected_width_in_blocks = (expected_width + expected_block_width - 1) / expected_block_width; expected_height_in_blocks = (expected_height + expected_block_height - 1) / expected_block_height; - todo_wine_if(test_data[i].expected_parameters.DxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) { ok(width_in_blocks == expected_width_in_blocks, "Test %u, frame %u: Expected width in blocks %u, got %u\n", i, frame_index, expected_width_in_blocks, width_in_blocks); ok(height_in_blocks == expected_height_in_blocks, "Test %u, frame %u: Expected height in blocks %u, got %u\n", i, frame_index, expected_height_in_blocks, height_in_blocks); - } /* pixel format tests */ @@ -586,20 +581,17 @@ static void test_dds_decoder_frame_data(IWICDdsFrameDecode *dds_frame, UINT fram ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride - 1, sizeof(buffer), buffer); - todo_wine_if(test_data[i].expected_parameters.DxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride * 2, sizeof(buffer), buffer); ok(hr == S_OK, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride, sizeof(buffer), buffer); ok(hr == S_OK, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride, frame_stride * height_in_blocks - 1, buffer); - todo_wine_if(test_data[i].expected_parameters.DxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride, frame_stride * height_in_blocks, buffer); ok(hr == S_OK, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, 0, sizeof(buffer), buffer); - todo_wine_if(test_data[i].expected_parameters.DxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride - 1, sizeof(buffer), buffer); ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); @@ -607,13 +599,11 @@ static void test_dds_decoder_frame_data(IWICDdsFrameDecode *dds_frame, UINT fram ok(hr == S_OK, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, 0, buffer); - todo_wine_if(test_data[i].expected_parameters.DxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) { ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, 1, buffer); ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, stride * rect.Height - 1, buffer); ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); - } hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, stride * rect.Height, buffer); ok(hr == S_OK, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr);