From: Connor McAdams cmcadams@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50210 Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx11_43/Makefile.in | 5 +- dlls/d3dx11_43/d3dx11_43_main.c | 9 -- dlls/d3dx11_43/dxhelpers.h | 21 +++ dlls/d3dx11_43/tests/d3dx11.c | 21 +-- dlls/d3dx11_43/texture.c | 243 ++++++++++++++++++++++++++++++++ 5 files changed, 275 insertions(+), 24 deletions(-) create mode 100644 dlls/d3dx11_43/dxhelpers.h
diff --git a/dlls/d3dx11_43/Makefile.in b/dlls/d3dx11_43/Makefile.in index a44fafb1541..1491bd23fb4 100644 --- a/dlls/d3dx11_43/Makefile.in +++ b/dlls/d3dx11_43/Makefile.in @@ -1,12 +1,15 @@ EXTRADEFS = -DD3DX11_SDK_VERSION=43 MODULE = d3dx11_43.dll IMPORTLIB = d3dx11 -IMPORTS = d3dcompiler +IMPORTS = d3dcompiler gdi32 ole32 user32 +PARENTSRC = ../d3dx9_36 +DELAYIMPORTS = windowscodecs
EXTRADLLFLAGS = -Wb,--prefer-native
SOURCES = \ async.c \ + d3dx_helpers.c \ d3dx11_43_main.c \ texture.c \ version.rc diff --git a/dlls/d3dx11_43/d3dx11_43_main.c b/dlls/d3dx11_43/d3dx11_43_main.c index 5dad027864f..00c1db35e42 100644 --- a/dlls/d3dx11_43/d3dx11_43_main.c +++ b/dlls/d3dx11_43/d3dx11_43_main.c @@ -66,12 +66,3 @@ HRESULT WINAPI D3DX11GetImageInfoFromFileW(const WCHAR *filename, ID3DX11ThreadP
return E_NOTIMPL; } - -HRESULT WINAPI D3DX11GetImageInfoFromMemory(const void *src_data, SIZE_T src_data_size, ID3DX11ThreadPump *pump, - D3DX11_IMAGE_INFO *img_info, HRESULT *hresult) -{ - FIXME("src_data %p, src_data_size %Iu, pump %p, img_info %p, hresult %p stub!\n", - src_data, src_data_size, pump, img_info, hresult); - - return E_NOTIMPL; -} diff --git a/dlls/d3dx11_43/dxhelpers.h b/dlls/d3dx11_43/dxhelpers.h new file mode 100644 index 00000000000..5be2ac93944 --- /dev/null +++ b/dlls/d3dx11_43/dxhelpers.h @@ -0,0 +1,21 @@ +/* + * Copyright 2025 Connor McAdams for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "d3dx_helpers.h" + +HRESULT get_image_info(const void *data, SIZE_T size, D3DX11_IMAGE_INFO *img_info); diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c index ac310d2a947..5e2d28824c3 100644 --- a/dlls/d3dx11_43/tests/d3dx11.c +++ b/dlls/d3dx11_43/tests/d3dx11.c @@ -1313,7 +1313,7 @@ static void test_D3DX11GetImageInfoFromMemory(void) ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
hr = D3DX11GetImageInfoFromMemory(bmp_1bpp, sizeof(bmp_1bpp) - 1, NULL, &info, NULL); - ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
hr = D3DX11GetImageInfoFromMemory(bmp_1bpp + 1, sizeof(bmp_1bpp) - 1, NULL, &info, NULL); ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); @@ -1503,9 +1503,9 @@ static void test_D3DX11GetImageInfoFromMemory(void) check_dds_dxt10_format(DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM, FALSE); check_dds_dxt10_format(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, FALSE); /* Formats unsupported on d3dx10, but now supported on d3dx11. */ - check_dds_dxt10_format(DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_UF16, FALSE); - check_dds_dxt10_format(DXGI_FORMAT_BC6H_SF16, DXGI_FORMAT_BC6H_SF16, FALSE); - check_dds_dxt10_format(DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM, FALSE); + todo_wine check_dds_dxt10_format(DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_UF16, FALSE); + todo_wine check_dds_dxt10_format(DXGI_FORMAT_BC6H_SF16, DXGI_FORMAT_BC6H_SF16, FALSE); + todo_wine check_dds_dxt10_format(DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM, FALSE); }
START_TEST(d3dx11) @@ -1514,14 +1514,7 @@ START_TEST(d3dx11) test_D3DX11CreateAsyncFileLoader(); test_D3DX11CreateAsyncResourceLoader(); test_D3DX11CompileFromFile(); - if (!strcmp(winetest_platform, "wine")) - { - skip("Skipping D3DX11GetImageInfoFromMemory() tests.\n"); - } - else - { - test_D3DX11GetImageInfoFromMemory(); - test_legacy_dds_header_image_info(); - test_dxt10_dds_header_image_info(); - } + test_D3DX11GetImageInfoFromMemory(); + test_legacy_dds_header_image_info(); + test_dxt10_dds_header_image_info(); } diff --git a/dlls/d3dx11_43/texture.c b/dlls/d3dx11_43/texture.c index fe7ab8549d0..cbf3b630f58 100644 --- a/dlls/d3dx11_43/texture.c +++ b/dlls/d3dx11_43/texture.c @@ -18,11 +18,235 @@
#include "d3dx11.h" #include "d3dcompiler.h" +#include "dxhelpers.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+/* + * These are mappings from legacy DDS header formats to DXGI formats. Some + * don't map to a DXGI_FORMAT at all, and some only map to the default format. + */ +static DXGI_FORMAT dxgi_format_from_legacy_dds_d3dx_pixel_format_id(enum d3dx_pixel_format_id format) +{ + switch (format) + { + /* + * Some of these formats do have DXGI_FORMAT equivalents, but get + * mapped to DXGI_FORMAT_R8G8B8A8_UNORM instead. + */ + case D3DX_PIXEL_FORMAT_P8_UINT: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_P8_UINT_A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_R8G8B8X8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B8G8R8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B5G6R5_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B5G5R5X1_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B5G5R5A1_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B2G3R3_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B2G3R3A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B4G4R4A4_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B4G4R4X4_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_L8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_L4A4_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_L8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + + /* B10G10R10A2 doesn't exist in DXGI, both map to R10G10B10A2. */ + case D3DX_PIXEL_FORMAT_B10G10R10A2_UNORM: + case D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM: return DXGI_FORMAT_R10G10B10A2_UNORM; + + case D3DX_PIXEL_FORMAT_U16V16W16Q16_SNORM: return DXGI_FORMAT_R16G16B16A16_SNORM; + case D3DX_PIXEL_FORMAT_L16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; + case D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; + case D3DX_PIXEL_FORMAT_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; + case D3DX_PIXEL_FORMAT_A8_UNORM: return DXGI_FORMAT_A8_UNORM; + case D3DX_PIXEL_FORMAT_R16_FLOAT: return DXGI_FORMAT_R16_FLOAT; + case D3DX_PIXEL_FORMAT_R16G16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT; + case D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; + case D3DX_PIXEL_FORMAT_R32_FLOAT: return DXGI_FORMAT_R32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32_FLOAT: return DXGI_FORMAT_R32G32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM: return DXGI_FORMAT_G8R8_G8B8_UNORM; + case D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM: return DXGI_FORMAT_R8G8_B8G8_UNORM; + + case D3DX_PIXEL_FORMAT_DXT1_UNORM: return DXGI_FORMAT_BC1_UNORM; + case D3DX_PIXEL_FORMAT_DXT2_UNORM: return DXGI_FORMAT_BC2_UNORM; + case D3DX_PIXEL_FORMAT_DXT3_UNORM: return DXGI_FORMAT_BC2_UNORM; + case D3DX_PIXEL_FORMAT_DXT4_UNORM: return DXGI_FORMAT_BC3_UNORM; + case D3DX_PIXEL_FORMAT_DXT5_UNORM: return DXGI_FORMAT_BC3_UNORM; + case D3DX_PIXEL_FORMAT_BC4_UNORM: return DXGI_FORMAT_BC4_UNORM; + case D3DX_PIXEL_FORMAT_BC4_SNORM: return DXGI_FORMAT_BC4_SNORM; + case D3DX_PIXEL_FORMAT_BC5_UNORM: return DXGI_FORMAT_BC5_UNORM; + case D3DX_PIXEL_FORMAT_BC5_SNORM: return DXGI_FORMAT_BC5_SNORM; + + /* These formats are known and explicitly unsupported on d3dx10+. */ + case D3DX_PIXEL_FORMAT_U8V8W8Q8_SNORM: + case D3DX_PIXEL_FORMAT_U8V8_SNORM: + case D3DX_PIXEL_FORMAT_U16V16_SNORM: + case D3DX_PIXEL_FORMAT_U8V8_SNORM_L8X8_UNORM: + case D3DX_PIXEL_FORMAT_U10V10W10_SNORM_A2_UNORM: + case D3DX_PIXEL_FORMAT_UYVY: + case D3DX_PIXEL_FORMAT_YUY2: + return DXGI_FORMAT_UNKNOWN; + + default: + FIXME("Unknown d3dx_pixel_format_id %#x.\n", format); + return DXGI_FORMAT_UNKNOWN; + } +} + +static DXGI_FORMAT dxgi_format_from_d3dx_pixel_format_id(enum d3dx_pixel_format_id format) +{ + switch (format) + { + case D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; + case D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM: return DXGI_FORMAT_B8G8R8X8_UNORM; + case D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM: return DXGI_FORMAT_R10G10B10A2_UNORM; + case D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; + case D3DX_PIXEL_FORMAT_R8_UNORM: return DXGI_FORMAT_R8_UNORM; + case D3DX_PIXEL_FORMAT_R8G8_UNORM: return DXGI_FORMAT_R8G8_UNORM; + case D3DX_PIXEL_FORMAT_R16_UNORM: return DXGI_FORMAT_R16_UNORM; + case D3DX_PIXEL_FORMAT_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; + case D3DX_PIXEL_FORMAT_A8_UNORM: return DXGI_FORMAT_A8_UNORM; + case D3DX_PIXEL_FORMAT_R16_FLOAT: return DXGI_FORMAT_R16_FLOAT; + case D3DX_PIXEL_FORMAT_R16G16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT; + case D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; + case D3DX_PIXEL_FORMAT_R32_FLOAT: return DXGI_FORMAT_R32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32_FLOAT: return DXGI_FORMAT_R32G32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32B32_FLOAT: return DXGI_FORMAT_R32G32B32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM: return DXGI_FORMAT_G8R8_G8B8_UNORM; + case D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM: return DXGI_FORMAT_R8G8_B8G8_UNORM; + case D3DX_PIXEL_FORMAT_BC1_UNORM: return DXGI_FORMAT_BC1_UNORM; + case D3DX_PIXEL_FORMAT_BC2_UNORM: return DXGI_FORMAT_BC2_UNORM; + case D3DX_PIXEL_FORMAT_BC3_UNORM: return DXGI_FORMAT_BC3_UNORM; + case D3DX_PIXEL_FORMAT_BC4_UNORM: return DXGI_FORMAT_BC4_UNORM; + case D3DX_PIXEL_FORMAT_BC4_SNORM: return DXGI_FORMAT_BC4_SNORM; + case D3DX_PIXEL_FORMAT_BC5_UNORM: return DXGI_FORMAT_BC5_UNORM; + case D3DX_PIXEL_FORMAT_BC5_SNORM: return DXGI_FORMAT_BC5_SNORM; + case D3DX_PIXEL_FORMAT_R16G16B16A16_SNORM: return DXGI_FORMAT_R16G16B16A16_SNORM; + case D3DX_PIXEL_FORMAT_R8G8B8A8_SNORM: return DXGI_FORMAT_R8G8B8A8_SNORM; + case D3DX_PIXEL_FORMAT_R8G8_SNORM: return DXGI_FORMAT_R8G8_SNORM; + case D3DX_PIXEL_FORMAT_R16G16_SNORM: return DXGI_FORMAT_R16G16_SNORM; + + /* + * These have DXGI_FORMAT equivalents, but are explicitly unsupported on + * d3dx10+. + */ + case D3DX_PIXEL_FORMAT_B5G6R5_UNORM: + case D3DX_PIXEL_FORMAT_B5G5R5A1_UNORM: + case D3DX_PIXEL_FORMAT_B4G4R4A4_UNORM: + return DXGI_FORMAT_UNKNOWN; + + default: + FIXME("Unhandled d3dx_pixel_format_id %#x.\n", format); + return DXGI_FORMAT_UNKNOWN; + } +} + +static D3DX11_IMAGE_FILE_FORMAT d3dx11_image_file_format_from_d3dx_image_file_format(enum d3dx_image_file_format iff) +{ + switch (iff) + { + case D3DX_IMAGE_FILE_FORMAT_BMP: return D3DX11_IFF_BMP; + case D3DX_IMAGE_FILE_FORMAT_JPG: return D3DX11_IFF_JPG; + case D3DX_IMAGE_FILE_FORMAT_PNG: return D3DX11_IFF_PNG; + case D3DX_IMAGE_FILE_FORMAT_DDS: return D3DX11_IFF_DDS; + case D3DX_IMAGE_FILE_FORMAT_TIFF: return D3DX11_IFF_TIFF; + case D3DX_IMAGE_FILE_FORMAT_GIF: return D3DX11_IFF_GIF; + case D3DX_IMAGE_FILE_FORMAT_WMP: return D3DX11_IFF_WMP; + case D3DX_IMAGE_FILE_FORMAT_DDS_DXT10: return D3DX11_IFF_DDS; + default: + FIXME("No D3DX11_IMAGE_FILE_FORMAT for d3dx_image_file_format %d.\n", iff); + return D3DX11_IFF_FORCE_DWORD; + } +} + +static HRESULT d3dx11_image_info_from_d3dx_image(D3DX11_IMAGE_INFO *info, struct d3dx_image *image) +{ + D3DX11_IMAGE_FILE_FORMAT iff = d3dx11_image_file_format_from_d3dx_image_file_format(image->image_file_format); + DXGI_FORMAT format; + + memset(info, 0, sizeof(*info)); + switch (image->image_file_format) + { + case D3DX_IMAGE_FILE_FORMAT_DDS_DXT10: + format = dxgi_format_from_d3dx_pixel_format_id(image->format); + break; + + case D3DX_IMAGE_FILE_FORMAT_DDS: + format = dxgi_format_from_legacy_dds_d3dx_pixel_format_id(image->format); + break; + + default: + if (iff == D3DX11_IFF_FORCE_DWORD) + return E_FAIL; + + /* All other image file formats use the default format. */ + format = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + } + + if (format == DXGI_FORMAT_UNKNOWN) + { + WARN("Tried to load file with unsupported pixel format %#x.\n", image->format); + return E_FAIL; + } + + switch (image->resource_type) + { + case D3DX_RESOURCE_TYPE_TEXTURE_2D: + info->ResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D; + break; + + case D3DX_RESOURCE_TYPE_CUBE_TEXTURE: + info->ResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D; + info->MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; + break; + + case D3DX_RESOURCE_TYPE_TEXTURE_3D: + info->ResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE3D; + break; + + default: + ERR("Unhandled resource type %d.\n", image->resource_type); + return E_FAIL; + } + + info->ImageFileFormat = iff; + info->Width = image->size.width; + info->Height = image->size.height; + info->Depth = image->size.depth; + info->ArraySize = image->layer_count; + info->MipLevels = image->mip_levels; + info->Format = format; + return S_OK; +} + +HRESULT get_image_info(const void *data, SIZE_T size, D3DX11_IMAGE_INFO *img_info) +{ + struct d3dx_image image; + HRESULT hr; + + if (!data || !size) + return E_FAIL; + + hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10); + if (SUCCEEDED(hr)) + hr = d3dx11_image_info_from_d3dx_image(img_info, &image); + + if (hr != S_OK) + { + WARN("Invalid or unsupported image file.\n"); + return E_FAIL; + } + return S_OK; +} + HRESULT WINAPI D3DX11CreateShaderResourceViewFromMemory(ID3D11Device *device, const void *data, SIZE_T data_size, D3DX11_IMAGE_LOAD_INFO *load_info, ID3DX11ThreadPump *pump, ID3D11ShaderResourceView **view, HRESULT *hresult) @@ -98,3 +322,22 @@ HRESULT WINAPI D3DX11LoadTextureFromTexture(ID3D11DeviceContext *context, ID3D11
return E_NOTIMPL; } + +HRESULT WINAPI D3DX11GetImageInfoFromMemory(const void *src_data, SIZE_T src_data_size, ID3DX11ThreadPump *pump, + D3DX11_IMAGE_INFO *img_info, HRESULT *hresult) +{ + HRESULT hr; + + TRACE("src_data %p, src_data_size %Iu, pump %p, img_info %p, hresult %p.\n", src_data, src_data_size, pump, + img_info, hresult); + + if (!src_data) + return E_FAIL; + if (pump) + FIXME("D3DX11 thread pump is currently unimplemented.\n"); + + hr = get_image_info(src_data, src_data_size, img_info); + if (hresult) + *hresult = hr; + return hr; +}