From: Ziqing Hui Subject: [PATCH 2/3] d3dx10: Handle format converting for D3DX10CreateTextureFromMemory. Message-Id: <04afa552-7b66-7dfd-41ee-2924651fc380@codeweavers.com> Date: Fri, 18 Jun 2021 14:29:42 +0800 Signed-off-by: Ziqing Hui --- dlls/d3dx10_43/tests/d3dx10.c | 3 +- dlls/d3dx10_43/texture.c | 89 ++++++++++++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 211b0fce5ba..184a061ff0e 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -1147,7 +1147,6 @@ static void check_resource_data(ID3D10Resource *resource, const struct test_imag { line_match = !memcmp(image->expected_data + stride * i, (BYTE *)map.pData + map.RowPitch * i, stride); - todo_wine ok_(__FILE__, line)(line_match, "Data mismatch for line %u.\n", i); if (!line_match) break; @@ -1987,7 +1986,7 @@ static void test_create_texture(void) winetest_push_context("Test %u", i); hr = D3DX10CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, NULL, NULL, &resource, NULL); - todo_wine_if(test_image[i].expected_info.Format != DXGI_FORMAT_R8G8B8A8_UNORM) + todo_wine_if(is_block_compressed(test_image[i].expected_info.Format)) ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); if (hr == S_OK) { diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index be5461d5421..84164bf54a5 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -45,6 +45,32 @@ file_formats[] = { &GUID_ContainerFormatWmp, D3DX10_IFF_WMP }, }; +static const struct +{ + const GUID *wic_guid; + DXGI_FORMAT dxgi_format; +} +wic_pixel_formats[] = +{ + { &GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM }, + { &GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM }, + { &GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM }, + { &GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM }, + { &GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT }, + { &GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT }, + { &GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM }, + { &GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM }, + { &GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, + { &GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, + { &GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM }, + { &GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM }, + { &GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, + { &GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM }, + { &GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT }, + { &GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT }, + { &GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT } +}; + static const DXGI_FORMAT to_be_converted_format[] = { DXGI_FORMAT_UNKNOWN, @@ -69,6 +95,19 @@ static D3DX10_IMAGE_FILE_FORMAT wic_container_guid_to_file_format(GUID *containe return D3DX10_IFF_FORCE_DWORD; } +static const GUID *dxgi_format_to_wic_guid(DXGI_FORMAT format) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); ++i) + { + if (wic_pixel_formats[i].dxgi_format == format) + return wic_pixel_formats[i].wic_guid; + } + + return NULL; +} + static D3D10_RESOURCE_DIMENSION wic_dimension_to_d3dx10_dimension(WICDdsDimension wic_dimension) { switch (wic_dimension) @@ -516,14 +555,17 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s D3DX10_IMAGE_LOAD_INFO *load_info, ID3DX10ThreadPump *pump, ID3D10Resource **texture, HRESULT *hresult) { unsigned int frame_count, width, height, stride, frame_size; + IWICFormatConverter *converter = NULL; D3D10_TEXTURE2D_DESC texture_2d_desc; IWICBitmapFrameDecode *frame = NULL; IWICImagingFactory *factory = NULL; IWICBitmapDecoder *decoder = NULL; + GUID src_format, *dst_format; ID3D10Texture2D *texture_2d; D3DX10_IMAGE_INFO img_info; IWICStream *stream = NULL; BYTE *buffer = NULL; + BOOL can_convert; HRESULT hr; TRACE("device %p, src_data %p, src_data_size %lu, load_info %p, pump %p, texture %p, hresult %p.\n", @@ -539,11 +581,6 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s hr = D3DX10GetImageInfoFromMemory(src_data, src_data_size, NULL, &img_info, NULL); if (FAILED(hr)) return E_FAIL; - if (img_info.Format != DXGI_FORMAT_R8G8B8A8_UNORM) - { - FIXME("Unsupported format %#x.\n", img_info.Format); - return E_FAIL; - } WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); IWICImagingFactory_CreateStream(factory, &stream); @@ -557,6 +594,9 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s if (FAILED(hr) || !frame_count) goto end; hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); + if (FAILED(hr)) + goto end; + hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &src_format); if (FAILED(hr)) goto end; @@ -572,9 +612,42 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s goto end; } - hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer); - if (FAILED(hr)) + dst_format = (GUID *)dxgi_format_to_wic_guid(img_info.Format); + if (!dst_format) + { + FIXME("Unsupported DXGI format %#x.\n", img_info.Format); + hr = E_FAIL; goto end; + } + if (IsEqualGUID(&src_format, dst_format)) + { + hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer); + if (FAILED(hr)) + goto end; + } + else + { + hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); + if (FAILED(hr)) + goto end; + hr = IWICFormatConverter_CanConvert(converter, &src_format, dst_format, &can_convert); + if (FAILED(hr)) + goto end; + if (!can_convert) + { + WARN("Format converting %s to %s is not supported by WIC.\n", + debugstr_guid(&src_format), debugstr_guid(dst_format)); + hr = E_FAIL; + goto end; + } + hr = IWICFormatConverter_Initialize(converter, (IWICBitmapSource *)frame, dst_format, + WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) + goto end; + hr = IWICFormatConverter_CopyPixels(converter, NULL, stride, frame_size, buffer); + if (FAILED(hr)) + goto end; + } memset(&texture_2d_desc, 0, sizeof(texture_2d_desc)); texture_2d_desc.Width = width; @@ -595,6 +668,8 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s *texture = (ID3D10Resource *)texture_2d; end: + if (converter) + IWICFormatConverter_Release(converter); if (buffer) heap_free(buffer); if (frame)