Ziqing Hui : d3dx10: Handle format conversion in D3DX10CreateTextureFromMemory().

Alexandre Julliard julliard at winehq.org
Thu Jul 1 15:53:51 CDT 2021


Module: wine
Branch: master
Commit: ce0e61dbe839bd80ddc2b9d472cce25b05a9618a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ce0e61dbe839bd80ddc2b9d472cce25b05a9618a

Author: Ziqing Hui <zhui at codeweavers.com>
Date:   Thu Jul  1 14:08:49 2021 +0800

d3dx10: Handle format conversion in D3DX10CreateTextureFromMemory().

Signed-off-by: Ziqing Hui <zhui at codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3dx10_43/tests/d3dx10.c |  3 +-
 dlls/d3dx10_43/texture.c      | 83 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c
index 251613d246f..d5d1f02441c 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;
@@ -1998,7 +1997,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 8655048fa5f..8765f312f4c 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,6 +555,7 @@ 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;
     D3D10_SUBRESOURCE_DATA resource_data;
     IWICBitmapFrameDecode *frame = NULL;
@@ -524,7 +564,10 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
     ID3D10Texture2D *texture_2d;
     D3DX10_IMAGE_INFO img_info;
     IWICStream *stream = NULL;
+    const GUID *dst_format;
     BYTE *buffer = NULL;
+    BOOL can_convert;
+    GUID src_format;
     HRESULT hr;
 
     TRACE("device %p, src_data %p, src_data_size %lu, load_info %p, pump %p, texture %p, hresult %p.\n",
@@ -539,11 +582,6 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
 
     if (FAILED(D3DX10GetImageInfoFromMemory(src_data, src_data_size, NULL, &img_info, NULL)))
         return E_FAIL;
-    if (img_info.Format != DXGI_FORMAT_R8G8B8A8_UNORM)
-    {
-        FIXME("Unsupported format %#x.\n", img_info.Format);
-        return E_FAIL;
-    }
 
     if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory)))
         goto end;
@@ -557,6 +595,8 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
         goto end;
     if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame)))
         goto end;
+    if (FAILED(hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &src_format)))
+        goto end;
 
     width = img_info.Width;
     height = img_info.Height;
@@ -568,8 +608,37 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
         hr = E_FAIL;
         goto end;
     }
-    if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer)))
+
+    if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format)))
+    {
+        hr = E_FAIL;
+        FIXME("Unsupported DXGI format %#x.\n", img_info.Format);
         goto end;
+    }
+
+    if (IsEqualGUID(&src_format, dst_format))
+    {
+        if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer)))
+            goto end;
+    }
+    else
+    {
+        if (FAILED(hr = IWICImagingFactory_CreateFormatConverter(factory, &converter)))
+            goto end;
+        if (FAILED(hr = IWICFormatConverter_CanConvert(converter, &src_format, dst_format, &can_convert)))
+            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));
+            goto end;
+        }
+        if (FAILED(hr = IWICFormatConverter_Initialize(converter, (IWICBitmapSource *)frame, dst_format,
+                WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom)))
+            goto end;
+        if (FAILED(hr = IWICFormatConverter_CopyPixels(converter, NULL, stride, frame_size, buffer)))
+            goto end;
+    }
 
     memset(&texture_2d_desc, 0, sizeof(texture_2d_desc));
     texture_2d_desc.Width = width;
@@ -593,6 +662,8 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s
     hr = S_OK;
 
 end:
+    if (converter)
+        IWICFormatConverter_Release(converter);
     if (buffer)
         heap_free(buffer);
     if (frame)




More information about the wine-cvs mailing list