[PATCH v2 0/8] MR10887: d3dx{10,11}: Add support for loading 2D texture array DDS files, and implement D3DX10LoadTextureFromTexture().
This patch series implements `D3DX10LoadTextureFromTexture()`, which is the d3dX10 equivalent to d3dx9's `D3DXLoadSurfaceFromSurface()`/`D3DXLoadVolumeFromVolume()`. -- v2: d3dx10: Add support for 3D textures in D3DX10LoadTextureFromTexture(). d3dx10: Add support for mipmap generation in D3DX10LoadTextureFromTexture(). d3dx10: Implement texture level loading in D3DX10LoadTextureFromTexture(). https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 60 +++++++++++++++++++++++++++++++++++ dlls/d3dx11_43/tests/d3dx11.c | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 252a64cddd2..3eed87bc0b8 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -843,6 +843,45 @@ static const uint8_t dds_dxt10_4_4[] = 0xf0,0xf0,0xf0,0xf0, }; +/* A 4x4 2D texture array with 2 elements and 2 mips. */ +static const uint8_t dds_2d_array_4_4[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x04,0x00,0x00,0x00, + 0x04,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,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, + 0x00,0xff,0xff,0xff, +}; + +static const uint8_t dds_2d_array_4_4_data[] = +{ + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, +}; + /* 1x1 wmp image */ static const uint8_t test_wmp[] = { @@ -1701,6 +1740,7 @@ test_image[] = test_bmp_24bpp, sizeof(test_bmp_24bpp), test_bmp_24bpp_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_BMP} }, + /* 5. */ { test_bmp_32bpp_xrgb, sizeof(test_bmp_32bpp_xrgb), test_bmp_32bpp_xrgb_data, {2, 2, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_BMP} @@ -1721,6 +1761,7 @@ test_image[] = test_gif, sizeof(test_gif), test_gif_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_GIF} }, + /* 10. */ { test_tiff, sizeof(test_tiff), test_tiff_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_TIFF} @@ -1741,6 +1782,7 @@ test_image[] = test_dds_24bpp, sizeof(test_dds_24bpp), test_dds_24bpp_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} }, + /* 15. */ { test_dds_32bpp, sizeof(test_dds_32bpp), test_dds_32bpp_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} @@ -1761,6 +1803,7 @@ test_image[] = test_dds_dxt1, sizeof(test_dds_dxt1), test_dds_dxt1_data, {4, 4, 1, 1, 1, 0, DXGI_FORMAT_BC1_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} }, + /* 20. */ { test_dds_dxt1_4x8, sizeof(test_dds_dxt1_4x8), test_dds_dxt1_4x8_data, {4, 8, 1, 1, 4, 0, DXGI_FORMAT_BC1_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} @@ -1781,6 +1824,7 @@ test_image[] = test_dds_dxt5, sizeof(test_dds_dxt5), test_dds_dxt5_data, {4, 2, 1, 1, 1, 0, DXGI_FORMAT_BC3_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} }, + /* 25. */ { test_dds_dxt5_8x8, sizeof(test_dds_dxt5_8x8), test_dds_dxt5_8x8_data, {8, 8, 1, 1, 4, 0, DXGI_FORMAT_BC3_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} @@ -1801,6 +1845,11 @@ test_image[] = test_dds_volume, sizeof(test_dds_volume), test_dds_volume_data, {4, 4, 2, 1, 3, 0, DXGI_FORMAT_BC2_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, D3DX10_IFF_DDS} }, + /* 30. */ + { + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), dds_2d_array_4_4_data, + {4, 4, 1, 2, 2, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} + }, { test_wmp, sizeof(test_wmp), test_wmp_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_WMP} @@ -3858,6 +3907,7 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size); + todo_wine_if (i == 30) 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) @@ -3879,6 +3929,7 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size); + todo_wine_if (i == 30) 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) @@ -3902,6 +3953,7 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size); + todo_wine_if (i == 30) 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) @@ -4306,6 +4358,7 @@ static void test_D3DX10CreateThreadPump(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10ThreadPump_WaitForAllItems(pump); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine_if (i == 30) ok(work_item_hr == S_OK || (work_item_hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), "Got unexpected hr %#lx.\n", work_item_hr); @@ -5057,6 +5110,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); + todo_wine_if (i == 30) 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) @@ -5072,6 +5126,7 @@ static void test_create_texture(void) 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); + todo_wine_if (i == 30) 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) @@ -5089,6 +5144,7 @@ static void test_create_texture(void) 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); + todo_wine_if (i == 30) 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) @@ -5269,6 +5325,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromFileW(device, path, NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); + todo_wine_if (i == 30) 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) @@ -5281,6 +5338,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromFileA(device, get_str_a(path), NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); + todo_wine_if (i == 30) 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) @@ -5384,6 +5442,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromResourceW(device, resource_module, test_resource_name, NULL, NULL, &resource, &hr2); + todo_wine_if (i == 30) 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); @@ -5397,6 +5456,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromResourceA(device, resource_module, get_str_a(test_resource_name), NULL, NULL, &resource, &hr2); + todo_wine_if (i == 30) 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); diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c index a56f415dced..d6855b0ec6f 100644 --- a/dlls/d3dx11_43/tests/d3dx11.c +++ b/dlls/d3dx11_43/tests/d3dx11.c @@ -844,6 +844,45 @@ static const uint8_t dds_dxt10_4_4[] = 0xf0,0xf0,0xf0,0xf0, }; +/* A 4x4 2D texture array with 2 elements and 2 mips. */ +static const uint8_t dds_2d_array_4_4[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x04,0x00,0x00,0x00, + 0x04,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,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, + 0x00,0xff,0xff,0xff, +}; + +static const uint8_t dds_2d_array_4_4_data[] = +{ + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, +}; + /* 1x1 wmp image */ static const uint8_t test_wmp[] = { @@ -1674,6 +1713,7 @@ test_image[] = 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} }, + /* 5. */ { 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} @@ -1694,6 +1734,7 @@ test_image[] = 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} }, + /* 10. */ { 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} @@ -1714,6 +1755,7 @@ test_image[] = 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} }, + /* 15. */ { 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} @@ -1734,6 +1776,7 @@ test_image[] = 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} }, + /* 20. */ { 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} @@ -1754,6 +1797,7 @@ test_image[] = 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} }, + /* 25. */ { 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} @@ -1774,6 +1818,11 @@ test_image[] = 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} }, + /* 30. */ + { + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), dds_2d_array_4_4_data, + {4, 4, 1, 2, 2, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RESOURCE_DIMENSION_TEXTURE2D, D3DX11_IFF_DDS} + }, { 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} @@ -3895,6 +3944,7 @@ static void test_create_texture(void) 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); + todo_wine_if (i == 30) 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) @@ -3910,6 +3960,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, &load_info, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); + todo_wine_if (i == 30) 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) @@ -3927,6 +3978,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, &load_info, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); + todo_wine_if (i == 30) 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) @@ -4101,6 +4153,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromFileW(device, path, NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); + todo_wine_if (i == 30) 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) @@ -4113,6 +4166,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromFileA(device, get_str_a(path), NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); + todo_wine_if (i == 30) 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) @@ -4216,6 +4270,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromResourceW(device, resource_module, test_resource_name, NULL, NULL, &resource, &hr2); + todo_wine_if (i == 30) ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX11_IFF_WMP), "Got unexpected hr %#lx.\n", hr); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); @@ -4229,6 +4284,7 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromResourceA(device, resource_module, get_str_a(test_resource_name), NULL, NULL, &resource, &hr2); + todo_wine_if (i == 30) ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX11_IFF_WMP), "Got unexpected hr %#lx.\n", hr); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 11 ----------- dlls/d3dx10_43/texture.c | 17 ++++++++--------- dlls/d3dx11_43/tests/d3dx11.c | 7 ------- dlls/d3dx11_43/texture.c | 17 ++++++++--------- 4 files changed, 16 insertions(+), 36 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 3eed87bc0b8..78278da0a60 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -3907,7 +3907,6 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size); - todo_wine_if (i == 30) 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) @@ -3929,7 +3928,6 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size); - todo_wine_if (i == 30) 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) @@ -3953,7 +3951,6 @@ static void test_D3DX10CreateAsyncTextureProcessor(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10DataProcessor_Process(dp, (void *)test_image[i].data, test_image[i].size); - todo_wine_if (i == 30) 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) @@ -4358,7 +4355,6 @@ static void test_D3DX10CreateThreadPump(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID3DX10ThreadPump_WaitForAllItems(pump); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine_if (i == 30) ok(work_item_hr == S_OK || (work_item_hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX10_IFF_WMP), "Got unexpected hr %#lx.\n", work_item_hr); @@ -5110,7 +5106,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); - todo_wine_if (i == 30) 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) @@ -5126,7 +5121,6 @@ static void test_create_texture(void) 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); - todo_wine_if (i == 30) 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) @@ -5144,7 +5138,6 @@ static void test_create_texture(void) 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); - todo_wine_if (i == 30) 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) @@ -5325,7 +5318,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromFileW(device, path, NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); - todo_wine_if (i == 30) 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) @@ -5338,7 +5330,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromFileA(device, get_str_a(path), NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); - todo_wine_if (i == 30) 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) @@ -5442,7 +5433,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromResourceW(device, resource_module, test_resource_name, NULL, NULL, &resource, &hr2); - todo_wine_if (i == 30) 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); @@ -5456,7 +5446,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX10CreateTextureFromResourceA(device, resource_module, get_str_a(test_resource_name), NULL, NULL, &resource, &hr2); - todo_wine_if (i == 30) 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); diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index bb312ae42ff..0fd300b66a0 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -637,7 +637,7 @@ void init_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info, D3DX10_IMAGE_LOAD_I HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, D3D10_SUBRESOURCE_DATA **resource_data) { - uint32_t loaded_mip_level_count, max_mip_level_count; + uint32_t loaded_mip_level_count, max_mip_level_count, loaded_layer_count; const struct pixel_format_desc *fmt_desc, *src_desc; struct d3dx_subresource_data *sub_rsrcs = NULL; D3DX10_IMAGE_INFO img_info; @@ -661,12 +661,11 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO goto end; } - if ((!(img_info.MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE) || img_info.ArraySize != 6) - && img_info.ArraySize != 1) + loaded_layer_count = img_info.ArraySize; + if ((loaded_layer_count > 1) && (img_info.ResourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D)) { - FIXME("img_info.ArraySize = %u not supported.\n", img_info.ArraySize); - hr = E_NOTIMPL; - goto end; + TRACE("Ignoring array size variable %u for 3D texture.\n", img_info.ArraySize); + loaded_layer_count = 1; } if (load_info->FirstMipLevel == D3DX10_DEFAULT || load_info->FirstMipLevel >= img_info.MipLevels) @@ -720,13 +719,13 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO } 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); + load_info->MipLevels, loaded_layer_count, fmt_desc, &sub_rsrcs); if (FAILED(hr)) goto end; src_desc = get_d3dx_pixel_format_info(image.format); loaded_mip_level_count = min(img_info.MipLevels - load_info->FirstMipLevel, load_info->MipLevels); - for (i = 0; i < img_info.ArraySize; ++i) + for (i = 0; i < loaded_layer_count; ++i) { struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth }; @@ -765,7 +764,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO } d3dx_get_mip_level_size(&base_level_size, base_level); - for (i = 0; i < img_info.ArraySize; ++i) + for (i = 0; i < loaded_layer_count; ++i) { struct volume src_size, dst_size; diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c index d6855b0ec6f..bdf34daa761 100644 --- a/dlls/d3dx11_43/tests/d3dx11.c +++ b/dlls/d3dx11_43/tests/d3dx11.c @@ -3944,7 +3944,6 @@ static void test_create_texture(void) 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); - todo_wine_if (i == 30) 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) @@ -3960,7 +3959,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, &load_info, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); - todo_wine_if (i == 30) 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) @@ -3978,7 +3976,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromMemory(device, test_image[i].data, test_image[i].size, &load_info, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); - todo_wine_if (i == 30) 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) @@ -4153,7 +4150,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromFileW(device, path, NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); - todo_wine_if (i == 30) 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) @@ -4166,7 +4162,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromFileA(device, get_str_a(path), NULL, NULL, &resource, &hr2); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); - todo_wine_if (i == 30) 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) @@ -4270,7 +4265,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromResourceW(device, resource_module, test_resource_name, NULL, NULL, &resource, &hr2); - todo_wine_if (i == 30) ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX11_IFF_WMP), "Got unexpected hr %#lx.\n", hr); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); @@ -4284,7 +4278,6 @@ static void test_create_texture(void) hr2 = 0xdeadbeef; hr = D3DX11CreateTextureFromResourceA(device, resource_module, get_str_a(test_resource_name), NULL, NULL, &resource, &hr2); - todo_wine_if (i == 30) ok(hr == S_OK || broken(hr == E_FAIL && test_image[i].expected_info.ImageFileFormat == D3DX11_IFF_WMP), "Got unexpected hr %#lx.\n", hr); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2); diff --git a/dlls/d3dx11_43/texture.c b/dlls/d3dx11_43/texture.c index 21f5b008964..5d4eaa4ef48 100644 --- a/dlls/d3dx11_43/texture.c +++ b/dlls/d3dx11_43/texture.c @@ -372,7 +372,7 @@ static void init_load_info(const D3DX11_IMAGE_LOAD_INFO *load_info, D3DX11_IMAGE HRESULT load_texture_data(const void *data, SIZE_T size, D3DX11_IMAGE_LOAD_INFO *load_info, D3D11_SUBRESOURCE_DATA **resource_data) { - uint32_t loaded_mip_level_count, max_mip_level_count; + uint32_t loaded_mip_level_count, max_mip_level_count, loaded_layer_count; const struct pixel_format_desc *fmt_desc, *src_desc; struct d3dx_subresource_data *sub_rsrcs = NULL; D3DX11_IMAGE_INFO img_info; @@ -396,12 +396,11 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX11_IMAGE_LOAD_INFO goto end; } - if ((!(img_info.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) || img_info.ArraySize != 6) - && img_info.ArraySize != 1) + loaded_layer_count = img_info.ArraySize; + if ((loaded_layer_count > 1) && (img_info.ResourceDimension == D3D11_RESOURCE_DIMENSION_TEXTURE3D)) { - FIXME("img_info.ArraySize = %u not supported.\n", img_info.ArraySize); - hr = E_NOTIMPL; - goto end; + TRACE("Ignoring array size variable %u for 3D texture.\n", img_info.ArraySize); + loaded_layer_count = 1; } if (load_info->FirstMipLevel == D3DX11_DEFAULT || load_info->FirstMipLevel >= img_info.MipLevels) @@ -455,13 +454,13 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX11_IMAGE_LOAD_INFO } 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); + load_info->MipLevels, loaded_layer_count, fmt_desc, &sub_rsrcs); if (FAILED(hr)) goto end; src_desc = get_d3dx_pixel_format_info(image.format); loaded_mip_level_count = min(img_info.MipLevels - load_info->FirstMipLevel, load_info->MipLevels); - for (i = 0; i < img_info.ArraySize; ++i) + for (i = 0; i < loaded_layer_count; ++i) { struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth }; @@ -500,7 +499,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX11_IMAGE_LOAD_INFO } d3dx_get_mip_level_size(&base_level_size, base_level); - for (i = 0; i < img_info.ArraySize; ++i) + for (i = 0; i < loaded_layer_count; ++i) { struct volume src_size, dst_size; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 693 ++++++++++++++++++++++++++++++++++ 1 file changed, 693 insertions(+) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 78278da0a60..0816cc073d7 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -882,6 +882,75 @@ static const uint8_t dds_2d_array_4_4_data[] = 0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, }; +/* A 4x4x4 3D texture with 2 mips. */ +static const uint8_t dds_dxt10_3d_texture_4_4[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x01,0x10,0x80,0x00,0x04,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,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,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1c,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, + 0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, + 0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, + 0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff, + 0x00,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff, + 0xff,0x00,0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x80,0x80,0x80,0xff, +}; + +/* 8x8 DXT10 DDS file with a format of DXGI_FORMAT_R8G8B8A8_UNORM and 4 mips. */ +static const uint8_t dds_dxt10_8_8[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x08,0x00,0x00,0x00, + 0x08,0x00,0x00,0x00,0x20,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,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff, + 0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff, + 0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff, + 0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff,0x40,0x40,0x40,0xff, + 0x40,0x40,0x40,0xff,0x20,0x20,0x20,0xff,0x20,0x20,0x20,0xff,0x20,0x20,0x20,0xff, + 0x20,0x20,0x20,0xff,0x10,0x10,0x10,0xff, +}; + /* 1x1 wmp image */ static const uint8_t test_wmp[] = { @@ -3102,6 +3171,73 @@ static void check_resource_data(ID3D10Resource *resource, const struct test_imag } } +#define check_test_resource_data(resource, data) check_test_resource_data_(__LINE__, resource, data) +static void check_test_resource_data_(unsigned int line, ID3D10Resource *resource, const void *expected_data) +{ + D3D10_RESOURCE_DIMENSION resource_dimension; + const uint8_t *cur_data = expected_data; + uint32_t levels, layers, i, j, fmt_bpp; + struct resource_readback rb = { 0 }; + DXGI_FORMAT format; + HRESULT hr; + + ID3D10Resource_GetType(resource, &resource_dimension); + switch (resource_dimension) + { + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: + { + D3D10_TEXTURE2D_DESC desc_2d; + ID3D10Texture2D *tex_2d; + + hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture2D, (void **)&tex_2d); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID3D10Texture2D_GetDesc(tex_2d, &desc_2d); + ID3D10Texture2D_Release(tex_2d); + + levels = desc_2d.MipLevels; + layers = desc_2d.ArraySize; + format = desc_2d.Format; + break; + } + + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: + { + D3D10_TEXTURE3D_DESC desc_3d; + ID3D10Texture3D *tex_3d; + + hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture3D, (void **)&tex_3d); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID3D10Texture3D_GetDesc(tex_3d, &desc_3d); + ID3D10Texture3D_Release(tex_3d); + + levels = desc_3d.MipLevels; + layers = 1; + format = desc_3d.Format; + break; + } + + default: + assert(0 && "Unsupported resource type."); + break; + } + + fmt_bpp = (get_bpp_from_format(format) + 7) / 8; + for (i = 0; i < layers; ++i) + { + for (j = 0; j < levels; ++j) + { + winetest_push_context("Layer %u, level %u", i, j); + get_resource_readback(resource, (i * levels) + j, &rb); + + _check_test_readback(__FILE__, line, &rb, cur_data, rb.width, rb.height, rb.depth, format, 0); + cur_data += (rb.width * fmt_bpp * rb.height * rb.depth); + + release_resource_readback(&rb); + winetest_pop_context(); + } + } +} + static void test_D3DX10UnsetAllDeviceObjects(void) { static const D3D10_INPUT_ELEMENT_DESC layout_desc[] = @@ -6009,6 +6145,562 @@ static void test_srgb_filter_flags(void) ok(!ID3D10Device_Release(device), "Unexpected refcount.\n"); } +struct test_resource +{ + D3D10_RESOURCE_DIMENSION type; + union + { + D3D10_TEXTURE2D_DESC desc_2d; + D3D10_TEXTURE3D_DESC desc_3d; + } desc; +}; + +static void init_subresource_data(D3D10_SUBRESOURCE_DATA *subresources, const void *data, uint32_t width, uint32_t height, + uint32_t depth, uint32_t mip_levels, uint32_t array_size, DXGI_FORMAT format) +{ + const uint8_t *pixel_ptr = data; + uint32_t i, j; + + for (i = 0; i < array_size; ++i) + { + uint32_t tmp_width, tmp_height, tmp_depth; + + tmp_width = width; + tmp_height = height; + tmp_depth = depth; + for (j = 0; j < mip_levels; ++j) + { + D3D10_SUBRESOURCE_DATA *subresource = &subresources[(i * mip_levels) + j]; + + subresource->pSysMem = pixel_ptr; + subresource->SysMemPitch = (tmp_width * get_bpp_from_format(format) + 7) / 8; + subresource->SysMemSlicePitch = subresource->SysMemPitch * tmp_height; + if (is_block_compressed(format)) + subresource->SysMemPitch *= 4; + pixel_ptr += (subresource->SysMemSlicePitch * tmp_depth); + + tmp_width = max(tmp_width / 2, 1); + tmp_height = max(tmp_height / 2, 1); + tmp_depth = max(tmp_depth / 2, 1); + } + } +} + +static ID3D10Resource *create_texture_resource(ID3D10Device *device, const struct test_resource *test_rsrc) +{ + D3D10_SUBRESOURCE_DATA subresources[16] = { 0 }; + uint8_t buffer[8192] = { 0 }; + ID3D10Resource *ret = NULL; + HRESULT hr = S_OK; + + switch (test_rsrc->type) + { + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: + { + const D3D10_TEXTURE2D_DESC *desc_2d = &test_rsrc->desc.desc_2d; + + assert((desc_2d->MipLevels * desc_2d->ArraySize) <= ARRAY_SIZE(subresources)); + init_subresource_data(subresources, buffer, desc_2d->Width, desc_2d->Height, 1, desc_2d->MipLevels, + desc_2d->ArraySize, desc_2d->Format); + hr = ID3D10Device_CreateTexture2D(device, desc_2d, subresources, (ID3D10Texture2D **)&ret); + break; + } + + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: + { + const D3D10_TEXTURE3D_DESC *desc_3d = &test_rsrc->desc.desc_3d; + + assert(desc_3d->MipLevels <= ARRAY_SIZE(subresources)); + init_subresource_data(subresources, buffer, desc_3d->Width, desc_3d->Height, desc_3d->Depth, + desc_3d->MipLevels, 1, desc_3d->Format); + hr = ID3D10Device_CreateTexture3D(device, desc_3d, subresources, (ID3D10Texture3D **)&ret); + break; + } + + default: + assert(0 && "Invalid resource type."); + } + + if (FAILED(hr)) + trace("Failed to create texture, hr %#lx.\n", hr); + return ret; +} + +static void test_load_texture_from_texture(void) +{ + static const uint8_t test_10_expected[] = + { + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + }; + static const uint8_t test_15_expected[] = + { + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff,0x80,0x80,0x80,0xff, + 0x80,0x80,0x80,0xff, + }; + static const uint8_t test_16_expected[] = + { + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0xff, + 0x10,0x10,0x10,0xff, + }; + static const uint8_t test_18_expected[] = + { + 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + }; + static const D3DX10_IMAGE_LOAD_INFO d3dx10_from_file_load_info = + { + D3DX10_FROM_FILE, D3DX10_FROM_FILE, D3DX10_FROM_FILE, D3DX10_DEFAULT, D3DX10_FROM_FILE, D3DX10_DEFAULT, + D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT, DXGI_FORMAT_FROM_FILE, D3DX10_FILTER_NONE, + D3DX10_FILTER_NONE, NULL + }; + static const struct + { + D3DX10_TEXTURE_LOAD_INFO load_info; + const uint8_t *src_data; + unsigned int src_data_size; + D3D10_BOX src_box; + BOOL use_src_box; + + struct test_resource dst_rsrc; + D3D10_BOX dst_box; + BOOL use_dst_box; + HRESULT expected_hr; + const uint8_t *expected_dst; + unsigned int broken_below_version; + BOOL todo_hr; + } tests[] = + { + /* + * Source and destination are the same texture. If the elements and + * levels match, the function will fail. + */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + }, + /* Invalid pSrcBox dimensions. */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 1, 0, 0, 0, 0, 0 }, TRUE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, D3DERR_INVALIDCALL, .broken_below_version = 40, .todo_hr = TRUE + }, + /* Invalid pDstBox dimensions. */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0, 1, 0, 0, 0, 0 }, TRUE, D3DERR_INVALIDCALL, .broken_below_version = 40, .todo_hr = TRUE + }, + /* + * Invalid filter flags. Still validated even if SrcFirstMip is higher + * than number of levels in the source texture. + */ + { + { NULL, NULL, 3, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, 9, D3DX10_DEFAULT }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + }, + /* + * Filter flags aren't validated if DstFirstMip is higher than the + * number of levels. + */ + { + { NULL, NULL, 0, 1, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, 9, D3DX10_FILTER_NONE }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, .todo_hr = TRUE + }, + /* + * 5. + * Filter flags aren't validated if SrcFirstElement is higher than the + * number of source elements. + */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 2, 0, D3DX10_DEFAULT, 9, D3DX10_FILTER_NONE }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, .todo_hr = TRUE + }, + /* + * Filter flags aren't validated if DstFirstElement is higher than the + * number of destination elements. + */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 1, D3DX10_DEFAULT, 9, D3DX10_FILTER_NONE }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, .todo_hr = TRUE + }, + /* Invalid mip filter flags. */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_DEFAULT, 9 }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 3, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + }, + /* + * Invalid mip filter flags. If no mips are generated, no validation is + * done. + */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, 9 }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, &dds_2d_array_4_4[0x94], .todo_hr = TRUE + }, + /* Destination texture is immutable. */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_IMMUTABLE, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + }, + /* + * 10. + * Source and destination are the same texture. + * Source is level 0 of element 0. + * Destination is level 0 of element 1. + * Load levels 0-1 from element 0 into levels 0-1 of element 1. + */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 1, D3DX10_DEFAULT, D3DX10_FILTER_NONE, D3DX10_DEFAULT }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_10_expected, .todo_hr = TRUE + }, + /* Load a 3D texture into a 2D texture. */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, D3DX10_DEFAULT }, + dds_dxt10_3d_texture_4_4, sizeof(dds_dxt10_3d_texture_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x94], .todo_hr = TRUE + }, + /* Load a 3D texture into a 2D texture with a source box offset. */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, D3DX10_DEFAULT }, + dds_dxt10_3d_texture_4_4, sizeof(dds_dxt10_3d_texture_4_4), { 0, 0, 1, 4, 4, 2 }, TRUE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0xd4], .todo_hr = TRUE + }, + /* Load a 3D texture into a 3D texture with identical dimensions. */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, D3DX10_DEFAULT }, + dds_dxt10_3d_texture_4_4, sizeof(dds_dxt10_3d_texture_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE3D, + .desc.desc_3d = + { + 4, 4, 4, 2, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x94], .todo_hr = TRUE + }, + /* Load a 3D texture into a 3D texture with a first mip offset. */ + { + { NULL, NULL, 1, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, D3DX10_DEFAULT }, + dds_dxt10_3d_texture_4_4, sizeof(dds_dxt10_3d_texture_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE3D, + .desc.desc_3d = + { + 2, 2, 2, 1, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x194], .todo_hr = TRUE + }, + /* + * 15. + * Source and destination are the same texture. + * Source is level 0 of element 0. + * Destination is level 1 of element 0. + * Load level n into level n+1. + */ + { + { NULL, NULL, 0, 1, 3, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, 9 }, + dds_dxt10_8_8, sizeof(dds_dxt10_8_8), { 0 }, FALSE, + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_15_expected, .todo_hr = TRUE + }, + /* + * Source and destination are the same texture. + * Source is level 3 of element 0. + * Destination is level 0 of element 0. + * Load level 3 into level 0, generate levels 1-3 from level 0. + */ + { + { NULL, NULL, 3, 0, 4, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_POINT, D3DX10_FILTER_POINT }, + dds_dxt10_8_8, sizeof(dds_dxt10_8_8), { 0 }, FALSE, + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_16_expected, .todo_hr = TRUE + }, + /* + * Argument of 0 for NumElements/NumMips matches behavior of + * D3DX10_DEFAULT. + */ + { + { NULL, NULL, 0, 0, 0, 0, 0, 0, D3DX10_FILTER_NONE, 9 }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, &dds_2d_array_4_4[0x94], .todo_hr = TRUE + }, + /* + * Empty source box results in a 1x1x1 box. + */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, 9 }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, TRUE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, FALSE, S_OK, test_18_expected, .todo_hr = TRUE + }, + /* + * Empty destination box results in a 1x1x1 box. + */ + { + { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, 9 }, + dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, + { + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + .desc.desc_2d = + { + 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, + 0, 0, + } + }, { 0 }, TRUE, S_OK, test_18_expected, .todo_hr = TRUE + }, + }; + const uint8_t empty_buffer[8192] = { 0 }; + ID3D10Resource *src_rsrc, *dst_rsrc; + const uint8_t *expected_dst; + ID3D10Device *device; + unsigned int i; + HRESULT hr; + + if (D3DX10_SDK_VERSION <= 34) + { + skip("D3DX10LoadTextureFromTexture() behavior is broken in version 34 and below.\n"); + return; + } + + device = create_device(); + if (!device) + { + skip("Failed to create device, skipping tests.\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + D3DX10_IMAGE_LOAD_INFO img_load_info = d3dx10_from_file_load_info; + D3DX10_TEXTURE_LOAD_INFO load_info = tests[i].load_info; + D3D10_BOX src_box = tests[i].src_box; + D3D10_BOX dst_box = tests[i].dst_box; + + if (D3DX10_SDK_VERSION < tests[i].broken_below_version) + { + skip("Test %u broken on version %u, skipping test.\n", i, D3DX10_SDK_VERSION); + continue; + } + + winetest_push_context("Test %u", i); + + hr = D3DX10CreateTextureFromMemory(device, tests[i].src_data, tests[i].src_data_size, &img_load_info, NULL, + &src_rsrc, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + load_info.pSrcBox = (tests[i].use_src_box) ? &src_box : NULL; + load_info.pDstBox = (tests[i].use_dst_box) ? &dst_box : NULL; + expected_dst = (tests[i].expected_dst) ? tests[i].expected_dst : empty_buffer; + + dst_rsrc = (tests[i].dst_rsrc.type) ? create_texture_resource(device, &tests[i].dst_rsrc) : src_rsrc; + ok(!!dst_rsrc, "Got unexpected dst_rsrc %p.\n", dst_rsrc); + + hr = D3DX10LoadTextureFromTexture(src_rsrc, &load_info, dst_rsrc); + todo_wine_if(tests[i].todo_hr) ok(hr == tests[i].expected_hr, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + check_test_resource_data(dst_rsrc, expected_dst); + + ID3D10Resource_Release(src_rsrc); + if (dst_rsrc != src_rsrc) + ID3D10Resource_Release(dst_rsrc); + + winetest_pop_context(); + } + + /* NULL load_info argument, gets default load_info values. */ + hr = D3DX10CreateTextureFromMemory(device, dds_2d_array_4_4, sizeof(dds_2d_array_4_4), + (D3DX10_IMAGE_LOAD_INFO *)&d3dx10_from_file_load_info, NULL, &src_rsrc, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + dst_rsrc = create_texture_resource(device, &tests[8].dst_rsrc); + ok(!!dst_rsrc, "Got unexpected dst_rsrc %p.\n", dst_rsrc); + + /* Test NULL arguments for source/dest resource. */ + hr = D3DX10LoadTextureFromTexture(src_rsrc, NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + + hr = D3DX10LoadTextureFromTexture(NULL, NULL, dst_rsrc); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + + hr = D3DX10LoadTextureFromTexture(NULL, NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + + /* NULL load_info argument, gets default load_info values. */ + hr = D3DX10LoadTextureFromTexture(src_rsrc, NULL, dst_rsrc); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + check_test_resource_data(dst_rsrc, &dds_2d_array_4_4[0x94]); + + ID3D10Resource_Release(src_rsrc); + ID3D10Resource_Release(dst_rsrc); + + /* NULL load_info argument on 3D texture. */ + hr = D3DX10CreateTextureFromMemory(device, dds_dxt10_3d_texture_4_4, sizeof(dds_dxt10_3d_texture_4_4), + (D3DX10_IMAGE_LOAD_INFO *)&d3dx10_from_file_load_info, NULL, &src_rsrc, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + dst_rsrc = create_texture_resource(device, &tests[13].dst_rsrc); + ok(!!dst_rsrc, "Got unexpected dst_rsrc %p.\n", dst_rsrc); + + hr = D3DX10LoadTextureFromTexture(src_rsrc, NULL, dst_rsrc); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + check_test_resource_data(dst_rsrc, &dds_dxt10_3d_texture_4_4[0x94]); + + ID3D10Resource_Release(src_rsrc); + ID3D10Resource_Release(dst_rsrc); + + ok(!ID3D10Device_Release(device), "Unexpected refcount.\n"); +} + #define check_rect(rect, left, top, right, bottom) _check_rect(__LINE__, rect, left, top, right, bottom) static inline void _check_rect(unsigned int line, const RECT *rect, int left, int top, int right, int bottom) { @@ -7500,4 +8192,5 @@ START_TEST(d3dx10) test_image_filters(); test_dxt_formats(); test_srgb_filter_flags(); + test_load_texture_from_texture(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/d3dx10_43_main.c | 8 -------- dlls/d3dx10_43/tests/d3dx10.c | 12 ++++++------ dlls/d3dx10_43/texture.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/dlls/d3dx10_43/d3dx10_43_main.c b/dlls/d3dx10_43/d3dx10_43_main.c index ec7407508d3..ba6de566576 100644 --- a/dlls/d3dx10_43/d3dx10_43_main.c +++ b/dlls/d3dx10_43/d3dx10_43_main.c @@ -168,11 +168,3 @@ D3DX_CPU_OPTIMIZATION WINAPI D3DXCpuOptimizations(BOOL enable) return D3DX_NOT_OPTIMIZED; } - -HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_TEXTURE_LOAD_INFO *load_info, - ID3D10Resource *dst_texture) -{ - FIXME("src_texture %p, load_info %p, dst_texture %p stub!\n", src_texture, load_info, dst_texture); - - return E_NOTIMPL; -} diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 0816cc073d7..8bd05c41f35 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -6328,7 +6328,7 @@ static void test_load_texture_from_texture(void) { { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT }, dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, - { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, D3DERR_INVALIDCALL }, /* Invalid pSrcBox dimensions. */ { @@ -6341,7 +6341,7 @@ static void test_load_texture_from_texture(void) 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, D3DERR_INVALIDCALL, .broken_below_version = 40, .todo_hr = TRUE + }, { 0 }, FALSE, D3DERR_INVALIDCALL, .broken_below_version = 40 }, /* Invalid pDstBox dimensions. */ { @@ -6354,7 +6354,7 @@ static void test_load_texture_from_texture(void) 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0, 1, 0, 0, 0, 0 }, TRUE, D3DERR_INVALIDCALL, .broken_below_version = 40, .todo_hr = TRUE + }, { 0, 1, 0, 0, 0, 0 }, TRUE, D3DERR_INVALIDCALL, .broken_below_version = 40 }, /* * Invalid filter flags. Still validated even if SrcFirstMip is higher @@ -6665,13 +6665,13 @@ static void test_load_texture_from_texture(void) /* Test NULL arguments for source/dest resource. */ hr = D3DX10LoadTextureFromTexture(src_rsrc, NULL, NULL); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); hr = D3DX10LoadTextureFromTexture(NULL, NULL, dst_rsrc); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); hr = D3DX10LoadTextureFromTexture(NULL, NULL, NULL); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); /* NULL load_info argument, gets default load_info values. */ hr = D3DX10LoadTextureFromTexture(src_rsrc, NULL, dst_rsrc); diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 0fd300b66a0..b3787685b10 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -27,6 +27,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx); +#define D3DERR_INVALIDCALL 0x8876086c + /* * 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. @@ -911,3 +913,34 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s *hresult = hr; return hr; } + +static BOOL d3d10_box_is_valid(const D3D10_BOX *box) +{ + return (box->left <= box->right) && (box->top <= box->bottom) && (box->front <= box->back); +} + +HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_TEXTURE_LOAD_INFO *load_info, + ID3D10Resource *dst_texture) +{ + static const D3DX10_TEXTURE_LOAD_INFO default_load_info = { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, + D3DX10_DEFAULT, D3DX10_DEFAULT }; + D3DX10_TEXTURE_LOAD_INFO info = (load_info) ? *load_info : default_load_info; + + FIXME("src_texture %p, load_info %p, dst_texture %p stub!\n", src_texture, load_info, dst_texture); + + if (!src_texture || !dst_texture) + return D3DERR_INVALIDCALL; + + if ((info.pSrcBox && !d3d10_box_is_valid(info.pSrcBox)) || (info.pDstBox && !d3d10_box_is_valid(info.pDstBox))) + return D3DERR_INVALIDCALL; + + /* + * If the source and destination texture are the same, we can't load into + * the same subresource. + */ + if (src_texture == dst_texture && info.SrcFirstMip == info.DstFirstMip + && info.SrcFirstElement == info.DstFirstElement) + return D3DERR_INVALIDCALL; + + return E_NOTIMPL; +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 8 ++-- dlls/d3dx10_43/texture.c | 72 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 8bd05c41f35..7a4a3c83cf9 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -6386,7 +6386,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, .todo_hr = TRUE + }, { 0 }, FALSE, S_OK }, /* * 5. @@ -6403,7 +6403,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, .todo_hr = TRUE + }, { 0 }, FALSE, S_OK }, /* * Filter flags aren't validated if DstFirstElement is higher than the @@ -6419,7 +6419,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, .todo_hr = TRUE + }, { 0 }, FALSE, S_OK }, /* Invalid mip filter flags. */ { @@ -6461,7 +6461,7 @@ static void test_load_texture_from_texture(void) 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_IMMUTABLE, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + }, { 0 }, FALSE, D3DERR_INVALIDCALL }, /* * 10. diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index b3787685b10..fd72ec81825 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -919,12 +919,64 @@ static BOOL d3d10_box_is_valid(const D3D10_BOX *box) return (box->left <= box->right) && (box->top <= box->bottom) && (box->front <= box->back); } +struct d3dx_texture_info +{ + enum d3dx_resource_type resource_type; + const struct pixel_format_desc *fmt; + + struct volume size; + uint32_t levels; + uint32_t layers; + + D3D10_USAGE usage; +}; + +static HRESULT d3dx_texture_info_from_d3d10_resource(ID3D10Resource *rsrc, struct d3dx_texture_info *info) +{ + D3D10_RESOURCE_DIMENSION rsrc_dim; + HRESULT hr; + + ID3D10Resource_GetType(rsrc, &rsrc_dim); + switch (rsrc_dim) + { + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: + { + D3D10_TEXTURE2D_DESC desc_2d; + ID3D10Texture2D *tex_2d; + + hr = ID3D10Resource_QueryInterface(rsrc, &IID_ID3D10Texture2D, (void **)&tex_2d); + if (FAILED(hr)) + return hr; + ID3D10Texture2D_GetDesc(tex_2d, &desc_2d); + ID3D10Texture2D_Release(tex_2d); + + info->resource_type = D3DX_RESOURCE_TYPE_TEXTURE_2D; + info->fmt = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(desc_2d.Format)); + if (is_unknown_format(info->fmt)) + return E_NOTIMPL; + set_volume_struct(&info->size, desc_2d.Width, desc_2d.Height, 1); + info->levels = desc_2d.MipLevels; + info->layers = desc_2d.ArraySize; + info->usage = desc_2d.Usage; + break; + } + + default: + FIXME("Unhandled resource type %d.\n", rsrc_dim); + return E_NOTIMPL; + } + + return S_OK; +} + HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_TEXTURE_LOAD_INFO *load_info, ID3D10Resource *dst_texture) { static const D3DX10_TEXTURE_LOAD_INFO default_load_info = { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 0, D3DX10_DEFAULT, D3DX10_DEFAULT, D3DX10_DEFAULT }; D3DX10_TEXTURE_LOAD_INFO info = (load_info) ? *load_info : default_load_info; + struct d3dx_texture_info src_info, dst_info; + HRESULT hr; FIXME("src_texture %p, load_info %p, dst_texture %p stub!\n", src_texture, load_info, dst_texture); @@ -942,5 +994,25 @@ HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_ && info.SrcFirstElement == info.DstFirstElement) return D3DERR_INVALIDCALL; + hr = d3dx_texture_info_from_d3d10_resource(src_texture, &src_info); + if (FAILED(hr)) + return hr; + + hr = d3dx_texture_info_from_d3d10_resource(dst_texture, &dst_info); + if (FAILED(hr)) + return hr; + + /* Destination cannot be immutable. */ + if (dst_info.usage == D3D10_USAGE_IMMUTABLE) + return D3DERR_INVALIDCALL; + + /* + * Attempting to load beyond the number of levels/layers in the passed in + * textures, nothing to load, return early. + */ + if ((info.DstFirstMip >= dst_info.levels) || (info.SrcFirstElement >= src_info.layers) + || (info.DstFirstElement >= dst_info.layers)) + return S_OK; + return E_NOTIMPL; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 19 ++- dlls/d3dx10_43/texture.c | 249 +++++++++++++++++++++++++++++++++- 2 files changed, 256 insertions(+), 12 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 7a4a3c83cf9..2715f67fa8e 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -6370,7 +6370,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + }, { 0 }, FALSE, D3DERR_INVALIDCALL }, /* * Filter flags aren't validated if DstFirstMip is higher than the @@ -6448,7 +6448,7 @@ static void test_load_texture_from_texture(void) 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, &dds_2d_array_4_4[0x94], .todo_hr = TRUE + }, { 0 }, FALSE, S_OK, &dds_2d_array_4_4[0x94] }, /* Destination texture is immutable. */ { @@ -6473,7 +6473,7 @@ static void test_load_texture_from_texture(void) { { NULL, NULL, 0, 0, D3DX10_DEFAULT, 0, 1, D3DX10_DEFAULT, D3DX10_FILTER_NONE, D3DX10_DEFAULT }, dds_2d_array_4_4, sizeof(dds_2d_array_4_4), { 0 }, FALSE, - { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_10_expected, .todo_hr = TRUE + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_10_expected }, /* Load a 3D texture into a 2D texture. */ { @@ -6537,7 +6537,7 @@ static void test_load_texture_from_texture(void) { { NULL, NULL, 0, 1, 3, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_NONE, 9 }, dds_dxt10_8_8, sizeof(dds_dxt10_8_8), { 0 }, FALSE, - { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_15_expected, .todo_hr = TRUE + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_15_expected }, /* * Source and destination are the same texture. @@ -6564,7 +6564,7 @@ static void test_load_texture_from_texture(void) 4, 4, 2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, &dds_2d_array_4_4[0x94], .todo_hr = TRUE + }, { 0 }, FALSE, S_OK, &dds_2d_array_4_4[0x94] }, /* * Empty source box results in a 1x1x1 box. @@ -6579,7 +6579,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, test_18_expected, .todo_hr = TRUE + }, { 0 }, FALSE, S_OK, test_18_expected }, /* * Empty destination box results in a 1x1x1 box. @@ -6594,7 +6594,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, TRUE, S_OK, test_18_expected, .todo_hr = TRUE + }, { 0 }, TRUE, S_OK, test_18_expected }, }; const uint8_t empty_buffer[8192] = { 0 }; @@ -6675,9 +6675,8 @@ static void test_load_texture_from_texture(void) /* NULL load_info argument, gets default load_info values. */ hr = D3DX10LoadTextureFromTexture(src_rsrc, NULL, dst_rsrc); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - check_test_resource_data(dst_rsrc, &dds_2d_array_4_4[0x94]); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_test_resource_data(dst_rsrc, &dds_2d_array_4_4[0x94]); ID3D10Resource_Release(src_rsrc); ID3D10Resource_Release(dst_rsrc); diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index fd72ec81825..71140e9d60b 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -914,6 +914,53 @@ HRESULT WINAPI D3DX10CreateTextureFromMemory(ID3D10Device *device, const void *s return hr; } +static void init_d3d10_box(D3D10_BOX *box, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t front, + uint32_t back) +{ + box->left = left; + box->top = top; + box->right = max(right, left + 1); + box->bottom = max(bottom, top + 1); + box->front = front; + box->back = max(back, front + 1); +} + +static void d3d10_box_get_next_level(D3D10_BOX *box) +{ + init_d3d10_box(box, box->left >> 1, box->top >> 1, box->right >> 1, box->bottom >> 1, + box->front >> 1, box->back >> 1); +} + +static BOOL d3d10_box_clamp(D3D10_BOX *box, unsigned int level, struct volume *size) +{ + struct volume level_size = *size; + BOOL clamped; + + if (level) + d3dx_get_mip_level_size(&level_size, level); + + clamped = (box->right > level_size.width) || (box->bottom > level_size.height) || (box->back > level_size.depth); + if (box->right > level_size.width) + { + box->right = level_size.width; + box->left = min(box->right - 1, box->left); + } + + if (box->bottom > level_size.height) + { + box->bottom = level_size.height; + box->top = min(box->bottom - 1, box->top); + } + + if (box->back > level_size.depth) + { + box->back = level_size.depth; + box->front = min(box->back - 1, box->front); + } + + return clamped; +} + static BOOL d3d10_box_is_valid(const D3D10_BOX *box) { return (box->left <= box->right) && (box->top <= box->bottom) && (box->front <= box->back); @@ -969,6 +1016,153 @@ static HRESULT d3dx_texture_info_from_d3d10_resource(ID3D10Resource *rsrc, struc return S_OK; } +static HRESULT d3d10_staging_resource_from_d3dx_texture_info(ID3D10Device *device, struct d3dx_texture_info *info, + BOOL is_dst, ID3D10Resource **rsrc) +{ + const UINT cpu_flags = is_dst ? (D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE) : D3D10_CPU_ACCESS_READ; + + *rsrc = NULL; + switch (info->resource_type) + { + case D3DX_RESOURCE_TYPE_TEXTURE_2D: + { + D3D10_TEXTURE2D_DESC desc = { info->size.width, info->size.height, 1, 1, 0, { 1, 0 }, D3D10_USAGE_STAGING, + 0, cpu_flags }; + + desc.Format = dxgi_format_from_d3dx_pixel_format_id(info->fmt->format); + return ID3D10Device_CreateTexture2D(device, &desc, NULL, (ID3D10Texture2D **)rsrc); + } + + default: + return E_NOTIMPL; + } +} + +static HRESULT d3dx_subresource_data_from_d3d10_staging_resource_map(ID3D10Resource *rsrc, + enum d3dx_resource_type rtype, BOOL is_dst, struct d3dx_subresource_data *out_data) +{ + const D3D10_MAP map_type = is_dst ? D3D10_MAP_READ_WRITE : D3D10_MAP_READ; + HRESULT hr; + + memset(out_data, 0, sizeof(*out_data)); + switch (rtype) + { + case D3DX_RESOURCE_TYPE_TEXTURE_2D: + { + ID3D10Texture2D *tex = (ID3D10Texture2D *)rsrc; + D3D10_MAPPED_TEXTURE2D map; + + hr = ID3D10Texture2D_Map(tex, 0, map_type, 0, &map); + if (SUCCEEDED(hr)) + { + out_data->data = map.pData; + out_data->row_pitch = map.RowPitch; + } + break; + } + + default: + hr = E_NOTIMPL; + break; + } + + return hr; +} + +static void d3d10_staging_resource_unmap(ID3D10Resource *rsrc, enum d3dx_resource_type rtype) +{ + switch (rtype) + { + case D3DX_RESOURCE_TYPE_TEXTURE_2D: + ID3D10Texture2D_Unmap((ID3D10Texture2D *)rsrc, 0); + break; + + default: + break; + } +} + +static HRESULT d3d10_load_texture_from_texture(struct d3dx_texture_info *src_info, ID3D10Resource *src_rsrc, + const D3D10_BOX *src_box, uint32_t src_first_layer, uint32_t src_first_level, + struct d3dx_texture_info *dst_info, ID3D10Resource *dst_rsrc, const D3D10_BOX *dst_box, + uint32_t dst_first_layer, uint32_t dst_first_level, uint32_t layer_load_count, uint32_t level_load_count, + uint32_t filter) +{ + ID3D10Resource *src_staging, *dst_staging; + ID3D10Device *device = NULL; + unsigned int i, j; + HRESULT hr; + + if (FAILED(hr = d3dx_validate_filter(filter))) + { + WARN("Invalid filter argument %#x.\n", filter); + return hr; + } + + src_staging = dst_staging = NULL; + ID3D10Resource_GetDevice(src_rsrc, &device); + hr = d3d10_staging_resource_from_d3dx_texture_info(device, src_info, FALSE, &src_staging); + if (FAILED(hr)) + goto exit; + + hr = d3d10_staging_resource_from_d3dx_texture_info(device, dst_info, TRUE, &dst_staging); + if (FAILED(hr)) + goto exit; + + for (i = 0; i < layer_load_count; ++i) + { + unsigned int src_sub_rsrc_idx = (src_first_layer + i) * src_info->levels + src_first_level; + unsigned int dst_sub_rsrc_idx = (dst_first_layer + i) * dst_info->levels + dst_first_level; + D3D10_BOX src_level_box = *src_box; + D3D10_BOX dst_level_box = *dst_box; + + for (j = 0; j < level_load_count; ++j) + { + struct d3dx_subresource_data src_sub_rsrc, dst_sub_rsrc; + struct d3dx_pixels src_pixels, dst_pixels; + + ID3D10Device_CopySubresourceRegion(device, src_staging, 0, 0, 0, 0, src_rsrc, src_sub_rsrc_idx + j, NULL); + hr = d3dx_subresource_data_from_d3d10_staging_resource_map(src_staging, src_info->resource_type, FALSE, + &src_sub_rsrc); + if (FAILED(hr)) + goto exit; + + ID3D10Device_CopySubresourceRegion(device, dst_staging, 0, 0, 0, 0, dst_rsrc, dst_sub_rsrc_idx + j, NULL); + hr = d3dx_subresource_data_from_d3d10_staging_resource_map(dst_staging, dst_info->resource_type, TRUE, + &dst_sub_rsrc); + if (FAILED(hr)) + goto exit; + + /* Account for source/destination box offsets. */ + d3dx_pixels_init(src_sub_rsrc.data, src_sub_rsrc.row_pitch, src_sub_rsrc.slice_pitch, NULL, + src_info->fmt->format, src_level_box.left, src_level_box.top, src_level_box.right, + src_level_box.bottom, src_level_box.front, src_level_box.back, &src_pixels); + d3dx_pixels_init(dst_sub_rsrc.data, dst_sub_rsrc.row_pitch, dst_sub_rsrc.slice_pitch, NULL, + dst_info->fmt->format, dst_level_box.left, dst_level_box.top, dst_level_box.right, + dst_level_box.bottom, dst_level_box.front, dst_level_box.back, &dst_pixels); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_info->fmt, &src_pixels, src_info->fmt, filter, 0); + d3d10_staging_resource_unmap(src_staging, src_info->resource_type); + d3d10_staging_resource_unmap(dst_staging, dst_info->resource_type); + if (FAILED(hr)) + goto exit; + + ID3D10Device_CopySubresourceRegion(device, dst_rsrc, dst_sub_rsrc_idx + j, 0, 0, 0, dst_staging, 0, &dst_level_box); + d3d10_box_get_next_level(&src_level_box); + d3d10_box_get_next_level(&dst_level_box); + } + } + +exit: + if (device) + ID3D10Device_Release(device); + if (src_staging) + ID3D10Resource_Release(src_staging); + if (dst_staging) + ID3D10Resource_Release(dst_staging); + return hr; +} + HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_TEXTURE_LOAD_INFO *load_info, ID3D10Resource *dst_texture) { @@ -976,9 +1170,11 @@ HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_ D3DX10_DEFAULT, D3DX10_DEFAULT }; D3DX10_TEXTURE_LOAD_INFO info = (load_info) ? *load_info : default_load_info; struct d3dx_texture_info src_info, dst_info; + uint32_t loaded_level_count; + D3D10_BOX src_box, dst_box; HRESULT hr; - FIXME("src_texture %p, load_info %p, dst_texture %p stub!\n", src_texture, load_info, dst_texture); + TRACE("src_texture %p, load_info %p, dst_texture %p.\n", src_texture, load_info, dst_texture); if (!src_texture || !dst_texture) return D3DERR_INVALIDCALL; @@ -1014,5 +1210,54 @@ HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_ || (info.DstFirstElement >= dst_info.layers)) return S_OK; - return E_NOTIMPL; + /* + * Native doesn't validate the SrcFirstMip argument, and will read OOB if + * passed a value higher than the actual number of levels. + */ + if (info.SrcFirstMip >= src_info.levels) + { + WARN("Attempted to load first mip from source beyond total number of mips, clamping.\n"); + info.SrcFirstMip = src_info.levels - 1; + } + + if (!info.NumElements) + info.NumElements = D3DX10_DEFAULT; + info.NumElements = min(info.NumElements, min(src_info.layers - info.SrcFirstElement, + dst_info.layers - info.DstFirstElement)); + + if (!info.NumMips) + info.NumMips = D3DX10_DEFAULT; + info.NumMips = min(dst_info.levels - info.DstFirstMip, info.NumMips); + loaded_level_count = min(src_info.levels - info.SrcFirstMip, info.NumMips); + + if (loaded_level_count < info.NumMips) + { + FIXME("Mipmap generation is currently unimplemented.\n"); + return E_NOTIMPL; + } + + if (info.pSrcBox) + init_d3d10_box(&src_box, info.pSrcBox->left, info.pSrcBox->top, info.pSrcBox->right, info.pSrcBox->bottom, + info.pSrcBox->front, info.pSrcBox->back); + else + init_d3d10_box(&src_box, 0, 0, src_info.size.width, src_info.size.height, 0, src_info.size.depth); + /* Native will do an OOB access in this case, we'll just clamp instead. */ + if (d3d10_box_clamp(&src_box, info.SrcFirstMip, &src_info.size) && info.pSrcBox) + WARN("Clamped passed in pSrcBox values.\n"); + + if (info.pDstBox) + init_d3d10_box(&dst_box, info.pDstBox->left, info.pDstBox->top, info.pDstBox->right, info.pDstBox->bottom, + info.pDstBox->front, info.pDstBox->back); + else + init_d3d10_box(&dst_box, 0, 0, dst_info.size.width, dst_info.size.height, 0, dst_info.size.depth); + /* Native will do an OOB access in this case, we'll just clamp instead. */ + if (d3d10_box_clamp(&dst_box, info.DstFirstMip, &dst_info.size) && info.pDstBox) + WARN("Clamped passed in pDstBox values.\n"); + + if (!info.Filter || info.Filter == D3DX10_DEFAULT) + info.Filter = D3DX10_FILTER_LINEAR; + + return d3d10_load_texture_from_texture(&src_info, src_texture, &src_box, info.SrcFirstElement, info.SrcFirstMip, + &dst_info, dst_texture, &dst_box, info.DstFirstElement, info.DstFirstMip, info.NumElements, + loaded_level_count, info.Filter); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 4 ++-- dlls/d3dx10_43/texture.c | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 2715f67fa8e..4380da7ab83 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -6432,7 +6432,7 @@ static void test_load_texture_from_texture(void) 4, 4, 3, 2, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, D3DERR_INVALIDCALL, .todo_hr = TRUE + }, { 0 }, FALSE, D3DERR_INVALIDCALL }, /* * Invalid mip filter flags. If no mips are generated, no validation is @@ -6548,7 +6548,7 @@ static void test_load_texture_from_texture(void) { { NULL, NULL, 3, 0, 4, 0, 0, D3DX10_DEFAULT, D3DX10_FILTER_POINT, D3DX10_FILTER_POINT }, dds_dxt10_8_8, sizeof(dds_dxt10_8_8), { 0 }, FALSE, - { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_16_expected, .todo_hr = TRUE + { D3D10_RESOURCE_DIMENSION_UNKNOWN }, { 0 }, FALSE, S_OK, test_16_expected }, /* * Argument of 0 for NumElements/NumMips matches behavior of diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 71140e9d60b..4b741823722 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -925,6 +925,12 @@ static void init_d3d10_box(D3D10_BOX *box, uint32_t left, uint32_t top, uint32_t box->back = max(back, front + 1); } +static void d3d10_box_get_level(D3D10_BOX *box, unsigned int level) +{ + init_d3d10_box(box, box->left >> level, box->top >> level, box->right >> level, box->bottom >> level, + box->front >> level, box->back >> level); +} + static void d3d10_box_get_next_level(D3D10_BOX *box) { init_d3d10_box(box, box->left >> 1, box->top >> 1, box->right >> 1, box->bottom >> 1, @@ -1230,12 +1236,6 @@ HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_ info.NumMips = min(dst_info.levels - info.DstFirstMip, info.NumMips); loaded_level_count = min(src_info.levels - info.SrcFirstMip, info.NumMips); - if (loaded_level_count < info.NumMips) - { - FIXME("Mipmap generation is currently unimplemented.\n"); - return E_NOTIMPL; - } - if (info.pSrcBox) init_d3d10_box(&src_box, info.pSrcBox->left, info.pSrcBox->top, info.pSrcBox->right, info.pSrcBox->bottom, info.pSrcBox->front, info.pSrcBox->back); @@ -1257,7 +1257,23 @@ HRESULT WINAPI D3DX10LoadTextureFromTexture(ID3D10Resource *src_texture, D3DX10_ if (!info.Filter || info.Filter == D3DX10_DEFAULT) info.Filter = D3DX10_FILTER_LINEAR; - return d3d10_load_texture_from_texture(&src_info, src_texture, &src_box, info.SrcFirstElement, info.SrcFirstMip, + hr = d3d10_load_texture_from_texture(&src_info, src_texture, &src_box, info.SrcFirstElement, info.SrcFirstMip, &dst_info, dst_texture, &dst_box, info.DstFirstElement, info.DstFirstMip, info.NumElements, loaded_level_count, info.Filter); + if (SUCCEEDED(hr) && loaded_level_count < info.NumMips) + { + const uint32_t base_level = loaded_level_count - 1; + D3D10_BOX src_level_box, dst_level_box; + + src_level_box = dst_level_box = dst_box; + d3d10_box_get_level(&src_level_box, base_level); + d3d10_box_get_level(&dst_level_box, base_level + 1); + if (!info.MipFilter || info.MipFilter == D3DX10_DEFAULT) + info.MipFilter = D3DX10_FILTER_LINEAR; + hr = d3d10_load_texture_from_texture(&dst_info, dst_texture, &src_level_box, info.DstFirstElement, base_level, + &dst_info, dst_texture, &dst_level_box, info.DstFirstElement, base_level + 1, info.NumElements, + (info.NumMips - loaded_level_count), info.MipFilter); + } + + return hr; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 13 +++++---- dlls/d3dx10_43/texture.c | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 4380da7ab83..0008a995ff8 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -6486,7 +6486,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x94], .todo_hr = TRUE + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x94] }, /* Load a 3D texture into a 2D texture with a source box offset. */ { @@ -6499,7 +6499,7 @@ static void test_load_texture_from_texture(void) 4, 4, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0xd4], .todo_hr = TRUE + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0xd4] }, /* Load a 3D texture into a 3D texture with identical dimensions. */ { @@ -6512,7 +6512,7 @@ static void test_load_texture_from_texture(void) 4, 4, 4, 2, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x94], .todo_hr = TRUE + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x94] }, /* Load a 3D texture into a 3D texture with a first mip offset. */ { @@ -6525,7 +6525,7 @@ static void test_load_texture_from_texture(void) 2, 2, 2, 1, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, } - }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x194], .todo_hr = TRUE + }, { 0 }, FALSE, S_OK, &dds_dxt10_3d_texture_4_4[0x194] }, /* * 15. @@ -6690,9 +6690,8 @@ static void test_load_texture_from_texture(void) ok(!!dst_rsrc, "Got unexpected dst_rsrc %p.\n", dst_rsrc); hr = D3DX10LoadTextureFromTexture(src_rsrc, NULL, dst_rsrc); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - check_test_resource_data(dst_rsrc, &dds_dxt10_3d_texture_4_4[0x94]); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_test_resource_data(dst_rsrc, &dds_dxt10_3d_texture_4_4[0x94]); ID3D10Resource_Release(src_rsrc); ID3D10Resource_Release(dst_rsrc); diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 4b741823722..1a54609f6ef 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -1014,6 +1014,28 @@ static HRESULT d3dx_texture_info_from_d3d10_resource(ID3D10Resource *rsrc, struc break; } + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: + { + D3D10_TEXTURE3D_DESC desc_3d; + ID3D10Texture3D *tex_3d; + + hr = ID3D10Resource_QueryInterface(rsrc, &IID_ID3D10Texture3D, (void **)&tex_3d); + if (FAILED(hr)) + return hr; + ID3D10Texture3D_GetDesc(tex_3d, &desc_3d); + ID3D10Texture3D_Release(tex_3d); + + info->resource_type = D3DX_RESOURCE_TYPE_TEXTURE_3D; + info->fmt = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(desc_3d.Format)); + if (is_unknown_format(info->fmt)) + return E_NOTIMPL; + set_volume_struct(&info->size, desc_3d.Width, desc_3d.Height, desc_3d.Depth); + info->levels = desc_3d.MipLevels; + info->layers = 1; + info->usage = desc_3d.Usage; + break; + } + default: FIXME("Unhandled resource type %d.\n", rsrc_dim); return E_NOTIMPL; @@ -1039,6 +1061,15 @@ static HRESULT d3d10_staging_resource_from_d3dx_texture_info(ID3D10Device *devic return ID3D10Device_CreateTexture2D(device, &desc, NULL, (ID3D10Texture2D **)rsrc); } + case D3DX_RESOURCE_TYPE_TEXTURE_3D: + { + D3D10_TEXTURE3D_DESC desc = { info->size.width, info->size.height, info->size.depth, 1, 0, + D3D10_USAGE_STAGING, 0, cpu_flags }; + + desc.Format = dxgi_format_from_d3dx_pixel_format_id(info->fmt->format); + return ID3D10Device_CreateTexture3D(device, &desc, NULL, (ID3D10Texture3D **)rsrc); + } + default: return E_NOTIMPL; } @@ -1067,6 +1098,21 @@ static HRESULT d3dx_subresource_data_from_d3d10_staging_resource_map(ID3D10Resou break; } + case D3DX_RESOURCE_TYPE_TEXTURE_3D: + { + ID3D10Texture3D *tex = (ID3D10Texture3D *)rsrc; + D3D10_MAPPED_TEXTURE3D map; + + hr = ID3D10Texture3D_Map(tex, 0, map_type, 0, &map); + if (SUCCEEDED(hr)) + { + out_data->data = map.pData; + out_data->row_pitch = map.RowPitch; + out_data->slice_pitch = map.DepthPitch; + } + break; + } + default: hr = E_NOTIMPL; break; @@ -1083,6 +1129,10 @@ static void d3d10_staging_resource_unmap(ID3D10Resource *rsrc, enum d3dx_resourc ID3D10Texture2D_Unmap((ID3D10Texture2D *)rsrc, 0); break; + case D3DX_RESOURCE_TYPE_TEXTURE_3D: + ID3D10Texture3D_Unmap((ID3D10Texture3D *)rsrc, 0); + break; + default: break; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
On Mon May 18 13:49:48 2026 +0000, Matteo Bruni wrote:
Can we avoid using staging textures when the situation allows? There should be a few cases where it's possible to directly access the user's texture (e.g. src or dst is a mappable `D3D10_USAGE_STAGING` texture). This could be introduced in a follow up patch as well. Yeah it's possible, I just avoided it in this initial patch set to simplify things. :) The initial patch that implements `D3DX10LoadTextureFromTexture()` felt kind of big already, even without support for those cases.
I can add it in this MR, or in another MR if that's fine. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10887#note_140381
On Mon May 18 15:15:15 2026 +0000, Connor McAdams wrote:
Yeah it's possible, I just avoided it in this initial patch set to simplify things. :) The initial patch that implements `D3DX10LoadTextureFromTexture()` felt kind of big already, even without support for those cases. I can add it in this MR, or in another MR if that's fine. Another MR seems great :grinning:
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10887#note_140401
This merge request was approved by Matteo Bruni. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10887
participants (3)
-
Connor McAdams -
Connor McAdams (@cmcadams) -
Matteo Bruni (@Mystral)