diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0001-d3dx11_42-Implement-D3DX11CreateTextureFromMemory.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0001-d3dx11_42-Implement-D3DX11CreateTextureFromMemory.patch deleted file mode 100644 index 1ff62340..00000000 --- a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0001-d3dx11_42-Implement-D3DX11CreateTextureFromMemory.patch +++ /dev/null @@ -1,406 +0,0 @@ -From 18e01f69f4a3ad85253bb73dcd3ff197074c8810 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 3 Aug 2021 11:13:18 +1000 -Subject: [PATCH] d3dx11_42: Implement D3DX11CreateTextureFromMemory - -Signed-off-by: Alistair Leslie-Hughes ---- - dlls/d3dx11_43/texture.c | 365 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 359 insertions(+), 6 deletions(-) - -diff --git a/dlls/d3dx11_43/texture.c b/dlls/d3dx11_43/texture.c -index cbf3b630f58..0bc5ef9ab03 100644 ---- a/dlls/d3dx11_43/texture.c -+++ b/dlls/d3dx11_43/texture.c -@@ -15,12 +15,15 @@ - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ -+#define COBJMACROS - - #include "d3dx11.h" - #include "d3dcompiler.h" - #include "dxhelpers.h" - -+#include "wincodec.h" - #include "wine/debug.h" -+#include "wine/heap.h" - - WINE_DEFAULT_DEBUG_CHANNEL(d3dx); - -@@ -277,16 +280,366 @@ HRESULT WINAPI D3DX11CreateTextureFromFileW(ID3D11Device *device, const WCHAR *f - return E_NOTIMPL; - } - --HRESULT WINAPI D3DX11CreateTextureFromMemory(ID3D11Device *device, const void *data, -- SIZE_T data_size, D3DX11_IMAGE_LOAD_INFO *load_info, ID3DX11ThreadPump *pump, -- ID3D11Resource **texture, HRESULT *hresult) -+static const DXGI_FORMAT block_compressed_formats[] = -+{ -+ DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB, -+ DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB, -+ DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB, -+ DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM, -+ DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM, -+ DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16, -+ DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB -+}; -+ -+static BOOL is_block_compressed(DXGI_FORMAT format) - { -- FIXME("device %p, data %p, data_size %Iu, load_info %p, pump %p, texture %p, hresult %p stub.\n", -- device, data, data_size, load_info, pump, texture, hresult); -+ unsigned int i; - -- return E_NOTIMPL; -+ for (i = 0; i < ARRAY_SIZE(block_compressed_formats); ++i) -+ if (format == block_compressed_formats[i]) -+ return TRUE; -+ -+ return FALSE; -+} -+ -+static unsigned int get_bpp_from_format(DXGI_FORMAT format) -+{ -+ switch (format) -+ { -+ case DXGI_FORMAT_R32G32B32A32_TYPELESS: -+ case DXGI_FORMAT_R32G32B32A32_FLOAT: -+ case DXGI_FORMAT_R32G32B32A32_UINT: -+ case DXGI_FORMAT_R32G32B32A32_SINT: -+ return 128; -+ case DXGI_FORMAT_R32G32B32_TYPELESS: -+ case DXGI_FORMAT_R32G32B32_FLOAT: -+ case DXGI_FORMAT_R32G32B32_UINT: -+ case DXGI_FORMAT_R32G32B32_SINT: -+ return 96; -+ case DXGI_FORMAT_R16G16B16A16_TYPELESS: -+ case DXGI_FORMAT_R16G16B16A16_FLOAT: -+ case DXGI_FORMAT_R16G16B16A16_UNORM: -+ case DXGI_FORMAT_R16G16B16A16_UINT: -+ case DXGI_FORMAT_R16G16B16A16_SNORM: -+ case DXGI_FORMAT_R16G16B16A16_SINT: -+ case DXGI_FORMAT_R32G32_TYPELESS: -+ case DXGI_FORMAT_R32G32_FLOAT: -+ case DXGI_FORMAT_R32G32_UINT: -+ case DXGI_FORMAT_R32G32_SINT: -+ case DXGI_FORMAT_R32G8X24_TYPELESS: -+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: -+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: -+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: -+ case DXGI_FORMAT_Y416: -+ case DXGI_FORMAT_Y210: -+ case DXGI_FORMAT_Y216: -+ return 64; -+ case DXGI_FORMAT_R10G10B10A2_TYPELESS: -+ case DXGI_FORMAT_R10G10B10A2_UNORM: -+ case DXGI_FORMAT_R10G10B10A2_UINT: -+ case DXGI_FORMAT_R11G11B10_FLOAT: -+ case DXGI_FORMAT_R8G8B8A8_TYPELESS: -+ case DXGI_FORMAT_R8G8B8A8_UNORM: -+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: -+ case DXGI_FORMAT_R8G8B8A8_UINT: -+ case DXGI_FORMAT_R8G8B8A8_SNORM: -+ case DXGI_FORMAT_R8G8B8A8_SINT: -+ case DXGI_FORMAT_R16G16_TYPELESS: -+ case DXGI_FORMAT_R16G16_FLOAT: -+ case DXGI_FORMAT_R16G16_UNORM: -+ case DXGI_FORMAT_R16G16_UINT: -+ case DXGI_FORMAT_R16G16_SNORM: -+ case DXGI_FORMAT_R16G16_SINT: -+ case DXGI_FORMAT_R32_TYPELESS: -+ case DXGI_FORMAT_D32_FLOAT: -+ case DXGI_FORMAT_R32_FLOAT: -+ case DXGI_FORMAT_R32_UINT: -+ case DXGI_FORMAT_R32_SINT: -+ case DXGI_FORMAT_R24G8_TYPELESS: -+ case DXGI_FORMAT_D24_UNORM_S8_UINT: -+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: -+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT: -+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: -+ case DXGI_FORMAT_R8G8_B8G8_UNORM: -+ case DXGI_FORMAT_G8R8_G8B8_UNORM: -+ case DXGI_FORMAT_B8G8R8A8_UNORM: -+ case DXGI_FORMAT_B8G8R8X8_UNORM: -+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: -+ case DXGI_FORMAT_B8G8R8A8_TYPELESS: -+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: -+ case DXGI_FORMAT_B8G8R8X8_TYPELESS: -+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: -+ case DXGI_FORMAT_AYUV: -+ case DXGI_FORMAT_Y410: -+ case DXGI_FORMAT_YUY2: -+ return 32; -+ case DXGI_FORMAT_P010: -+ case DXGI_FORMAT_P016: -+ return 24; -+ case DXGI_FORMAT_R8G8_TYPELESS: -+ case DXGI_FORMAT_R8G8_UNORM: -+ case DXGI_FORMAT_R8G8_UINT: -+ case DXGI_FORMAT_R8G8_SNORM: -+ case DXGI_FORMAT_R8G8_SINT: -+ case DXGI_FORMAT_R16_TYPELESS: -+ case DXGI_FORMAT_R16_FLOAT: -+ case DXGI_FORMAT_D16_UNORM: -+ case DXGI_FORMAT_R16_UNORM: -+ case DXGI_FORMAT_R16_UINT: -+ case DXGI_FORMAT_R16_SNORM: -+ case DXGI_FORMAT_R16_SINT: -+ case DXGI_FORMAT_B5G6R5_UNORM: -+ case DXGI_FORMAT_B5G5R5A1_UNORM: -+ case DXGI_FORMAT_A8P8: -+ case DXGI_FORMAT_B4G4R4A4_UNORM: -+ return 16; -+ case DXGI_FORMAT_NV12: -+ case DXGI_FORMAT_420_OPAQUE: -+ case DXGI_FORMAT_NV11: -+ return 12; -+ case DXGI_FORMAT_R8_TYPELESS: -+ case DXGI_FORMAT_R8_UNORM: -+ case DXGI_FORMAT_R8_UINT: -+ case DXGI_FORMAT_R8_SNORM: -+ case DXGI_FORMAT_R8_SINT: -+ case DXGI_FORMAT_A8_UNORM: -+ case DXGI_FORMAT_AI44: -+ case DXGI_FORMAT_IA44: -+ case DXGI_FORMAT_P8: -+ case DXGI_FORMAT_BC2_TYPELESS: -+ case DXGI_FORMAT_BC2_UNORM: -+ case DXGI_FORMAT_BC2_UNORM_SRGB: -+ case DXGI_FORMAT_BC3_TYPELESS: -+ case DXGI_FORMAT_BC3_UNORM: -+ case DXGI_FORMAT_BC3_UNORM_SRGB: -+ case DXGI_FORMAT_BC5_TYPELESS: -+ case DXGI_FORMAT_BC5_UNORM: -+ case DXGI_FORMAT_BC5_SNORM: -+ case DXGI_FORMAT_BC6H_TYPELESS: -+ case DXGI_FORMAT_BC6H_UF16: -+ case DXGI_FORMAT_BC6H_SF16: -+ case DXGI_FORMAT_BC7_TYPELESS: -+ case DXGI_FORMAT_BC7_UNORM: -+ case DXGI_FORMAT_BC7_UNORM_SRGB: -+ return 8; -+ case DXGI_FORMAT_BC1_TYPELESS: -+ case DXGI_FORMAT_BC1_UNORM: -+ case DXGI_FORMAT_BC1_UNORM_SRGB: -+ case DXGI_FORMAT_BC4_TYPELESS: -+ case DXGI_FORMAT_BC4_UNORM: -+ case DXGI_FORMAT_BC4_SNORM: -+ return 4; -+ case DXGI_FORMAT_R1_UNORM: -+ return 1; -+ default: -+ return 0; -+ } -+} -+ -+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_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB }, -+ { &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 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; - } - -+HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT sdk_version, IWICImagingFactory **imaging_factory); -+ -+HRESULT WINAPI D3DX11CreateTextureFromMemory(ID3D11Device *device, const void *src_data, -+ SIZE_T src_data_size, D3DX11_IMAGE_LOAD_INFO *load_info, ID3DX11ThreadPump *pump, -+ ID3D11Resource **texture, HRESULT *hresult) -+ { -+ unsigned int frame_count, width, height, stride, frame_size; -+ IWICFormatConverter *converter = NULL; -+ IWICDdsFrameDecode *dds_frame = NULL; -+ D3D11_TEXTURE2D_DESC texture_2d_desc; -+ D3D11_SUBRESOURCE_DATA resource_data; -+ IWICBitmapFrameDecode *frame = NULL; -+ IWICImagingFactory *factory = NULL; -+ IWICBitmapDecoder *decoder = NULL; -+ ID3D11Texture2D *texture_2d; -+ D3DX11_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, data %p, data_size %Iu, load_info %p, pump %p, texture %p, hresult %p.\n", -+ device, src_data, src_data_size, load_info, pump, texture, hresult); -+ -+ if (!src_data || !src_data_size || !texture) -+ return E_FAIL; -+ if (pump) -+ FIXME("Thread pump is not supported yet.\n"); -+ -+ if (load_info) -+ { -+ img_info.Width = load_info->Width; -+ img_info.Height = load_info->Height; -+ img_info.Depth = load_info->Depth; -+ img_info.ArraySize = 1; -+ img_info.MipLevels = load_info->MipLevels; -+ img_info.MiscFlags = load_info->MiscFlags; -+ img_info.Format = load_info->Format; -+ } -+ else -+ { -+ if (FAILED(D3DX11GetImageInfoFromMemory(src_data, src_data_size, NULL, &img_info, NULL))) -+ return E_FAIL; -+ if (img_info.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) -+ { -+ FIXME("Cube map is not supported.\n"); -+ return E_FAIL; -+ } -+ } -+ -+ if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) -+ goto end; -+ if (FAILED(hr = IWICImagingFactory_CreateStream(factory, &stream))) -+ goto end; -+ if (FAILED(hr = IWICStream_InitializeFromMemory(stream, (BYTE *)src_data, src_data_size))) -+ goto end; -+ if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder))) -+ goto end; -+ if (FAILED(hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count)) || !frame_count) -+ 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; -+ if (is_block_compressed(img_info.Format)) -+ { -+ width = (width + 3) & ~3; -+ height = (height + 3) & ~3; -+ } -+ stride = (width * get_bpp_from_format(img_info.Format) + 7) / 8; -+ frame_size = stride * height; -+ -+ if (!(buffer = heap_alloc(frame_size))) -+ { -+ hr = E_FAIL; -+ goto end; -+ } -+ -+ if (is_block_compressed(img_info.Format)) -+ { -+ if (FAILED(hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICDdsFrameDecode, (void **)&dds_frame))) -+ goto end; -+ if (FAILED(hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, stride * 4, frame_size, buffer))) -+ goto end; -+ } -+ else -+ { -+ 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; -+ texture_2d_desc.Height = height; -+ texture_2d_desc.MipLevels = 1; -+ texture_2d_desc.ArraySize = img_info.ArraySize; -+ texture_2d_desc.Format = img_info.Format; -+ texture_2d_desc.SampleDesc.Count = 1; -+ texture_2d_desc.Usage = D3D11_USAGE_DEFAULT; -+ texture_2d_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; -+ texture_2d_desc.MiscFlags = img_info.MiscFlags; -+ -+ resource_data.pSysMem = buffer; -+ resource_data.SysMemPitch = stride; -+ resource_data.SysMemSlicePitch = frame_size; -+ -+ if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_2d_desc, &resource_data, &texture_2d))) -+ goto end; -+ -+ *texture = (ID3D11Resource *)texture_2d; -+ hr = S_OK; -+ -+end: -+ if (converter) -+ IWICFormatConverter_Release(converter); -+ if (dds_frame) -+ IWICDdsFrameDecode_Release(dds_frame); -+ if (buffer) -+ heap_free(buffer); -+ if (frame) -+ IWICBitmapFrameDecode_Release(frame); -+ if (decoder) -+ IWICBitmapDecoder_Release(decoder); -+ if (stream) -+ IWICStream_Release(stream); -+ if (factory) -+ IWICImagingFactory_Release(factory); -+ -+ return hr; -+ } -+ - HRESULT WINAPI D3DX11SaveTextureToFileW(ID3D11DeviceContext *context, ID3D11Resource *texture, - D3DX11_IMAGE_FILE_FORMAT format, const WCHAR *filename) - { --- -2.51.0 - diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0001-d3dx9-Add-an-optimization-to-stb_dxt.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0001-d3dx9-Add-an-optimization-to-stb_dxt.patch new file mode 100644 index 00000000..80a7922c --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0001-d3dx9-Add-an-optimization-to-stb_dxt.patch @@ -0,0 +1,37 @@ +From 4d8b800f0ebe625824b12b081026283e4c3c1efc Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Thu, 8 Aug 2024 07:30:25 -0400 +Subject: [PATCH] d3dx9: Add an optimization to stb_dxt. + +This optimzation helps us to more closely match the output of native +d3dx's DXT compression, which helps with d3dx10 tests. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx9_36/stb_dxt.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/dlls/d3dx9_36/stb_dxt.h b/dlls/d3dx9_36/stb_dxt.h +index c25f6b015da..2b40829deac 100644 +--- a/dlls/d3dx9_36/stb_dxt.h ++++ b/dlls/d3dx9_36/stb_dxt.h +@@ -565,6 +565,16 @@ static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int + dest[1] = (unsigned char)mn; + dest += 2; + ++ /* ++ * Wine specific optimization to more closely match Windows behavior: If ++ * max is equal to minimum, just set all bits to 0 (which means the value ++ * is the value of max in this case). ++ */ ++ if (mx == mn) { ++ memset(dest, 0, 6); ++ return; ++ } ++ + // determine bias and emit color indices + // given the choice of mx/mn, these indices are optimal: + // http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/ +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0002-d3dx10-Use-shared-code-in-load_texture_data-when-pos.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0002-d3dx10-Use-shared-code-in-load_texture_data-when-pos.patch new file mode 100644 index 00000000..ec6e17e7 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0002-d3dx10-Use-shared-code-in-load_texture_data-when-pos.patch @@ -0,0 +1,222 @@ +From 3f2a65b69375bc84e10f4a4cc32c1d7ed34d4acb Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Mon, 15 Sep 2025 14:23:52 -0400 +Subject: [PATCH] d3dx10: Use shared code in load_texture_data() when possible. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 2 +- + dlls/d3dx10_43/texture.c | 112 +++++++++++++++++++++++++++++++++- + dlls/d3dx9_36/d3dx_helpers.c | 6 +- + dlls/d3dx9_36/d3dx_helpers.h | 4 ++ + 4 files changed, 118 insertions(+), 6 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 75e4b4023d8..119b74c7ece 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -1579,7 +1579,7 @@ static void check_texture2d_data(ID3D10Texture2D *texture, const struct test_ima + { + line_match = !memcmp(expected_data + stride * i, + (BYTE *)map.pData + map.RowPitch * i, stride); +- todo_wine_if(is_block_compressed(image->expected_info.Format) ++ todo_wine_if(is_block_compressed(image->expected_info.Format) && image->data != test_dds_dxt5 + && (image->expected_info.Width % 4 != 0 || image->expected_info.Height % 4 != 0)) + ok_(__FILE__, line)(line_match, "Data mismatch for line %u, array slice %u.\n", i, array_slice); + if (!line_match) +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index ab488dcfa2f..f578ab0f789 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -873,6 +873,93 @@ static HRESULT convert_image(IWICImagingFactory *factory, IWICBitmapFrameDecode + return hr; + } + ++static HRESULT d3dx_load_texture_data(struct d3dx_image *image, D3DX10_IMAGE_LOAD_INFO *load_info, ++ const D3DX10_IMAGE_INFO *img_info, D3D10_SUBRESOURCE_DATA **resource_data) ++{ ++ const struct pixel_format_desc *fmt_desc, *src_desc; ++ D3DX10_IMAGE_LOAD_INFO tmp_load_info = *load_info; ++ uint32_t i, j, pixels_size, pixels_offset; ++ uint8_t *res_data = NULL, *pixels_buffer; ++ HRESULT hr = S_OK; ++ ++ if (img_info->ImageFileFormat == D3DX10_IFF_BMP) ++ return E_NOTIMPL; ++ ++ fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(img_info->Format)); ++ if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) ++ { ++ FIXME("Unknown DXGI format supplied, %#x.\n", img_info->Format); ++ return E_NOTIMPL; ++ } ++ ++ /* Potentially round up width/height to align with block size. */ ++ tmp_load_info.Width = (img_info->Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); ++ tmp_load_info.Height = (img_info->Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); ++ tmp_load_info.Depth = img_info->Depth; ++ tmp_load_info.MipLevels = img_info->MipLevels; ++ tmp_load_info.Format = img_info->Format; ++ ++ pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, tmp_load_info.Width, tmp_load_info.Height, ++ tmp_load_info.Depth, tmp_load_info.MipLevels) * img_info->ArraySize; ++ pixels_offset = (sizeof(**resource_data) * tmp_load_info.MipLevels * img_info->ArraySize); ++ if (!(res_data = malloc(pixels_size + pixels_offset))) ++ return E_FAIL; ++ ++ pixels_buffer = res_data + pixels_offset; ++ *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; ++ ++ src_desc = get_d3dx_pixel_format_info(image->format); ++ for (i = 0; i < img_info->ArraySize; ++i) ++ { ++ struct volume dst_size = { tmp_load_info.Width, tmp_load_info.Height, tmp_load_info.Depth }; ++ ++ for (j = 0; j < tmp_load_info.MipLevels; ++j) ++ { ++ const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; ++ struct d3dx_pixels src_pixels, dst_pixels; ++ uint32_t dst_row_pitch, dst_slice_pitch; ++ ++ hr = d3dx_image_get_pixels(image, i, j, &src_pixels); ++ if (FAILED(hr)) ++ break; ++ ++ hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, ++ &dst_slice_pitch); ++ if (FAILED(hr)) ++ break; ++ ++ set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, ++ dst_size.height, dst_size.depth, &unaligned_rect); ++ ++ hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, D3DX10_FILTER_POINT, 0); ++ if (FAILED(hr)) ++ break; ++ ++ (*resource_data)[i * tmp_load_info.MipLevels + j].pSysMem = pixels_buffer; ++ (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemPitch = dst_row_pitch; ++ (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemSlicePitch = dst_slice_pitch; ++ ++ pixels_buffer += dst_slice_pitch * dst_size.depth; ++ d3dx_get_next_mip_level_size(&dst_size); ++ } ++ } ++ ++ if (FAILED(hr)) ++ { ++ *resource_data = NULL; ++ free(res_data); ++ return hr; ++ } ++ ++ *load_info = tmp_load_info; ++ load_info->Usage = D3D10_USAGE_DEFAULT; ++ load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; ++ load_info->CpuAccessFlags = 0; ++ load_info->MiscFlags = img_info->MiscFlags; ++ ++ return S_OK; ++} ++ + HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, + D3D10_SUBRESOURCE_DATA **resource_data) + { +@@ -885,9 +972,13 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + BYTE *res_data = NULL, *buffer; + D3DX10_IMAGE_INFO img_info; + IWICStream *stream = NULL; ++ struct d3dx_image image; + const GUID *dst_format; + HRESULT hr; + ++ if (!data || !size) ++ return E_FAIL; ++ + if (load_info->Width != D3DX10_DEFAULT) + FIXME("load_info->Width is ignored.\n"); + if (load_info->Height != D3DX10_DEFAULT) +@@ -915,15 +1006,32 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + if (load_info->pSrcInfo) + FIXME("load_info->pSrcInfo is ignored.\n"); + +- if (FAILED(D3DX10GetImageInfoFromMemory(data, size, NULL, &img_info, NULL))) ++ hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_SUPPORT_DXT10); ++ if (FAILED(hr)) + return E_FAIL; ++ ++ hr = d3dx10_image_info_from_d3dx_image(&img_info, &image); ++ if (FAILED(hr)) ++ { ++ WARN("Invalid or unsupported image file, hr %#lx.\n", hr); ++ hr = E_FAIL; ++ goto end; ++ } ++ + if ((!(img_info.MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE) || img_info.ArraySize != 6) + && img_info.ArraySize != 1) + { + FIXME("img_info.ArraySize = %u not supported.\n", img_info.ArraySize); +- return E_NOTIMPL; ++ hr = E_NOTIMPL; ++ goto end; + } + ++ if (SUCCEEDED(hr = d3dx_load_texture_data(&image, load_info, &img_info, resource_data))) ++ { ++ TRACE("Successfully used shared code to load texture data.\n"); ++ res_data = NULL; ++ goto end; ++ } + + if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) + goto end; +diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c +index 60394ca1d9b..76763c4521f 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.c ++++ b/dlls/d3dx9_36/d3dx_helpers.c +@@ -377,7 +377,7 @@ static HRESULT dds_pixel_format_from_d3dx_pixel_format_id(struct dds_pixel_forma + return D3D_OK; + } + +-static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(DXGI_FORMAT format) ++enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format) + { + switch (format) + { +@@ -417,7 +417,7 @@ static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(DXGI_FORM + } + } + +-static void d3dx_get_next_mip_level_size(struct volume *size) ++void d3dx_get_next_mip_level_size(struct volume *size) + { + size->width = max(size->width / 2, 1); + size->height = max(size->height / 2, 1); +@@ -431,7 +431,7 @@ static const char *debug_volume(const struct volume *volume) + return wine_dbg_sprintf("(%ux%ux%u)", volume->width, volume->height, volume->depth); + } + +-static HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, ++HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, + uint32_t *pitch, uint32_t *size) + { + const struct pixel_format_desc *format_desc = get_d3dx_pixel_format_info(format); +diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h +index 8263d832bfa..91839296b47 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.h ++++ b/dlls/d3dx9_36/d3dx_helpers.h +@@ -391,6 +391,10 @@ void format_to_d3dx_color(const struct pixel_format_desc *format, const BYTE *sr + struct d3dx_color *dst); + void format_from_d3dx_color(const struct pixel_format_desc *format, const struct d3dx_color *src, BYTE *dst); + ++enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format); ++void d3dx_get_next_mip_level_size(struct volume *size); ++HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, ++ uint32_t *pitch, uint32_t *size); + uint32_t d3dx_calculate_layer_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, + uint32_t depth, uint32_t mip_levels); + HRESULT d3dx_init_dds_header(struct dds_header *header, enum d3dx_resource_type resource_type, +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0002-d3dx9-Add-support-for-GUID_WICPixelFormat16bppGray.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0002-d3dx9-Add-support-for-GUID_WICPixelFormat16bppGray.patch deleted file mode 100644 index 5b0a8a33..00000000 --- a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0002-d3dx9-Add-support-for-GUID_WICPixelFormat16bppGray.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 3c5ed75d72440b3c1ff668c3aece8216b561bece Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 13 Sep 2025 08:17:15 +1000 -Subject: [PATCH] d3dx9: Add support for GUID_WICPixelFormat16bppGray - -Stop error with HighFleet on startup. ---- - dlls/d3dx9_36/d3dx_helpers.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c -index 60394ca1d9b..26b00191b68 100644 ---- a/dlls/d3dx9_36/d3dx_helpers.c -+++ b/dlls/d3dx9_36/d3dx_helpers.c -@@ -140,6 +140,7 @@ static const struct - { &GUID_WICPixelFormat2bppIndexed, D3DX_PIXEL_FORMAT_P2_UINT }, - { &GUID_WICPixelFormat4bppIndexed, D3DX_PIXEL_FORMAT_P4_UINT }, - { &GUID_WICPixelFormat8bppGray, D3DX_PIXEL_FORMAT_L8_UNORM }, -+ { &GUID_WICPixelFormat16bppGray, D3DX_PIXEL_FORMAT_R16_UNORM }, - { &GUID_WICPixelFormat16bppBGR555, D3DX_PIXEL_FORMAT_B5G5R5X1_UNORM }, - { &GUID_WICPixelFormat16bppBGR565, D3DX_PIXEL_FORMAT_B5G6R5_UNORM }, - { &GUID_WICPixelFormat24bppBGR, D3DX_PIXEL_FORMAT_B8G8R8_UNORM }, --- -2.51.0 - diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0003-d3dx10-Add-support-for-decompressing-BC4-and-BC5-for.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0003-d3dx10-Add-support-for-decompressing-BC4-and-BC5-for.patch new file mode 100644 index 00000000..488615dd --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0003-d3dx10-Add-support-for-decompressing-BC4-and-BC5-for.patch @@ -0,0 +1,119 @@ +From 38bc3286663b541150cfd34e01b33ee09f738ab7 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Mon, 15 Sep 2025 14:39:47 -0400 +Subject: [PATCH] d3dx10: Add support for decompressing BC4 and BC5 formats. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/texture.c | 1 + + dlls/d3dx9_36/bcdec.h | 6 +++--- + dlls/d3dx9_36/d3dx_helpers.c | 21 +++++++++++++++++++++ + dlls/d3dx9_36/d3dx_helpers.h | 1 + + 4 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index f578ab0f789..a3acd063ac9 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -113,6 +113,7 @@ static DXGI_FORMAT dxgi_format_from_d3dx_pixel_format_id(enum d3dx_pixel_format_ + 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_R8_SNORM: return DXGI_FORMAT_R8_SNORM; + 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; +diff --git a/dlls/d3dx9_36/bcdec.h b/dlls/d3dx9_36/bcdec.h +index 5ead984c466..1b57a454926 100644 +--- a/dlls/d3dx9_36/bcdec.h ++++ b/dlls/d3dx9_36/bcdec.h +@@ -90,9 +90,9 @@ + BCDECDEF void bcdec_bc1(const void* compressedBlock, void* decompressedBlock, int destinationPitch); + BCDECDEF void bcdec_bc2(const void* compressedBlock, void* decompressedBlock, int destinationPitch); + BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +-#ifdef WINE_UNUSED /* unused for now in Wine */ + BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch); + BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, int destinationPitch); ++#ifdef WINE_UNUSED /* unused for now in Wine */ + BCDECDEF void bcdec_bc6h_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); + BCDECDEF void bcdec_bc6h_half(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); + BCDECDEF void bcdec_bc7(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +@@ -275,8 +275,6 @@ BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, in + bcdec__smooth_alpha_block(compressedBlock, ((char*)decompressedBlock) + 3, destinationPitch, 4); + } + +-#ifdef WINE_UNUSED /* unused for now in Wine */ +- + BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + bcdec__smooth_alpha_block(compressedBlock, decompressedBlock, destinationPitch, 1); + } +@@ -286,6 +284,8 @@ BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, in + bcdec__smooth_alpha_block(((char*)compressedBlock) + 8, ((char*)decompressedBlock) + 1, destinationPitch, 2); + } + ++#ifdef WINE_UNUSED /* unused for now in Wine */ ++ + /* http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend */ + static int bcdec__extend_sign(int val, int bits) { + return (val << (32 - bits)) >> (32 - bits); +diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c +index 76763c4521f..afbacecf320 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.c ++++ b/dlls/d3dx9_36/d3dx_helpers.c +@@ -81,6 +81,7 @@ static const struct pixel_format_desc formats[] = + {D3DX_PIXEL_FORMAT_R16G16B16_UNORM, { 0, 16, 16, 16}, { 0, 0, 16, 32}, 6, 1, 1, 6, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_INTERNAL}, + {D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM, {16, 16, 16, 16}, {48, 0, 16, 32}, 8, 1, 1, 8, CTYPE_UNORM, CTYPE_UNORM, 0 }, + {D3DX_PIXEL_FORMAT_R8_UNORM, { 0, 8, 0, 0}, { 0, 0, 0, 0}, 1, 1, 1, 1, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, ++ {D3DX_PIXEL_FORMAT_R8_SNORM, { 0, 8, 0, 0}, { 0, 0, 0, 0}, 1, 1, 1, 1, CTYPE_EMPTY, CTYPE_SNORM, FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_R8G8_UNORM, { 0, 8, 8, 0}, { 0, 0, 8, 0}, 2, 1, 1, 2, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_R16_UNORM, { 0, 16, 0, 0}, { 0, 0, 0, 0}, 2, 1, 1, 2, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_R16G16_UNORM, { 0, 16, 16, 0}, { 0, 0, 16, 0}, 4, 1, 1, 4, CTYPE_EMPTY, CTYPE_UNORM, 0 }, +@@ -390,6 +391,7 @@ enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format) + case DXGI_FORMAT_R10G10B10A2_UNORM: return D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM; + case DXGI_FORMAT_R16G16B16A16_UNORM: return D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM; + case DXGI_FORMAT_R8_UNORM: return D3DX_PIXEL_FORMAT_R8_UNORM; ++ case DXGI_FORMAT_R8_SNORM: return D3DX_PIXEL_FORMAT_R8_SNORM; + case DXGI_FORMAT_R8G8_UNORM: return D3DX_PIXEL_FORMAT_R8G8_UNORM; + case DXGI_FORMAT_R16_UNORM: return D3DX_PIXEL_FORMAT_R16_UNORM; + case DXGI_FORMAT_R16G16_UNORM: return D3DX_PIXEL_FORMAT_R16G16_UNORM; +@@ -2553,6 +2555,25 @@ static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct p + decompress_bcn_block = bcdec_bc3; + break; + ++ case D3DX_PIXEL_FORMAT_BC4_UNORM: ++ case D3DX_PIXEL_FORMAT_BC4_SNORM: ++ if (desc->rgb_type == CTYPE_UNORM) ++ uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8_UNORM); ++ else ++ uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8_SNORM); ++ decompress_bcn_block = bcdec_bc4; ++ break; ++ ++ case D3DX_PIXEL_FORMAT_BC5_UNORM: ++ case D3DX_PIXEL_FORMAT_BC5_SNORM: ++ if (desc->rgb_type == CTYPE_UNORM) ++ uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8G8_UNORM); ++ else ++ uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8G8_SNORM); ++ decompress_bcn_block = bcdec_bc5; ++ break; ++ ++ + default: + FIXME("Unexpected compressed texture format %u.\n", desc->format); + return E_NOTIMPL; +diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h +index 91839296b47..663febd279b 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.h ++++ b/dlls/d3dx9_36/d3dx_helpers.h +@@ -188,6 +188,7 @@ enum d3dx_pixel_format_id + D3DX_PIXEL_FORMAT_R16G16B16_UNORM, + D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM, + D3DX_PIXEL_FORMAT_R8_UNORM, ++ D3DX_PIXEL_FORMAT_R8_SNORM, + D3DX_PIXEL_FORMAT_R8G8_UNORM, + D3DX_PIXEL_FORMAT_R16_UNORM, + D3DX_PIXEL_FORMAT_R16G16_UNORM, +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0003-d3dx9_36-Use-correct-pixel-type-for-DXT-format.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0003-d3dx9_36-Use-correct-pixel-type-for-DXT-format.patch deleted file mode 100644 index 36d0ce33..00000000 --- a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0003-d3dx9_36-Use-correct-pixel-type-for-DXT-format.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 9d0bf8024bf5d97540fd1fa7456766fea808bc20 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 13 Sep 2025 08:17:15 +1000 -Subject: [PATCH] d3dx9_36: Use correct pixel type for DXT* format - -Required for Puyo-Puyo tetris. ---- - dlls/d3dx9_36/d3dx_helpers.c | 18 ++++++++++++++++-- - 1 file changed, 16 insertions(+), 2 deletions(-) - -diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c -index 26b00191b68..694b1b53548 100644 ---- a/dlls/d3dx9_36/d3dx_helpers.c -+++ b/dlls/d3dx9_36/d3dx_helpers.c -@@ -290,8 +290,8 @@ static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dds_pixel_format(cons - { - uint32_t i; - -- TRACE("pixel_format: size %lu, flags %#lx, fourcc %#lx, bpp %lu.\n", pixel_format->size, -- pixel_format->flags, pixel_format->fourcc, pixel_format->bpp); -+ TRACE("pixel_format: size %lu, flags %#lx, fourcc %s, bpp %lu.\n", pixel_format->size, -+ pixel_format->flags, debugstr_fourcc(pixel_format->fourcc), pixel_format->bpp); - TRACE("rmask %#lx, gmask %#lx, bmask %#lx, amask %#lx.\n", pixel_format->rmask, pixel_format->gmask, - pixel_format->bmask, pixel_format->amask); - -@@ -1152,6 +1152,20 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src - if ((image->format = d3dx_pixel_format_id_from_dds_pixel_format(&header->pixel_format)) == D3DX_PIXEL_FORMAT_COUNT) - return D3DXERR_INVALIDDATA; - -+ switch (image->format) -+ { -+ case D3DX_PIXEL_FORMAT_DXT1_UNORM: -+ case D3DX_PIXEL_FORMAT_DXT2_UNORM: -+ case D3DX_PIXEL_FORMAT_DXT3_UNORM: -+ case D3DX_PIXEL_FORMAT_DXT4_UNORM: -+ case D3DX_PIXEL_FORMAT_DXT5_UNORM: -+ image->format = D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM; -+ break; -+ default: -+ /* Leave format as is */ -+ break; -+ } -+ - image->image_file_format = D3DX_IMAGE_FILE_FORMAT_DDS; - image->layer_count = 1; - if (header->flags & DDS_DEPTH) --- -2.51.0 - diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0004-d3dx10-Add-support-for-compressing-BC4-and-BC5-forma.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0004-d3dx10-Add-support-for-compressing-BC4-and-BC5-forma.patch new file mode 100644 index 00000000..6bf1d64e --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0004-d3dx10-Add-support-for-compressing-BC4-and-BC5-forma.patch @@ -0,0 +1,90 @@ +From 92319f7205bce8ecb23e3c17141d8a371cb01e47 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Mon, 15 Sep 2025 14:46:56 -0400 +Subject: [PATCH] d3dx10: Add support for compressing BC4 and BC5 formats. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx9_36/d3dx_helpers.c | 26 ++++++++++++++++++++++++++ + dlls/d3dx9_36/stb_dxt.h | 5 ----- + 2 files changed, 26 insertions(+), 5 deletions(-) + +diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c +index afbacecf320..aae7efccf69 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.c ++++ b/dlls/d3dx9_36/d3dx_helpers.c +@@ -2789,6 +2789,16 @@ static void d3dx_compress_block(enum d3dx_pixel_format_id fmt, uint8_t *block_bu + stb_compress_dxt_block(dst_buf, block_buf, TRUE, 0); + break; + ++ case D3DX_PIXEL_FORMAT_BC4_UNORM: ++ case D3DX_PIXEL_FORMAT_BC4_SNORM: ++ stb_compress_bc4_block(dst_buf, block_buf); ++ break; ++ ++ case D3DX_PIXEL_FORMAT_BC5_UNORM: ++ case D3DX_PIXEL_FORMAT_BC5_SNORM: ++ stb_compress_bc5_block(dst_buf, block_buf); ++ break; ++ + default: + assert(0); + break; +@@ -2818,6 +2828,22 @@ static HRESULT d3dx_pixels_compress(struct d3dx_pixels *src_pixels, + assert(src_desc->format == D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM); + break; + ++ case D3DX_PIXEL_FORMAT_BC4_UNORM: ++ assert(src_desc->format == D3DX_PIXEL_FORMAT_R8_UNORM); ++ break; ++ ++ case D3DX_PIXEL_FORMAT_BC4_SNORM: ++ assert(src_desc->format == D3DX_PIXEL_FORMAT_R8_SNORM); ++ break; ++ ++ case D3DX_PIXEL_FORMAT_BC5_UNORM: ++ assert(src_desc->format == D3DX_PIXEL_FORMAT_R8G8_UNORM); ++ break; ++ ++ case D3DX_PIXEL_FORMAT_BC5_SNORM: ++ assert(src_desc->format == D3DX_PIXEL_FORMAT_R8G8_SNORM); ++ break; ++ + default: + FIXME("Unexpected compressed texture format %u.\n", dst_desc->format); + return E_NOTIMPL; +diff --git a/dlls/d3dx9_36/stb_dxt.h b/dlls/d3dx9_36/stb_dxt.h +index 2b40829deac..46375273e64 100644 +--- a/dlls/d3dx9_36/stb_dxt.h ++++ b/dlls/d3dx9_36/stb_dxt.h +@@ -56,10 +56,8 @@ extern "C" { + #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower. + + STBDDEF void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); +-#ifdef WINE_UNUSED /* unused for now in Wine */ + STBDDEF void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src_r_one_byte_per_pixel); + STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel); +-#endif /* WINE_UNUSED */ + + #define STB_COMPRESS_DXT_BLOCK + +@@ -626,8 +624,6 @@ void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int a + stb__CompressColorBlock(dest,(unsigned char*) src,mode); + } + +-#ifdef WINE_UNUSED /* unused for now in Wine */ +- + void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src) + { + stb__CompressAlphaBlock(dest,(unsigned char*) src, 1); +@@ -638,7 +634,6 @@ void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src) + stb__CompressAlphaBlock(dest,(unsigned char*) src,2); + stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2); + } +-#endif /* WINE_UNUSED */ + + #endif // STB_DXT_IMPLEMENTATION + +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0005-d3dx10-Exclusively-use-shared-code-to-load-DDS-files.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0005-d3dx10-Exclusively-use-shared-code-to-load-DDS-files.patch new file mode 100644 index 00000000..12737bb2 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0005-d3dx10-Exclusively-use-shared-code-to-load-DDS-files.patch @@ -0,0 +1,248 @@ +From a94c1e21dd77923b37d2ce7ad10d3235c148cbb3 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Thu, 8 Aug 2024 09:06:03 -0400 +Subject: [PATCH] d3dx10: Exclusively use shared code to load DDS files in + load_texture_data(). + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/texture.c | 171 ++++++----------------------------- + dlls/d3dx9_36/d3dx_helpers.c | 4 + + 2 files changed, 31 insertions(+), 144 deletions(-) + +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index a3acd063ac9..7b2490a4d00 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -805,32 +805,6 @@ void init_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info, D3DX10_IMAGE_LOAD_I + out->pSrcInfo = NULL; + } + +-static HRESULT dds_get_frame_info(IWICDdsFrameDecode *frame, const D3DX10_IMAGE_INFO *img_info, +- WICDdsFormatInfo *format_info, unsigned int *stride, unsigned int *frame_size) +-{ +- unsigned int width, height; +- HRESULT hr; +- +- if (FAILED(hr = IWICDdsFrameDecode_GetFormatInfo(frame, format_info))) +- return hr; +- if (FAILED(hr = IWICDdsFrameDecode_GetSizeInBlocks(frame, &width, &height))) +- return hr; +- +- if (img_info->Format == format_info->DxgiFormat) +- { +- *stride = width * format_info->BytesPerBlock; +- *frame_size = *stride * height; +- } +- else +- { +- width *= format_info->BlockWidth; +- height *= format_info->BlockHeight; +- *stride = (width * get_bpp_from_format(img_info->Format) + 7) / 8; +- *frame_size = *stride * height; +- } +- return S_OK; +-} +- + static HRESULT convert_image(IWICImagingFactory *factory, IWICBitmapFrameDecode *frame, + const GUID *dst_format, unsigned int stride, unsigned int frame_size, BYTE *buffer) + { +@@ -964,12 +938,10 @@ static HRESULT d3dx_load_texture_data(struct d3dx_image *image, D3DX10_IMAGE_LOA + HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, + D3D10_SUBRESOURCE_DATA **resource_data) + { +- unsigned int stride, frame_size, i, j; +- IWICDdsFrameDecode *dds_frame = NULL; + IWICBitmapFrameDecode *frame = NULL; + IWICImagingFactory *factory = NULL; +- IWICDdsDecoder *dds_decoder = NULL; + IWICBitmapDecoder *decoder = NULL; ++ unsigned int stride, frame_size; + BYTE *res_data = NULL, *buffer; + D3DX10_IMAGE_INFO img_info; + IWICStream *stream = NULL; +@@ -1033,6 +1005,10 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + res_data = NULL; + goto end; + } ++ else if (img_info.ImageFileFormat == D3DX10_IFF_DDS) ++ { ++ goto end; ++ } + + if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) + goto end; +@@ -1042,122 +1018,32 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + goto end; + if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder))) + goto end; ++ if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) ++ goto end; + +- if (img_info.ImageFileFormat == D3DX10_IFF_DDS) +- { +- WICDdsFormatInfo format_info; +- size_t size = 0; +- +- if (FAILED(hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICDdsDecoder, (void **)&dds_decoder))) +- goto end; +- +- for (i = 0; i < img_info.ArraySize; ++i) +- { +- for (j = 0; j < img_info.MipLevels; ++j) +- { +- if (FAILED(hr = IWICDdsDecoder_GetFrame(dds_decoder, i, j, 0, &frame))) +- goto end; +- if (FAILED(hr = IWICBitmapFrameDecode_QueryInterface(frame, +- &IID_IWICDdsFrameDecode, (void **)&dds_frame))) +- goto end; +- if (FAILED(hr = dds_get_frame_info(dds_frame, &img_info, &format_info, &stride, &frame_size))) +- goto end; +- +- if (!i && !j) +- { +- img_info.Width = (img_info.Width + format_info.BlockWidth - 1) & ~(format_info.BlockWidth - 1); +- img_info.Height = (img_info.Height + format_info.BlockHeight - 1) & ~(format_info.BlockHeight - 1); +- } +- +- size += sizeof(**resource_data) + frame_size; +- +- IWICDdsFrameDecode_Release(dds_frame); +- dds_frame = NULL; +- IWICBitmapFrameDecode_Release(frame); +- frame = NULL; +- } +- } +- +- if (!(res_data = malloc(size))) +- { +- hr = E_FAIL; +- goto end; +- } +- *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; ++ stride = (img_info.Width * get_bpp_from_format(img_info.Format) + 7) / 8; ++ frame_size = stride * img_info.Height; + +- size = 0; +- for (i = 0; i < img_info.ArraySize; ++i) +- { +- for (j = 0; j < img_info.MipLevels; ++j) +- { +- if (FAILED(hr = IWICDdsDecoder_GetFrame(dds_decoder, i, j, 0, &frame))) +- goto end; +- if (FAILED(hr = IWICBitmapFrameDecode_QueryInterface(frame, +- &IID_IWICDdsFrameDecode, (void **)&dds_frame))) +- goto end; +- if (FAILED(hr = dds_get_frame_info(dds_frame, &img_info, &format_info, &stride, &frame_size))) +- goto end; +- +- buffer = res_data + sizeof(**resource_data) * img_info.ArraySize * img_info.MipLevels + size; +- size += frame_size; +- +- if (img_info.Format == format_info.DxgiFormat) +- { +- if (FAILED(hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, stride, frame_size, buffer))) +- goto end; +- } +- else +- { +- 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 (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) +- goto end; +- } +- +- IWICDdsFrameDecode_Release(dds_frame); +- dds_frame = NULL; +- IWICBitmapFrameDecode_Release(frame); +- frame = NULL; +- +- (*resource_data)[i * img_info.MipLevels + j].pSysMem = buffer; +- (*resource_data)[i * img_info.MipLevels + j].SysMemPitch = stride; +- (*resource_data)[i * img_info.MipLevels + j].SysMemSlicePitch = frame_size; +- } +- } +- } +- else ++ if (!(res_data = malloc(sizeof(**resource_data) + frame_size))) + { +- if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) +- goto end; +- +- stride = (img_info.Width * get_bpp_from_format(img_info.Format) + 7) / 8; +- frame_size = stride * img_info.Height; +- +- if (!(res_data = malloc(sizeof(**resource_data) + frame_size))) +- { +- hr = E_FAIL; +- goto end; +- } +- buffer = res_data + sizeof(**resource_data); +- +- 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 (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) +- goto end; ++ hr = E_FAIL; ++ goto end; ++ } ++ buffer = res_data + sizeof(**resource_data); + +- *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; +- (*resource_data)->pSysMem = buffer; +- (*resource_data)->SysMemPitch = stride; +- (*resource_data)->SysMemSlicePitch = frame_size; ++ 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 (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) ++ goto end; ++ ++ *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; ++ (*resource_data)->pSysMem = buffer; ++ (*resource_data)->SysMemPitch = stride; ++ (*resource_data)->SysMemSlicePitch = frame_size; + + load_info->Width = img_info.Width; + load_info->Height = img_info.Height; +@@ -1171,10 +1057,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + hr = S_OK; + + end: +- if (dds_decoder) +- IWICDdsDecoder_Release(dds_decoder); +- if (dds_frame) +- IWICDdsFrameDecode_Release(dds_frame); ++ d3dx_image_cleanup(&image); + free(res_data); + if (frame) + IWICBitmapFrameDecode_Release(frame); +diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c +index aae7efccf69..23b8bdabd6a 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.c ++++ b/dlls/d3dx9_36/d3dx_helpers.c +@@ -408,6 +408,10 @@ enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format) + case DXGI_FORMAT_BC1_UNORM: return D3DX_PIXEL_FORMAT_BC1_UNORM; + case DXGI_FORMAT_BC2_UNORM: return D3DX_PIXEL_FORMAT_BC2_UNORM; + case DXGI_FORMAT_BC3_UNORM: return D3DX_PIXEL_FORMAT_BC3_UNORM; ++ case DXGI_FORMAT_BC4_UNORM: return D3DX_PIXEL_FORMAT_BC4_UNORM; ++ case DXGI_FORMAT_BC4_SNORM: return D3DX_PIXEL_FORMAT_BC4_SNORM; ++ case DXGI_FORMAT_BC5_UNORM: return D3DX_PIXEL_FORMAT_BC5_UNORM; ++ case DXGI_FORMAT_BC5_SNORM: return D3DX_PIXEL_FORMAT_BC5_SNORM; + case DXGI_FORMAT_R8G8B8A8_SNORM: return D3DX_PIXEL_FORMAT_R8G8B8A8_SNORM; + case DXGI_FORMAT_R8G8_SNORM: return D3DX_PIXEL_FORMAT_R8G8_SNORM; + case DXGI_FORMAT_R16G16_SNORM: return D3DX_PIXEL_FORMAT_R16G16_SNORM; +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0006-d3dx10-Exclusively-use-shared-code-in-load_texture_d.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0006-d3dx10-Exclusively-use-shared-code-in-load_texture_d.patch new file mode 100644 index 00000000..2e485836 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0006-d3dx10-Exclusively-use-shared-code-in-load_texture_d.patch @@ -0,0 +1,518 @@ +From e43e799a7a96a24e4c6dbe3d71aaa27f8a94b129 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Wed, 17 Sep 2025 10:37:10 -0400 +Subject: [PATCH] d3dx10: Exclusively use shared code in load_texture_data(). + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/texture.c | 419 +++++------------------------------ + dlls/d3dx9_36/d3dx_helpers.c | 3 +- + 2 files changed, 62 insertions(+), 360 deletions(-) + +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index 7b2490a4d00..2c09040838b 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -22,13 +22,10 @@ + + #include "d3d10_1.h" + #include "d3dx10.h" +-#include "wincodec.h" + #include "dxhelpers.h" + + WINE_DEFAULT_DEBUG_CHANNEL(d3dx); + +-HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT sdk_version, IWICImagingFactory **imaging_factory); +- + /* + * 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. +@@ -172,179 +169,6 @@ static D3DX10_IMAGE_FILE_FORMAT d3dx10_image_file_format_from_d3dx_image_file_fo + } + } + +-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 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 unsigned int get_bpp_from_format(DXGI_FORMAT format) +-{ +- switch (format) +- { +- case DXGI_FORMAT_R32G32B32A32_TYPELESS: +- case DXGI_FORMAT_R32G32B32A32_FLOAT: +- case DXGI_FORMAT_R32G32B32A32_UINT: +- case DXGI_FORMAT_R32G32B32A32_SINT: +- return 128; +- case DXGI_FORMAT_R32G32B32_TYPELESS: +- case DXGI_FORMAT_R32G32B32_FLOAT: +- case DXGI_FORMAT_R32G32B32_UINT: +- case DXGI_FORMAT_R32G32B32_SINT: +- return 96; +- case DXGI_FORMAT_R16G16B16A16_TYPELESS: +- case DXGI_FORMAT_R16G16B16A16_FLOAT: +- case DXGI_FORMAT_R16G16B16A16_UNORM: +- case DXGI_FORMAT_R16G16B16A16_UINT: +- case DXGI_FORMAT_R16G16B16A16_SNORM: +- case DXGI_FORMAT_R16G16B16A16_SINT: +- case DXGI_FORMAT_R32G32_TYPELESS: +- case DXGI_FORMAT_R32G32_FLOAT: +- case DXGI_FORMAT_R32G32_UINT: +- case DXGI_FORMAT_R32G32_SINT: +- case DXGI_FORMAT_R32G8X24_TYPELESS: +- case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: +- case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: +- case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: +- case DXGI_FORMAT_Y416: +- case DXGI_FORMAT_Y210: +- case DXGI_FORMAT_Y216: +- return 64; +- case DXGI_FORMAT_R10G10B10A2_TYPELESS: +- case DXGI_FORMAT_R10G10B10A2_UNORM: +- case DXGI_FORMAT_R10G10B10A2_UINT: +- case DXGI_FORMAT_R11G11B10_FLOAT: +- case DXGI_FORMAT_R8G8B8A8_TYPELESS: +- case DXGI_FORMAT_R8G8B8A8_UNORM: +- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: +- case DXGI_FORMAT_R8G8B8A8_UINT: +- case DXGI_FORMAT_R8G8B8A8_SNORM: +- case DXGI_FORMAT_R8G8B8A8_SINT: +- case DXGI_FORMAT_R16G16_TYPELESS: +- case DXGI_FORMAT_R16G16_FLOAT: +- case DXGI_FORMAT_R16G16_UNORM: +- case DXGI_FORMAT_R16G16_UINT: +- case DXGI_FORMAT_R16G16_SNORM: +- case DXGI_FORMAT_R16G16_SINT: +- case DXGI_FORMAT_R32_TYPELESS: +- case DXGI_FORMAT_D32_FLOAT: +- case DXGI_FORMAT_R32_FLOAT: +- case DXGI_FORMAT_R32_UINT: +- case DXGI_FORMAT_R32_SINT: +- case DXGI_FORMAT_R24G8_TYPELESS: +- case DXGI_FORMAT_D24_UNORM_S8_UINT: +- case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: +- case DXGI_FORMAT_X24_TYPELESS_G8_UINT: +- case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: +- case DXGI_FORMAT_R8G8_B8G8_UNORM: +- case DXGI_FORMAT_G8R8_G8B8_UNORM: +- case DXGI_FORMAT_B8G8R8A8_UNORM: +- case DXGI_FORMAT_B8G8R8X8_UNORM: +- case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: +- case DXGI_FORMAT_B8G8R8A8_TYPELESS: +- case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: +- case DXGI_FORMAT_B8G8R8X8_TYPELESS: +- case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: +- case DXGI_FORMAT_AYUV: +- case DXGI_FORMAT_Y410: +- case DXGI_FORMAT_YUY2: +- return 32; +- case DXGI_FORMAT_P010: +- case DXGI_FORMAT_P016: +- return 24; +- case DXGI_FORMAT_R8G8_TYPELESS: +- case DXGI_FORMAT_R8G8_UNORM: +- case DXGI_FORMAT_R8G8_UINT: +- case DXGI_FORMAT_R8G8_SNORM: +- case DXGI_FORMAT_R8G8_SINT: +- case DXGI_FORMAT_R16_TYPELESS: +- case DXGI_FORMAT_R16_FLOAT: +- case DXGI_FORMAT_D16_UNORM: +- case DXGI_FORMAT_R16_UNORM: +- case DXGI_FORMAT_R16_UINT: +- case DXGI_FORMAT_R16_SNORM: +- case DXGI_FORMAT_R16_SINT: +- case DXGI_FORMAT_B5G6R5_UNORM: +- case DXGI_FORMAT_B5G5R5A1_UNORM: +- case DXGI_FORMAT_A8P8: +- case DXGI_FORMAT_B4G4R4A4_UNORM: +- return 16; +- case DXGI_FORMAT_NV12: +- case DXGI_FORMAT_420_OPAQUE: +- case DXGI_FORMAT_NV11: +- return 12; +- case DXGI_FORMAT_R8_TYPELESS: +- case DXGI_FORMAT_R8_UNORM: +- case DXGI_FORMAT_R8_UINT: +- case DXGI_FORMAT_R8_SNORM: +- case DXGI_FORMAT_R8_SINT: +- case DXGI_FORMAT_A8_UNORM: +- case DXGI_FORMAT_AI44: +- case DXGI_FORMAT_IA44: +- case DXGI_FORMAT_P8: +- case DXGI_FORMAT_BC2_TYPELESS: +- case DXGI_FORMAT_BC2_UNORM: +- case DXGI_FORMAT_BC2_UNORM_SRGB: +- case DXGI_FORMAT_BC3_TYPELESS: +- case DXGI_FORMAT_BC3_UNORM: +- case DXGI_FORMAT_BC3_UNORM_SRGB: +- case DXGI_FORMAT_BC5_TYPELESS: +- case DXGI_FORMAT_BC5_UNORM: +- case DXGI_FORMAT_BC5_SNORM: +- case DXGI_FORMAT_BC6H_TYPELESS: +- case DXGI_FORMAT_BC6H_UF16: +- case DXGI_FORMAT_BC6H_SF16: +- case DXGI_FORMAT_BC7_TYPELESS: +- case DXGI_FORMAT_BC7_UNORM: +- case DXGI_FORMAT_BC7_UNORM_SRGB: +- return 8; +- case DXGI_FORMAT_BC1_TYPELESS: +- case DXGI_FORMAT_BC1_UNORM: +- case DXGI_FORMAT_BC1_UNORM_SRGB: +- case DXGI_FORMAT_BC4_TYPELESS: +- case DXGI_FORMAT_BC4_UNORM: +- case DXGI_FORMAT_BC4_SNORM: +- return 4; +- case DXGI_FORMAT_R1_UNORM: +- return 1; +- default: +- return 0; +- } +-} +- + HRESULT WINAPI D3DX10GetImageInfoFromFileA(const char *src_file, ID3DX10ThreadPump *pump, D3DX10_IMAGE_INFO *info, + HRESULT *result) + { +@@ -805,149 +629,15 @@ void init_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info, D3DX10_IMAGE_LOAD_I + out->pSrcInfo = NULL; + } + +-static HRESULT convert_image(IWICImagingFactory *factory, IWICBitmapFrameDecode *frame, +- const GUID *dst_format, unsigned int stride, unsigned int frame_size, BYTE *buffer) +-{ +- IWICFormatConverter *converter; +- BOOL can_convert; +- GUID src_format; +- HRESULT hr; +- +- if (FAILED(hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &src_format))) +- return hr; +- +- if (IsEqualGUID(&src_format, dst_format)) +- { +- if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer))) +- return hr; +- return S_OK; +- } +- +- if (FAILED(hr = IWICImagingFactory_CreateFormatConverter(factory, &converter))) +- return hr; +- if (FAILED(hr = IWICFormatConverter_CanConvert(converter, &src_format, dst_format, &can_convert))) +- { +- IWICFormatConverter_Release(converter); +- return hr; +- } +- if (!can_convert) +- { +- WARN("Format converting %s to %s is not supported by WIC.\n", +- debugstr_guid(&src_format), debugstr_guid(dst_format)); +- IWICFormatConverter_Release(converter); +- return E_NOTIMPL; +- } +- if (FAILED(hr = IWICFormatConverter_Initialize(converter, (IWICBitmapSource *)frame, dst_format, +- WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom))) +- { +- IWICFormatConverter_Release(converter); +- return hr; +- } +- hr = IWICFormatConverter_CopyPixels(converter, NULL, stride, frame_size, buffer); +- IWICFormatConverter_Release(converter); +- return hr; +-} +- +-static HRESULT d3dx_load_texture_data(struct d3dx_image *image, D3DX10_IMAGE_LOAD_INFO *load_info, +- const D3DX10_IMAGE_INFO *img_info, D3D10_SUBRESOURCE_DATA **resource_data) ++HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, ++ D3D10_SUBRESOURCE_DATA **resource_data) + { + const struct pixel_format_desc *fmt_desc, *src_desc; +- D3DX10_IMAGE_LOAD_INFO tmp_load_info = *load_info; + uint32_t i, j, pixels_size, pixels_offset; + uint8_t *res_data = NULL, *pixels_buffer; +- HRESULT hr = S_OK; +- +- if (img_info->ImageFileFormat == D3DX10_IFF_BMP) +- return E_NOTIMPL; +- +- fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(img_info->Format)); +- if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) +- { +- FIXME("Unknown DXGI format supplied, %#x.\n", img_info->Format); +- return E_NOTIMPL; +- } +- +- /* Potentially round up width/height to align with block size. */ +- tmp_load_info.Width = (img_info->Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); +- tmp_load_info.Height = (img_info->Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); +- tmp_load_info.Depth = img_info->Depth; +- tmp_load_info.MipLevels = img_info->MipLevels; +- tmp_load_info.Format = img_info->Format; +- +- pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, tmp_load_info.Width, tmp_load_info.Height, +- tmp_load_info.Depth, tmp_load_info.MipLevels) * img_info->ArraySize; +- pixels_offset = (sizeof(**resource_data) * tmp_load_info.MipLevels * img_info->ArraySize); +- if (!(res_data = malloc(pixels_size + pixels_offset))) +- return E_FAIL; +- +- pixels_buffer = res_data + pixels_offset; +- *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; +- +- src_desc = get_d3dx_pixel_format_info(image->format); +- for (i = 0; i < img_info->ArraySize; ++i) +- { +- struct volume dst_size = { tmp_load_info.Width, tmp_load_info.Height, tmp_load_info.Depth }; +- +- for (j = 0; j < tmp_load_info.MipLevels; ++j) +- { +- const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; +- struct d3dx_pixels src_pixels, dst_pixels; +- uint32_t dst_row_pitch, dst_slice_pitch; +- +- hr = d3dx_image_get_pixels(image, i, j, &src_pixels); +- if (FAILED(hr)) +- break; +- +- hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, +- &dst_slice_pitch); +- if (FAILED(hr)) +- break; +- +- set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, +- dst_size.height, dst_size.depth, &unaligned_rect); +- +- hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, D3DX10_FILTER_POINT, 0); +- if (FAILED(hr)) +- break; +- +- (*resource_data)[i * tmp_load_info.MipLevels + j].pSysMem = pixels_buffer; +- (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemPitch = dst_row_pitch; +- (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemSlicePitch = dst_slice_pitch; +- +- pixels_buffer += dst_slice_pitch * dst_size.depth; +- d3dx_get_next_mip_level_size(&dst_size); +- } +- } +- +- if (FAILED(hr)) +- { +- *resource_data = NULL; +- free(res_data); +- return hr; +- } +- +- *load_info = tmp_load_info; +- load_info->Usage = D3D10_USAGE_DEFAULT; +- load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; +- load_info->CpuAccessFlags = 0; +- load_info->MiscFlags = img_info->MiscFlags; +- +- return S_OK; +-} +- +-HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, +- D3D10_SUBRESOURCE_DATA **resource_data) +-{ +- IWICBitmapFrameDecode *frame = NULL; +- IWICImagingFactory *factory = NULL; +- IWICBitmapDecoder *decoder = NULL; +- unsigned int stride, frame_size; +- BYTE *res_data = NULL, *buffer; + D3DX10_IMAGE_INFO img_info; +- IWICStream *stream = NULL; + struct d3dx_image image; +- const GUID *dst_format; +- HRESULT hr; ++ HRESULT hr = S_OK; + + if (!data || !size) + return E_FAIL; +@@ -979,6 +669,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + if (load_info->pSrcInfo) + FIXME("load_info->pSrcInfo is ignored.\n"); + ++ *resource_data = NULL; + hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_SUPPORT_DXT10); + if (FAILED(hr)) + return E_FAIL; +@@ -999,74 +690,84 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + goto end; + } + +- if (SUCCEEDED(hr = d3dx_load_texture_data(&image, load_info, &img_info, resource_data))) ++ fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(img_info.Format)); ++ if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) + { +- TRACE("Successfully used shared code to load texture data.\n"); +- res_data = NULL; ++ FIXME("Unknown DXGI format supplied, %#x.\n", img_info.Format); ++ hr = E_NOTIMPL; + goto end; + } +- else if (img_info.ImageFileFormat == D3DX10_IFF_DDS) ++ ++ /* Potentially round up width/height to align with block size. */ ++ load_info->Width = (img_info.Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); ++ load_info->Height = (img_info.Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); ++ load_info->Depth = img_info.Depth; ++ load_info->MipLevels = img_info.MipLevels; ++ load_info->Format = img_info.Format; ++ ++ pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, load_info->Width, load_info->Height, ++ load_info->Depth, load_info->MipLevels) * img_info.ArraySize; ++ pixels_offset = (sizeof(**resource_data) * load_info->MipLevels * img_info.ArraySize); ++ if (!(res_data = malloc(pixels_size + pixels_offset))) + { ++ hr = E_OUTOFMEMORY; + goto end; + } + +- if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) +- goto end; +- if (FAILED(hr = IWICImagingFactory_CreateStream(factory, &stream))) +- goto end; +- if (FAILED(hr = IWICStream_InitializeFromMemory(stream, (BYTE *)data, size))) +- goto end; +- if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder))) +- goto end; +- if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) +- goto end; +- +- stride = (img_info.Width * get_bpp_from_format(img_info.Format) + 7) / 8; +- frame_size = stride * img_info.Height; ++ pixels_buffer = res_data + pixels_offset; ++ *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; + +- if (!(res_data = malloc(sizeof(**resource_data) + frame_size))) ++ src_desc = get_d3dx_pixel_format_info(image.format); ++ for (i = 0; i < img_info.ArraySize; ++i) + { +- hr = E_FAIL; +- goto end; ++ struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth }; ++ ++ for (j = 0; j < load_info->MipLevels; ++j) ++ { ++ const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; ++ struct d3dx_pixels src_pixels, dst_pixels; ++ uint32_t dst_row_pitch, dst_slice_pitch; ++ ++ hr = d3dx_image_get_pixels(&image, i, j, &src_pixels); ++ if (FAILED(hr)) ++ break; ++ ++ hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, ++ &dst_slice_pitch); ++ if (FAILED(hr)) ++ break; ++ ++ set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, ++ dst_size.height, dst_size.depth, &unaligned_rect); ++ ++ hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, D3DX10_FILTER_POINT, 0); ++ if (FAILED(hr)) ++ break; ++ ++ (*resource_data)[i * load_info->MipLevels + j].pSysMem = pixels_buffer; ++ (*resource_data)[i * load_info->MipLevels + j].SysMemPitch = dst_row_pitch; ++ (*resource_data)[i * load_info->MipLevels + j].SysMemSlicePitch = dst_slice_pitch; ++ ++ pixels_buffer += dst_slice_pitch * dst_size.depth; ++ d3dx_get_next_mip_level_size(&dst_size); ++ } + } +- buffer = res_data + sizeof(**resource_data); + +- if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format))) ++ if (FAILED(hr)) + { +- hr = E_FAIL; +- FIXME("Unsupported DXGI format %#x.\n", img_info.Format); ++ *resource_data = NULL; + goto end; + } +- if (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) +- goto end; +- +- *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; +- (*resource_data)->pSysMem = buffer; +- (*resource_data)->SysMemPitch = stride; +- (*resource_data)->SysMemSlicePitch = frame_size; + +- load_info->Width = img_info.Width; +- load_info->Height = img_info.Height; +- load_info->MipLevels = img_info.MipLevels; +- load_info->Format = img_info.Format; ++ res_data = NULL; + load_info->Usage = D3D10_USAGE_DEFAULT; + load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; ++ load_info->CpuAccessFlags = 0; + load_info->MiscFlags = img_info.MiscFlags; + +- res_data = NULL; +- hr = S_OK; +- + end: + d3dx_image_cleanup(&image); + free(res_data); +- if (frame) +- IWICBitmapFrameDecode_Release(frame); +- if (decoder) +- IWICBitmapDecoder_Release(decoder); +- if (stream) +- IWICStream_Release(stream); +- if (factory) +- IWICImagingFactory_Release(factory); + return hr; + } + +diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c +index 23b8bdabd6a..13ecc81018d 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.c ++++ b/dlls/d3dx9_36/d3dx_helpers.c +@@ -1492,7 +1492,8 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src + break; + } + +- if (image_is_argb(bitmap_frame, image)) ++ /* D3DX10/D3DX11 ignore alpha channels in X8 bitmaps. */ ++ if (!(flags & D3DX_IMAGE_SUPPORT_DXT10) && image_is_argb(bitmap_frame, image)) + image->format = D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM; + + if (!(flags & D3DX_IMAGE_INFO_ONLY)) +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0007-d3dx10-tests-Add-tests-for-the-D3DX10_IMAGE_LOAD_INF.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0007-d3dx10-tests-Add-tests-for-the-D3DX10_IMAGE_LOAD_INF.patch new file mode 100644 index 00000000..61710d58 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0007-d3dx10-tests-Add-tests-for-the-D3DX10_IMAGE_LOAD_INF.patch @@ -0,0 +1,862 @@ +From 699fef6f9d66949b6d2f74c3785b04aab5603e2a Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Wed, 14 Aug 2024 10:12:24 -0400 +Subject: [PATCH] d3dx10/tests: Add tests for the D3DX10_IMAGE_LOAD_INFO + structure argument. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 746 +++++++++++++++++++++++++++++++++- + 1 file changed, 741 insertions(+), 5 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 119b74c7ece..6155855713e 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -732,6 +732,68 @@ static const BYTE test_dds_volume_data[] = + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x87, 0x0f, 0x78, 0x05, 0x05, 0x50, 0x50, + }; + ++/* ++ * 4x4x4 24-bit volume dds, 3 mipmaps. Level 0 is red, level 1 is green, level 2 is ++ * blue. ++ */ ++static const uint8_t dds_volume_24bit_4_4_4[] = ++{ ++ 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x0f,0x10,0x82,0x00,0x04,0x00,0x00,0x00, ++ 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, ++ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, ++ 0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0x00 ++}; ++ ++/* ++ * 8x8 24-bit dds, 4 mipmaps. Level 0 is red, level 1 is green, level 2 is ++ * blue, and level 3 is black. ++ */ ++static const uint8_t dds_24bit_8_8[] = ++{ ++ 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x0a,0x00,0x08,0x00,0x00,0x00, ++ 0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, ++ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00 ++}; ++ + /* 1x1 wmp image */ + static const BYTE test_wmp[] = + { +@@ -922,6 +984,169 @@ test_image[] = + }, + }; + ++static const struct test_image_load_info ++{ ++ const uint8_t *data; ++ uint32_t size; ++ D3DX10_IMAGE_LOAD_INFO load_info; ++ HRESULT expected_hr; ++ ++ D3D10_RESOURCE_DIMENSION expected_type; ++ union ++ { ++ D3D10_TEXTURE2D_DESC desc_2d; ++ D3D10_TEXTURE3D_DESC desc_3d; ++ } expected_resource_desc; ++ D3DX10_IMAGE_INFO expected_info; ++ BOOL todo_resource_desc; ++} ++test_image_load_info[] = ++{ ++ /* ++ * FirstMipLevel set to 1 - Does not match D3DX_SKIP_DDS_MIP_LEVELS ++ * behavior from d3dx9, image info values represent mip level 0, and ++ * texture values are pulled from this. The texture data is loaded ++ * starting from the specified mip level, however. ++ */ ++ { ++ dds_volume_24bit_4_4_4, sizeof(dds_volume_24bit_4_4_4), ++ { D3DX10_FROM_FILE, D3DX10_DEFAULT, 0, 1, D3DX10_DEFAULT, (D3D10_USAGE)D3DX10_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT }, ++ S_OK, D3D10_RESOURCE_DIMENSION_TEXTURE3D, ++ { .desc_3d = { 4, 4, 4, 3, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0 } }, ++ { 4, 4, 4, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, D3DX10_IFF_DDS }, ++ }, ++ /* ++ * Autogen mips misc flag specified. In the case of a cube texture image, ++ * the autogen mips flag is OR'd against D3D10_RESOURCE_MISC_TEXTURECUBE, ++ * even if it isn't specified. ++ */ ++ { ++ test_dds_cube, sizeof(test_dds_cube), ++ { D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, (D3D10_USAGE)D3DX10_DEFAULT, ++ (D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET), D3DX10_DEFAULT, D3D10_RESOURCE_MISC_GENERATE_MIPS, ++ DXGI_FORMAT_R8G8B8A8_UNORM, D3DX10_DEFAULT, D3DX10_DEFAULT }, ++ S_OK, D3D10_RESOURCE_DIMENSION_TEXTURE2D, ++ { .desc_2d = { 4, 4, 3, 6, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, ++ (D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET), 0, ++ (D3D10_RESOURCE_MISC_GENERATE_MIPS | D3D10_RESOURCE_MISC_TEXTURECUBE) } }, ++ { 4, 4, 1, 6, 3, DDS_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_BC1_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX10_IFF_DDS }, .todo_resource_desc = TRUE, ++ }, ++ /* ++ * Even with the autogen mips misc flag specified, the mip levels argument ++ * of load info is respected. ++ */ ++ { ++ test_dds_cube, sizeof(test_dds_cube), ++ { D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 2, (D3D10_USAGE)D3DX10_DEFAULT, ++ (D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET), D3DX10_DEFAULT, D3D10_RESOURCE_MISC_GENERATE_MIPS, ++ DXGI_FORMAT_R8G8B8A8_UNORM, D3DX10_DEFAULT, D3DX10_DEFAULT }, ++ S_OK, D3D10_RESOURCE_DIMENSION_TEXTURE2D, ++ { .desc_2d = { 4, 4, 2, 6, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, ++ (D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET), 0, ++ (D3D10_RESOURCE_MISC_GENERATE_MIPS | D3D10_RESOURCE_MISC_TEXTURECUBE) } }, ++ { 4, 4, 1, 6, 3, DDS_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_BC1_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX10_IFF_DDS }, .todo_resource_desc = TRUE, ++ }, ++}; ++ ++static const struct test_invalid_image_load_info ++{ ++ const uint8_t *data; ++ uint32_t size; ++ D3DX10_IMAGE_LOAD_INFO load_info; ++ HRESULT expected_hr; ++ HRESULT expected_process_hr; ++ HRESULT expected_create_device_object_hr; ++ BOOL todo_hr; ++ BOOL todo_process_hr; ++ BOOL todo_create_device_object_hr; ++} test_invalid_image_load_info[] = ++{ ++ /* ++ * A depth value that isn't D3DX10_FROM_FILE/D3DX10_DEFAULT/0 on a 2D ++ * texture results in failure. ++ */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ D3DX10_DEFAULT, D3DX10_DEFAULT, 2, D3DX10_DEFAULT, D3DX10_DEFAULT, (D3D10_USAGE)D3DX10_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT ++ }, ++ E_FAIL, E_FAIL, .todo_hr = TRUE, .todo_process_hr = TRUE ++ }, ++ /* Invalid filter value. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, (D3D10_USAGE)D3DX10_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 7, D3DX10_DEFAULT ++ }, ++ D3DERR_INVALIDCALL, D3DERR_INVALIDCALL, .todo_hr = TRUE, .todo_process_hr = TRUE ++ }, ++ /* Invalid mipfilter value, only checked if mips are generated. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, (D3D10_USAGE)D3DX10_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 7 ++ }, ++ S_OK, S_OK, S_OK ++ }, ++ /* Invalid mipfilter value. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ 2, 2, D3DX10_DEFAULT, D3DX10_DEFAULT, 2, (D3D10_USAGE)D3DX10_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 7 ++ }, ++ D3DERR_INVALIDCALL, D3DERR_INVALIDCALL, .todo_hr = TRUE, .todo_process_hr = TRUE ++ }, ++ /* ++ * Usage/BindFlags/CpuAccessFlags are validated in the call to ++ * CreateDeviceObject(). ++ */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_CPU_ACCESS_READ, D3D10_USAGE_DYNAMIC, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT ++ }, ++ E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ }, ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_USAGE_DEFAULT, ++ D3D10_BIND_DEPTH_STENCIL, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT ++ }, ++ E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ }, ++ /* ++ * D3D10_RESOURCE_MISC_GENERATE_MIPS requires binding as a shader resource ++ * and a render target. ++ */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_USAGE_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_RESOURCE_MISC_GENERATE_MIPS, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT ++ }, ++ E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ }, ++ /* Can't set the cube texture flag if the image isn't a cube texture. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_USAGE_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_RESOURCE_MISC_TEXTURECUBE, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT ++ }, ++ E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ }, ++}; ++ ++ + static WCHAR temp_dir[MAX_PATH]; + + static DXGI_FORMAT block_compressed_formats[] = +@@ -1373,7 +1598,99 @@ static inline void check_image_info_values_(uint32_t line, const D3DX10_IMAGE_IN + image_file_format, info->ImageFileFormat); + } + +-static ID3D10Texture2D *get_texture2d_readback(ID3D10Texture2D *texture) ++#define check_texture2d_desc_values(desc, width, height, mip_levels, array_size, format, sample_count, sample_quality, \ ++ usage, bind_flags, cpu_access_flags, misc_flags, wine_todo) \ ++ check_texture2d_desc_values_(__LINE__, desc, width, height, mip_levels, array_size, format, sample_count, sample_quality, \ ++ usage, bind_flags, cpu_access_flags, misc_flags, wine_todo) ++static inline void check_texture2d_desc_values_(uint32_t line, const D3D10_TEXTURE2D_DESC *desc, uint32_t width, ++ uint32_t height, uint32_t mip_levels, uint32_t array_size, DXGI_FORMAT format, uint32_t sample_count, ++ uint32_t sample_quality, D3D10_USAGE usage, uint32_t bind_flags, uint32_t cpu_access_flags, uint32_t misc_flags, ++ BOOL wine_todo) ++{ ++ const D3D10_TEXTURE2D_DESC expected_desc = { width, height, mip_levels, array_size, format, { sample_count, sample_quality }, ++ usage, bind_flags, cpu_access_flags, misc_flags }; ++ BOOL matched; ++ ++ matched = !memcmp(&expected_desc, desc, sizeof(*desc)); ++ todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected 2D texture desc values.\n"); ++ if (matched) ++ return; ++ ++ todo_wine_if(wine_todo && desc->Width != width) ++ ok_(__FILE__, line)(desc->Width == width, "Expected width %u, got %u.\n", width, desc->Width); ++ todo_wine_if(wine_todo && desc->Height != height) ++ ok_(__FILE__, line)(desc->Height == height, "Expected height %u, got %u.\n", height, desc->Height); ++ todo_wine_if(wine_todo && desc->ArraySize != array_size) ++ ok_(__FILE__, line)(desc->ArraySize == array_size, "Expected array_size %u, got %u.\n", array_size, ++ desc->ArraySize); ++ todo_wine_if(wine_todo && desc->MipLevels != mip_levels) ++ ok_(__FILE__, line)(desc->MipLevels == mip_levels, "Expected mip_levels %u, got %u.\n", mip_levels, ++ desc->MipLevels); ++ todo_wine_if(wine_todo && desc->Format != format) ++ ok_(__FILE__, line)(desc->Format == format, "Expected texture format %#x, got %#x.\n", format, desc->Format); ++ todo_wine_if(wine_todo && desc->SampleDesc.Count != sample_count) ++ ok_(__FILE__, line)(desc->SampleDesc.Count == sample_count, "Expected sample_count %u, got %u.\n", sample_count, ++ desc->SampleDesc.Count); ++ todo_wine_if(wine_todo && desc->SampleDesc.Quality != sample_quality) ++ ok_(__FILE__, line)(desc->SampleDesc.Quality == sample_quality, "Expected sample_quality %u, got %u.\n", sample_quality, ++ desc->SampleDesc.Quality); ++ todo_wine_if(wine_todo && desc->Usage != usage) ++ ok_(__FILE__, line)(desc->Usage == usage, "Expected usage %u, got %u.\n", usage, ++ desc->Usage); ++ todo_wine_if(wine_todo && desc->BindFlags != bind_flags) ++ ok_(__FILE__, line)(desc->BindFlags == bind_flags, "Expected bind_flags %#x, got %#x.\n", bind_flags, ++ desc->BindFlags); ++ todo_wine_if(wine_todo && desc->CPUAccessFlags != cpu_access_flags) ++ ok_(__FILE__, line)(desc->CPUAccessFlags == cpu_access_flags, "Expected cpu_access_flags %#x, got %#x.\n", ++ cpu_access_flags, desc->CPUAccessFlags); ++ todo_wine_if(wine_todo && desc->MiscFlags != misc_flags) ++ ok_(__FILE__, line)(desc->MiscFlags == misc_flags, "Expected misc_flags %#x, got %#x.\n", misc_flags, ++ desc->MiscFlags); ++} ++ ++#define check_texture3d_desc_values(desc, width, height, depth, mip_levels, format, usage, bind_flags, cpu_access_flags, \ ++ misc_flags, wine_todo) \ ++ check_texture3d_desc_values_(__LINE__, desc, width, height, depth, mip_levels, format, usage, bind_flags, \ ++ cpu_access_flags, misc_flags, wine_todo) ++static inline void check_texture3d_desc_values_(uint32_t line, const D3D10_TEXTURE3D_DESC *desc, uint32_t width, ++ uint32_t height, uint32_t depth, uint32_t mip_levels, DXGI_FORMAT format, D3D10_USAGE usage, uint32_t bind_flags, ++ uint32_t cpu_access_flags, uint32_t misc_flags, BOOL wine_todo) ++{ ++ const D3D10_TEXTURE3D_DESC expected_desc = { width, height, depth, mip_levels, format, usage, bind_flags, ++ cpu_access_flags, misc_flags }; ++ BOOL matched; ++ ++ matched = !memcmp(&expected_desc, desc, sizeof(*desc)); ++ todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected 3D texture desc values.\n"); ++ if (matched) ++ return; ++ ++ todo_wine_if(wine_todo && desc->Width != width) ++ ok_(__FILE__, line)(desc->Width == width, "Expected width %u, got %u.\n", width, desc->Width); ++ todo_wine_if(wine_todo && desc->Height != height) ++ ok_(__FILE__, line)(desc->Height == height, "Expected height %u, got %u.\n", height, desc->Height); ++ todo_wine_if(wine_todo && desc->Depth != depth) ++ ok_(__FILE__, line)(desc->Depth == depth, "Expected depth %u, got %u.\n", depth, desc->Depth); ++ todo_wine_if(wine_todo && desc->MipLevels != mip_levels) ++ ok_(__FILE__, line)(desc->MipLevels == mip_levels, "Expected mip_levels %u, got %u.\n", mip_levels, ++ desc->MipLevels); ++ todo_wine_if(wine_todo && desc->Format != format) ++ ok_(__FILE__, line)(desc->Format == format, "Expected texture format %#x, got %#x.\n", format, desc->Format); ++ todo_wine_if(wine_todo && desc->Usage != usage) ++ ok_(__FILE__, line)(desc->Usage == usage, "Expected usage %u, got %u.\n", usage, ++ desc->Usage); ++ todo_wine_if(wine_todo && desc->BindFlags != bind_flags) ++ ok_(__FILE__, line)(desc->BindFlags == bind_flags, "Expected bind_flags %#x, got %#x.\n", bind_flags, ++ desc->BindFlags); ++ todo_wine_if(wine_todo && desc->CPUAccessFlags != cpu_access_flags) ++ ok_(__FILE__, line)(desc->CPUAccessFlags == cpu_access_flags, "Expected cpu_access_flags %#x, got %#x.\n", ++ cpu_access_flags, desc->CPUAccessFlags); ++ todo_wine_if(wine_todo && desc->MiscFlags != misc_flags) ++ ok_(__FILE__, line)(desc->MiscFlags == misc_flags, "Expected misc_flags %#x, got %#x.\n", misc_flags, ++ desc->MiscFlags); ++} ++ ++static ID3D10Texture2D *get_texture2d_readback_iface(ID3D10Texture2D *texture) + { + D3D10_TEXTURE2D_DESC desc; + ID3D10Texture2D *readback; +@@ -1399,7 +1716,7 @@ static ID3D10Texture2D *get_texture2d_readback(ID3D10Texture2D *texture) + return readback; + } + +-static ID3D10Texture3D *get_texture3d_readback(ID3D10Texture3D *texture) ++static ID3D10Texture3D *get_texture3d_readback_iface(ID3D10Texture3D *texture) + { + D3D10_TEXTURE3D_DESC desc; + ID3D10Texture3D *readback; +@@ -1425,6 +1742,64 @@ static ID3D10Texture3D *get_texture3d_readback(ID3D10Texture3D *texture) + return readback; + } + ++#define check_test_image_load_info_resource(resource, image_load_info) \ ++ check_test_image_load_info_resource_(__LINE__, resource, image_load_info) ++static void check_test_image_load_info_resource_(uint32_t line, ID3D10Resource *resource, ++ const struct test_image_load_info *image_load_info) ++{ ++ D3D10_RESOURCE_DIMENSION resource_dimension; ++ HRESULT hr; ++ ++ ID3D10Resource_GetType(resource, &resource_dimension); ++ todo_wine_if(image_load_info->expected_type == D3D10_RESOURCE_DIMENSION_TEXTURE3D) ++ ok(resource_dimension == image_load_info->expected_type, "Got unexpected ResourceDimension %u, expected %u.\n", ++ resource_dimension, image_load_info->expected_type); ++ ++ if (resource_dimension != image_load_info->expected_type) ++ return; ++ ++ switch (resource_dimension) ++ { ++ case D3D10_RESOURCE_DIMENSION_TEXTURE2D: ++ { ++ const D3D10_TEXTURE2D_DESC *expected_desc_2d = &image_load_info->expected_resource_desc.desc_2d; ++ D3D10_TEXTURE2D_DESC desc_2d; ++ ID3D10Texture2D *tex_2d; ++ ++ hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture2D, (void **)&tex_2d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D10Texture2D_GetDesc(tex_2d, &desc_2d); ++ check_texture2d_desc_values_(line, &desc_2d, expected_desc_2d->Width, expected_desc_2d->Height, ++ expected_desc_2d->MipLevels, expected_desc_2d->ArraySize, expected_desc_2d->Format, ++ expected_desc_2d->SampleDesc.Count, expected_desc_2d->SampleDesc.Quality, expected_desc_2d->Usage, ++ expected_desc_2d->BindFlags, expected_desc_2d->CPUAccessFlags, expected_desc_2d->MiscFlags, ++ image_load_info->todo_resource_desc); ++ ID3D10Texture2D_Release(tex_2d); ++ break; ++ } ++ ++ case D3D10_RESOURCE_DIMENSION_TEXTURE3D: ++ { ++ const D3D10_TEXTURE3D_DESC *expected_desc_3d = &image_load_info->expected_resource_desc.desc_3d; ++ D3D10_TEXTURE3D_DESC desc_3d; ++ ID3D10Texture3D *tex_3d; ++ ++ hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture3D, (void **)&tex_3d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D10Texture3D_GetDesc(tex_3d, &desc_3d); ++ check_texture3d_desc_values_(line, &desc_3d, expected_desc_3d->Width, expected_desc_3d->Height, ++ expected_desc_3d->Depth, expected_desc_3d->MipLevels, expected_desc_3d->Format, expected_desc_3d->Usage, ++ expected_desc_3d->BindFlags, expected_desc_3d->CPUAccessFlags, expected_desc_3d->MiscFlags, ++ image_load_info->todo_resource_desc); ++ ID3D10Texture3D_Release(tex_3d); ++ break; ++ } ++ ++ default: ++ break; ++ } ++} ++ + static void check_resource_info(ID3D10Resource *resource, const struct test_image *image, unsigned int line) + { + unsigned int expected_mip_levels, expected_width, expected_height, max_dimension; +@@ -1549,7 +1924,7 @@ static void check_texture2d_data(ID3D10Texture2D *texture, const struct test_ima + BOOL line_match; + HRESULT hr; + +- readback = get_texture2d_readback(texture); ++ readback = get_texture2d_readback_iface(texture); + ok_(__FILE__, line)(readback != NULL, "Failed to get texture readback.\n"); + if (!readback) + return; +@@ -1603,7 +1978,7 @@ static void check_texture3d_data(ID3D10Texture3D *texture, const struct test_ima + BOOL line_match; + HRESULT hr; + +- readback = get_texture3d_readback(texture); ++ readback = get_texture3d_readback_iface(texture); + ok_(__FILE__, line)(readback != NULL, "Failed to get texture readback.\n"); + if (!readback) + return; +@@ -1661,6 +2036,172 @@ static void check_resource_data(ID3D10Resource *resource, const struct test_imag + } + } + ++/* ++ * Taken from the d3d10core tests. If there's a missing resource type or ++ * texture format checking function, check to see if it exists there first. ++ */ ++struct resource_readback ++{ ++ D3D10_RESOURCE_DIMENSION dimension; ++ ID3D10Resource *resource; ++ D3D10_MAPPED_TEXTURE3D map_desc; ++ uint32_t width, height, depth, sub_resource_idx; ++}; ++ ++static void get_texture_readback(ID3D10Texture2D *texture, uint32_t sub_resource_idx, ++ struct resource_readback *rb) ++{ ++ D3D10_TEXTURE2D_DESC texture_desc; ++ D3D10_MAPPED_TEXTURE2D map_desc; ++ uint32_t miplevel; ++ ID3D10Device *device; ++ HRESULT hr; ++ ++ memset(rb, 0, sizeof(*rb)); ++ rb->dimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; ++ ++ ID3D10Texture2D_GetDevice(texture, &device); ++ ++ ID3D10Texture2D_GetDesc(texture, &texture_desc); ++ texture_desc.Usage = D3D10_USAGE_STAGING; ++ texture_desc.BindFlags = 0; ++ texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; ++ texture_desc.MiscFlags = 0; ++ if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D10Texture2D **)&rb->resource))) ++ { ++ trace("Failed to create texture, hr %#lx.\n", hr); ++ ID3D10Device_Release(device); ++ return; ++ } ++ ++ miplevel = sub_resource_idx % texture_desc.MipLevels; ++ rb->width = max(1, texture_desc.Width >> miplevel); ++ rb->height = max(1, texture_desc.Height >> miplevel); ++ rb->depth = 1; ++ rb->sub_resource_idx = sub_resource_idx; ++ ++ ID3D10Device_CopyResource(device, rb->resource, (ID3D10Resource *)texture); ++ if (FAILED(hr = ID3D10Texture2D_Map((ID3D10Texture2D *)rb->resource, sub_resource_idx, ++ D3D10_MAP_READ, 0, &map_desc))) ++ { ++ trace("Failed to map sub-resource %u, hr %#lx.\n", sub_resource_idx, hr); ++ ID3D10Resource_Release(rb->resource); ++ rb->resource = NULL; ++ } ++ rb->map_desc.pData = map_desc.pData; ++ rb->map_desc.RowPitch = map_desc.RowPitch; ++ rb->map_desc.DepthPitch = 0; ++ ++ ID3D10Device_Release(device); ++} ++ ++static void *get_readback_data(struct resource_readback *rb, uint32_t x, uint32_t y, unsigned byte_width) ++{ ++ return (uint8_t *)rb->map_desc.pData + y * rb->map_desc.RowPitch + x * byte_width; ++} ++ ++static uint32_t get_readback_u32(struct resource_readback *rb, uint32_t x, uint32_t y) ++{ ++ return *(uint32_t *)get_readback_data(rb, x, y, sizeof(uint32_t)); ++} ++ ++static uint32_t get_readback_color(struct resource_readback *rb, uint32_t x, uint32_t y) ++{ ++ return get_readback_u32(rb, x, y); ++} ++ ++static void release_resource_readback(struct resource_readback *rb) ++{ ++ switch (rb->dimension) ++ { ++ case D3D10_RESOURCE_DIMENSION_BUFFER: ++ ID3D10Buffer_Unmap((ID3D10Buffer *)rb->resource); ++ break; ++ case D3D10_RESOURCE_DIMENSION_TEXTURE1D: ++ ID3D10Texture1D_Unmap((ID3D10Texture1D *)rb->resource, rb->sub_resource_idx); ++ break; ++ case D3D10_RESOURCE_DIMENSION_TEXTURE2D: ++ ID3D10Texture2D_Unmap((ID3D10Texture2D *)rb->resource, rb->sub_resource_idx); ++ break; ++ case D3D10_RESOURCE_DIMENSION_TEXTURE3D: ++ ID3D10Texture3D_Unmap((ID3D10Texture3D *)rb->resource, rb->sub_resource_idx); ++ break; ++ default: ++ trace("Unhandled resource dimension %#x.\n", rb->dimension); ++ break; ++ } ++ ID3D10Resource_Release(rb->resource); ++} ++ ++static BOOL compare_color(uint32_t c1, uint32_t c2, uint8_t max_diff) ++{ ++ return compare_uint(c1 & 0xff, c2 & 0xff, max_diff) ++ && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff) ++ && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff) ++ && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); ++} ++ ++#define check_readback_data_color(a, b, c, d) check_readback_data_color_(__LINE__, a, b, c, d) ++static void check_readback_data_color_(uint32_t line, struct resource_readback *rb, ++ const RECT *rect, uint32_t expected_color, uint8_t max_diff) ++{ ++ unsigned int x = 0, y = 0, color = 0; ++ BOOL all_match = FALSE; ++ RECT default_rect; ++ ++ if (!rect) ++ { ++ SetRect(&default_rect, 0, 0, rb->width, rb->height); ++ rect = &default_rect; ++ } ++ ++ for (y = rect->top; y < rect->bottom; ++y) ++ { ++ for (x = rect->left; x < rect->right; ++x) ++ { ++ color = get_readback_color(rb, x, y); ++ if (!compare_color(color, expected_color, max_diff)) ++ goto done; ++ } ++ } ++ all_match = TRUE; ++ ++done: ++ ok_(__FILE__, line)(all_match, ++ "Got 0x%08x, expected 0x%08x at (%u, %u), sub-resource %u.\n", ++ color, expected_color, x, y, rb->sub_resource_idx); ++} ++ ++#define check_texture_sub_resource_color(a, b, c, d, e) check_texture_sub_resource_color_(__LINE__, a, b, c, d, e) ++static void check_texture_sub_resource_color_(uint32_t line, ID3D10Texture2D *texture, ++ uint32_t sub_resource_idx, const RECT *rect, uint32_t expected_color, uint8_t max_diff) ++{ ++ struct resource_readback rb; ++ ++ get_texture_readback(texture, sub_resource_idx, &rb); ++ check_readback_data_color_(line, &rb, rect, expected_color, max_diff); ++ release_resource_readback(&rb); ++} ++ ++static void set_d3dx10_image_load_info(D3DX10_IMAGE_LOAD_INFO *info, uint32_t width, uint32_t height, uint32_t depth, ++ uint32_t first_mip_level, uint32_t mip_levels, D3D10_USAGE usage, uint32_t bind_flags, uint32_t cpu_access_flags, ++ uint32_t misc_flags, DXGI_FORMAT format, uint32_t filter, uint32_t mip_filter, D3DX10_IMAGE_INFO *src_info) ++{ ++ info->Width = width; ++ info->Height = height; ++ info->Depth = depth; ++ info->FirstMipLevel = first_mip_level; ++ info->MipLevels = mip_levels; ++ info->Usage = usage; ++ info->BindFlags = bind_flags; ++ info->CpuAccessFlags = cpu_access_flags; ++ info->MiscFlags = misc_flags; ++ info->Format = format; ++ info->Filter = filter; ++ info->MipFilter = mip_filter; ++ info->pSrcInfo = src_info; ++} ++ + static void test_D3DX10UnsetAllDeviceObjects(void) + { + static const D3D10_INPUT_ELEMENT_DESC layout_desc[] = +@@ -2480,6 +3021,35 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) + winetest_pop_context(); + } + ++ for (i = 0; i < ARRAY_SIZE(test_invalid_image_load_info); ++i) ++ { ++ const struct test_invalid_image_load_info *test_load_info = &test_invalid_image_load_info[i]; ++ D3DX10_IMAGE_LOAD_INFO load_info = test_load_info->load_info; ++ ++ winetest_push_context("Test %u", i); ++ ++ hr = D3DX10CreateAsyncTextureProcessor(device, &load_info, &dp); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ hr = ID3DX10DataProcessor_Process(dp, (void *)test_load_info->data, test_load_info->size); ++ todo_wine_if(test_load_info->todo_process_hr) ++ ok(hr == test_load_info->expected_process_hr, "Got unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ resource = NULL; ++ hr = ID3DX10DataProcessor_CreateDeviceObject(dp, (void **)&resource); ++ todo_wine_if(test_load_info->todo_create_device_object_hr) ++ ok(hr == test_load_info->expected_create_device_object_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ ID3D10Resource_Release(resource); ++ } ++ ++ hr = ID3DX10DataProcessor_Destroy(dp); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ winetest_pop_context(); ++ } ++ + CoUninitialize(); + + ok(!ID3D10Device_Release(device), "Unexpected refcount.\n"); +@@ -3485,14 +4055,19 @@ static void test_get_image_info(void) + + static void test_create_texture(void) + { ++ static const uint32_t dds_24bit_8_8_mip_level_expected[] = { 0xff0000ff, 0xff00ff00, 0xffff0000, 0xff000000 }; + static const WCHAR test_resource_name[] = L"resource.data"; + static const WCHAR test_filename[] = L"image.data"; ++ D3D10_TEXTURE2D_DESC tex_2d_desc; ++ D3DX10_IMAGE_LOAD_INFO load_info; ++ D3DX10_IMAGE_INFO img_info; + ID3D10Resource *resource; ++ ID3D10Texture2D *tex_2d; + HMODULE resource_module; + ID3D10Device *device; + WCHAR path[MAX_PATH]; ++ uint32_t i, mip_level; + HRESULT hr, hr2; +- unsigned int i; + + device = create_device(); + if (!device) +@@ -3559,6 +4134,114 @@ static void test_create_texture(void) + winetest_pop_context(); + } + ++ for (i = 0; i < ARRAY_SIZE(test_invalid_image_load_info); ++i) ++ { ++ const struct test_invalid_image_load_info *test_load_info = &test_invalid_image_load_info[i]; ++ ++ winetest_push_context("Test %u", i); ++ ++ hr2 = 0xdeadbeef; ++ load_info = test_load_info->load_info; ++ hr = D3DX10CreateTextureFromMemory(device, test_load_info->data, test_load_info->size, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ todo_wine_if(test_load_info->todo_hr) ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ ID3D10Resource_Release(resource); ++ ++ winetest_pop_context(); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(test_image_load_info); ++i) ++ { ++ const struct test_image_load_info *test_load_info = &test_image_load_info[i]; ++ ++ winetest_push_context("Test %u", i); ++ ++ load_info = test_load_info->load_info; ++ load_info.pSrcInfo = &img_info; ++ ++ resource = NULL; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromMemory(device, test_load_info->data, test_load_info->size, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ { ++ check_test_image_load_info_resource(resource, test_load_info); ++ ID3D10Resource_Release(resource); ++ } ++ ++ winetest_pop_context(); ++ } ++ ++ /* Check behavior of the FirstMipLevel argument. */ ++ for (i = 0; i < 2; ++i) ++ { ++ winetest_push_context("FirstMipLevel %u", i); ++ memset(&img_info, 0, sizeof(img_info)); ++ set_d3dx10_image_load_info(&load_info, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, i, D3DX10_FROM_FILE, ++ D3D10_USAGE_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, ++ D3DX10_DEFAULT, &img_info); ++ ++ resource = NULL; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromMemory(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ check_image_info_values(&img_info, 8, 8, 1, 1, 4, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX10_IFF_DDS, FALSE); ++ ++ hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture2D, (void **)&tex_2d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ ID3D10Texture2D_GetDesc(tex_2d, &tex_2d_desc); ++ check_texture2d_desc_values(&tex_2d_desc, 8, 8, 4, 1, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 0, D3D10_USAGE_DEFAULT, ++ D3D10_BIND_SHADER_RESOURCE, 0, 0, FALSE); ++ for (mip_level = 0; mip_level < 4; ++mip_level) ++ { ++ winetest_push_context("MipLevel %u", mip_level); ++ todo_wine_if(i && mip_level != 3) check_texture_sub_resource_color(tex_2d, mip_level, NULL, ++ dds_24bit_8_8_mip_level_expected[min(3, mip_level + i)], 0); ++ winetest_pop_context(); ++ } ++ ++ ID3D10Texture2D_Release(tex_2d); ++ ID3D10Resource_Release(resource); ++ winetest_pop_context(); ++ } ++ ++ /* ++ * If FirstMipLevel is set to a value that is larger than the total number ++ * of mip levels in the image, it falls back to 0. ++ */ ++ memset(&img_info, 0, sizeof(img_info)); ++ set_d3dx10_image_load_info(&load_info, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 5, D3DX10_FROM_FILE, ++ D3D10_USAGE_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, ++ D3DX10_DEFAULT, &img_info); ++ ++ resource = NULL; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromMemory(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ check_image_info_values(&img_info, 8, 8, 1, 1, 4, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX10_IFF_DDS, FALSE); ++ ++ hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture2D, (void **)&tex_2d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D10Texture2D_GetDesc(tex_2d, &tex_2d_desc); ++ check_texture2d_desc_values(&tex_2d_desc, 8, 8, 4, 1, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 0, D3D10_USAGE_DEFAULT, ++ D3D10_BIND_SHADER_RESOURCE, 0, 0, FALSE); ++ for (mip_level = 0; mip_level < 4; ++mip_level) ++ { ++ winetest_push_context("MipLevel %u", mip_level); ++ check_texture_sub_resource_color(tex_2d, mip_level, NULL, dds_24bit_8_8_mip_level_expected[mip_level], 0); ++ winetest_pop_context(); ++ } ++ ++ ID3D10Texture2D_Release(tex_2d); ++ ID3D10Resource_Release(resource); ++ + hr2 = 0xdeadbeef; + add_work_item_count = 0; + hr = D3DX10CreateTextureFromMemory(device, test_image[0].data, test_image[0].size, +@@ -3622,6 +4305,31 @@ static void test_create_texture(void) + winetest_pop_context(); + } + ++ for (i = 0; i < ARRAY_SIZE(test_invalid_image_load_info); ++i) ++ { ++ const struct test_invalid_image_load_info *test_load_info = &test_invalid_image_load_info[i]; ++ ++ winetest_push_context("Test %u", i); ++ create_file(test_filename, test_image[i].data, test_image[i].size, path); ++ load_info = test_load_info->load_info; ++ ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromFileW(device, path, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ todo_wine_if(test_load_info->todo_hr) ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ ID3D10Resource_Release(resource); ++ ++ hr = D3DX10CreateTextureFromFileA(device, get_str_a(path), &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ todo_wine_if(test_load_info->todo_hr) ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ ID3D10Resource_Release(resource); ++ ++ delete_file(test_filename); ++ winetest_pop_context(); ++ } ++ + /* D3DX10CreateTextureFromResource tests */ + + hr2 = 0xdeadbeef; +@@ -3681,6 +4389,34 @@ static void test_create_texture(void) + winetest_pop_context(); + } + ++ for (i = 0; i < ARRAY_SIZE(test_invalid_image_load_info); ++i) ++ { ++ const struct test_invalid_image_load_info *test_load_info = &test_invalid_image_load_info[i]; ++ ++ winetest_push_context("Test %u", i); ++ resource_module = create_resource_module(test_resource_name, test_load_info->data, test_load_info->size); ++ load_info = test_load_info->load_info; ++ ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromResourceW(device, resource_module, ++ test_resource_name, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ todo_wine_if(test_load_info->todo_hr) ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ ID3D10Resource_Release(resource); ++ ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromResourceA(device, resource_module, ++ get_str_a(test_resource_name), &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ todo_wine_if(test_load_info->todo_hr) ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ ID3D10Resource_Release(resource); ++ ++ delete_resource_module(test_resource_name, resource_module); ++ winetest_pop_context(); ++ } ++ + CoUninitialize(); + + ok(!ID3D10Device_Release(device), "Unexpected refcount.\n"); +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0008-d3dx10-Set-D3DX10_IMAGE_LOAD_INFO-pSrcInfo-value-if-.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0008-d3dx10-Set-D3DX10_IMAGE_LOAD_INFO-pSrcInfo-value-if-.patch new file mode 100644 index 00000000..e0a4290f --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0008-d3dx10-Set-D3DX10_IMAGE_LOAD_INFO-pSrcInfo-value-if-.patch @@ -0,0 +1,220 @@ +From 60ece0635b1d6f5176190a4c2fa68fc9b7a8d9cd Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Wed, 17 Sep 2025 15:05:17 -0400 +Subject: [PATCH] d3dx10: Set D3DX10_IMAGE_LOAD_INFO pSrcInfo value if passed + in. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 116 ++++++++++++++++++++++++++++++++++ + dlls/d3dx10_43/texture.c | 4 +- + 2 files changed, 118 insertions(+), 2 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 6155855713e..f660b9a2953 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -2964,6 +2964,12 @@ static void test_D3DX10CreateAsyncTextureInfoProcessor(void) + CoUninitialize(); + } + ++static const D3DX10_IMAGE_LOAD_INFO d3dx10_default_load_info = ++{ ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, ++ D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, NULL ++}; ++ + static void test_D3DX10CreateAsyncTextureProcessor(void) + { + ID3DX10DataProcessor *dp; +@@ -2998,6 +3004,9 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) + + for (i = 0; i < ARRAY_SIZE(test_image); ++i) + { ++ D3DX10_IMAGE_LOAD_INFO load_info = d3dx10_default_load_info; ++ D3DX10_IMAGE_INFO info = { 0 }; ++ + winetest_push_context("Test %u", i); + + hr = D3DX10CreateAsyncTextureProcessor(device, NULL, &dp); +@@ -3018,6 +3027,27 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) + hr = ID3DX10DataProcessor_Destroy(dp); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ++ /* Check that D3DX10_IMAGE_INFO argument is set. */ ++ load_info.pSrcInfo = &info; ++ hr = D3DX10CreateAsyncTextureProcessor(device, &load_info, &dp); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size); ++ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), ++ "Got unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ hr = ID3DX10DataProcessor_CreateDeviceObject(dp, (void **)&resource); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ check_resource_info(resource, test_image + i, __LINE__); ++ check_resource_data(resource, test_image + i, __LINE__); ++ check_image_info(&info, test_image + i, __LINE__); ++ ID3D10Resource_Release(resource); ++ } ++ ++ hr = ID3DX10DataProcessor_Destroy(dp); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ + winetest_pop_context(); + } + +@@ -4117,6 +4147,8 @@ static void test_create_texture(void) + + for (i = 0; i < ARRAY_SIZE(test_image); ++i) + { ++ D3DX10_IMAGE_INFO info = { 0 }; ++ + winetest_push_context("Test %u", i); + + hr2 = 0xdeadbeef; +@@ -4131,6 +4163,22 @@ static void test_create_texture(void) + ID3D10Resource_Release(resource); + } + ++ /* Check that D3DX10_IMAGE_INFO argument is set. */ ++ load_info = d3dx10_default_load_info; ++ load_info.pSrcInfo = &info; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), ++ "Got unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ check_resource_info(resource, test_image + i, __LINE__); ++ check_resource_data(resource, test_image + i, __LINE__); ++ check_image_info(&info, test_image + i, __LINE__); ++ ID3D10Resource_Release(resource); ++ } ++ + winetest_pop_context(); + } + +@@ -4274,6 +4322,8 @@ static void test_create_texture(void) + + for (i = 0; i < ARRAY_SIZE(test_image); ++i) + { ++ D3DX10_IMAGE_INFO info = { 0 }; ++ + winetest_push_context("Test %u", i); + create_file(test_filename, test_image[i].data, test_image[i].size, path); + +@@ -4301,6 +4351,37 @@ static void test_create_texture(void) + ID3D10Resource_Release(resource); + } + ++ /* Check that D3DX10_IMAGE_INFO argument is set. */ ++ load_info = d3dx10_default_load_info; ++ load_info.pSrcInfo = &info; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromFileW(device, path, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), ++ "Got unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ check_resource_info(resource, test_image + i, __LINE__); ++ check_resource_data(resource, test_image + i, __LINE__); ++ check_image_info(&info, test_image + i, __LINE__); ++ ID3D10Resource_Release(resource); ++ } ++ ++ load_info = d3dx10_default_load_info; ++ load_info.pSrcInfo = &info; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromFileA(device, get_str_a(path), &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), ++ "Got unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ check_resource_info(resource, test_image + i, __LINE__); ++ check_resource_data(resource, test_image + i, __LINE__); ++ check_image_info(&info, test_image + i, __LINE__); ++ ID3D10Resource_Release(resource); ++ } ++ + delete_file(test_filename); + winetest_pop_context(); + } +@@ -4351,6 +4432,8 @@ static void test_create_texture(void) + + for (i = 0; i < ARRAY_SIZE(test_image); ++i) + { ++ D3DX10_IMAGE_INFO info = { 0 }; ++ + winetest_push_context("Test %u", i); + resource_module = create_resource_module(test_resource_name, test_image[i].data, test_image[i].size); + +@@ -4385,6 +4468,39 @@ static void test_create_texture(void) + ID3D10Resource_Release(resource); + } + ++ /* Check that D3DX10_IMAGE_INFO argument is set. */ ++ load_info = d3dx10_default_load_info; ++ load_info.pSrcInfo = &info; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromResourceW(device, resource_module, ++ test_resource_name, &load_info, NULL, &resource, &hr2); ++ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), ++ "Got unexpected hr %#lx.\n", hr); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ if (hr == S_OK) ++ { ++ check_resource_info(resource, test_image + i, __LINE__); ++ check_resource_data(resource, test_image + i, __LINE__); ++ check_image_info(&info, test_image + i, __LINE__); ++ ID3D10Resource_Release(resource); ++ } ++ ++ load_info = d3dx10_default_load_info; ++ load_info.pSrcInfo = &info; ++ hr2 = 0xdeadbeef; ++ hr = D3DX10CreateTextureFromResourceA(device, resource_module, ++ get_str_a(test_resource_name), &load_info, NULL, &resource, &hr2); ++ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), ++ "Got unexpected hr %#lx.\n", hr); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ if (hr == S_OK) ++ { ++ check_resource_info(resource, test_image + i, __LINE__); ++ check_resource_data(resource, test_image + i, __LINE__); ++ check_image_info(&info, test_image + i, __LINE__); ++ ID3D10Resource_Release(resource); ++ } ++ + delete_resource_module(test_resource_name, resource_module); + winetest_pop_context(); + } +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index 2c09040838b..4d279bccbd5 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -666,8 +666,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + FIXME("load_info->Filter is ignored.\n"); + if (load_info->MipFilter != D3DX10_DEFAULT) + FIXME("load_info->MipFilter is ignored.\n"); +- if (load_info->pSrcInfo) +- FIXME("load_info->pSrcInfo is ignored.\n"); + + *resource_data = NULL; + hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_SUPPORT_DXT10); +@@ -764,6 +762,8 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; + load_info->CpuAccessFlags = 0; + load_info->MiscFlags = img_info.MiscFlags; ++ if (load_info->pSrcInfo) ++ *load_info->pSrcInfo = img_info; + + end: + d3dx_image_cleanup(&image); +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0009-d3dx10-Create-3D-textures-for-images-representing-3D.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0009-d3dx10-Create-3D-textures-for-images-representing-3D.patch new file mode 100644 index 00000000..a0cafa07 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0009-d3dx10-Create-3D-textures-for-images-representing-3D.patch @@ -0,0 +1,234 @@ +From da45b8dd00ab02ba03d8608afdf32085f5d28603 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Wed, 17 Sep 2025 15:26:50 -0400 +Subject: [PATCH] d3dx10: Create 3D textures for images representing 3D + textures. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/async.c | 11 +++++- + dlls/d3dx10_43/tests/d3dx10.c | 35 ++++++++++++------ + dlls/d3dx10_43/texture.c | 69 +++++++++++++++++++++++++++-------- + 3 files changed, 86 insertions(+), 29 deletions(-) + +diff --git a/dlls/d3dx10_43/async.c b/dlls/d3dx10_43/async.c +index 62627886804..e2cd14a7736 100644 +--- a/dlls/d3dx10_43/async.c ++++ b/dlls/d3dx10_43/async.c +@@ -322,6 +322,8 @@ struct texture_processor + { + ID3DX10DataProcessor ID3DX10DataProcessor_iface; + ID3D10Device *device; ++ D3DX10_IMAGE_INFO img_info; ++ D3DX10_IMAGE_INFO *img_info_out; + D3DX10_IMAGE_LOAD_INFO load_info; + D3D10_SUBRESOURCE_DATA *resource_data; + }; +@@ -334,6 +336,7 @@ static inline struct texture_processor *texture_processor_from_ID3DX10DataProces + static HRESULT WINAPI texture_processor_Process(ID3DX10DataProcessor *iface, void *data, SIZE_T size) + { + struct texture_processor *processor = texture_processor_from_ID3DX10DataProcessor(iface); ++ HRESULT hr; + + TRACE("iface %p, data %p, size %Iu.\n", iface, data, size); + +@@ -343,7 +346,10 @@ static HRESULT WINAPI texture_processor_Process(ID3DX10DataProcessor *iface, voi + free(processor->resource_data); + processor->resource_data = NULL; + } +- return load_texture_data(data, size, &processor->load_info, &processor->resource_data); ++ hr = load_texture_data(data, size, &processor->load_info, &processor->resource_data); ++ if (SUCCEEDED(hr) && processor->img_info_out) ++ *processor->img_info_out = processor->img_info; ++ return hr; + } + + static HRESULT WINAPI texture_processor_CreateDeviceObject(ID3DX10DataProcessor *iface, void **object) +@@ -594,7 +600,10 @@ HRESULT WINAPI D3DX10CreateAsyncTextureProcessor(ID3D10Device *device, + object->ID3DX10DataProcessor_iface.lpVtbl = &texture_processor_vtbl; + object->device = device; + ID3D10Device_AddRef(device); ++ if (load_info) ++ object->img_info_out = load_info->pSrcInfo; + init_load_info(load_info, &object->load_info); ++ object->load_info.pSrcInfo = &object->img_info; + + *processor = &object->ID3DX10DataProcessor_iface; + return S_OK; +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index f660b9a2953..818889138a5 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -20,6 +20,7 @@ + #include "initguid.h" + #include "d3d10_1.h" + #include "d3dx10.h" ++#include "wine/wined3d.h" + #include "wine/test.h" + #include + +@@ -69,6 +70,8 @@ + #define DDS_PF_BUMPLUMINANCE 0x00040000 + #define DDS_PF_BUMPDUDV 0x00080000 + ++static bool wined3d_opengl; ++ + struct dds_pixel_format + { + DWORD size; +@@ -1751,13 +1754,8 @@ static void check_test_image_load_info_resource_(uint32_t line, ID3D10Resource * + HRESULT hr; + + ID3D10Resource_GetType(resource, &resource_dimension); +- todo_wine_if(image_load_info->expected_type == D3D10_RESOURCE_DIMENSION_TEXTURE3D) +- ok(resource_dimension == image_load_info->expected_type, "Got unexpected ResourceDimension %u, expected %u.\n", +- resource_dimension, image_load_info->expected_type); +- +- if (resource_dimension != image_load_info->expected_type) +- return; +- ++ ok(resource_dimension == image_load_info->expected_type, "Got unexpected ResourceDimension %u, expected %u.\n", ++ resource_dimension, image_load_info->expected_type); + switch (resource_dimension) + { + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: +@@ -1826,10 +1824,9 @@ static void check_resource_info(ID3D10Resource *resource, const struct test_imag + } + + ID3D10Resource_GetType(resource, &resource_dimension); +- todo_wine_if (image->expected_info.ResourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D) +- ok(resource_dimension == image->expected_info.ResourceDimension, +- "Got unexpected ResourceDimension %u, expected %u.\n", +- resource_dimension, image->expected_info.ResourceDimension); ++ ok(resource_dimension == image->expected_info.ResourceDimension, ++ "Got unexpected ResourceDimension %u, expected %u.\n", ++ resource_dimension, image->expected_info.ResourceDimension); + + switch (resource_dimension) + { +@@ -2022,7 +2019,10 @@ static void check_resource_data(ID3D10Resource *resource, const struct test_imag + + if (SUCCEEDED(ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture3D, (void **)&texture3d))) + { +- check_texture3d_data(texture3d, image, line); ++ if (wined3d_opengl && is_block_compressed(image->expected_info.Format)) ++ skip("Skipping compressed format 3D texture readback test.\n"); ++ else ++ check_texture3d_data(texture3d, image, line); + ID3D10Texture3D_Release(texture3d); + } + else if (SUCCEEDED(ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture2D, (void **)&texture2d))) +@@ -5992,6 +5992,17 @@ static void test_preprocess_shader(void) + + START_TEST(d3dx10) + { ++ HMODULE wined3d; ++ ++ if ((wined3d = GetModuleHandleA("wined3d.dll"))) ++ { ++ enum wined3d_renderer (CDECL *p_wined3d_get_renderer)(void); ++ ++ if ((p_wined3d_get_renderer = (void *)GetProcAddress(wined3d, "wined3d_get_renderer")) ++ && p_wined3d_get_renderer() == WINED3D_RENDERER_OPENGL) ++ wined3d_opengl = true; ++ } ++ + test_D3DX10UnsetAllDeviceObjects(); + test_D3DX10CreateAsyncMemoryLoader(); + test_D3DX10CreateAsyncFileLoader(); +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index 4d279bccbd5..a21ce7ff139 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -439,9 +439,12 @@ static HRESULT create_texture(ID3D10Device *device, const void *data, SIZE_T siz + { + D3D10_SUBRESOURCE_DATA *resource_data; + D3DX10_IMAGE_LOAD_INFO load_info_copy; ++ D3DX10_IMAGE_INFO img_info; + HRESULT hr; + + init_load_info(load_info, &load_info_copy); ++ if (!load_info_copy.pSrcInfo) ++ load_info_copy.pSrcInfo = &img_info; + + if (FAILED((hr = load_texture_data(data, size, &load_info_copy, &resource_data)))) + return hr; +@@ -774,25 +777,59 @@ end: + HRESULT create_d3d_texture(ID3D10Device *device, D3DX10_IMAGE_LOAD_INFO *load_info, + D3D10_SUBRESOURCE_DATA *resource_data, ID3D10Resource **texture) + { +- D3D10_TEXTURE2D_DESC texture_2d_desc; +- ID3D10Texture2D *texture_2d; + HRESULT hr; + +- memset(&texture_2d_desc, 0, sizeof(texture_2d_desc)); +- texture_2d_desc.Width = load_info->Width; +- texture_2d_desc.Height = load_info->Height; +- texture_2d_desc.MipLevels = load_info->MipLevels; +- texture_2d_desc.ArraySize = load_info->MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE ? 6 : 1; +- texture_2d_desc.Format = load_info->Format; +- texture_2d_desc.SampleDesc.Count = 1; +- texture_2d_desc.Usage = load_info->Usage; +- texture_2d_desc.BindFlags = load_info->BindFlags; +- texture_2d_desc.MiscFlags = load_info->MiscFlags; +- +- if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, resource_data, &texture_2d))) +- return hr; ++ *texture = NULL; ++ switch (load_info->pSrcInfo->ResourceDimension) ++ { ++ case D3D10_RESOURCE_DIMENSION_TEXTURE2D: ++ { ++ D3D10_TEXTURE2D_DESC texture_2d_desc = { 0 }; ++ ID3D10Texture2D *texture_2d; ++ ++ texture_2d_desc.Width = load_info->Width; ++ texture_2d_desc.Height = load_info->Height; ++ texture_2d_desc.MipLevels = load_info->MipLevels; ++ texture_2d_desc.ArraySize = load_info->pSrcInfo->ArraySize; ++ texture_2d_desc.Format = load_info->Format; ++ texture_2d_desc.SampleDesc.Count = 1; ++ texture_2d_desc.Usage = load_info->Usage; ++ texture_2d_desc.BindFlags = load_info->BindFlags; ++ texture_2d_desc.CPUAccessFlags = load_info->CpuAccessFlags; ++ texture_2d_desc.MiscFlags = load_info->MiscFlags; ++ ++ if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, resource_data, &texture_2d))) ++ return hr; ++ *texture = (ID3D10Resource *)texture_2d; ++ break; ++ } ++ ++ case D3D10_RESOURCE_DIMENSION_TEXTURE3D: ++ { ++ D3D10_TEXTURE3D_DESC texture_3d_desc = { 0 }; ++ ID3D10Texture3D *texture_3d; ++ ++ texture_3d_desc.Width = load_info->Width; ++ texture_3d_desc.Height = load_info->Height; ++ texture_3d_desc.Depth = load_info->Depth; ++ texture_3d_desc.MipLevels = load_info->MipLevels; ++ texture_3d_desc.Format = load_info->Format; ++ texture_3d_desc.Usage = load_info->Usage; ++ texture_3d_desc.BindFlags = load_info->BindFlags; ++ texture_3d_desc.CPUAccessFlags = load_info->CpuAccessFlags; ++ texture_3d_desc.MiscFlags = load_info->MiscFlags; ++ ++ if (FAILED(hr = ID3D10Device_CreateTexture3D(device, &texture_3d_desc, resource_data, &texture_3d))) ++ return hr; ++ *texture = (ID3D10Resource *)texture_3d; ++ break; ++ } ++ ++ default: ++ FIXME("Unhandled resource dimension %d.\n", load_info->pSrcInfo->ResourceDimension); ++ return E_NOTIMPL; ++ } + +- *texture = (ID3D10Resource *)texture_2d; + return S_OK; + } + +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0010-d3dx10-Handle-filter-value-passed-in-via-D3DX10_IMAG.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0010-d3dx10-Handle-filter-value-passed-in-via-D3DX10_IMAG.patch new file mode 100644 index 00000000..3ac6c3fd --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0010-d3dx10-Handle-filter-value-passed-in-via-D3DX10_IMAG.patch @@ -0,0 +1,138 @@ +From 24011cea5836f9b2b4cecbf971fe4b6400ebb9d5 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Thu, 18 Sep 2025 11:42:06 -0400 +Subject: [PATCH] d3dx10: Handle filter value passed in via + D3DX10_IMAGE_LOAD_INFO. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 2 +- + dlls/d3dx10_43/texture.c | 12 +++++++++--- + dlls/d3dx9_36/d3dx9_private.h | 10 +--------- + dlls/d3dx9_36/d3dx_helpers.c | 9 +++++++++ + dlls/d3dx9_36/d3dx_helpers.h | 2 ++ + dlls/d3dx9_36/texture.c | 2 +- + 6 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 818889138a5..4be5d37d70d 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -1086,7 +1086,7 @@ static const struct test_invalid_image_load_info + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, (D3D10_USAGE)D3DX10_DEFAULT, + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 7, D3DX10_DEFAULT + }, +- D3DERR_INVALIDCALL, D3DERR_INVALIDCALL, .todo_hr = TRUE, .todo_process_hr = TRUE ++ D3DERR_INVALIDCALL, D3DERR_INVALIDCALL + }, + /* Invalid mipfilter value, only checked if mips are generated. */ + { +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index a21ce7ff139..bb1e1456fc2 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -665,12 +665,18 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + FIXME("load_info->MiscFlags is ignored.\n"); + if (load_info->Format != D3DX10_DEFAULT) + FIXME("load_info->Format is ignored.\n"); +- if (load_info->Filter != D3DX10_DEFAULT) +- FIXME("load_info->Filter is ignored.\n"); + if (load_info->MipFilter != D3DX10_DEFAULT) + FIXME("load_info->MipFilter is ignored.\n"); + + *resource_data = NULL; ++ if (!load_info->Filter || load_info->Filter == D3DX10_DEFAULT) ++ load_info->Filter = D3DX10_FILTER_TRIANGLE | D3DX10_FILTER_DITHER; ++ if (FAILED(hr = d3dx_validate_filter(load_info->Filter))) ++ { ++ ERR("Invalid filter argument %#x.\n", load_info->Filter); ++ return hr; ++ } ++ + hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_SUPPORT_DXT10); + if (FAILED(hr)) + return E_FAIL; +@@ -741,7 +747,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, + dst_size.height, dst_size.depth, &unaligned_rect); + +- hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, D3DX10_FILTER_POINT, 0); ++ hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, load_info->Filter, 0); + if (FAILED(hr)) + break; + +diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h +index 655529b004b..394b1a1cee2 100644 +--- a/dlls/d3dx9_36/d3dx9_private.h ++++ b/dlls/d3dx9_36/d3dx9_private.h +@@ -35,20 +35,12 @@ + #define FOURCC_TX_1 0x54580100 + + #define D3DX9_FILTER_INVALID_BITS 0xff80fff8 +-static inline HRESULT d3dx9_validate_filter(uint32_t filter) +-{ +- if ((filter & D3DX9_FILTER_INVALID_BITS) || !(filter & 0x7) || ((filter & 0x7) > D3DX_FILTER_BOX)) +- return D3DERR_INVALIDCALL; +- +- return D3D_OK; +-} +- + static inline HRESULT d3dx9_handle_load_filter(DWORD *filter) + { + if (*filter == D3DX_DEFAULT) + *filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + +- return d3dx9_validate_filter(*filter); ++ return d3dx_validate_filter(*filter); + } + + BOOL d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image); +diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c +index 13ecc81018d..ddd208913af 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.c ++++ b/dlls/d3dx9_36/d3dx_helpers.c +@@ -53,6 +53,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx); + #define D3DX_FILTER_SRGB_OUT 0x00400000 + #define D3DX_FILTER_SRGB 0x00600000 + ++#define D3DX_FILTER_INVALID_BITS 0xff80fff8 ++HRESULT d3dx_validate_filter(uint32_t filter) ++{ ++ if ((filter & D3DX_FILTER_INVALID_BITS) || !(filter & 0x7) || ((filter & 0x7) > D3DX_FILTER_BOX)) ++ return D3DERR_INVALIDCALL; ++ ++ return D3D_OK; ++} ++ + HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**); + + /************************************************************ +diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h +index 663febd279b..c7292990799 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.h ++++ b/dlls/d3dx9_36/d3dx_helpers.h +@@ -386,6 +386,8 @@ static inline BOOL is_conversion_to_supported(const struct pixel_format_desc *fo + return !is_index_format(format) && !is_packed_format(format) && !is_unknown_format(format); + } + ++HRESULT d3dx_validate_filter(uint32_t filter); ++ + const struct pixel_format_desc *get_d3dx_pixel_format_info(enum d3dx_pixel_format_id format); + + void format_to_d3dx_color(const struct pixel_format_desc *format, const BYTE *src, const PALETTEENTRY *palette, +diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c +index 02bfbca2cc6..c64f9564406 100644 +--- a/dlls/d3dx9_36/texture.c ++++ b/dlls/d3dx9_36/texture.c +@@ -59,7 +59,7 @@ HRESULT WINAPI D3DXFilterTexture(IDirect3DBaseTexture9 *texture, + if (!texture) + return D3DERR_INVALIDCALL; + +- if (filter != D3DX_DEFAULT && FAILED(hr = d3dx9_validate_filter(filter))) ++ if (filter != D3DX_DEFAULT && FAILED(hr = d3dx_validate_filter(filter))) + return hr; + + if (srclevel == D3DX_DEFAULT) +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0011-d3dx10-Add-support-for-custom-texture-dimension-argu.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0011-d3dx10-Add-support-for-custom-texture-dimension-argu.patch new file mode 100644 index 00000000..ea7af965 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0011-d3dx10-Add-support-for-custom-texture-dimension-argu.patch @@ -0,0 +1,69 @@ +From 167f1d10d28e0935feabf82b5d9f429cbef2001d Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Thu, 18 Sep 2025 13:18:04 -0400 +Subject: [PATCH] d3dx10: Add support for custom texture dimension arguments in + D3DX10_IMAGE_LOAD_INFO. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 2 +- + dlls/d3dx10_43/texture.c | 23 ++++++++++++++--------- + 2 files changed, 15 insertions(+), 10 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 4be5d37d70d..8248461c970 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -1077,7 +1077,7 @@ static const struct test_invalid_image_load_info + D3DX10_DEFAULT, D3DX10_DEFAULT, 2, D3DX10_DEFAULT, D3DX10_DEFAULT, (D3D10_USAGE)D3DX10_DEFAULT, + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT + }, +- E_FAIL, E_FAIL, .todo_hr = TRUE, .todo_process_hr = TRUE ++ E_FAIL, E_FAIL + }, + /* Invalid filter value. */ + { +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index bb1e1456fc2..fc9841cc279 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -645,12 +645,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + if (!data || !size) + return E_FAIL; + +- if (load_info->Width != D3DX10_DEFAULT) +- FIXME("load_info->Width is ignored.\n"); +- if (load_info->Height != D3DX10_DEFAULT) +- FIXME("load_info->Height is ignored.\n"); +- if (load_info->Depth != D3DX10_DEFAULT) +- FIXME("load_info->Depth is ignored.\n"); + if (load_info->FirstMipLevel != D3DX10_DEFAULT) + FIXME("load_info->FirstMipLevel is ignored.\n"); + if (load_info->MipLevels != D3DX10_DEFAULT) +@@ -706,9 +700,20 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + } + + /* Potentially round up width/height to align with block size. */ +- load_info->Width = (img_info.Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); +- load_info->Height = (img_info.Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); +- load_info->Depth = img_info.Depth; ++ if (!load_info->Width || load_info->Width == D3DX10_FROM_FILE || load_info->Width == D3DX10_DEFAULT) ++ load_info->Width = (img_info.Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); ++ if (!load_info->Height || load_info->Height == D3DX10_FROM_FILE || load_info->Height == D3DX10_DEFAULT) ++ load_info->Height = (img_info.Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); ++ if (!load_info->Depth || load_info->Depth == D3DX10_FROM_FILE || load_info->Depth == D3DX10_DEFAULT) ++ load_info->Depth = img_info.Depth; ++ ++ if ((load_info->Depth > 1) && (img_info.ResourceDimension != D3D10_RESOURCE_DIMENSION_TEXTURE3D)) ++ { ++ ERR("Invalid depth value %u for image with dimension %d.\n", load_info->Depth, img_info.ResourceDimension); ++ hr = E_FAIL; ++ goto end; ++ } ++ + load_info->MipLevels = img_info.MipLevels; + load_info->Format = img_info.Format; + +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0012-d3dx10-Add-support-for-generating-mipmaps-to-load_te.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0012-d3dx10-Add-support-for-generating-mipmaps-to-load_te.patch new file mode 100644 index 00000000..3c6ce323 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0012-d3dx10-Add-support-for-generating-mipmaps-to-load_te.patch @@ -0,0 +1,323 @@ +From c69ef561499aa26de02b67d3ef0df888e603b448 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Fri, 19 Sep 2025 10:48:28 -0400 +Subject: [PATCH] d3dx10: Add support for generating mipmaps to + load_texture_data(). + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 3 +- + dlls/d3dx10_43/texture.c | 97 ++++++++++++++++++++++------------- + dlls/d3dx9_36/d3dx_helpers.c | 69 +++++++++++++++++++++++++ + dlls/d3dx9_36/d3dx_helpers.h | 17 ++++++ + 4 files changed, 147 insertions(+), 39 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 8248461c970..6e5cc1bb146 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -1104,7 +1104,7 @@ static const struct test_invalid_image_load_info + 2, 2, D3DX10_DEFAULT, D3DX10_DEFAULT, 2, (D3D10_USAGE)D3DX10_DEFAULT, + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, 7 + }, +- D3DERR_INVALIDCALL, D3DERR_INVALIDCALL, .todo_hr = TRUE, .todo_process_hr = TRUE ++ D3DERR_INVALIDCALL, D3DERR_INVALIDCALL + }, + /* + * Usage/BindFlags/CpuAccessFlags are validated in the call to +@@ -1840,7 +1840,6 @@ static void check_resource_info(ID3D10Resource *resource, const struct test_imag + ok_(__FILE__, line)(desc_2d.Height == expected_height, + "Got unexpected Height %u, expected %u.\n", + desc_2d.Height, expected_height); +- todo_wine_if(expected_mip_levels != image->expected_info.MipLevels) + ok_(__FILE__, line)(desc_2d.MipLevels == expected_mip_levels, + "Got unexpected MipLevels %u, expected %u.\n", + desc_2d.MipLevels, expected_mip_levels); +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index fc9841cc279..3348911cdff 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -636,10 +636,11 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + D3D10_SUBRESOURCE_DATA **resource_data) + { + const struct pixel_format_desc *fmt_desc, *src_desc; +- uint32_t i, j, pixels_size, pixels_offset; +- uint8_t *res_data = NULL, *pixels_buffer; ++ struct d3dx_subresource_data *sub_rsrcs = NULL; ++ uint32_t loaded_mip_levels, max_mip_levels; + D3DX10_IMAGE_INFO img_info; + struct d3dx_image image; ++ unsigned int i, j; + HRESULT hr = S_OK; + + if (!data || !size) +@@ -647,8 +648,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + + if (load_info->FirstMipLevel != D3DX10_DEFAULT) + FIXME("load_info->FirstMipLevel is ignored.\n"); +- if (load_info->MipLevels != D3DX10_DEFAULT) +- FIXME("load_info->MipLevels is ignored.\n"); + if (load_info->Usage != D3DX10_DEFAULT) + FIXME("load_info->Usage is ignored.\n"); + if (load_info->BindFlags != D3DX10_DEFAULT) +@@ -659,8 +658,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + FIXME("load_info->MiscFlags is ignored.\n"); + if (load_info->Format != D3DX10_DEFAULT) + FIXME("load_info->Format is ignored.\n"); +- if (load_info->MipFilter != D3DX10_DEFAULT) +- FIXME("load_info->MipFilter is ignored.\n"); + + *resource_data = NULL; + if (!load_info->Filter || load_info->Filter == D3DX10_DEFAULT) +@@ -714,64 +711,90 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + goto end; + } + +- load_info->MipLevels = img_info.MipLevels; ++ max_mip_levels = d3dx_get_max_mip_levels_for_size(load_info->Width, load_info->Height, load_info->Depth); ++ if (!load_info->MipLevels || load_info->MipLevels == D3DX10_DEFAULT || load_info->MipLevels == D3DX10_FROM_FILE) ++ load_info->MipLevels = (load_info->MipLevels == D3DX10_FROM_FILE) ? img_info.MipLevels : max_mip_levels; ++ load_info->MipLevels = min(max_mip_levels, load_info->MipLevels); + load_info->Format = img_info.Format; + +- pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, load_info->Width, load_info->Height, +- load_info->Depth, load_info->MipLevels) * img_info.ArraySize; +- pixels_offset = (sizeof(**resource_data) * load_info->MipLevels * img_info.ArraySize); +- if (!(res_data = malloc(pixels_size + pixels_offset))) +- { +- hr = E_OUTOFMEMORY; ++ hr = d3dx_create_subresource_data_for_texture(load_info->Width, load_info->Height, load_info->Depth, ++ load_info->MipLevels, img_info.ArraySize, fmt_desc, &sub_rsrcs); ++ if (FAILED(hr)) + goto end; +- } +- +- pixels_buffer = res_data + pixels_offset; +- *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; + + src_desc = get_d3dx_pixel_format_info(image.format); ++ loaded_mip_levels = min(img_info.MipLevels, load_info->MipLevels); + for (i = 0; i < img_info.ArraySize; ++i) + { + struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth }; + +- for (j = 0; j < load_info->MipLevels; ++j) ++ for (j = 0; j < loaded_mip_levels; ++j) + { ++ struct d3dx_subresource_data *sub_rsrc = &sub_rsrcs[i * load_info->MipLevels + j]; + const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; + struct d3dx_pixels src_pixels, dst_pixels; +- uint32_t dst_row_pitch, dst_slice_pitch; + + hr = d3dx_image_get_pixels(&image, i, j, &src_pixels); + if (FAILED(hr)) +- break; ++ goto end; + +- hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, +- &dst_slice_pitch); +- if (FAILED(hr)) +- break; +- +- set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, ++ set_d3dx_pixels(&dst_pixels, sub_rsrc->data, sub_rsrc->row_pitch, sub_rsrc->slice_pitch, NULL, dst_size.width, + dst_size.height, dst_size.depth, &unaligned_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, load_info->Filter, 0); + if (FAILED(hr)) +- break; ++ goto end; + +- (*resource_data)[i * load_info->MipLevels + j].pSysMem = pixels_buffer; +- (*resource_data)[i * load_info->MipLevels + j].SysMemPitch = dst_row_pitch; +- (*resource_data)[i * load_info->MipLevels + j].SysMemSlicePitch = dst_slice_pitch; +- +- pixels_buffer += dst_slice_pitch * dst_size.depth; + d3dx_get_next_mip_level_size(&dst_size); + } + } + +- if (FAILED(hr)) ++ if (loaded_mip_levels < load_info->MipLevels) + { +- *resource_data = NULL; +- goto end; ++ struct volume base_level_size = { load_info->Width, load_info->Height, load_info->Depth }; ++ const uint32_t base_level = loaded_mip_levels - 1; ++ ++ if (!load_info->MipFilter || load_info->MipFilter == D3DX10_DEFAULT) ++ load_info->MipFilter = D3DX10_FILTER_LINEAR; ++ if (FAILED(hr = d3dx_validate_filter(load_info->MipFilter))) ++ { ++ ERR("Invalid mip filter argument %#x.\n", load_info->MipFilter); ++ goto end; ++ } ++ ++ d3dx_get_mip_level_size(&base_level_size, base_level); ++ for (i = 0; i < img_info.ArraySize; ++i) ++ { ++ struct volume src_size, dst_size; ++ ++ src_size = dst_size = base_level_size; ++ for (j = base_level; j < (load_info->MipLevels - 1); ++j) ++ { ++ struct d3dx_subresource_data *dst_data = &sub_rsrcs[i * load_info->MipLevels + j + 1]; ++ struct d3dx_subresource_data *src_data = &sub_rsrcs[i * load_info->MipLevels + j]; ++ const RECT src_unaligned_rect = { 0, 0, src_size.width, src_size.height }; ++ struct d3dx_pixels src_pixels, dst_pixels; ++ RECT dst_unaligned_rect; ++ ++ d3dx_get_next_mip_level_size(&dst_size); ++ SetRect(&dst_unaligned_rect, 0, 0, dst_size.width, dst_size.height); ++ set_d3dx_pixels(&dst_pixels, dst_data->data, dst_data->row_pitch, dst_data->slice_pitch, NULL, ++ dst_size.width, dst_size.height, dst_size.depth, &dst_unaligned_rect); ++ set_d3dx_pixels(&src_pixels, src_data->data, src_data->row_pitch, src_data->slice_pitch, NULL, ++ src_size.width, src_size.height, src_size.depth, &src_unaligned_rect); ++ ++ hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, fmt_desc, load_info->MipFilter, 0); ++ if (FAILED(hr)) ++ goto end; ++ ++ src_size = dst_size; ++ } ++ } + } + +- res_data = NULL; ++ *resource_data = (D3D10_SUBRESOURCE_DATA *)sub_rsrcs; ++ sub_rsrcs = NULL; ++ + load_info->Usage = D3D10_USAGE_DEFAULT; + load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; + load_info->CpuAccessFlags = 0; +@@ -781,7 +804,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + + end: + d3dx_image_cleanup(&image); +- free(res_data); ++ free(sub_rsrcs); + return hr; + } + +diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c +index ddd208913af..7cfa85e1e1f 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.c ++++ b/dlls/d3dx9_36/d3dx_helpers.c +@@ -439,6 +439,28 @@ void d3dx_get_next_mip_level_size(struct volume *size) + size->depth = max(size->depth / 2, 1); + } + ++void d3dx_get_mip_level_size(struct volume *size, uint32_t level) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < level; ++i) ++ d3dx_get_next_mip_level_size(size); ++} ++ ++uint32_t d3dx_get_max_mip_levels_for_size(uint32_t width, uint32_t height, uint32_t depth) ++{ ++ struct volume tmp = { width, height, depth }; ++ uint32_t mip_levels = 1; ++ ++ while (!(tmp.width == 1 && tmp.height == 1 && tmp.depth == 1)) ++ { ++ d3dx_get_next_mip_level_size(&tmp); ++ mip_levels++; ++ } ++ ++ return mip_levels; ++} ++ + static const char *debug_volume(const struct volume *volume) + { + if (!volume) +@@ -3130,3 +3152,50 @@ void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bott + aligned_rect->bottom = min((aligned_rect->bottom + fmt_desc->block_height - 1) + & ~(fmt_desc->block_height - 1), height); + } ++ ++HRESULT d3dx_create_subresource_data_for_texture(uint32_t width, uint32_t height, uint32_t depth, ++ uint32_t mip_levels, uint32_t layer_count, const struct pixel_format_desc *fmt_desc, ++ struct d3dx_subresource_data **out_sub_rsrc_data) ++{ ++ struct d3dx_subresource_data *sub_rsrcs = NULL; ++ uint8_t *sub_rsrc_data = NULL, *pixels_ptr; ++ uint32_t pixels_size, pixels_offset; ++ unsigned int i, j; ++ HRESULT hr = S_OK; ++ ++ *out_sub_rsrc_data = NULL; ++ pixels_offset = sizeof(*sub_rsrcs) * mip_levels * layer_count; ++ pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, width, height, depth, mip_levels) * layer_count; ++ if (!(sub_rsrc_data = malloc(pixels_size + pixels_offset))) ++ return E_OUTOFMEMORY; ++ ++ sub_rsrcs = (struct d3dx_subresource_data *)sub_rsrc_data; ++ pixels_ptr = sub_rsrc_data + pixels_offset; ++ for (i = 0; i < layer_count; ++i) ++ { ++ struct volume size = { width, height, depth }; ++ ++ for (j = 0; j < mip_levels; ++j) ++ { ++ uint32_t row_pitch, slice_pitch; ++ ++ hr = d3dx_calculate_pixels_size(fmt_desc->format, size.width, size.height, &row_pitch, &slice_pitch); ++ if (FAILED(hr)) ++ goto exit; ++ ++ sub_rsrcs[i * mip_levels + j].data = pixels_ptr; ++ sub_rsrcs[i * mip_levels + j].row_pitch = row_pitch; ++ sub_rsrcs[i * mip_levels + j].slice_pitch = slice_pitch; ++ ++ pixels_ptr += slice_pitch * size.depth; ++ d3dx_get_next_mip_level_size(&size); ++ } ++ } ++ ++ *out_sub_rsrc_data = sub_rsrcs; ++ sub_rsrc_data = NULL; ++ ++exit: ++ free(sub_rsrc_data); ++ return hr; ++} +diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h +index c7292990799..ee189a3a79c 100644 +--- a/dlls/d3dx9_36/d3dx_helpers.h ++++ b/dlls/d3dx9_36/d3dx_helpers.h +@@ -396,6 +396,8 @@ void format_from_d3dx_color(const struct pixel_format_desc *format, const struct + + enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format); + void d3dx_get_next_mip_level_size(struct volume *size); ++void d3dx_get_mip_level_size(struct volume *size, uint32_t level); ++uint32_t d3dx_get_max_mip_levels_for_size(uint32_t width, uint32_t height, uint32_t depth); + HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, + uint32_t *pitch, uint32_t *size); + uint32_t d3dx_calculate_layer_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, +@@ -430,6 +432,21 @@ struct d3dx_buffer_wrapper + HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc, + enum d3dx_image_file_format file_format, const struct d3dx_buffer_wrapper *wrapper, struct d3dx_buffer *dst_buffer); + ++/* ++ * Structure that is able to be cast to D3D10_SUBRESOURCE_DATA and ++ * D3D11_SUBRESOURCE_DATA. ++ */ ++struct d3dx_subresource_data ++{ ++ const void *data; ++ UINT row_pitch; ++ UINT slice_pitch; ++}; ++ ++HRESULT d3dx_create_subresource_data_for_texture(uint32_t width, uint32_t height, uint32_t depth, ++ uint32_t mip_levels, uint32_t layer_count, const struct pixel_format_desc *fmt_desc, ++ struct d3dx_subresource_data **out_sub_rsrc_data); ++ + /* debug helpers */ + const char *debug_d3dx_image_file_format(enum d3dx_image_file_format format); + #endif /* __WINE_D3DX_HELPERS_H */ +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0013-d3dx10-Add-support-for-the-format-field-in-D3DX10_IM.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0013-d3dx10-Add-support-for-the-format-field-in-D3DX10_IM.patch new file mode 100644 index 00000000..1b1dd971 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0013-d3dx10-Add-support-for-the-format-field-in-D3DX10_IM.patch @@ -0,0 +1,50 @@ +From e851890d08e8b98fc1efc1c28b96244546a63e0c Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Fri, 19 Sep 2025 10:52:08 -0400 +Subject: [PATCH] d3dx10: Add support for the format field in + D3DX10_IMAGE_LOAD_INFO. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/texture.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index 3348911cdff..302efeccac1 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -656,8 +656,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + FIXME("load_info->CpuAccessFlags is ignored.\n"); + if (load_info->MiscFlags != D3DX10_DEFAULT) + FIXME("load_info->MiscFlags is ignored.\n"); +- if (load_info->Format != D3DX10_DEFAULT) +- FIXME("load_info->Format is ignored.\n"); + + *resource_data = NULL; + if (!load_info->Filter || load_info->Filter == D3DX10_DEFAULT) +@@ -688,10 +686,12 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + goto end; + } + +- fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(img_info.Format)); ++ if (load_info->Format == D3DX10_DEFAULT || load_info->Format == DXGI_FORMAT_FROM_FILE) ++ load_info->Format = img_info.Format; ++ fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(load_info->Format)); + if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) + { +- FIXME("Unknown DXGI format supplied, %#x.\n", img_info.Format); ++ FIXME("Unknown DXGI format supplied, %#x.\n", load_info->Format); + hr = E_NOTIMPL; + goto end; + } +@@ -715,7 +715,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + if (!load_info->MipLevels || load_info->MipLevels == D3DX10_DEFAULT || load_info->MipLevels == D3DX10_FROM_FILE) + load_info->MipLevels = (load_info->MipLevels == D3DX10_FROM_FILE) ? img_info.MipLevels : max_mip_levels; + load_info->MipLevels = min(max_mip_levels, load_info->MipLevels); +- load_info->Format = img_info.Format; + + hr = d3dx_create_subresource_data_for_texture(load_info->Width, load_info->Height, load_info->Depth, + load_info->MipLevels, img_info.ArraySize, fmt_desc, &sub_rsrcs); +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0014-d3dx10-Handle-FirstMipLevel-argument-in-load_texture.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0014-d3dx10-Handle-FirstMipLevel-argument-in-load_texture.patch new file mode 100644 index 00000000..7e2e05ab --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0014-d3dx10-Handle-FirstMipLevel-argument-in-load_texture.patch @@ -0,0 +1,68 @@ +From 1a2093da3b46e635f99bb09d1c0ec336d8206b66 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Fri, 19 Sep 2025 11:37:58 -0400 +Subject: [PATCH] d3dx10: Handle FirstMipLevel argument in load_texture_data(). + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 2 +- + dlls/d3dx10_43/texture.c | 9 +++++---- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 6e5cc1bb146..2f26f8e14f1 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -4247,7 +4247,7 @@ static void test_create_texture(void) + for (mip_level = 0; mip_level < 4; ++mip_level) + { + winetest_push_context("MipLevel %u", mip_level); +- todo_wine_if(i && mip_level != 3) check_texture_sub_resource_color(tex_2d, mip_level, NULL, ++ check_texture_sub_resource_color(tex_2d, mip_level, NULL, + dds_24bit_8_8_mip_level_expected[min(3, mip_level + i)], 0); + winetest_pop_context(); + } +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index 302efeccac1..cd5fc112110 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -646,8 +646,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + if (!data || !size) + return E_FAIL; + +- if (load_info->FirstMipLevel != D3DX10_DEFAULT) +- FIXME("load_info->FirstMipLevel is ignored.\n"); + if (load_info->Usage != D3DX10_DEFAULT) + FIXME("load_info->Usage is ignored.\n"); + if (load_info->BindFlags != D3DX10_DEFAULT) +@@ -686,6 +684,9 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + goto end; + } + ++ if (load_info->FirstMipLevel == D3DX10_DEFAULT || (load_info->FirstMipLevel >= img_info.MipLevels)) ++ load_info->FirstMipLevel = 0; ++ + if (load_info->Format == D3DX10_DEFAULT || load_info->Format == DXGI_FORMAT_FROM_FILE) + load_info->Format = img_info.Format; + fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(load_info->Format)); +@@ -722,7 +723,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + goto end; + + src_desc = get_d3dx_pixel_format_info(image.format); +- loaded_mip_levels = min(img_info.MipLevels, load_info->MipLevels); ++ loaded_mip_levels = min((img_info.MipLevels - load_info->FirstMipLevel), load_info->MipLevels); + for (i = 0; i < img_info.ArraySize; ++i) + { + struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth }; +@@ -733,7 +734,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; + struct d3dx_pixels src_pixels, dst_pixels; + +- hr = d3dx_image_get_pixels(&image, i, j, &src_pixels); ++ hr = d3dx_image_get_pixels(&image, i, j + load_info->FirstMipLevel, &src_pixels); + if (FAILED(hr)) + goto end; + +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0015-d3dx10-Pass-D3DX10_IMAGE_LOAD_INFO-texture-creation-.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0015-d3dx10-Pass-D3DX10_IMAGE_LOAD_INFO-texture-creation-.patch new file mode 100644 index 00000000..276bbeb8 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0015-d3dx10-Pass-D3DX10_IMAGE_LOAD_INFO-texture-creation-.patch @@ -0,0 +1,109 @@ +From ee999e236f7de9c21cc6cdd9d1e2ecfe85ee43e7 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Fri, 19 Sep 2025 11:45:26 -0400 +Subject: [PATCH] d3dx10: Pass D3DX10_IMAGE_LOAD_INFO texture creation + arguments through in load_texture_data(). + +Signed-off-by: Connor McAdams +--- + dlls/d3dx10_43/tests/d3dx10.c | 12 ++++++------ + dlls/d3dx10_43/texture.c | 18 +++++------------- + 2 files changed, 11 insertions(+), 19 deletions(-) + +diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c +index 2f26f8e14f1..c6cd1fa88cd 100644 +--- a/dlls/d3dx10_43/tests/d3dx10.c ++++ b/dlls/d3dx10_43/tests/d3dx10.c +@@ -1034,7 +1034,7 @@ test_image_load_info[] = + (D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET), 0, + (D3D10_RESOURCE_MISC_GENERATE_MIPS | D3D10_RESOURCE_MISC_TEXTURECUBE) } }, + { 4, 4, 1, 6, 3, DDS_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_BC1_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, +- D3DX10_IFF_DDS }, .todo_resource_desc = TRUE, ++ D3DX10_IFF_DDS } + }, + /* + * Even with the autogen mips misc flag specified, the mip levels argument +@@ -1050,7 +1050,7 @@ test_image_load_info[] = + (D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET), 0, + (D3D10_RESOURCE_MISC_GENERATE_MIPS | D3D10_RESOURCE_MISC_TEXTURECUBE) } }, + { 4, 4, 1, 6, 3, DDS_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_BC1_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, +- D3DX10_IFF_DDS }, .todo_resource_desc = TRUE, ++ D3DX10_IFF_DDS } + }, + }; + +@@ -1116,7 +1116,7 @@ static const struct test_invalid_image_load_info + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_CPU_ACCESS_READ, D3D10_USAGE_DYNAMIC, + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT + }, +- E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ E_INVALIDARG, S_OK, E_INVALIDARG + }, + { + test_dds_32bpp, sizeof(test_dds_32bpp), +@@ -1124,7 +1124,7 @@ static const struct test_invalid_image_load_info + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_USAGE_DEFAULT, + D3D10_BIND_DEPTH_STENCIL, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT + }, +- E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ E_INVALIDARG, S_OK, E_INVALIDARG + }, + /* + * D3D10_RESOURCE_MISC_GENERATE_MIPS requires binding as a shader resource +@@ -1136,7 +1136,7 @@ static const struct test_invalid_image_load_info + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_USAGE_DEFAULT, + D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_RESOURCE_MISC_GENERATE_MIPS, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT + }, +- E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ E_INVALIDARG, S_OK, E_INVALIDARG + }, + /* Can't set the cube texture flag if the image isn't a cube texture. */ + { +@@ -1145,7 +1145,7 @@ static const struct test_invalid_image_load_info + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_USAGE_DEFAULT, + D3DX10_DEFAULT, D3DX10_DEFAULT, D3D10_RESOURCE_MISC_TEXTURECUBE, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT + }, +- E_INVALIDARG, S_OK, E_INVALIDARG, .todo_hr = TRUE, .todo_create_device_object_hr = TRUE, ++ E_INVALIDARG, S_OK, E_INVALIDARG + }, + }; + +diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c +index cd5fc112110..80f17fdde0f 100644 +--- a/dlls/d3dx10_43/texture.c ++++ b/dlls/d3dx10_43/texture.c +@@ -646,15 +646,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + if (!data || !size) + return E_FAIL; + +- if (load_info->Usage != D3DX10_DEFAULT) +- FIXME("load_info->Usage is ignored.\n"); +- if (load_info->BindFlags != D3DX10_DEFAULT) +- FIXME("load_info->BindFlags is ignored.\n"); +- if (load_info->CpuAccessFlags != D3DX10_DEFAULT) +- FIXME("load_info->CpuAccessFlags is ignored.\n"); +- if (load_info->MiscFlags != D3DX10_DEFAULT) +- FIXME("load_info->MiscFlags is ignored.\n"); +- + *resource_data = NULL; + if (!load_info->Filter || load_info->Filter == D3DX10_DEFAULT) + load_info->Filter = D3DX10_FILTER_TRIANGLE | D3DX10_FILTER_DITHER; +@@ -795,10 +786,11 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO + *resource_data = (D3D10_SUBRESOURCE_DATA *)sub_rsrcs; + sub_rsrcs = NULL; + +- load_info->Usage = D3D10_USAGE_DEFAULT; +- load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; +- load_info->CpuAccessFlags = 0; +- load_info->MiscFlags = img_info.MiscFlags; ++ load_info->Usage = (load_info->Usage == D3DX10_DEFAULT) ? D3D10_USAGE_DEFAULT : load_info->Usage; ++ load_info->BindFlags = (load_info->BindFlags == D3DX10_DEFAULT) ? D3D10_BIND_SHADER_RESOURCE : load_info->BindFlags; ++ load_info->CpuAccessFlags = (load_info->CpuAccessFlags == D3DX10_DEFAULT) ? 0 : load_info->CpuAccessFlags; ++ load_info->MiscFlags = (load_info->MiscFlags == D3DX10_DEFAULT) ? 0 : load_info->MiscFlags; ++ load_info->MiscFlags |= img_info.MiscFlags; + if (load_info->pSrcInfo) + *load_info->pSrcInfo = img_info; + +-- +2.51.0 + diff --git a/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0016-d3dx11-Implement-D3DX11CreateTextureFromMemory-using.patch b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0016-d3dx11-Implement-D3DX11CreateTextureFromMemory-using.patch new file mode 100644 index 00000000..6a356d77 --- /dev/null +++ b/patches/d3dx11_43-D3DX11CreateTextureFromMemory/0016-d3dx11-Implement-D3DX11CreateTextureFromMemory-using.patch @@ -0,0 +1,2215 @@ +From a9453aa73ee6fc957e3f1e94efdb7bda3e254455 Mon Sep 17 00:00:00 2001 +From: Connor McAdams +Date: Fri, 19 Sep 2025 12:13:27 -0400 +Subject: [PATCH] d3dx11: Implement D3DX11CreateTextureFromMemory() using + shared code. + +Signed-off-by: Connor McAdams +--- + dlls/d3dx11_42/tests/Makefile.in | 2 +- + dlls/d3dx11_43/tests/Makefile.in | 2 +- + dlls/d3dx11_43/tests/d3dx11.c | 1795 +++++++++++++++++++++++++++++- + dlls/d3dx11_43/texture.c | 288 ++++- + 4 files changed, 2082 insertions(+), 5 deletions(-) + +diff --git a/dlls/d3dx11_42/tests/Makefile.in b/dlls/d3dx11_42/tests/Makefile.in +index f18be76d9d5..7eae4f26e0d 100644 +--- a/dlls/d3dx11_42/tests/Makefile.in ++++ b/dlls/d3dx11_42/tests/Makefile.in +@@ -1,5 +1,5 @@ + TESTDLL = d3dx11_42.dll +-IMPORTS = d3dx11_42 ++IMPORTS = d3dx11_42 ole32 + PARENTSRC = ../../d3dx11_43/tests + + SOURCES = \ +diff --git a/dlls/d3dx11_43/tests/Makefile.in b/dlls/d3dx11_43/tests/Makefile.in +index 3283e251bdd..fc9007fc878 100644 +--- a/dlls/d3dx11_43/tests/Makefile.in ++++ b/dlls/d3dx11_43/tests/Makefile.in +@@ -1,5 +1,5 @@ + TESTDLL = d3dx11_43.dll +-IMPORTS = d3dx11 ++IMPORTS = d3dx11 ole32 + + SOURCES = \ + d3dx11.c +diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c +index 5e2d28824c3..81bffdf4395 100644 +--- a/dlls/d3dx11_43/tests/d3dx11.c ++++ b/dlls/d3dx11_43/tests/d3dx11.c +@@ -20,15 +20,43 @@ + #include "initguid.h" + #include "d3d11.h" + #include "d3dx11.h" ++#include "wine/wined3d.h" + #include "wine/test.h" + #include + ++#define D3DERR_INVALIDCALL 0x8876086c ++#define DDS_RESOURCE_MISC_TEXTURECUBE 0x04 ++ ++static bool wined3d_opengl; ++ + #ifndef MAKEFOURCC + #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ + ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) + #endif + ++static DXGI_FORMAT block_compressed_formats[] = ++{ ++ DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB, ++ DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB, ++ DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB, ++ DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM, ++ DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM, ++ DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16, ++ DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB ++}; ++ ++static BOOL is_block_compressed(DXGI_FORMAT format) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(block_compressed_formats); ++i) ++ if (format == block_compressed_formats[i]) ++ return TRUE; ++ ++ return FALSE; ++} ++ + static unsigned int get_bpp_from_format(DXGI_FORMAT format) + { + switch (format) +@@ -163,6 +191,13 @@ static unsigned int get_bpp_from_format(DXGI_FORMAT format) + } + } + ++static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) ++{ ++ unsigned int diff = x > y ? x - y : y - x; ++ ++ return diff <= max_diff; ++} ++ + /* 1x1 bmp (1 bpp) */ + static const unsigned char bmp_1bpp[] = + { +@@ -384,6 +419,974 @@ static const unsigned char noimage[4] = + 0x11,0x22,0x33,0x44 + }; + ++/* 1x1 1bpp bmp image */ ++static const BYTE test_bmp_1bpp[] = ++{ ++ 0x42, 0x4d, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x28, 0x00, ++ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x02, 0x00, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf1, 0xf2, 0xf3, 0x80, 0xf4, 0xf5, 0xf6, 0x81, 0x00, 0x00, ++ 0x00, 0x00 ++}; ++static const BYTE test_bmp_1bpp_data[] = ++{ ++ 0xf3, 0xf2, 0xf1, 0xff ++}; ++ ++/* 1x1 4bpp bmp image */ ++static const BYTE test_bmp_4bpp[] = ++{ ++ 0x42, 0x4d, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x28, 0x00, ++ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x02, 0x00, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf1, 0xf2, 0xf3, 0x80, 0xf4, 0xf5, 0xf6, 0x81, 0x00, 0x00, ++ 0x00, 0x00 ++}; ++static const BYTE test_bmp_4bpp_data[] = ++{ ++ 0xf3, 0xf2, 0xf1, 0xff ++}; ++ ++/* 1x1 8bpp bmp image */ ++static const BYTE test_bmp_8bpp[] = ++{ ++ 0x42, 0x4d, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x28, 0x00, ++ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x02, 0x00, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf1, 0xf2, 0xf3, 0x80, 0xf4, 0xf5, 0xf6, 0x81, 0x00, 0x00, ++ 0x00, 0x00 ++}; ++static const BYTE test_bmp_8bpp_data[] = ++{ ++ 0xf3, 0xf2, 0xf1, 0xff ++}; ++ ++/* 1x1 16bpp bmp image */ ++static const BYTE test_bmp_16bpp[] = ++{ ++ 0x42, 0x4d, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, ++ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x42, 0x00, 0x00, 0x00, 0x00 ++}; ++static const BYTE test_bmp_16bpp_data[] = ++{ ++ 0x84, 0x84, 0x73, 0xff ++}; ++ ++/* 1x1 24bpp bmp image */ ++static const BYTE test_bmp_24bpp[] = ++{ ++ 0x42, 0x4d, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, ++ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x84, 0x84, 0x00, 0x00, 0x00 ++}; ++static const BYTE test_bmp_24bpp_data[] = ++{ ++ 0x84, 0x84, 0x73, 0xff ++}; ++ ++/* 2x2 32bpp XRGB bmp image */ ++static const BYTE test_bmp_32bpp_xrgb[] = ++{ ++ 0x42, 0x4d, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb0, 0xc0, 0x00, 0xa1, 0xb1, 0xc1, 0x00, 0xa2, 0xb2, ++ 0xc2, 0x00, 0xa3, 0xb3, 0xc3, 0x00 ++}; ++static const BYTE test_bmp_32bpp_xrgb_data[] = ++{ ++ 0xc2, 0xb2, 0xa2, 0xff, 0xc3, 0xb3, 0xa3, 0xff, 0xc0, 0xb0, 0xa0, 0xff, 0xc1, 0xb1, 0xa1, 0xff ++ ++}; ++ ++/* 2x2 32bpp ARGB bmp image */ ++static const BYTE test_bmp_32bpp_argb[] = ++{ ++ 0x42, 0x4d, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb0, 0xc0, 0x00, 0xa1, 0xb1, 0xc1, 0x00, 0xa2, 0xb2, ++ 0xc2, 0x00, 0xa3, 0xb3, 0xc3, 0x01 ++}; ++static const BYTE test_bmp_32bpp_argb_data[] = ++{ ++ 0xc2, 0xb2, 0xa2, 0xff, 0xc3, 0xb3, 0xa3, 0xff, 0xc0, 0xb0, 0xa0, 0xff, 0xc1, 0xb1, 0xa1, 0xff ++ ++}; ++ ++/* 1x1 8bpp gray png image */ ++static const BYTE test_png_8bpp_gray[] = ++{ ++ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, ++ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x7e, 0x9b, ++ 0x55, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0x0f, 0x00, 0x01, ++ 0x01, 0x01, 0x00, 0x1b, 0xb6, 0xee, 0x56, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, ++ 0x42, 0x60, 0x82 ++}; ++static const BYTE test_png_8bpp_gray_data[] = ++{ ++ 0xff, 0xff, 0xff, 0xff ++}; ++ ++/* 1x1 jpg image */ ++static const BYTE test_jpg[] = ++{ ++ 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x01, 0x2c, ++ 0x01, 0x2c, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, ++ 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, ++ 0x0b, 0x09, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f, 0x11, 0x11, 0x13, 0x16, 0x1c, 0x17, 0x13, ++ 0x14, 0x1a, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1a, 0x1d, 0x1d, 0x1f, 0x1f, 0x1f, 0x13, 0x17, ++ 0x22, 0x24, 0x22, 0x1e, 0x24, 0x1c, 0x1e, 0x1f, 0x1e, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x05, 0x05, ++ 0x05, 0x07, 0x06, 0x07, 0x0e, 0x08, 0x08, 0x0e, 0x1e, 0x14, 0x11, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, ++ 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, ++ 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, ++ 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0xff, 0xc0, ++ 0x00, 0x11, 0x08, 0x00, 0x01, 0x00, 0x01, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, ++ 0x01, 0xff, 0xc4, 0x00, 0x15, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0xc4, 0x00, 0x14, 0x10, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, ++ 0x00, 0x14, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, ++ 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xb2, 0xc0, 0x07, 0xff, 0xd9 ++}; ++static const BYTE test_jpg_data[] = ++{ ++ 0xff, 0xff, 0xff, 0xff ++}; ++ ++/* 1x1 gif image */ ++static const BYTE test_gif[] = ++{ ++ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, ++ 0x01, 0x00, 0x3b ++}; ++static const BYTE test_gif_data[] = ++{ ++ 0xff, 0xff, 0xff, 0xff ++}; ++ ++/* 1x1 tiff image */ ++static const BYTE test_tiff[] = ++{ ++ 0x49, 0x49, 0x2a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xfe, 0x00, ++ 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x03, 0x01, ++ 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x01, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x00, 0xd8, 0x00, ++ 0x00, 0x00, 0x11, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x12, 0x01, ++ 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x01, 0x03, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x16, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, ++ 0x00, 0x00, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1a, 0x01, ++ 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x05, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x28, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x6d, 0x65, ++ 0x68, 0x2f, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, ++ 0x69, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, ++ 0x00, 0x00, 0x00, 0x01 ++}; ++static const BYTE test_tiff_data[] = ++{ ++ 0x00, 0x00, 0x00, 0xff ++}; ++ ++/* 1x1 alpha dds image */ ++static const BYTE test_dds_alpha[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff ++}; ++static const BYTE test_dds_alpha_data[] = ++{ ++ 0xff ++}; ++ ++/* 1x1 luminance dds image */ ++static const BYTE test_dds_luminance[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x82 ++}; ++static const BYTE test_dds_luminance_data[] = ++{ ++ 0x82, 0x82, 0x82, 0xff ++}; ++ ++/* 1x1 16bpp dds image */ ++static const BYTE test_dds_16bpp[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, ++ 0xe0, 0x03, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x0e, 0x42 ++}; ++static const BYTE test_dds_16bpp_data[] = ++{ ++ 0x84, 0x84, 0x73, 0xff ++}; ++ ++/* 1x1 24bpp dds image */ ++static const BYTE test_dds_24bpp[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, ++ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x70, 0x81, 0x83 ++}; ++static const BYTE test_dds_24bpp_data[] = ++{ ++ 0x83, 0x81, 0x70, 0xff ++}; ++ ++/* 1x1 32bpp dds image */ ++static const BYTE test_dds_32bpp[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, ++ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x70, 0x81, 0x83, 0xff ++}; ++static const BYTE test_dds_32bpp_data[] = ++{ ++ 0x83, 0x81, 0x70, 0xff ++}; ++ ++/* 1x1 64bpp dds image */ ++static const BYTE test_dds_64bpp[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x83, 0x83, 0x81, 0x81, 0x70, 0x70, 0xff, 0xff ++}; ++static const BYTE test_dds_64bpp_data[] = ++{ ++ 0x83, 0x83, 0x81, 0x81, 0x70, 0x70, 0xff, 0xff ++}; ++ ++/* 1x1 96bpp dds image */ ++static const BYTE test_dds_96bpp[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x31, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x84, 0x83, 0x03, 0x3f, 0x82, 0x81, 0x01, 0x3f, 0xe2, 0xe0, 0xe0, 0x3e ++}; ++static const BYTE test_dds_96bpp_data[] = ++{ ++ 0x84, 0x83, 0x03, 0x3f, 0x82, 0x81, 0x01, 0x3f, 0xe2, 0xe0, 0xe0, 0x3e ++}; ++ ++/* 1x1 128bpp dds image */ ++static const BYTE test_dds_128bpp[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x84, 0x83, 0x03, 0x3f, 0x82, 0x81, 0x01, 0x3f, 0xe2, 0xe0, 0xe0, 0x3e, 0x00, 0x00, 0x80, 0x3f ++}; ++static const BYTE test_dds_128bpp_data[] = ++{ ++ 0x84, 0x83, 0x03, 0x3f, 0x82, 0x81, 0x01, 0x3f, 0xe2, 0xe0, 0xe0, 0x3e, 0x00, 0x00, 0x80, 0x3f ++ ++}; ++ ++/* 4x4 DXT1 dds image */ ++static const BYTE test_dds_dxt1[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x2a, 0x31, 0xf5, 0xbc, 0xe3, 0x6e, 0x2a, 0x3a ++}; ++static const BYTE test_dds_dxt1_data[] = ++{ ++ 0x2a, 0x31, 0xf5, 0xbc, 0xe3, 0x6e, 0x2a, 0x3a ++}; ++ ++/* 4x8 DXT1 dds image */ ++static const BYTE test_dds_dxt1_4x8[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x92, 0xce, 0x09, 0x7a, 0x5d, 0xdd, 0xa7, 0x26, 0x55, 0xde, 0xaf, 0x52, 0xbc, 0xf8, 0x6c, 0x44, ++ 0x53, 0xbd, 0x8b, 0x72, 0x55, 0x33, 0x88, 0xaa, 0xb2, 0x9c, 0x6c, 0x93, 0x55, 0x00, 0x55, 0x00, ++ 0x0f, 0x9c, 0x0f, 0x9c, 0x00, 0x00, 0x00, 0x00, ++}; ++static const BYTE test_dds_dxt1_4x8_data[] = ++{ ++ 0x92, 0xce, 0x09, 0x7a, 0x5d, 0xdd, 0xa7, 0x26, 0x55, 0xde, 0xaf, 0x52, 0xbc, 0xf8, 0x6c, 0x44, ++}; ++ ++/* 4x4 DXT2 dds image */ ++static const BYTE test_dds_dxt2[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xde, 0xc4, 0x10, 0x2f, 0xbf, 0xff, 0x7b, ++ 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x53, 0x00, 0x00, 0x52, 0x52, 0x55, 0x55, ++ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0x59, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55 ++}; ++static const BYTE test_dds_dxt2_data[] = ++{ ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xde, 0xc4, 0x10, 0x2f, 0xbf, 0xff, 0x7b ++ ++}; ++ ++/* 1x3 DXT3 dds image */ ++static const BYTE test_dds_dxt3[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x92, 0x38, 0x84, 0x00, 0xff, 0x55, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x53, 0x8b, 0x53, 0x8b, 0x00, 0x00, 0x00, 0x00 ++}; ++static const BYTE test_dds_dxt3_data[] = ++{ ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4e, 0x92, 0xd6, 0x83, 0x00, 0xaa, 0x55, 0x55 ++ ++}; ++ ++/* 4x4 DXT4 dds image */ ++static const BYTE test_dds_dxt4[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xde, 0xc4, 0x10, 0x2f, 0xbf, 0xff, 0x7b, ++ 0xff, 0x00, 0x40, 0x02, 0x24, 0x49, 0x92, 0x24, 0x57, 0x53, 0x00, 0x00, 0x52, 0x52, 0x55, 0x55, ++ 0xff, 0x00, 0x48, 0x92, 0x24, 0x49, 0x92, 0x24, 0xce, 0x59, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55 ++}; ++static const BYTE test_dds_dxt4_data[] = ++{ ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xde, 0xc4, 0x10, 0x2f, 0xbf, 0xff, 0x7b ++ ++}; ++ ++/* 4x2 DXT5 dds image */ ++static const BYTE test_dds_dxt5[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x87, 0x0f, 0x78, 0x05, 0x05, 0x50, 0x50 ++}; ++static const BYTE test_dds_dxt5_data[] = ++{ ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x87, 0x0f, 0x78, 0x05, 0x05, 0x05, 0x05 ++ ++}; ++ ++/* 8x8 DXT5 dds image */ ++static const BYTE test_dds_dxt5_8x8[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x8a, 0x72, 0x39, 0x5e, 0x5e, 0xfa, 0xa8, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd7, 0xd5, 0x4a, 0x2d, 0x2d, 0xad, 0xfd, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x9a, 0x73, 0x83, 0xa0, 0xf0, 0x78, 0x78, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x5b, 0x06, 0x19, 0x00, 0xe8, 0x78, 0x58, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xbe, 0x8c, 0x49, 0x35, 0xb5, 0xff, 0x7f, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x84, 0xab, 0x59, 0x11, 0xff, 0x11, 0xff, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x6a, 0xf0, 0x6a, 0x00, 0x00, 0x00, 0x00, ++}; ++static const BYTE test_dds_dxt5_8x8_data[] = ++{ ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x8a, 0x72, 0x39, 0x5e, 0x5e, 0xfa, 0xa8, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd7, 0xd5, 0x4a, 0x2d, 0x2d, 0xad, 0xfd, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x9a, 0x73, 0x83, 0xa0, 0xf0, 0x78, 0x78, ++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x5b, 0x06, 0x19, 0x00, 0xe8, 0x78, 0x58, ++}; ++ ++/* 4x4 BC4 dds image */ ++static const BYTE test_dds_bc4[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x42, 0x43, 0x34, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xd9, 0x15, 0xbc, 0x41, 0x5b, 0xa3, 0x3d, 0x3a, 0x8f, 0x3d, 0x45, 0x81, 0x20, 0x45, 0x81, 0x20, ++ 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++static const BYTE test_dds_bc4_data[] = ++{ ++ 0xd9, 0x15, 0xbc, 0x41, 0x5b, 0xa3, 0x3d, 0x3a ++}; ++ ++/* 6x3 BC5 dds image */ ++static const BYTE test_dds_bc5[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x42, 0x43, 0x35, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x9f, 0x28, 0x73, 0xac, 0xd5, 0x80, 0xaa, 0xd5, 0x70, 0x2c, 0x4e, 0xd6, 0x76, 0x1d, 0xd6, 0x76, ++ 0xd5, 0x0f, 0xc3, 0x50, 0x96, 0xcf, 0x53, 0x96, 0xdf, 0x16, 0xc3, 0x50, 0x96, 0xcf, 0x53, 0x96, ++ 0x83, 0x55, 0x08, 0x83, 0x30, 0x08, 0x83, 0x30, 0x79, 0x46, 0x31, 0x1c, 0xc3, 0x31, 0x1c, 0xc3, ++ 0x6d, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++static const BYTE test_dds_bc5_data[] = ++{ ++ 0x95, 0x35, 0xe2, 0xa3, 0xf5, 0xd2, 0x28, 0x68, 0x65, 0x32, 0x7c, 0x4e, 0xdb, 0xe4, 0x56, 0x0a, ++ 0xb9, 0x33, 0xaf, 0xf0, 0x52, 0xbe, 0xed, 0x27, 0xb4, 0x2e, 0xa6, 0x60, 0x4e, 0xb6, 0x5d, 0x3f ++ ++}; ++ ++/* 4x4 DXT1 cube map */ ++static const BYTE test_dds_cube[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, 0x32, 0x96, 0x0b, 0x7b, 0xcc, 0x55, 0xcc, 0x55, ++ 0x0e, 0x84, 0x0e, 0x84, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0x32, 0x96, 0x0b, 0x7b, 0xcc, 0x55, 0xcc, 0x55, 0x0e, 0x84, 0x0e, 0x84, 0x00, 0x00, 0x00, 0x00, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, 0x32, 0x96, 0x0b, 0x7b, 0xcc, 0x55, 0xcc, 0x55, ++ 0x0e, 0x84, 0x0e, 0x84, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0x32, 0x96, 0x0b, 0x7b, 0xcc, 0x55, 0xcc, 0x55, 0x0e, 0x84, 0x0e, 0x84, 0x00, 0x00, 0x00, 0x00, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, 0x32, 0x96, 0x0b, 0x7b, 0xcc, 0x55, 0xcc, 0x55, ++ 0x0e, 0x84, 0x0e, 0x84, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0x32, 0x96, 0x0b, 0x7b, 0xcc, 0x55, 0xcc, 0x55, 0x0e, 0x84, 0x0e, 0x84, 0x00, 0x00, 0x00, 0x00 ++}; ++static const BYTE test_dds_cube_data[] = ++{ ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7, ++ 0xf5, 0xa7, 0x08, 0x69, 0x74, 0xc0, 0xbf, 0xd7 ++}; ++ ++/* 4x4x2 DXT3 volume dds, 2 mipmaps */ ++static const BYTE test_dds_volume[] = ++{ ++ 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x8a, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, ++ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x87, 0x0f, 0x78, 0x05, 0x05, 0x50, 0x50, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x87, 0x0f, 0x78, 0x05, 0x05, 0x50, 0x50, ++ 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0xcf, 0x79, 0x01, 0x54, 0x5c, 0x5c, ++ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, 0xef, 0x7b, 0xaa, 0xab, 0xab, 0xab ++}; ++static const BYTE test_dds_volume_data[] = ++{ ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x87, 0x0f, 0x78, 0x05, 0x05, 0x50, 0x50, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x87, 0x0f, 0x78, 0x05, 0x05, 0x50, 0x50, ++}; ++ ++/* ++ * 4x4x4 24-bit volume dds, 3 mipmaps. Level 0 is red, level 1 is green, level 2 is ++ * blue. ++ */ ++static const uint8_t dds_volume_24bit_4_4_4[] = ++{ ++ 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x0f,0x10,0x82,0x00,0x04,0x00,0x00,0x00, ++ 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, ++ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, ++ 0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0x00 ++}; ++ ++/* ++ * 8x8 24-bit dds, 4 mipmaps. Level 0 is red, level 1 is green, level 2 is ++ * blue, and level 3 is black. ++ */ ++static const uint8_t dds_24bit_8_8[] = ++{ ++ 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x0a,0x00,0x08,0x00,0x00,0x00, ++ 0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, ++ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, ++ 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, ++ 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00 ++}; ++ ++/* 1x1 wmp image */ ++static const BYTE test_wmp[] = ++{ ++ 0x49, 0x49, 0xbc, 0x01, 0x20, 0x00, 0x00, 0x00, 0x24, 0xc3, 0xdd, 0x6f, 0x03, 0x4e, 0xfe, 0x4b, ++ 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x08, 0x00, 0x01, 0xbc, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xbc, ++ 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbc, 0x04, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x81, 0xbc, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x82, 0xbc, 0x0b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x06, 0xc0, 0x42, 0x83, 0xbc, ++ 0x0b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x06, 0xc0, 0x42, 0xc0, 0xbc, 0x04, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0xc1, 0xbc, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x92, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x4d, 0x50, 0x48, 0x4f, 0x54, 0x4f, 0x00, 0x11, 0x45, ++ 0xc0, 0x71, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xc0, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x25, 0xff, 0xff, 0x00, 0x00, 0x01, ++ 0x01, 0xc8, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x10, 0x10, 0xa6, 0x18, 0x8c, 0x21, ++ 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x4e, 0x0f, 0x3a, 0x4c, 0x94, 0x9d, 0xba, 0x79, 0xe7, 0x38, ++ 0x4c, 0xcf, 0x14, 0xc3, 0x43, 0x91, 0x88, 0xfb, 0xdc, 0xe0, 0x7c, 0x34, 0x70, 0x9b, 0x28, 0xa9, ++ 0x18, 0x74, 0x62, 0x87, 0x8e, 0xe4, 0x68, 0x5f, 0xb9, 0xcc, 0x0e, 0xe1, 0x8c, 0x76, 0x3a, 0x9b, ++ 0x82, 0x76, 0x71, 0x13, 0xde, 0x50, 0xd4, 0x2d, 0xc2, 0xda, 0x1e, 0x3b, 0xa6, 0xa1, 0x62, 0x7b, ++ 0xca, 0x1a, 0x85, 0x4b, 0x6e, 0x74, 0xec, 0x60 ++}; ++static const BYTE test_wmp_data[] = ++{ ++ 0xff, 0xff, 0xff, 0xff ++}; ++ ++static const struct test_image ++{ ++ const BYTE *data; ++ unsigned int size; ++ const BYTE *expected_data; ++ D3DX11_IMAGE_INFO expected_info; ++ D3D11_SRV_DIMENSION expected_srv_dimension; ++} ++test_image[] = ++{ ++ { ++ test_bmp_1bpp, sizeof(test_bmp_1bpp), test_bmp_1bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_BMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_bmp_4bpp, sizeof(test_bmp_4bpp), test_bmp_4bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_BMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_bmp_8bpp, sizeof(test_bmp_8bpp), test_bmp_8bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_BMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_bmp_16bpp, sizeof(test_bmp_16bpp), test_bmp_16bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_BMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_bmp_24bpp, sizeof(test_bmp_24bpp), test_bmp_24bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_BMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_bmp_32bpp_xrgb, sizeof(test_bmp_32bpp_xrgb), test_bmp_32bpp_xrgb_data, ++ {2, 2, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_BMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_bmp_32bpp_argb, sizeof(test_bmp_32bpp_argb), test_bmp_32bpp_argb_data, ++ {2, 2, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_BMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_png_8bpp_gray, sizeof(test_png_8bpp_gray), test_png_8bpp_gray_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_PNG}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_jpg, sizeof(test_jpg), test_jpg_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_JPG}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_gif, sizeof(test_gif), test_gif_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_GIF}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_tiff, sizeof(test_tiff), test_tiff_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_TIFF}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_alpha, sizeof(test_dds_alpha), test_dds_alpha_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_luminance, sizeof(test_dds_luminance), test_dds_luminance_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_16bpp, sizeof(test_dds_16bpp), test_dds_16bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_24bpp, sizeof(test_dds_24bpp), test_dds_24bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), test_dds_32bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_64bpp, sizeof(test_dds_64bpp), test_dds_64bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R16G16B16A16_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_96bpp, sizeof(test_dds_96bpp), test_dds_96bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R32G32B32_FLOAT, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_128bpp, sizeof(test_dds_128bpp), test_dds_128bpp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R32G32B32A32_FLOAT, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_dxt1, sizeof(test_dds_dxt1), test_dds_dxt1_data, ++ {4, 4, 1, 1, 1, 0, DXGI_FORMAT_BC1_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_dxt1_4x8, sizeof(test_dds_dxt1_4x8), test_dds_dxt1_4x8_data, ++ {4, 8, 1, 1, 4, 0, DXGI_FORMAT_BC1_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_dxt2, sizeof(test_dds_dxt2), test_dds_dxt2_data, ++ {4, 4, 1, 1, 3, 0, DXGI_FORMAT_BC2_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_dxt3, sizeof(test_dds_dxt3), test_dds_dxt3_data, ++ {1, 3, 1, 1, 2, 0, DXGI_FORMAT_BC2_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_dxt4, sizeof(test_dds_dxt4), test_dds_dxt4_data, ++ {4, 4, 1, 1, 3, 0, DXGI_FORMAT_BC3_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_dxt5, sizeof(test_dds_dxt5), test_dds_dxt5_data, ++ {4, 2, 1, 1, 1, 0, DXGI_FORMAT_BC3_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_dxt5_8x8, sizeof(test_dds_dxt5_8x8), test_dds_dxt5_8x8_data, ++ {8, 8, 1, 1, 4, 0, DXGI_FORMAT_BC3_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_bc4, sizeof(test_dds_bc4), test_dds_bc4_data, ++ {4, 4, 1, 1, 3, 0, DXGI_FORMAT_BC4_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_bc5, sizeof(test_dds_bc5), test_dds_bc5_data, ++ {6, 3, 1, 1, 3, 0, DXGI_FORMAT_BC5_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++ { ++ test_dds_cube, sizeof(test_dds_cube), test_dds_cube_data, ++ {4, 4, 1, 6, 3, 0x4, DXGI_FORMAT_BC1_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURECUBE ++ }, ++ { ++ test_dds_volume, sizeof(test_dds_volume), test_dds_volume_data, ++ {4, 4, 2, 1, 3, 0, DXGI_FORMAT_BC2_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE3D, D3DX11_IFF_DDS}, ++ D3D11_SRV_DIMENSION_TEXTURE3D ++ }, ++ { ++ test_wmp, sizeof(test_wmp), test_wmp_data, ++ {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_WMP}, ++ D3D11_SRV_DIMENSION_TEXTURE2D ++ }, ++}; ++ ++static const struct test_image_load_info ++{ ++ const uint8_t *data; ++ uint32_t size; ++ D3DX11_IMAGE_LOAD_INFO load_info; ++ HRESULT expected_hr; ++ ++ D3D11_SRV_DIMENSION expected_srv_dimension; ++ D3D11_RESOURCE_DIMENSION expected_type; ++ union ++ { ++ D3D11_TEXTURE2D_DESC desc_2d; ++ D3D11_TEXTURE3D_DESC desc_3d; ++ } expected_resource_desc; ++ D3DX11_IMAGE_INFO expected_info; ++ BOOL todo_resource_desc; ++} ++test_image_load_info[] = ++{ ++ /* ++ * FirstMipLevel set to 1 - Does not match D3DX_SKIP_DDS_MIP_LEVELS ++ * behavior from d3dx9, image info values represent mip level 0, and ++ * texture values are pulled from this. The texture data is loaded ++ * starting from the specified mip level, however. ++ */ ++ { ++ dds_volume_24bit_4_4_4, sizeof(dds_volume_24bit_4_4_4), ++ { D3DX11_FROM_FILE, D3DX11_DEFAULT, 0, 1, D3DX11_DEFAULT, (D3D11_USAGE)D3DX11_DEFAULT, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ S_OK, D3D11_SRV_DIMENSION_TEXTURE3D, D3D11_RESOURCE_DIMENSION_TEXTURE3D, ++ { .desc_3d = { 4, 4, 4, 3, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0 } }, ++ { 4, 4, 4, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE3D, D3DX11_IFF_DDS }, ++ }, ++ /* ++ * Autogen mips misc flag specified. In the case of a cube texture image, ++ * the autogen mips flag is OR'd against D3D11_RESOURCE_MISC_TEXTURECUBE, ++ * even if it isn't specified. ++ */ ++ { ++ test_dds_cube, sizeof(test_dds_cube), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, (D3D11_USAGE)D3DX11_DEFAULT, ++ (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), D3DX11_DEFAULT, D3D11_RESOURCE_MISC_GENERATE_MIPS, ++ DXGI_FORMAT_R8G8B8A8_UNORM, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ S_OK, D3D11_SRV_DIMENSION_TEXTURECUBE, D3D11_RESOURCE_DIMENSION_TEXTURE2D, ++ { .desc_2d = { 4, 4, 3, 6, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D11_USAGE_DEFAULT, ++ (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), 0, ++ (D3D11_RESOURCE_MISC_GENERATE_MIPS | D3D11_RESOURCE_MISC_TEXTURECUBE) } }, ++ { 4, 4, 1, 6, 3, DDS_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_BC1_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX11_IFF_DDS }, ++ }, ++ /* ++ * Even with the autogen mips misc flag specified, the mip levels argument ++ * of load info is respected. ++ */ ++ { ++ test_dds_cube, sizeof(test_dds_cube), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, 2, (D3D11_USAGE)D3DX11_DEFAULT, ++ (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), D3DX11_DEFAULT, D3D11_RESOURCE_MISC_GENERATE_MIPS, ++ DXGI_FORMAT_R8G8B8A8_UNORM, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ S_OK, D3D11_SRV_DIMENSION_TEXTURECUBE, D3D11_RESOURCE_DIMENSION_TEXTURE2D, ++ { .desc_2d = { 4, 4, 2, 6, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D11_USAGE_DEFAULT, ++ (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), 0, ++ (D3D11_RESOURCE_MISC_GENERATE_MIPS | D3D11_RESOURCE_MISC_TEXTURECUBE) } }, ++ { 4, 4, 1, 6, 3, DDS_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_BC1_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX11_IFF_DDS }, ++ }, ++}; ++ ++static const struct test_invalid_image_load_info ++{ ++ const uint8_t *data; ++ uint32_t size; ++ D3DX11_IMAGE_LOAD_INFO load_info; ++ HRESULT expected_hr; ++ HRESULT expected_process_hr; ++ HRESULT expected_create_device_object_hr; ++ BOOL todo_hr; ++ BOOL todo_process_hr; ++ BOOL todo_create_device_object_hr; ++} ++test_invalid_image_load_info[] = ++{ ++ /* ++ * A depth value that isn't D3DX11_FROM_FILE/D3DX11_DEFAULT/0 on a 2D ++ * texture results in failure. ++ */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, 2, D3DX11_DEFAULT, D3DX11_DEFAULT, (D3D11_USAGE)D3DX11_DEFAULT, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ E_FAIL, E_FAIL, ++ }, ++ /* Invalid filter value. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, (D3D11_USAGE)D3DX11_DEFAULT, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, 7, D3DX11_DEFAULT }, ++ D3DERR_INVALIDCALL, D3DERR_INVALIDCALL, ++ }, ++ /* Invalid mipfilter value, only checked if mips are generated. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, (D3D11_USAGE)D3DX11_DEFAULT, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, 7 }, ++ S_OK, S_OK, S_OK ++ }, ++ /* Invalid mipfilter value. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { 2, 2, D3DX11_DEFAULT, D3DX11_DEFAULT, 2, (D3D11_USAGE)D3DX11_DEFAULT, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, 7 }, ++ D3DERR_INVALIDCALL, D3DERR_INVALIDCALL, ++ }, ++ /* ++ * Usage/BindFlags/CpuAccessFlags are validated in the call to ++ * CreateDeviceObject(). ++ */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3D11_CPU_ACCESS_READ, D3D11_USAGE_DYNAMIC, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ E_INVALIDARG, S_OK, E_INVALIDARG, ++ }, ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3D11_USAGE_DEFAULT, ++ D3D11_BIND_DEPTH_STENCIL, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ E_INVALIDARG, S_OK, E_INVALIDARG, ++ }, ++ /* ++ * D3D11_RESOURCE_MISC_GENERATE_MIPS requires binding as a shader resource ++ * and a render target. ++ */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3D11_USAGE_DEFAULT, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ E_INVALIDARG, S_OK, E_INVALIDARG, ++ }, ++ /* Can't set the cube texture flag if the image isn't a cube texture. */ ++ { ++ test_dds_32bpp, sizeof(test_dds_32bpp), ++ { D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3D11_USAGE_DEFAULT, ++ D3DX11_DEFAULT, D3DX11_DEFAULT, D3D11_RESOURCE_MISC_TEXTURECUBE, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT }, ++ E_INVALIDARG, S_OK, E_INVALIDARG ++ }, ++}; ++ + #define check_image_info_values(info, width, height, depth, array_size, mip_levels, misc_flags, format, resource_dimension, \ + image_file_format, wine_todo) \ + check_image_info_values_(__LINE__, info, width, height, depth, array_size, mip_levels, misc_flags, format, resource_dimension, \ +@@ -425,6 +1428,568 @@ static inline void check_image_info_values_(unsigned int line, const D3DX11_IMAG + image_file_format, info->ImageFileFormat); + } + ++#define check_texture2d_desc_values(desc, width, height, mip_levels, array_size, format, sample_count, sample_quality, \ ++ usage, bind_flags, cpu_access_flags, misc_flags, wine_todo) \ ++ check_texture2d_desc_values_(__LINE__, desc, width, height, mip_levels, array_size, format, sample_count, sample_quality, \ ++ usage, bind_flags, cpu_access_flags, misc_flags, wine_todo) ++static inline void check_texture2d_desc_values_(uint32_t line, const D3D11_TEXTURE2D_DESC *desc, uint32_t width, ++ uint32_t height, uint32_t mip_levels, uint32_t array_size, DXGI_FORMAT format, uint32_t sample_count, ++ uint32_t sample_quality, D3D11_USAGE usage, uint32_t bind_flags, uint32_t cpu_access_flags, uint32_t misc_flags, ++ BOOL wine_todo) ++{ ++ const D3D11_TEXTURE2D_DESC expected_desc = { width, height, mip_levels, array_size, format, { sample_count, sample_quality }, ++ usage, bind_flags, cpu_access_flags, misc_flags }; ++ BOOL matched; ++ ++ matched = !memcmp(&expected_desc, desc, sizeof(*desc)); ++ todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected 2D texture desc values.\n"); ++ if (matched) ++ return; ++ ++ todo_wine_if(wine_todo && desc->Width != width) ++ ok_(__FILE__, line)(desc->Width == width, "Expected width %u, got %u.\n", width, desc->Width); ++ todo_wine_if(wine_todo && desc->Height != height) ++ ok_(__FILE__, line)(desc->Height == height, "Expected height %u, got %u.\n", height, desc->Height); ++ todo_wine_if(wine_todo && desc->ArraySize != array_size) ++ ok_(__FILE__, line)(desc->ArraySize == array_size, "Expected array_size %u, got %u.\n", array_size, ++ desc->ArraySize); ++ todo_wine_if(wine_todo && desc->MipLevels != mip_levels) ++ ok_(__FILE__, line)(desc->MipLevels == mip_levels, "Expected mip_levels %u, got %u.\n", mip_levels, ++ desc->MipLevels); ++ ok_(__FILE__, line)(desc->Format == format, "Expected texture format %#x, got %#x.\n", format, desc->Format); ++ todo_wine_if(wine_todo && desc->SampleDesc.Count != sample_count) ++ ok_(__FILE__, line)(desc->SampleDesc.Count == sample_count, "Expected sample_count %u, got %u.\n", sample_count, ++ desc->SampleDesc.Count); ++ todo_wine_if(wine_todo && desc->SampleDesc.Quality != sample_quality) ++ ok_(__FILE__, line)(desc->SampleDesc.Quality == sample_quality, "Expected sample_quality %u, got %u.\n", sample_quality, ++ desc->SampleDesc.Quality); ++ todo_wine_if(wine_todo && desc->Usage != usage) ++ ok_(__FILE__, line)(desc->Usage == usage, "Expected usage %u, got %u.\n", usage, ++ desc->Usage); ++ todo_wine_if(wine_todo && desc->BindFlags != bind_flags) ++ ok_(__FILE__, line)(desc->BindFlags == bind_flags, "Expected bind_flags %#x, got %#x.\n", bind_flags, ++ desc->BindFlags); ++ todo_wine_if(wine_todo && desc->CPUAccessFlags != cpu_access_flags) ++ ok_(__FILE__, line)(desc->CPUAccessFlags == cpu_access_flags, "Expected cpu_access_flags %#x, got %#x.\n", ++ cpu_access_flags, desc->CPUAccessFlags); ++ todo_wine_if(wine_todo && desc->MiscFlags != misc_flags) ++ ok_(__FILE__, line)(desc->MiscFlags == misc_flags, "Expected misc_flags %#x, got %#x.\n", misc_flags, ++ desc->MiscFlags); ++} ++ ++#define check_texture3d_desc_values(desc, width, height, depth, mip_levels, format, usage, bind_flags, cpu_access_flags, \ ++ misc_flags, wine_todo) \ ++ check_texture3d_desc_values_(__LINE__, desc, width, height, depth, mip_levels, format, usage, bind_flags, \ ++ cpu_access_flags, misc_flags, wine_todo) ++static inline void check_texture3d_desc_values_(uint32_t line, const D3D11_TEXTURE3D_DESC *desc, uint32_t width, ++ uint32_t height, uint32_t depth, uint32_t mip_levels, DXGI_FORMAT format, D3D11_USAGE usage, uint32_t bind_flags, ++ uint32_t cpu_access_flags, uint32_t misc_flags, BOOL wine_todo) ++{ ++ const D3D11_TEXTURE3D_DESC expected_desc = { width, height, depth, mip_levels, format, usage, bind_flags, ++ cpu_access_flags, misc_flags }; ++ BOOL matched; ++ ++ matched = !memcmp(&expected_desc, desc, sizeof(*desc)); ++ todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected 3D texture desc values.\n"); ++ if (matched) ++ return; ++ ++ todo_wine_if(wine_todo && desc->Width != width) ++ ok_(__FILE__, line)(desc->Width == width, "Expected width %u, got %u.\n", width, desc->Width); ++ todo_wine_if(wine_todo && desc->Height != height) ++ ok_(__FILE__, line)(desc->Height == height, "Expected height %u, got %u.\n", height, desc->Height); ++ todo_wine_if(wine_todo && desc->Depth != depth) ++ ok_(__FILE__, line)(desc->Depth == depth, "Expected depth %u, got %u.\n", depth, desc->Depth); ++ todo_wine_if(wine_todo && desc->MipLevels != mip_levels) ++ ok_(__FILE__, line)(desc->MipLevels == mip_levels, "Expected mip_levels %u, got %u.\n", mip_levels, ++ desc->MipLevels); ++ ok_(__FILE__, line)(desc->Format == format, "Expected texture format %#x, got %#x.\n", format, desc->Format); ++ todo_wine_if(wine_todo && desc->Usage != usage) ++ ok_(__FILE__, line)(desc->Usage == usage, "Expected usage %u, got %u.\n", usage, ++ desc->Usage); ++ todo_wine_if(wine_todo && desc->BindFlags != bind_flags) ++ ok_(__FILE__, line)(desc->BindFlags == bind_flags, "Expected bind_flags %#x, got %#x.\n", bind_flags, ++ desc->BindFlags); ++ todo_wine_if(wine_todo && desc->CPUAccessFlags != cpu_access_flags) ++ ok_(__FILE__, line)(desc->CPUAccessFlags == cpu_access_flags, "Expected cpu_access_flags %#x, got %#x.\n", ++ cpu_access_flags, desc->CPUAccessFlags); ++ todo_wine_if(wine_todo && desc->MiscFlags != misc_flags) ++ ok_(__FILE__, line)(desc->MiscFlags == misc_flags, "Expected misc_flags %#x, got %#x.\n", misc_flags, ++ desc->MiscFlags); ++} ++ ++/* ++ * Taken from the d3d11 tests. If there's a missing resource type or ++ * texture format checking function, check to see if it exists there first. ++ */ ++struct resource_readback ++{ ++ ID3D11Resource *resource; ++ D3D11_MAPPED_SUBRESOURCE map_desc; ++ ID3D11DeviceContext *immediate_context; ++ uint32_t width, height, depth, sub_resource_idx; ++}; ++ ++static void init_resource_readback(ID3D11Resource *resource, ID3D11Resource *readback_resource, ++ uint32_t width, uint32_t height, uint32_t depth, uint32_t sub_resource_idx, ++ ID3D11Device *device, struct resource_readback *rb) ++{ ++ HRESULT hr; ++ ++ rb->resource = readback_resource; ++ rb->width = width; ++ rb->height = height; ++ rb->depth = depth; ++ rb->sub_resource_idx = sub_resource_idx; ++ ++ ID3D11Device_GetImmediateContext(device, &rb->immediate_context); ++ ++ ID3D11DeviceContext_CopyResource(rb->immediate_context, rb->resource, resource); ++ if (FAILED(hr = ID3D11DeviceContext_Map(rb->immediate_context, ++ rb->resource, sub_resource_idx, D3D11_MAP_READ, 0, &rb->map_desc))) ++ { ++ trace("Failed to map resource, hr %#lx.\n", hr); ++ ID3D11Resource_Release(rb->resource); ++ rb->resource = NULL; ++ ID3D11DeviceContext_Release(rb->immediate_context); ++ rb->immediate_context = NULL; ++ } ++} ++ ++static void get_texture_readback(ID3D11Texture2D *texture, uint32_t sub_resource_idx, ++ struct resource_readback *rb) ++{ ++ D3D11_TEXTURE2D_DESC texture_desc; ++ ID3D11Resource *rb_texture; ++ uint32_t miplevel; ++ ID3D11Device *device; ++ HRESULT hr; ++ ++ memset(rb, 0, sizeof(*rb)); ++ ++ ID3D11Texture2D_GetDevice(texture, &device); ++ ++ ID3D11Texture2D_GetDesc(texture, &texture_desc); ++ texture_desc.Usage = D3D11_USAGE_STAGING; ++ texture_desc.BindFlags = 0; ++ texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; ++ texture_desc.MiscFlags = 0; ++ if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture))) ++ { ++ trace("Failed to create texture, hr %#lx.\n", hr); ++ ID3D11Device_Release(device); ++ return; ++ } ++ ++ miplevel = sub_resource_idx % texture_desc.MipLevels; ++ init_resource_readback((ID3D11Resource *)texture, rb_texture, ++ max(1, texture_desc.Width >> miplevel), ++ max(1, texture_desc.Height >> miplevel), ++ 1, sub_resource_idx, device, rb); ++ ++ ID3D11Device_Release(device); ++} ++ ++static void get_texture3d_readback(ID3D11Texture3D *texture, unsigned int sub_resource_idx, ++ struct resource_readback *rb) ++{ ++ D3D11_TEXTURE3D_DESC texture_desc; ++ ID3D11Resource *rb_texture; ++ unsigned int miplevel; ++ ID3D11Device *device; ++ HRESULT hr; ++ ++ memset(rb, 0, sizeof(*rb)); ++ ++ ID3D11Texture3D_GetDevice(texture, &device); ++ ++ ID3D11Texture3D_GetDesc(texture, &texture_desc); ++ texture_desc.Usage = D3D11_USAGE_STAGING; ++ texture_desc.BindFlags = 0; ++ texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; ++ texture_desc.MiscFlags = 0; ++ if (FAILED(hr = ID3D11Device_CreateTexture3D(device, &texture_desc, NULL, (ID3D11Texture3D **)&rb_texture))) ++ { ++ trace("Failed to create texture, hr %#lx.\n", hr); ++ ID3D11Device_Release(device); ++ return; ++ } ++ ++ miplevel = sub_resource_idx % texture_desc.MipLevels; ++ init_resource_readback((ID3D11Resource *)texture, rb_texture, ++ max(1, texture_desc.Width >> miplevel), ++ max(1, texture_desc.Height >> miplevel), ++ max(1, texture_desc.Depth >> miplevel), ++ sub_resource_idx, device, rb); ++ ++ ID3D11Device_Release(device); ++} ++ ++static void *get_readback_data(struct resource_readback *rb, ++ uint32_t x, uint32_t y, uint32_t z, unsigned byte_width) ++{ ++ return (uint8_t *)rb->map_desc.pData + z * rb->map_desc.DepthPitch + y * rb->map_desc.RowPitch + x * byte_width; ++} ++ ++static uint32_t get_readback_u32(struct resource_readback *rb, uint32_t x, uint32_t y, uint32_t z) ++{ ++ return *(uint32_t *)get_readback_data(rb, x, y, z, sizeof(uint32_t)); ++} ++ ++static uint32_t get_readback_color(struct resource_readback *rb, uint32_t x, uint32_t y, uint32_t z) ++{ ++ return get_readback_u32(rb, x, y, z); ++} ++ ++static void release_resource_readback(struct resource_readback *rb) ++{ ++ ID3D11DeviceContext_Unmap(rb->immediate_context, rb->resource, rb->sub_resource_idx); ++ ID3D11Resource_Release(rb->resource); ++ ID3D11DeviceContext_Release(rb->immediate_context); ++} ++ ++static BOOL compare_color(uint32_t c1, uint32_t c2, uint8_t max_diff) ++{ ++ return compare_uint(c1 & 0xff, c2 & 0xff, max_diff) ++ && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff) ++ && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff) ++ && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); ++} ++ ++#define check_readback_data_color(a, b, c, d) check_readback_data_color_(__LINE__, a, b, c, d) ++static void check_readback_data_color_(uint32_t line, struct resource_readback *rb, ++ const RECT *rect, uint32_t expected_color, uint8_t max_diff) ++{ ++ uint32_t x = 0, y = 0, z = 0, color = 0; ++ BOOL all_match = FALSE; ++ RECT default_rect; ++ ++ if (!rect) ++ { ++ SetRect(&default_rect, 0, 0, rb->width, rb->height); ++ rect = &default_rect; ++ } ++ ++ for (z = 0; z < rb->depth; ++z) ++ { ++ for (y = rect->top; y < rect->bottom; ++y) ++ { ++ for (x = rect->left; x < rect->right; ++x) ++ { ++ color = get_readback_color(rb, x, y, z); ++ if (!compare_color(color, expected_color, max_diff)) ++ goto done; ++ } ++ } ++ } ++ all_match = TRUE; ++ ++done: ++ ok_(__FILE__, line)(all_match, ++ "Got 0x%08x, expected 0x%08x at (%u, %u, %u), sub-resource %u.\n", ++ color, expected_color, x, y, z, rb->sub_resource_idx); ++} ++ ++#define check_texture_sub_resource_color(a, b, c, d, e) check_texture_sub_resource_color_(__LINE__, a, b, c, d, e) ++static void check_texture_sub_resource_color_(uint32_t line, ID3D11Texture2D *texture, ++ uint32_t sub_resource_idx, const RECT *rect, uint32_t expected_color, uint8_t max_diff) ++{ ++ struct resource_readback rb; ++ ++ get_texture_readback(texture, sub_resource_idx, &rb); ++ check_readback_data_color_(line, &rb, rect, expected_color, max_diff); ++ release_resource_readback(&rb); ++} ++ ++static void set_d3dx11_image_load_info(D3DX11_IMAGE_LOAD_INFO *info, uint32_t width, uint32_t height, uint32_t depth, ++ uint32_t first_mip_level, uint32_t mip_levels, D3D11_USAGE usage, uint32_t bind_flags, uint32_t cpu_access_flags, ++ uint32_t misc_flags, DXGI_FORMAT format, uint32_t filter, uint32_t mip_filter, D3DX11_IMAGE_INFO *src_info) ++{ ++ info->Width = width; ++ info->Height = height; ++ info->Depth = depth; ++ info->FirstMipLevel = first_mip_level; ++ info->MipLevels = mip_levels; ++ info->Usage = usage; ++ info->BindFlags = bind_flags; ++ info->CpuAccessFlags = cpu_access_flags; ++ info->MiscFlags = misc_flags; ++ info->Format = format; ++ info->Filter = filter; ++ info->MipFilter = mip_filter; ++ info->pSrcInfo = src_info; ++} ++ ++#define check_test_image_load_info_resource(resource, image_load_info) \ ++ check_test_image_load_info_resource_(__LINE__, resource, image_load_info) ++static void check_test_image_load_info_resource_(uint32_t line, ID3D11Resource *resource, ++ const struct test_image_load_info *image_load_info) ++{ ++ D3D11_RESOURCE_DIMENSION resource_dimension; ++ HRESULT hr; ++ ++ ID3D11Resource_GetType(resource, &resource_dimension); ++ ok(resource_dimension == image_load_info->expected_type, "Got unexpected ResourceDimension %u, expected %u.\n", ++ resource_dimension, image_load_info->expected_type); ++ ++ switch (resource_dimension) ++ { ++ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: ++ { ++ const D3D11_TEXTURE2D_DESC *expected_desc_2d = &image_load_info->expected_resource_desc.desc_2d; ++ D3D11_TEXTURE2D_DESC desc_2d; ++ ID3D11Texture2D *tex_2d; ++ ++ hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void **)&tex_2d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D11Texture2D_GetDesc(tex_2d, &desc_2d); ++ check_texture2d_desc_values_(line, &desc_2d, expected_desc_2d->Width, expected_desc_2d->Height, ++ expected_desc_2d->MipLevels, expected_desc_2d->ArraySize, expected_desc_2d->Format, ++ expected_desc_2d->SampleDesc.Count, expected_desc_2d->SampleDesc.Quality, expected_desc_2d->Usage, ++ expected_desc_2d->BindFlags, expected_desc_2d->CPUAccessFlags, expected_desc_2d->MiscFlags, ++ image_load_info->todo_resource_desc); ++ ID3D11Texture2D_Release(tex_2d); ++ break; ++ } ++ ++ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: ++ { ++ const D3D11_TEXTURE3D_DESC *expected_desc_3d = &image_load_info->expected_resource_desc.desc_3d; ++ D3D11_TEXTURE3D_DESC desc_3d; ++ ID3D11Texture3D *tex_3d; ++ ++ hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture3D, (void **)&tex_3d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D11Texture3D_GetDesc(tex_3d, &desc_3d); ++ check_texture3d_desc_values_(line, &desc_3d, expected_desc_3d->Width, expected_desc_3d->Height, ++ expected_desc_3d->Depth, expected_desc_3d->MipLevels, expected_desc_3d->Format, expected_desc_3d->Usage, ++ expected_desc_3d->BindFlags, expected_desc_3d->CPUAccessFlags, expected_desc_3d->MiscFlags, ++ image_load_info->todo_resource_desc); ++ ID3D11Texture3D_Release(tex_3d); ++ break; ++ } ++ ++ default: ++ break; ++ } ++} ++ ++static void check_resource_info(ID3D11Resource *resource, const struct test_image *image, uint32_t line) ++{ ++ unsigned int expected_mip_levels, expected_width, expected_height, max_dimension; ++ D3D11_RESOURCE_DIMENSION resource_dimension; ++ D3D11_TEXTURE2D_DESC desc_2d; ++ D3D11_TEXTURE3D_DESC desc_3d; ++ ID3D11Texture2D *texture_2d; ++ ID3D11Texture3D *texture_3d; ++ HRESULT hr; ++ ++ expected_width = image->expected_info.Width; ++ expected_height = image->expected_info.Height; ++ if (is_block_compressed(image->expected_info.Format)) ++ { ++ expected_width = (expected_width + 3) & ~3; ++ expected_height = (expected_height + 3) & ~3; ++ } ++ expected_mip_levels = 0; ++ max_dimension = max(expected_width, expected_height); ++ while (max_dimension) ++ { ++ ++expected_mip_levels; ++ max_dimension >>= 1; ++ } ++ ++ ID3D11Resource_GetType(resource, &resource_dimension); ++ ok(resource_dimension == image->expected_info.ResourceDimension, ++ "Got unexpected ResourceDimension %u, expected %u.\n", ++ resource_dimension, image->expected_info.ResourceDimension); ++ ++ switch (resource_dimension) ++ { ++ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: ++ hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void **)&texture_2d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D11Texture2D_GetDesc(texture_2d, &desc_2d); ++ ok_(__FILE__, line)(desc_2d.Width == expected_width, ++ "Got unexpected Width %u, expected %u.\n", ++ desc_2d.Width, expected_width); ++ ok_(__FILE__, line)(desc_2d.Height == expected_height, ++ "Got unexpected Height %u, expected %u.\n", ++ desc_2d.Height, expected_height); ++ ok_(__FILE__, line)(desc_2d.MipLevels == expected_mip_levels, ++ "Got unexpected MipLevels %u, expected %u.\n", ++ desc_2d.MipLevels, expected_mip_levels); ++ ok_(__FILE__, line)(desc_2d.ArraySize == image->expected_info.ArraySize, ++ "Got unexpected ArraySize %u, expected %u.\n", ++ desc_2d.ArraySize, image->expected_info.ArraySize); ++ ok_(__FILE__, line)(desc_2d.Format == image->expected_info.Format, ++ "Got unexpected Format %u, expected %u.\n", ++ desc_2d.Format, image->expected_info.Format); ++ ok_(__FILE__, line)(desc_2d.SampleDesc.Count == 1, ++ "Got unexpected SampleDesc.Count %u, expected %u\n", ++ desc_2d.SampleDesc.Count, 1); ++ ok_(__FILE__, line)(desc_2d.SampleDesc.Quality == 0, ++ "Got unexpected SampleDesc.Quality %u, expected %u\n", ++ desc_2d.SampleDesc.Quality, 0); ++ ok_(__FILE__, line)(desc_2d.Usage == D3D11_USAGE_DEFAULT, ++ "Got unexpected Usage %u, expected %u\n", ++ desc_2d.Usage, D3D11_USAGE_DEFAULT); ++ ok_(__FILE__, line)(desc_2d.BindFlags == D3D11_BIND_SHADER_RESOURCE, ++ "Got unexpected BindFlags %#x, expected %#x\n", ++ desc_2d.BindFlags, D3D11_BIND_SHADER_RESOURCE); ++ ok_(__FILE__, line)(desc_2d.CPUAccessFlags == 0, ++ "Got unexpected CPUAccessFlags %#x, expected %#x\n", ++ desc_2d.CPUAccessFlags, 0); ++ ok_(__FILE__, line)(desc_2d.MiscFlags == image->expected_info.MiscFlags, ++ "Got unexpected MiscFlags %#x, expected %#x.\n", ++ desc_2d.MiscFlags, image->expected_info.MiscFlags); ++ ++ ID3D11Texture2D_Release(texture_2d); ++ break; ++ ++ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: ++ hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture3D, (void **)&texture_3d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D11Texture3D_GetDesc(texture_3d, &desc_3d); ++ ok_(__FILE__, line)(desc_3d.Width == expected_width, ++ "Got unexpected Width %u, expected %u.\n", ++ desc_3d.Width, expected_width); ++ ok_(__FILE__, line)(desc_3d.Height == expected_height, ++ "Got unexpected Height %u, expected %u.\n", ++ desc_3d.Height, expected_height); ++ ok_(__FILE__, line)(desc_3d.Depth == image->expected_info.Depth, ++ "Got unexpected Depth %u, expected %u.\n", ++ desc_3d.Depth, image->expected_info.Depth); ++ ok_(__FILE__, line)(desc_3d.MipLevels == expected_mip_levels, ++ "Got unexpected MipLevels %u, expected %u.\n", ++ desc_3d.MipLevels, expected_mip_levels); ++ ok_(__FILE__, line)(desc_3d.Format == image->expected_info.Format, ++ "Got unexpected Format %u, expected %u.\n", ++ desc_3d.Format, image->expected_info.Format); ++ ok_(__FILE__, line)(desc_3d.Usage == D3D11_USAGE_DEFAULT, ++ "Got unexpected Usage %u, expected %u\n", ++ desc_3d.Usage, D3D11_USAGE_DEFAULT); ++ ok_(__FILE__, line)(desc_3d.BindFlags == D3D11_BIND_SHADER_RESOURCE, ++ "Got unexpected BindFlags %#x, expected %#x\n", ++ desc_3d.BindFlags, D3D11_BIND_SHADER_RESOURCE); ++ ok_(__FILE__, line)(desc_3d.CPUAccessFlags == 0, ++ "Got unexpected CPUAccessFlags %#x, expected %#x\n", ++ desc_3d.CPUAccessFlags, 0); ++ ok_(__FILE__, line)(desc_3d.MiscFlags == image->expected_info.MiscFlags, ++ "Got unexpected MiscFlags %#x, expected %#x.\n", ++ desc_3d.MiscFlags, image->expected_info.MiscFlags); ++ ID3D11Texture3D_Release(texture_3d); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void check_texture2d_data(ID3D11Texture2D *texture, const struct test_image *image, unsigned int line) ++{ ++ unsigned int width, height, stride, i, array_slice; ++ struct resource_readback rb; ++ D3D11_TEXTURE2D_DESC desc; ++ const BYTE *expected_data; ++ BOOL line_match; ++ ++ ID3D11Texture2D_GetDesc(texture, &desc); ++ width = desc.Width; ++ height = desc.Height; ++ stride = (width * get_bpp_from_format(desc.Format) + 7) / 8; ++ if (is_block_compressed(desc.Format)) ++ { ++ stride *= 4; ++ height /= 4; ++ } ++ ++ expected_data = image->expected_data; ++ for (array_slice = 0; array_slice < desc.ArraySize; ++array_slice) ++ { ++ get_texture_readback(texture, array_slice * desc.MipLevels, &rb); ++ for (i = 0; i < height; ++i) ++ { ++ const uint8_t *rb_data = get_readback_data(&rb, 0, i, 0, 0); ++ ++ line_match = !memcmp(expected_data + stride * i, rb_data, stride); ++ todo_wine_if(is_block_compressed(image->expected_info.Format) && image->data != test_dds_dxt5 ++ && (image->expected_info.Width % 4 != 0 || image->expected_info.Height % 4 != 0)) ++ ok_(__FILE__, line)(line_match, "Data mismatch for line %u, array slice %u.\n", i, array_slice); ++ if (!line_match) ++ break; ++ } ++ expected_data += stride * height; ++ release_resource_readback(&rb); ++ } ++} ++ ++static void check_texture3d_data(ID3D11Texture3D *texture, const struct test_image *image, unsigned int line) ++{ ++ unsigned int width, height, depth, stride, i, j; ++ struct resource_readback rb; ++ D3D11_TEXTURE3D_DESC desc; ++ const BYTE *expected_data; ++ BOOL line_match; ++ ++ ID3D11Texture3D_GetDesc(texture, &desc); ++ width = desc.Width; ++ height = desc.Height; ++ depth = desc.Depth; ++ stride = (width * get_bpp_from_format(desc.Format) + 7) / 8; ++ if (is_block_compressed(desc.Format)) ++ { ++ stride *= 4; ++ height /= 4; ++ } ++ ++ expected_data = image->expected_data; ++ get_texture3d_readback(texture, 0, &rb); ++ for (j = 0; j < depth; ++j) ++ { ++ const BYTE *expected_data_slice = expected_data + ((stride * height) * j); ++ ++ for (i = 0; i < height; ++i) ++ { ++ const uint8_t *rb_data = get_readback_data(&rb, 0, i, j, 0); ++ ++ line_match = !memcmp(expected_data_slice + stride * i, rb_data, stride); ++ ok_(__FILE__, line)(line_match, "Data mismatch for line %u.\n", i); ++ if (!line_match) ++ { ++ for (unsigned int k = 0; k < stride; ++k) ++ trace("%02x\n", *((BYTE *)get_readback_data(&rb, k, i, j, 1))); ++ break; ++ } ++ } ++ } ++ release_resource_readback(&rb); ++} ++ ++static void check_resource_data(ID3D11Resource *resource, const struct test_image *image, unsigned int line) ++{ ++ ID3D11Texture3D *texture3d; ++ ID3D11Texture2D *texture2d; ++ ++ if (SUCCEEDED(ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture3D, (void **)&texture3d))) ++ { ++ if (wined3d_opengl && is_block_compressed(image->expected_info.Format)) ++ skip("Skipping compressed format 3D texture readback test.\n"); ++ else ++ check_texture3d_data(texture3d, image, line); ++ ID3D11Texture3D_Release(texture3d); ++ } ++ else if (SUCCEEDED(ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void **)&texture2d))) ++ { ++ check_texture2d_data(texture2d, image, line); ++ ID3D11Texture2D_Release(texture2d); ++ } ++ else ++ { ++ ok(0, "Failed to get 2D or 3D texture interface.\n"); ++ } ++} ++ + static WCHAR temp_dir[MAX_PATH]; + + static BOOL create_file(const WCHAR *filename, const char *data, unsigned int size, WCHAR *out_path) +@@ -482,6 +2047,34 @@ static void delete_directory(const WCHAR *dir) + RemoveDirectoryW(path); + } + ++static ID3D11Device *create_device(void) ++{ ++ HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, const D3D_FEATURE_LEVEL *, ++ UINT, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); ++ HMODULE d3d11_mod = LoadLibraryA("d3d11.dll"); ++ ID3D11Device *device; ++ ++ ++ if (!d3d11_mod) ++ { ++ win_skip("d3d11.dll not present\n"); ++ return NULL; ++ } ++ ++ pD3D11CreateDevice = (void *)GetProcAddress(d3d11_mod, "D3D11CreateDevice"); ++ if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, ++ NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL))) ++ return device; ++ if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, ++ NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL))) ++ return device; ++ if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0, ++ NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL))) ++ return device; ++ ++ return NULL; ++} ++ + static void test_D3DX11CreateAsyncMemoryLoader(void) + { + ID3DX11DataLoader *loader; +@@ -862,7 +2455,6 @@ struct dds_header + DWORD reserved2; + }; + +-#define DDS_RESOURCE_MISC_TEXTURECUBE 0x04 + struct dds_header_dxt10 + { + DWORD dxgi_format; +@@ -1508,8 +3100,208 @@ static void test_D3DX11GetImageInfoFromMemory(void) + todo_wine check_dds_dxt10_format(DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM, FALSE); + } + ++static void test_create_texture(void) ++{ ++ static const uint32_t dds_24bit_8_8_mip_level_expected[] = { 0xff0000ff, 0xff00ff00, 0xffff0000, 0xff000000 }; ++ D3D11_TEXTURE2D_DESC tex_2d_desc; ++ D3DX11_IMAGE_LOAD_INFO load_info; ++ D3DX11_IMAGE_INFO img_info; ++ ID3D11Resource *resource; ++ ID3D11Texture2D *tex_2d; ++ ID3D11Device *device; ++ uint32_t i, mip_level; ++ HRESULT hr, hr2; ++ ++ device = create_device(); ++ if (!device) ++ { ++ skip("Failed to create device, skipping tests.\n"); ++ return; ++ } ++ ++ CoInitialize(NULL); ++ ++ /* D3DX11CreateTextureFromMemory tests */ ++ resource = (ID3D11Resource *)0xdeadbeef; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(NULL, test_bmp_1bpp, sizeof(test_bmp_1bpp), NULL, NULL, &resource, &hr2); ++ ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); ++ ok(hr2 == 0xdeadbeef, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(resource == (ID3D11Resource *)0xdeadbeef, "Got unexpected resource %p.\n", resource); ++ ++ resource = (ID3D11Resource *)0xdeadbeef; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, NULL, 0, NULL, NULL, &resource, &hr2); ++ ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); ++ ok(hr2 == 0xdeadbeef, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(resource == (ID3D11Resource *)0xdeadbeef, "Got unexpected resource %p.\n", resource); ++ ++ resource = (ID3D11Resource *)0xdeadbeef; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, NULL, sizeof(test_bmp_1bpp), NULL, NULL, &resource, &hr2); ++ ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); ++ ok(hr2 == 0xdeadbeef, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(resource == (ID3D11Resource *)0xdeadbeef, "Got unexpected resource %p.\n", resource); ++ ++ resource = (ID3D11Resource *)0xdeadbeef; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, test_bmp_1bpp, 0, NULL, NULL, &resource, &hr2); ++ ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(resource == (ID3D11Resource *)0xdeadbeef, "Got unexpected resource %p.\n", resource); ++ ++ resource = (ID3D11Resource *)0xdeadbeef; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, test_bmp_1bpp, sizeof(test_bmp_1bpp) - 1, NULL, NULL, &resource, &hr2); ++ ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(resource == (ID3D11Resource *)0xdeadbeef, "Got unexpected resource %p.\n", resource); ++ ++ for (i = 0; i < ARRAY_SIZE(test_image); ++i) ++ { ++ winetest_push_context("Test %u", i); ++ ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, NULL, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX11_IFF_WMP), ++ "Got unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ check_resource_info(resource, test_image + i, __LINE__); ++ check_resource_data(resource, test_image + i, __LINE__); ++ ID3D11Resource_Release(resource); ++ } ++ ++ winetest_pop_context(); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(test_invalid_image_load_info); ++i) ++ { ++ const struct test_invalid_image_load_info *test_load_info = &test_invalid_image_load_info[i]; ++ ++ winetest_push_context("Test %u", i); ++ ++ hr2 = 0xdeadbeef; ++ load_info = test_load_info->load_info; ++ hr = D3DX11CreateTextureFromMemory(device, test_load_info->data, test_load_info->size, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ todo_wine_if(test_load_info->todo_hr) ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ ID3D11Resource_Release(resource); ++ ++ winetest_pop_context(); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(test_image_load_info); ++i) ++ { ++ const struct test_image_load_info *test_load_info = &test_image_load_info[i]; ++ ++ winetest_push_context("Test %u", i); ++ ++ load_info = test_load_info->load_info; ++ load_info.pSrcInfo = &img_info; ++ ++ resource = NULL; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, test_load_info->data, test_load_info->size, &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == test_load_info->expected_hr, "Got unexpected hr %#lx.\n", hr); ++ if (SUCCEEDED(hr)) ++ { ++ check_test_image_load_info_resource(resource, test_load_info); ++ ID3D11Resource_Release(resource); ++ } ++ ++ winetest_pop_context(); ++ } ++ ++ /* Check behavior of the FirstMipLevel argument. */ ++ for (i = 0; i < 2; ++i) ++ { ++ winetest_push_context("FirstMipLevel %u", i); ++ memset(&img_info, 0, sizeof(img_info)); ++ set_d3dx11_image_load_info(&load_info, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, i, D3DX11_FROM_FILE, ++ D3D11_USAGE_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, ++ D3DX11_DEFAULT, &img_info); ++ ++ resource = NULL; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ check_image_info_values(&img_info, 8, 8, 1, 1, 4, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX11_IFF_DDS, FALSE); ++ ++ hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void **)&tex_2d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ ID3D11Texture2D_GetDesc(tex_2d, &tex_2d_desc); ++ check_texture2d_desc_values(&tex_2d_desc, 8, 8, 4, 1, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 0, D3D11_USAGE_DEFAULT, ++ D3D11_BIND_SHADER_RESOURCE, 0, 0, FALSE); ++ for (mip_level = 0; mip_level < 4; ++mip_level) ++ { ++ winetest_push_context("MipLevel %u", mip_level); ++ check_texture_sub_resource_color(tex_2d, mip_level, NULL, ++ dds_24bit_8_8_mip_level_expected[min(3, mip_level + i)], 0); ++ winetest_pop_context(); ++ } ++ ++ ID3D11Texture2D_Release(tex_2d); ++ ID3D11Resource_Release(resource); ++ winetest_pop_context(); ++ } ++ ++ /* ++ * If FirstMipLevel is set to a value that is larger than the total number ++ * of mip levels in the image, it falls back to 0. ++ */ ++ memset(&img_info, 0, sizeof(img_info)); ++ set_d3dx11_image_load_info(&load_info, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, 5, D3DX11_FROM_FILE, ++ D3D11_USAGE_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, D3DX11_DEFAULT, ++ D3DX11_DEFAULT, &img_info); ++ ++ resource = NULL; ++ hr2 = 0xdeadbeef; ++ hr = D3DX11CreateTextureFromMemory(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), &load_info, NULL, &resource, &hr2); ++ ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ check_image_info_values(&img_info, 8, 8, 1, 1, 4, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, ++ D3DX11_IFF_DDS, FALSE); ++ ++ hr = ID3D11Resource_QueryInterface(resource, &IID_ID3D11Texture2D, (void **)&tex_2d); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID3D11Texture2D_GetDesc(tex_2d, &tex_2d_desc); ++ check_texture2d_desc_values(&tex_2d_desc, 8, 8, 4, 1, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 0, D3D11_USAGE_DEFAULT, ++ D3D11_BIND_SHADER_RESOURCE, 0, 0, FALSE); ++ for (mip_level = 0; mip_level < 4; ++mip_level) ++ { ++ winetest_push_context("MipLevel %u", mip_level); ++ check_texture_sub_resource_color(tex_2d, mip_level, NULL, dds_24bit_8_8_mip_level_expected[mip_level], 0); ++ winetest_pop_context(); ++ } ++ ++ ID3D11Texture2D_Release(tex_2d); ++ ID3D11Resource_Release(resource); ++ ++ CoUninitialize(); ++ ++ ok(!ID3D11Device_Release(device), "Unexpected refcount.\n"); ++} ++ + START_TEST(d3dx11) + { ++ HMODULE wined3d; ++ ++ if ((wined3d = GetModuleHandleA("wined3d.dll"))) ++ { ++ enum wined3d_renderer (CDECL *p_wined3d_get_renderer)(void); ++ ++ if ((p_wined3d_get_renderer = (void *)GetProcAddress(wined3d, "wined3d_get_renderer")) ++ && p_wined3d_get_renderer() == WINED3D_RENDERER_OPENGL) ++ wined3d_opengl = true; ++ } ++ + test_D3DX11CreateAsyncMemoryLoader(); + test_D3DX11CreateAsyncFileLoader(); + test_D3DX11CreateAsyncResourceLoader(); +@@ -1517,4 +3309,5 @@ START_TEST(d3dx11) + test_D3DX11GetImageInfoFromMemory(); + test_legacy_dds_header_image_info(); + test_dxt10_dds_header_image_info(); ++ test_create_texture(); + } +diff --git a/dlls/d3dx11_43/texture.c b/dlls/d3dx11_43/texture.c +index cbf3b630f58..f8605223a4f 100644 +--- a/dlls/d3dx11_43/texture.c ++++ b/dlls/d3dx11_43/texture.c +@@ -16,6 +16,8 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + ++#define COBJMACROS ++#include "d3d11.h" + #include "d3dx11.h" + #include "d3dcompiler.h" + #include "dxhelpers.h" +@@ -277,14 +279,296 @@ HRESULT WINAPI D3DX11CreateTextureFromFileW(ID3D11Device *device, const WCHAR *f + return E_NOTIMPL; + } + ++void init_load_info(const D3DX11_IMAGE_LOAD_INFO *load_info, D3DX11_IMAGE_LOAD_INFO *out) ++{ ++ if (load_info) ++ { ++ *out = *load_info; ++ return; ++ } ++ ++ out->Width = D3DX11_DEFAULT; ++ out->Height = D3DX11_DEFAULT; ++ out->Depth = D3DX11_DEFAULT; ++ out->FirstMipLevel = D3DX11_DEFAULT; ++ out->MipLevels = D3DX11_DEFAULT; ++ out->Usage = D3DX11_DEFAULT; ++ out->BindFlags = D3DX11_DEFAULT; ++ out->CpuAccessFlags = D3DX11_DEFAULT; ++ out->MiscFlags = D3DX11_DEFAULT; ++ out->Format = D3DX11_DEFAULT; ++ out->Filter = D3DX11_DEFAULT; ++ out->MipFilter = D3DX11_DEFAULT; ++ out->pSrcInfo = NULL; ++} ++ ++HRESULT load_texture_data(const void *data, SIZE_T size, D3DX11_IMAGE_LOAD_INFO *load_info, ++ D3D11_SUBRESOURCE_DATA **resource_data) ++{ ++ const struct pixel_format_desc *fmt_desc, *src_desc; ++ struct d3dx_subresource_data *sub_rsrcs = NULL; ++ uint32_t loaded_mip_levels, max_mip_levels; ++ D3DX11_IMAGE_INFO img_info; ++ struct d3dx_image image; ++ unsigned int i, j; ++ HRESULT hr = S_OK; ++ ++ if (!data || !size) ++ return E_FAIL; ++ ++ *resource_data = NULL; ++ if (!load_info->Filter || load_info->Filter == D3DX11_DEFAULT) ++ load_info->Filter = D3DX11_FILTER_TRIANGLE | D3DX11_FILTER_DITHER; ++ if (FAILED(hr = d3dx_validate_filter(load_info->Filter))) ++ { ++ ERR("Invalid filter argument %#x.\n", load_info->Filter); ++ return hr; ++ } ++ ++ hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_SUPPORT_DXT10); ++ if (FAILED(hr)) ++ return E_FAIL; ++ ++ hr = d3dx11_image_info_from_d3dx_image(&img_info, &image); ++ if (FAILED(hr)) ++ { ++ WARN("Invalid or unsupported image file, hr %#lx.\n", hr); ++ hr = E_FAIL; ++ goto end; ++ } ++ ++ if ((!(img_info.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) || img_info.ArraySize != 6) ++ && img_info.ArraySize != 1) ++ { ++ FIXME("img_info.ArraySize = %u not supported.\n", img_info.ArraySize); ++ hr = E_NOTIMPL; ++ goto end; ++ } ++ ++ if (load_info->FirstMipLevel == D3DX11_DEFAULT || (load_info->FirstMipLevel >= img_info.MipLevels)) ++ load_info->FirstMipLevel = 0; ++ ++ if (load_info->Format == D3DX11_DEFAULT || load_info->Format == DXGI_FORMAT_FROM_FILE) ++ load_info->Format = img_info.Format; ++ fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(load_info->Format)); ++ if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) ++ { ++ FIXME("Unknown DXGI format supplied, %#x.\n", load_info->Format); ++ hr = E_NOTIMPL; ++ goto end; ++ } ++ ++ /* Potentially round up width/height to align with block size. */ ++ if (!load_info->Width || load_info->Width == D3DX11_FROM_FILE || load_info->Width == D3DX11_DEFAULT) ++ load_info->Width = (img_info.Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); ++ if (!load_info->Height || load_info->Height == D3DX11_FROM_FILE || load_info->Height == D3DX11_DEFAULT) ++ load_info->Height = (img_info.Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); ++ if (!load_info->Depth || load_info->Depth == D3DX11_FROM_FILE || load_info->Depth == D3DX11_DEFAULT) ++ load_info->Depth = img_info.Depth; ++ ++ if ((load_info->Depth > 1) && (img_info.ResourceDimension != D3D11_RESOURCE_DIMENSION_TEXTURE3D)) ++ { ++ ERR("Invalid depth value %u for image with dimension %d.\n", load_info->Depth, img_info.ResourceDimension); ++ hr = E_FAIL; ++ goto end; ++ } ++ ++ max_mip_levels = d3dx_get_max_mip_levels_for_size(load_info->Width, load_info->Height, load_info->Depth); ++ if (!load_info->MipLevels || load_info->MipLevels == D3DX11_DEFAULT || load_info->MipLevels == D3DX11_FROM_FILE) ++ load_info->MipLevels = (load_info->MipLevels == D3DX11_FROM_FILE) ? img_info.MipLevels : max_mip_levels; ++ load_info->MipLevels = min(max_mip_levels, load_info->MipLevels); ++ ++ hr = d3dx_create_subresource_data_for_texture(load_info->Width, load_info->Height, load_info->Depth, ++ load_info->MipLevels, img_info.ArraySize, fmt_desc, &sub_rsrcs); ++ if (FAILED(hr)) ++ goto end; ++ ++ src_desc = get_d3dx_pixel_format_info(image.format); ++ loaded_mip_levels = min((img_info.MipLevels - load_info->FirstMipLevel), load_info->MipLevels); ++ for (i = 0; i < img_info.ArraySize; ++i) ++ { ++ struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth }; ++ ++ for (j = 0; j < loaded_mip_levels; ++j) ++ { ++ struct d3dx_subresource_data *sub_rsrc = &sub_rsrcs[i * load_info->MipLevels + j]; ++ const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; ++ struct d3dx_pixels src_pixels, dst_pixels; ++ ++ hr = d3dx_image_get_pixels(&image, i, j + load_info->FirstMipLevel, &src_pixels); ++ if (FAILED(hr)) ++ goto end; ++ ++ set_d3dx_pixels(&dst_pixels, sub_rsrc->data, sub_rsrc->row_pitch, sub_rsrc->slice_pitch, NULL, dst_size.width, ++ dst_size.height, dst_size.depth, &unaligned_rect); ++ ++ hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, load_info->Filter, 0); ++ if (FAILED(hr)) ++ goto end; ++ ++ d3dx_get_next_mip_level_size(&dst_size); ++ } ++ } ++ ++ if (loaded_mip_levels < load_info->MipLevels) ++ { ++ struct volume base_level_size = { load_info->Width, load_info->Height, load_info->Depth }; ++ const uint32_t base_level = loaded_mip_levels - 1; ++ ++ if (!load_info->MipFilter || load_info->MipFilter == D3DX11_DEFAULT) ++ load_info->MipFilter = D3DX11_FILTER_LINEAR; ++ if (FAILED(hr = d3dx_validate_filter(load_info->MipFilter))) ++ { ++ ERR("Invalid mip filter argument %#x.\n", load_info->MipFilter); ++ goto end; ++ } ++ ++ d3dx_get_mip_level_size(&base_level_size, base_level); ++ for (i = 0; i < img_info.ArraySize; ++i) ++ { ++ struct volume src_size, dst_size; ++ ++ src_size = dst_size = base_level_size; ++ for (j = base_level; j < (load_info->MipLevels - 1); ++j) ++ { ++ struct d3dx_subresource_data *dst_data = &sub_rsrcs[i * load_info->MipLevels + j + 1]; ++ struct d3dx_subresource_data *src_data = &sub_rsrcs[i * load_info->MipLevels + j]; ++ const RECT src_unaligned_rect = { 0, 0, src_size.width, src_size.height }; ++ struct d3dx_pixels src_pixels, dst_pixels; ++ RECT dst_unaligned_rect; ++ ++ d3dx_get_next_mip_level_size(&dst_size); ++ SetRect(&dst_unaligned_rect, 0, 0, dst_size.width, dst_size.height); ++ set_d3dx_pixels(&dst_pixels, dst_data->data, dst_data->row_pitch, dst_data->slice_pitch, NULL, ++ dst_size.width, dst_size.height, dst_size.depth, &dst_unaligned_rect); ++ set_d3dx_pixels(&src_pixels, src_data->data, src_data->row_pitch, src_data->slice_pitch, NULL, ++ src_size.width, src_size.height, src_size.depth, &src_unaligned_rect); ++ ++ hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, fmt_desc, load_info->MipFilter, 0); ++ if (FAILED(hr)) ++ goto end; ++ ++ src_size = dst_size; ++ } ++ } ++ } ++ ++ *resource_data = (D3D11_SUBRESOURCE_DATA *)sub_rsrcs; ++ sub_rsrcs = NULL; ++ ++ load_info->Usage = (load_info->Usage == D3DX11_DEFAULT) ? D3D11_USAGE_DEFAULT : load_info->Usage; ++ load_info->BindFlags = (load_info->BindFlags == D3DX11_DEFAULT) ? D3D11_BIND_SHADER_RESOURCE : load_info->BindFlags; ++ load_info->CpuAccessFlags = (load_info->CpuAccessFlags == D3DX11_DEFAULT) ? 0 : load_info->CpuAccessFlags; ++ load_info->MiscFlags = (load_info->MiscFlags == D3DX11_DEFAULT) ? 0 : load_info->MiscFlags; ++ load_info->MiscFlags |= img_info.MiscFlags; ++ if (load_info->pSrcInfo) ++ *load_info->pSrcInfo = img_info; ++ ++end: ++ d3dx_image_cleanup(&image); ++ free(sub_rsrcs); ++ return hr; ++} ++ ++HRESULT create_d3d_texture(ID3D11Device *device, D3DX11_IMAGE_LOAD_INFO *load_info, ++ D3D11_SUBRESOURCE_DATA *resource_data, ID3D11Resource **texture) ++{ ++ HRESULT hr; ++ ++ *texture = NULL; ++ switch (load_info->pSrcInfo->ResourceDimension) ++ { ++ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: ++ { ++ D3D11_TEXTURE2D_DESC texture_2d_desc = { 0 }; ++ ID3D11Texture2D *texture_2d; ++ ++ texture_2d_desc.Width = load_info->Width; ++ texture_2d_desc.Height = load_info->Height; ++ texture_2d_desc.MipLevels = load_info->MipLevels; ++ texture_2d_desc.ArraySize = load_info->pSrcInfo->ArraySize; ++ texture_2d_desc.Format = load_info->Format; ++ texture_2d_desc.SampleDesc.Count = 1; ++ texture_2d_desc.Usage = load_info->Usage; ++ texture_2d_desc.BindFlags = load_info->BindFlags; ++ texture_2d_desc.CPUAccessFlags = load_info->CpuAccessFlags; ++ texture_2d_desc.MiscFlags = load_info->MiscFlags; ++ ++ if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_2d_desc, resource_data, &texture_2d))) ++ return hr; ++ *texture = (ID3D11Resource *)texture_2d; ++ break; ++ } ++ ++ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: ++ { ++ D3D11_TEXTURE3D_DESC texture_3d_desc = { 0 }; ++ ID3D11Texture3D *texture_3d; ++ ++ texture_3d_desc.Width = load_info->Width; ++ texture_3d_desc.Height = load_info->Height; ++ texture_3d_desc.Depth = load_info->Depth; ++ texture_3d_desc.MipLevels = load_info->MipLevels; ++ texture_3d_desc.Format = load_info->Format; ++ texture_3d_desc.Usage = load_info->Usage; ++ texture_3d_desc.BindFlags = load_info->BindFlags; ++ texture_3d_desc.CPUAccessFlags = load_info->CpuAccessFlags; ++ texture_3d_desc.MiscFlags = load_info->MiscFlags; ++ ++ if (FAILED(hr = ID3D11Device_CreateTexture3D(device, &texture_3d_desc, resource_data, &texture_3d))) ++ return hr; ++ *texture = (ID3D11Resource *)texture_3d; ++ break; ++ } ++ ++ default: ++ FIXME("Unhandled resource dimension %d.\n", load_info->pSrcInfo->ResourceDimension); ++ return E_NOTIMPL; ++ } ++ ++ return S_OK; ++} ++ ++static HRESULT create_texture(ID3D11Device *device, const void *data, SIZE_T size, ++ D3DX11_IMAGE_LOAD_INFO *load_info, ID3D11Resource **texture) ++{ ++ D3D11_SUBRESOURCE_DATA *resource_data; ++ D3DX11_IMAGE_LOAD_INFO load_info_copy; ++ D3DX11_IMAGE_INFO img_info; ++ HRESULT hr; ++ ++ init_load_info(load_info, &load_info_copy); ++ if (!load_info_copy.pSrcInfo) ++ load_info_copy.pSrcInfo = &img_info; ++ ++ if (FAILED((hr = load_texture_data(data, size, &load_info_copy, &resource_data)))) ++ return hr; ++ hr = create_d3d_texture(device, &load_info_copy, resource_data, texture); ++ free(resource_data); ++ return hr; ++} ++ + HRESULT WINAPI D3DX11CreateTextureFromMemory(ID3D11Device *device, const void *data, + SIZE_T data_size, D3DX11_IMAGE_LOAD_INFO *load_info, ID3DX11ThreadPump *pump, + ID3D11Resource **texture, HRESULT *hresult) + { +- FIXME("device %p, data %p, data_size %Iu, load_info %p, pump %p, texture %p, hresult %p stub.\n", ++ HRESULT hr; ++ ++ TRACE("device %p, data %p, data_size %Iu, load_info %p, pump %p, texture %p, hresult %p.\n", + device, data, data_size, load_info, pump, texture, hresult); + +- return E_NOTIMPL; ++ if (!device) ++ return E_INVALIDARG; ++ if (!data) ++ return E_FAIL; ++ ++ if (pump) ++ FIXME("D3DX11 thread pump is currently unimplemented.\n"); ++ ++ hr = create_texture(device, data, data_size, load_info, texture); ++ if (hresult) ++ *hresult = hr; ++ return hr; + } + + HRESULT WINAPI D3DX11SaveTextureToFileW(ID3D11DeviceContext *context, ID3D11Resource *texture, +-- +2.51.0 +