From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 168 ++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index ded2940ba46..176ff83402f 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -21,6 +21,7 @@ #include "d3d10_1.h" #include "d3dx10.h" #include "wine/test.h" +#include <stdint.h>
#define D3DERR_INVALIDCALL 0x8876086c
@@ -47,6 +48,7 @@ #define DDS_PF_ALPHA 0x00000001 #define DDS_PF_ALPHA_ONLY 0x00000002 #define DDS_PF_FOURCC 0x00000004 +#define DDS_PF_INDEXED 0x00000020 #define DDS_PF_RGB 0x00000040 #define DDS_PF_LUMINANCE 0x00020000 #define DDS_PF_BUMPLUMINANCE 0x00040000 @@ -82,6 +84,15 @@ struct dds_header DWORD reserved2; };
+struct dds_header_dxt10 +{ + uint32_t dxgi_format; + uint32_t resource_dimension; + uint32_t misc_flag; + uint32_t array_size; + uint32_t misc_flags2; +}; + static void fill_dds_header(struct dds_header *header) { memset(header, 0, sizeof(*header)); @@ -102,6 +113,35 @@ static void fill_dds_header(struct dds_header *header) header->caps = DDS_CAPS_TEXTURE; }
+static void set_dxt10_dds_header(struct dds_header *header, uint32_t append_flags, uint32_t width, uint32_t height, + uint32_t depth, uint32_t mip_levels, uint32_t pitch, uint32_t caps, uint32_t caps2) +{ + memset(header, 0, sizeof(*header)); + + header->size = sizeof(*header); + header->flags = DDS_CAPS | DDS_PIXELFORMAT | append_flags; + header->height = height; + header->width = width; + header->depth = depth; + header->miplevels = mip_levels; + header->pitch_or_linear_size = pitch; + header->pixel_format.size = sizeof(header->pixel_format); + header->pixel_format.flags = DDS_PF_FOURCC; + header->pixel_format.fourcc = MAKEFOURCC('D','X','1','0'); + header->caps = caps; + header->caps2 = caps2; +} + +static void set_dds_header_dxt10(struct dds_header_dxt10 *dxt10, DXGI_FORMAT format, uint32_t resource_dimension, + uint32_t misc_flag, uint32_t array_size, uint32_t misc_flags2) +{ + dxt10->dxgi_format = format; + dxt10->resource_dimension = resource_dimension; + dxt10->misc_flag = misc_flag; + dxt10->array_size = array_size; + dxt10->misc_flags2 = misc_flags2; +} + /* 1x1 1bpp bmp image */ static const BYTE test_bmp_1bpp[] = { @@ -2770,6 +2810,7 @@ static void check_dds_pixel_format_(unsigned int line, DWORD flags, DWORD fourcc { DWORD magic; struct dds_header header; + PALETTEENTRY palette[256]; BYTE data[256]; } dds;
@@ -2793,6 +2834,87 @@ static void check_dds_pixel_format_(unsigned int line, DWORD flags, DWORD fourcc } }
+#define check_dds_pixel_format_unsupported(flags, fourcc, bpp, rmask, gmask, bmask, amask, expected_hr) \ + check_dds_pixel_format_unsupported_(__LINE__, flags, fourcc, bpp, rmask, gmask, bmask, amask, expected_hr) +static void check_dds_pixel_format_unsupported_(unsigned int line, DWORD flags, DWORD fourcc, DWORD bpp, + DWORD rmask, DWORD gmask, DWORD bmask, DWORD amask, HRESULT expected_hr) +{ + D3DX10_IMAGE_INFO info; + HRESULT hr; + struct + { + DWORD magic; + struct dds_header header; + PALETTEENTRY palette[256]; + BYTE data[256]; + } dds; + + dds.magic = MAKEFOURCC('D','D','S',' '); + fill_dds_header(&dds.header); + dds.header.pixel_format.flags = flags; + dds.header.pixel_format.fourcc = fourcc; + dds.header.pixel_format.bpp = bpp; + dds.header.pixel_format.rmask = rmask; + dds.header.pixel_format.gmask = gmask; + dds.header.pixel_format.bmask = bmask; + dds.header.pixel_format.amask = amask; + memset(dds.data, 0, sizeof(dds.data)); + + hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL); + ok_(__FILE__, line)(hr == expected_hr, "Got unexpected hr %#lx, expected %#lx.\n", hr, expected_hr); +} + +#define check_dds_dxt10_format(format, expected_format, wine_todo) \ + check_dds_dxt10_format_(__LINE__, format, expected_format, wine_todo) +static void check_dds_dxt10_format_(uint32_t line, DXGI_FORMAT format, DXGI_FORMAT expected_format, BOOL wine_todo) +{ + const uint32_t stride = (4 * get_bpp_from_format(format) + 7) / 8; + D3DX10_IMAGE_INFO info; + HRESULT hr; + struct + { + DWORD magic; + struct dds_header header; + struct dds_header_dxt10 dxt10; + BYTE data[256]; + } dds; + + dds.magic = MAKEFOURCC('D','D','S',' '); + set_dxt10_dds_header(&dds.header, 0, 4, 4, 1, 1, stride, 0, 0); + set_dds_header_dxt10(&dds.dxt10, format, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 0); + + hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx for DXGI format %#x.\n", hr, format); + if (SUCCEEDED(hr)) + { + todo_wine_if(wine_todo) ok_(__FILE__, line)(info.Format == expected_format, "Unexpected format %#x, expected %#x.\n", + info.Format, expected_format); + } +} + +#define check_dds_dxt10_format_unsupported(format, expected_hr) \ + check_dds_dxt10_format_unsupported_(__LINE__, format, expected_hr) +static void check_dds_dxt10_format_unsupported_(uint32_t line, DXGI_FORMAT format, HRESULT expected_hr) +{ + const uint32_t stride = (4 * get_bpp_from_format(format) + 7) / 8; + D3DX10_IMAGE_INFO info; + HRESULT hr; + struct + { + DWORD magic; + struct dds_header header; + struct dds_header_dxt10 dxt10; + BYTE data[256]; + } dds; + + dds.magic = MAKEFOURCC('D','D','S',' '); + set_dxt10_dds_header(&dds.header, 0, 4, 4, 1, 1, stride, 0, 0); + set_dds_header_dxt10(&dds.dxt10, format, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 0); + + hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL); + ok_(__FILE__, line)(hr == expected_hr, "Got unexpected hr %#lx for DXGI format %#x.\n", hr, format); +} + static void test_get_image_info(void) { static const WCHAR test_resource_name[] = L"resource.data"; @@ -2935,6 +3057,52 @@ static void test_get_image_info(void) check_dds_pixel_format(DDS_PF_LUMINANCE, 0, 16, 0xffff, 0, 0, 0, DXGI_FORMAT_R16G16B16A16_UNORM); check_dds_pixel_format(DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 16, 0x00ff, 0, 0, 0xff00, DXGI_FORMAT_R8G8B8A8_UNORM); check_dds_pixel_format(DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 8, 0x0f, 0, 0, 0xf0, DXGI_FORMAT_R8G8B8A8_UNORM); + check_dds_pixel_format(DDS_PF_INDEXED, 0, 8, 0, 0, 0, 0, DXGI_FORMAT_R8G8B8A8_UNORM); + check_dds_pixel_format(DDS_PF_INDEXED | DDS_PF_ALPHA, 0, 16, 0, 0, 0, 0xff00, DXGI_FORMAT_R8G8B8A8_UNORM); + check_dds_pixel_format(DDS_PF_FOURCC, 0x24, 0, 0, 0, 0, 0, DXGI_FORMAT_R16G16B16A16_UNORM); /* D3DFMT_A16B16G16R16 */ + check_dds_pixel_format(DDS_PF_FOURCC, 0x6e, 0, 0, 0, 0, 0, DXGI_FORMAT_R16G16B16A16_SNORM); /* D3DFMT_Q16W16V16U16 */ + check_dds_pixel_format(DDS_PF_FOURCC, 0x6f, 0, 0, 0, 0, 0, DXGI_FORMAT_R16_FLOAT); /* D3DFMT_R16F */ + check_dds_pixel_format(DDS_PF_FOURCC, 0x70, 0, 0, 0, 0, 0, DXGI_FORMAT_R16G16_FLOAT); /* D3DFMT_G16R16F */ + check_dds_pixel_format(DDS_PF_FOURCC, 0x71, 0, 0, 0, 0, 0, DXGI_FORMAT_R16G16B16A16_FLOAT); /* D3DFMT_A16B16G16R16F */ + check_dds_pixel_format(DDS_PF_FOURCC, 0x72, 0, 0, 0, 0, 0, DXGI_FORMAT_R32_FLOAT); /* D3DFMT_R32F */ + check_dds_pixel_format(DDS_PF_FOURCC, 0x73, 0, 0, 0, 0, 0, DXGI_FORMAT_R32G32_FLOAT); /* D3DFMT_G32R32F */ + check_dds_pixel_format(DDS_PF_FOURCC, 0x74, 0, 0, 0, 0, 0, DXGI_FORMAT_R32G32B32A32_FLOAT); /* D3DFMT_A32B32G32R32F */ + + /* Test for DDS pixel formats that are valid on d3dx9, but not d3dx10. */ + todo_wine check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('U','Y','V','Y'), 0, 0, 0, 0, 0, E_FAIL); + todo_wine check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0, E_FAIL); + /* Bumpmap formats aren't supported. */ + todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0, 0, E_FAIL); + todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, E_FAIL); + todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 32, 0xff, 0xff00, 0x00ff0000, 0xff000000, E_FAIL); + todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPLUMINANCE, 0, 32, 0x0000ff, 0x00ff00, 0xff0000, 0, E_FAIL); + + /* Newer fourCC formats. */ + check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC4_UNORM); + check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC5_UNORM); + check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC4_SNORM); + check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC5_SNORM); + /* ATI1 is unsupported, but ATI2 is supported. */ + todo_wine check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('A','T','I','1'), 0, 0, 0, 0, 0, E_FAIL); + check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('A','T','I','2'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC5_UNORM); + + todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_B5G6R5_UNORM, E_FAIL); + todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_B5G5R5A1_UNORM, E_FAIL); + /* Formats that are newer than d3d10. */ + todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC6H_UF16, E_FAIL); + todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC6H_SF16, E_FAIL); + todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC7_UNORM, E_FAIL); + todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_B4G4R4A4_UNORM, E_FAIL); + + /* + * These formats should map 1:1 from the DXT10 header, unlike legacy DDS + * file equivalents. + */ + check_dds_dxt10_format(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, TRUE); + check_dds_dxt10_format(DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, TRUE); + check_dds_dxt10_format(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, TRUE); + check_dds_dxt10_format(DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM, TRUE); + check_dds_dxt10_format(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, TRUE);
/* D3DX10GetImageInfoFromResource tests */
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 366 ++++++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 176ff83402f..de2be79d55f 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -39,11 +39,26 @@ #define DDS_PIXELFORMAT 0x00001000 #define DDS_MIPMAPCOUNT 0x00020000 #define DDS_LINEARSIZE 0x00080000 +#define DDS_DEPTH 0x00800000
/* dds_header.caps */ #define DDSCAPS_ALPHA 0x00000002 +#define DDS_CAPS_COMPLEX 0x00000008 #define DDS_CAPS_TEXTURE 0x00001000
+/* dds_header.caps2 */ +#define DDS_CAPS2_VOLUME 0x00200000 +#define DDS_CAPS2_CUBEMAP 0x00000200 +#define DDS_CAPS2_CUBEMAP_POSITIVEX 0x00000400 +#define DDS_CAPS2_CUBEMAP_NEGATIVEX 0x00000800 +#define DDS_CAPS2_CUBEMAP_POSITIVEY 0x00001000 +#define DDS_CAPS2_CUBEMAP_NEGATIVEY 0x00002000 +#define DDS_CAPS2_CUBEMAP_POSITIVEZ 0x00004000 +#define DDS_CAPS2_CUBEMAP_NEGATIVEZ 0x00008000 +#define DDS_CAPS2_CUBEMAP_ALL_FACES ( DDS_CAPS2_CUBEMAP_POSITIVEX | DDS_CAPS2_CUBEMAP_NEGATIVEX \ + | DDS_CAPS2_CUBEMAP_POSITIVEY | DDS_CAPS2_CUBEMAP_NEGATIVEY \ + | DDS_CAPS2_CUBEMAP_POSITIVEZ | DDS_CAPS2_CUBEMAP_NEGATIVEZ ) + /* dds_pixel_format.flags */ #define DDS_PF_ALPHA 0x00000001 #define DDS_PF_ALPHA_ONLY 0x00000002 @@ -84,6 +99,7 @@ struct dds_header DWORD reserved2; };
+#define DDS_RESOURCE_MISC_TEXTURECUBE 0x04 struct dds_header_dxt10 { uint32_t dxgi_format; @@ -1316,6 +1332,47 @@ static void check_image_info(D3DX10_IMAGE_INFO *image_info, const struct test_im image_info->ImageFileFormat, image->expected_info.ImageFileFormat); }
+#define check_image_info_values(info, width, height, depth, array_size, mip_levels, misc_flags, format, resource_dimension, \ + image_file_format, wine_todo) \ + check_image_info_values_(__LINE__, info, width, height, depth, array_size, mip_levels, misc_flags, format, resource_dimension, \ + image_file_format, wine_todo) +static inline void check_image_info_values_(uint32_t line, const D3DX10_IMAGE_INFO *info, uint32_t width, + uint32_t height, uint32_t depth, uint32_t array_size, uint32_t mip_levels, uint32_t misc_flags, + DXGI_FORMAT format, D3D10_RESOURCE_DIMENSION resource_dimension, D3DX10_IMAGE_FILE_FORMAT image_file_format, + BOOL wine_todo) +{ + const D3DX10_IMAGE_INFO expected_info = { width, height, depth, array_size, mip_levels, misc_flags, format, + resource_dimension, image_file_format }; + BOOL matched; + + matched = !memcmp(&expected_info, info, sizeof(*info)); + todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected image info values.\n"); + if (matched) + return; + + todo_wine_if(wine_todo && info->Width != width) + ok_(__FILE__, line)(info->Width == width, "Expected width %u, got %u.\n", width, info->Width); + todo_wine_if(wine_todo && info->Height != height) + ok_(__FILE__, line)(info->Height == height, "Expected height %u, got %u.\n", height, info->Height); + todo_wine_if(wine_todo && info->Depth != depth) + ok_(__FILE__, line)(info->Depth == depth, "Expected depth %u, got %u.\n", depth, info->Depth); + todo_wine_if(wine_todo && info->ArraySize != array_size) + ok_(__FILE__, line)(info->ArraySize == array_size, "Expected array_size %u, got %u.\n", array_size, + info->ArraySize); + todo_wine_if(wine_todo && info->MipLevels != mip_levels) + ok_(__FILE__, line)(info->MipLevels == mip_levels, "Expected mip_levels %u, got %u.\n", mip_levels, + info->MipLevels); + todo_wine_if(wine_todo && info->MiscFlags != misc_flags) + ok_(__FILE__, line)(info->MiscFlags == misc_flags, "Expected misc_flags %u, got %u.\n", misc_flags, + info->MiscFlags); + ok_(__FILE__, line)(info->Format == format, "Expected texture format %d, got %d.\n", format, info->Format); + todo_wine_if(wine_todo && info->ResourceDimension != resource_dimension) + ok_(__FILE__, line)(info->ResourceDimension == resource_dimension, "Expected resource_dimension %d, got %d.\n", + resource_dimension, info->ResourceDimension); + ok_(__FILE__, line)(info->ImageFileFormat == image_file_format, "Expected image_file_format %d, got %d.\n", + image_file_format, info->ImageFileFormat); +} + static ID3D10Texture2D *get_texture2d_readback(ID3D10Texture2D *texture) { D3D10_TEXTURE2D_DESC desc; @@ -2915,6 +2972,313 @@ static void check_dds_dxt10_format_unsupported_(uint32_t line, DXGI_FORMAT forma ok_(__FILE__, line)(hr == expected_hr, "Got unexpected hr %#lx for DXGI format %#x.\n", hr, format); }
+static void test_legacy_dds_header_image_info(void) +{ + struct expected + { + HRESULT hr; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t array_size; + uint32_t mip_levels; + uint32_t misc_flags; + DXGI_FORMAT format; + D3D10_RESOURCE_DIMENSION resource_dimension; + }; + static const struct + { + uint32_t flags; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t row_pitch; + uint32_t mip_levels; + uint32_t caps; + uint32_t caps2; + struct expected expected; + uint32_t pixel_data_size; + BOOL todo_hr; + } tests[] = + { + /* + * Only DDS header size is validated on d3dx10, unlike d3dx9 where image pixel size + * is as well. + */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 1, (4 * 4), 3, 0, 0, + { S_OK, 4, 4, 1, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, 0, + .todo_hr = TRUE + }, + /* Depth value set to 4, but no caps bits are set. Depth is ignored. */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 4, (4 * 4), 3, 0, 0, + { S_OK, 4, 4, 1, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, 292 + }, + /* The volume texture caps2 field is ignored. */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 4, (4 * 4), 3, + (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), DDS_CAPS2_VOLUME, + { S_OK, 4, 4, 1, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, 292 + }, + /* + * The DDS_DEPTH flag is the only thing checked to determine if a DDS + * file represents a 3D texture. + */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT | DDS_DEPTH), 4, 4, 4, (4 * 4), 3, 0, 0, + { S_OK, 4, 4, 4, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, }, 292 + }, + /* Even if the depth field is set to 0, it's still a 3D texture. */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT | DDS_DEPTH), 4, 4, 0, (4 * 4), 3, 0, 0, + { S_OK, 4, 4, 1, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, }, 292 + }, + /* + * 5. + * The DDS_DEPTH flag overrides cubemap caps. + */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT | DDS_DEPTH), 4, 4, 4, (4 * 4), 3, + (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), (DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_ALL_FACES), + { S_OK, 4, 4, 4, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, }, 292 + }, + /* Cubemap where width field does not equal height. */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 5, 1, (4 * 4), 1, + (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), (DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_ALL_FACES), + { + S_OK, 4, 5, 1, 6, 1, D3D10_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_R8G8B8A8_UNORM, + D3D10_RESOURCE_DIMENSION_TEXTURE2D, + }, (80 * 6) + }, + /* Partial cubemaps are not supported. */ + { + (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 1, (4 * 4), 1, + (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), (DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_POSITIVEX), + { E_FAIL, }, (64 * 6), .todo_hr = TRUE + }, + }; + D3DX10_IMAGE_INFO info; + unsigned int i; + struct + { + DWORD magic; + struct dds_header header; + } dds; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + const uint32_t file_size = sizeof(dds) + tests[i].pixel_data_size; + + winetest_push_context("Test %u", i); + + dds.magic = MAKEFOURCC('D','D','S',' '); + fill_dds_header(&dds.header); + dds.header.flags = tests[i].flags; + dds.header.width = tests[i].width; + dds.header.height = tests[i].height; + dds.header.depth = tests[i].depth; + dds.header.pitch_or_linear_size = tests[i].row_pitch; + dds.header.miplevels = tests[i].mip_levels; + dds.header.caps = tests[i].caps; + dds.header.caps2 = tests[i].caps2; + + memset(&info, 0, sizeof(info)); + hr = D3DX10GetImageInfoFromMemory(&dds, file_size, NULL, &info, NULL); + todo_wine_if(tests[i].todo_hr) ok(hr == tests[i].expected.hr, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr) && SUCCEEDED(tests[i].expected.hr)) + check_image_info_values(&info, tests[i].expected.width, tests[i].expected.height, + tests[i].expected.depth, tests[i].expected.array_size, tests[i].expected.mip_levels, + tests[i].expected.misc_flags, tests[i].expected.format, + tests[i].expected.resource_dimension, D3DX10_IFF_DDS, FALSE); + + winetest_pop_context(); + } + + /* + * Image size (e.g, the size of the pixels) isn't validated, but header + * size is. + */ + dds.magic = MAKEFOURCC('D','D','S',' '); + fill_dds_header(&dds.header); + + hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds) - 1, NULL, &info, NULL); + ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); + + hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +} + +static void test_dxt10_dds_header_image_info(void) +{ + struct expected + { + HRESULT hr; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t array_size; + uint32_t mip_levels; + uint32_t misc_flags; + DXGI_FORMAT format; + D3D10_RESOURCE_DIMENSION resource_dimension; + }; + static const struct + { + uint32_t append_flags; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t row_pitch; + uint32_t mip_levels; + uint32_t caps; + uint32_t caps2; + struct dds_header_dxt10 dxt10; + struct expected expected; + uint32_t pixel_data_size; + BOOL todo_hr; + BOOL todo_info; + } tests[] = + { + /* File size validation isn't done on d3dx10. */ + { + 0, 4, 4, 0, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 0, }, + { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, 0, + .todo_hr = TRUE + }, + /* + * Setting the misc_flags2 field to anything other than 0 results in + * E_FAIL. + */ + { + 0, 4, 4, 0, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 1, }, + { E_FAIL }, (4 * 4 * 4), .todo_hr = TRUE + }, + /* + * The misc_flags field isn't passed through directly, only the + * cube texture flag is (if it's set). + */ + { + 0, 4, 4, 0, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0xfffffffb, 1, 0, }, + { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, (4 * 4 * 4) + }, + /* Resource dimension field of the header isn't validated. */ + { + 0, 4, 4, 0, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, 500, 0, 1, 0, }, + { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, 500, }, (4 * 4 * 4), .todo_info = TRUE + }, + /* Depth value of 2, but D3D10_RESOURCE_DIMENSION_TEXTURE2D. */ + { + DDS_DEPTH, 4, 4, 2, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 0, }, + { S_OK, 4, 4, 2, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, (4 * 4 * 4 * 2) + }, + /* + * 5. + * Depth field value is ignored if DDS_DEPTH isn't set. + */ + { + 0, 4, 4, 2, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, 0, 1, 0, }, + { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, }, (4 * 4 * 4 * 2), + .todo_info = TRUE + }, + /* + * 3D texture with an array size larger than 1. Technically there's no + * such thing as a 3D texture array, but it succeeds. + */ + { + DDS_DEPTH, 4, 4, 2, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, 0, 2, 0, }, + { S_OK, 4, 4, 2, 2, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, }, (4 * 4 * 4 * 2 * 2) + }, + /* Cubemap caps are ignored for DXT10 files. */ + { + 0, 4, 4, 1, (4 * 4), 1, 0, DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_ALL_FACES, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 0, }, + { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D }, (4 * 4 * 4 * 6) + }, + /* Array size value is multiplied by 6 for cubemap files. */ + { + 0, 4, 4, 1, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, DDS_RESOURCE_MISC_TEXTURECUBE, 2, 0, }, + { + S_OK, 4, 4, 1, 12, 1, D3D10_RESOURCE_MISC_TEXTURECUBE, DXGI_FORMAT_R8G8B8A8_UNORM, + D3D10_RESOURCE_DIMENSION_TEXTURE2D + }, (4 * 4 * 4 * 12) + }, + /* Resource dimension is validated for cube textures. */ + { + 0, 4, 4, 1, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, DDS_RESOURCE_MISC_TEXTURECUBE, 2, 0, }, + { E_FAIL }, (4 * 4 * 4 * 12), .todo_hr = TRUE + }, + /* + * 10. + * 1D Texture cube, invalid. + */ + { + 0, 4, 4, 1, (4 * 4), 1, 0, 0, + { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE1D, DDS_RESOURCE_MISC_TEXTURECUBE, 2, 0, }, + { E_FAIL }, (4 * 4 * 4 * 12), .todo_hr = TRUE + }, + }; + D3DX10_IMAGE_INFO info; + unsigned int i; + struct + { + DWORD magic; + struct dds_header header; + struct dds_header_dxt10 dxt10; + } dds; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + const uint32_t file_size = sizeof(dds) + tests[i].pixel_data_size; + + winetest_push_context("Test %u", i); + + dds.magic = MAKEFOURCC('D','D','S',' '); + set_dxt10_dds_header(&dds.header, tests[i].append_flags, tests[i].width, tests[i].height, + tests[i].depth, tests[i].mip_levels, tests[i].row_pitch, tests[i].caps, + tests[i].caps2); + dds.dxt10 = tests[i].dxt10; + + memset(&info, 0, sizeof(info)); + hr = D3DX10GetImageInfoFromMemory(&dds, file_size, NULL, &info, NULL); + todo_wine_if(tests[i].todo_hr) ok(hr == tests[i].expected.hr, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr) && SUCCEEDED(tests[i].expected.hr)) + check_image_info_values(&info, tests[i].expected.width, tests[i].expected.height, + tests[i].expected.depth, tests[i].expected.array_size, tests[i].expected.mip_levels, + tests[i].expected.misc_flags, tests[i].expected.format, + tests[i].expected.resource_dimension, D3DX10_IFF_DDS, tests[i].todo_info); + + winetest_pop_context(); + } + + /* + * Image size (e.g, the size of the pixels) isn't validated, but header + * size is. + */ + dds.magic = MAKEFOURCC('D','D','S',' '); + set_dxt10_dds_header(&dds.header, tests[0].append_flags, tests[0].width, tests[0].height, + tests[0].depth, tests[0].mip_levels, tests[0].row_pitch, tests[0].caps, tests[0].caps2); + dds.dxt10 = tests[0].dxt10; + + hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds) - 1, NULL, &info, NULL); + ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); + + hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +} + static void test_get_image_info(void) { static const WCHAR test_resource_name[] = L"resource.data"; @@ -4830,4 +5194,6 @@ START_TEST(d3dx10) test_create_effect_from_file(); test_create_effect_from_resource(); test_preprocess_shader(); + test_legacy_dds_header_image_info(); + test_dxt10_dds_header_image_info(); }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 5 +- dlls/d3dx10_43/texture.c | 55 ++++++++++++- dlls/d3dx9_36/d3dx_helpers.c | 144 +++++++++++++++++++++++++++++----- dlls/d3dx9_36/d3dx_helpers.h | 14 ++++ 4 files changed, 191 insertions(+), 27 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index de2be79d55f..3a5e6efd6e5 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -3187,7 +3187,6 @@ static void test_dxt10_dds_header_image_info(void) 0, 4, 4, 2, (4 * 4), 1, 0, 0, { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, 0, 1, 0, }, { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, }, (4 * 4 * 4 * 2), - .todo_info = TRUE }, /* * 3D texture with an array size larger than 1. Technically there's no @@ -3465,8 +3464,8 @@ static void test_get_image_info(void) check_dds_dxt10_format(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, TRUE); check_dds_dxt10_format(DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, TRUE); check_dds_dxt10_format(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, TRUE); - check_dds_dxt10_format(DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM, TRUE); - check_dds_dxt10_format(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, TRUE); + check_dds_dxt10_format(DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM, FALSE); + check_dds_dxt10_format(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, FALSE);
/* D3DX10GetImageInfoFromResource tests */
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 70bf062dd33..0a65bfa8b73 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -99,6 +99,48 @@ static DXGI_FORMAT dxgi_format_from_legacy_dds_d3dx_pixel_format_id(enum d3dx_pi } }
+static DXGI_FORMAT dxgi_format_from_d3dx_pixel_format_id(enum d3dx_pixel_format_id format) +{ + switch (format) + { + case D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; + case D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM: return DXGI_FORMAT_B8G8R8X8_UNORM; + case D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM: return DXGI_FORMAT_R10G10B10A2_UNORM; + case D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; + case D3DX_PIXEL_FORMAT_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; + case D3DX_PIXEL_FORMAT_A8_UNORM: return DXGI_FORMAT_A8_UNORM; + case D3DX_PIXEL_FORMAT_R16_FLOAT: return DXGI_FORMAT_R16_FLOAT; + case D3DX_PIXEL_FORMAT_R16G16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT; + case D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; + case D3DX_PIXEL_FORMAT_R32_FLOAT: return DXGI_FORMAT_R32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32_FLOAT: return DXGI_FORMAT_R32G32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM: return DXGI_FORMAT_G8R8_G8B8_UNORM; + case D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM: return DXGI_FORMAT_R8G8_B8G8_UNORM; + case D3DX_PIXEL_FORMAT_BC1_UNORM: return DXGI_FORMAT_BC1_UNORM; + case D3DX_PIXEL_FORMAT_BC2_UNORM: return DXGI_FORMAT_BC2_UNORM; + case D3DX_PIXEL_FORMAT_BC3_UNORM: return DXGI_FORMAT_BC3_UNORM; + case D3DX_PIXEL_FORMAT_R16G16B16A16_SNORM: return DXGI_FORMAT_R16G16B16A16_SNORM; + case D3DX_PIXEL_FORMAT_R8G8B8A8_SNORM: return DXGI_FORMAT_R8G8B8A8_SNORM; + case D3DX_PIXEL_FORMAT_R8G8_SNORM: return DXGI_FORMAT_R8G8_SNORM; + case D3DX_PIXEL_FORMAT_R16G16_SNORM: return DXGI_FORMAT_R16G16_SNORM; + + /* + * These have DXGI_FORMAT equivalents, but are explicitly unsupported on + * d3dx10. + */ + case D3DX_PIXEL_FORMAT_B5G6R5_UNORM: + case D3DX_PIXEL_FORMAT_B5G5R5A1_UNORM: + case D3DX_PIXEL_FORMAT_B4G4R4A4_UNORM: + return DXGI_FORMAT_UNKNOWN; + + default: + FIXME("Unhandled d3dx_pixel_format_id %#x.\n", format); + return DXGI_FORMAT_UNKNOWN; + } +} + static D3DX10_IMAGE_FILE_FORMAT d3dx10_image_file_format_from_d3dx_image_file_format(enum d3dx_image_file_format iff) { switch (iff) @@ -107,6 +149,7 @@ static D3DX10_IMAGE_FILE_FORMAT d3dx10_image_file_format_from_d3dx_image_file_fo case D3DX_IMAGE_FILE_FORMAT_JPG: return D3DX10_IFF_JPG; case D3DX_IMAGE_FILE_FORMAT_PNG: return D3DX10_IFF_PNG; case D3DX_IMAGE_FILE_FORMAT_DDS: return D3DX10_IFF_DDS; + case D3DX_IMAGE_FILE_FORMAT_DDS_DXT10: return D3DX10_IFF_DDS; default: FIXME("No D3DX10_IMAGE_FILE_FORMAT for d3dx_image_file_format %d.\n", iff); return D3DX10_IFF_FORCE_DWORD; @@ -510,9 +553,14 @@ HRESULT WINAPI D3DX10GetImageInfoFromResourceW(HMODULE module, const WCHAR *reso static HRESULT d3dx10_image_info_from_d3dx_image(D3DX10_IMAGE_INFO *info, struct d3dx_image *image) { D3DX10_IMAGE_FILE_FORMAT iff = d3dx10_image_file_format_from_d3dx_image_file_format(image->image_file_format); - DXGI_FORMAT format = dxgi_format_from_legacy_dds_d3dx_pixel_format_id(image->format); + DXGI_FORMAT format;
memset(info, 0, sizeof(*info)); + if (image->image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS_DXT10) + format = dxgi_format_from_d3dx_pixel_format_id(image->format); + else + format = dxgi_format_from_legacy_dds_d3dx_pixel_format_id(image->format); + if (format == DXGI_FORMAT_UNKNOWN) { WARN("Tried to load DDS file with unsupported format %#x.\n", image->format); @@ -568,8 +616,9 @@ HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_inf if (!data || !size) return E_FAIL;
- if (SUCCEEDED(d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY)) - && image.image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS) + if (SUCCEEDED(d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10)) + && (image.image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS + || (image.image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS_DXT10))) { if (SUCCEEDED(d3dx10_image_info_from_d3dx_image(img_info, &image))) { diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 800398af0e1..3574bc8324f 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -363,6 +363,42 @@ static HRESULT dds_pixel_format_from_d3dx_pixel_format_id(struct dds_pixel_forma return D3D_OK; }
+static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: return D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM: return D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM: return D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM; + case DXGI_FORMAT_B5G6R5_UNORM: return D3DX_PIXEL_FORMAT_B5G6R5_UNORM; + case DXGI_FORMAT_B5G5R5A1_UNORM: return D3DX_PIXEL_FORMAT_B5G5R5A1_UNORM; + case DXGI_FORMAT_B4G4R4A4_UNORM: return D3DX_PIXEL_FORMAT_B4G4R4A4_UNORM; + case DXGI_FORMAT_R10G10B10A2_UNORM: return D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM; + case DXGI_FORMAT_R16G16B16A16_UNORM: return D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM; + case DXGI_FORMAT_R16G16_UNORM: return D3DX_PIXEL_FORMAT_R16G16_UNORM; + case DXGI_FORMAT_A8_UNORM: return D3DX_PIXEL_FORMAT_A8_UNORM; + case DXGI_FORMAT_R16_FLOAT: return D3DX_PIXEL_FORMAT_R16_FLOAT; + case DXGI_FORMAT_R16G16_FLOAT: return D3DX_PIXEL_FORMAT_R16G16_FLOAT; + case DXGI_FORMAT_R16G16B16A16_FLOAT: return D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT; + case DXGI_FORMAT_R32_FLOAT: return D3DX_PIXEL_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R32G32_FLOAT: return D3DX_PIXEL_FORMAT_R32G32_FLOAT; + case DXGI_FORMAT_R32G32B32A32_FLOAT: return D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT; + case DXGI_FORMAT_G8R8_G8B8_UNORM: return D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM; + case DXGI_FORMAT_R8G8_B8G8_UNORM: return D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM; + case DXGI_FORMAT_BC1_UNORM: return D3DX_PIXEL_FORMAT_BC1_UNORM; + case DXGI_FORMAT_BC2_UNORM: return D3DX_PIXEL_FORMAT_BC2_UNORM; + case DXGI_FORMAT_BC3_UNORM: return D3DX_PIXEL_FORMAT_BC3_UNORM; + case DXGI_FORMAT_R8G8B8A8_SNORM: return D3DX_PIXEL_FORMAT_R8G8B8A8_SNORM; + case DXGI_FORMAT_R8G8_SNORM: return D3DX_PIXEL_FORMAT_R8G8_SNORM; + case DXGI_FORMAT_R16G16_SNORM: return D3DX_PIXEL_FORMAT_R16G16_SNORM; + case DXGI_FORMAT_R16G16B16A16_SNORM: return D3DX_PIXEL_FORMAT_R16G16B16A16_SNORM; + + default: + FIXME("Unhandled DXGI format %#x.\n", format); + return D3DX_PIXEL_FORMAT_COUNT; + } +} + static void d3dx_get_next_mip_level_size(struct volume *size) { size->width = max(size->width / 2, 1); @@ -993,8 +1029,44 @@ static BOOL d3dx_get_image_file_format_from_file_signature(const void *src_data, return FALSE; }
+/* These defines match D3D10/D3D11 values. */ +#define DDS_RESOURCE_MISC_TEXTURECUBE 0x04 +#define DDS_RESOURCE_DIMENSION_TEXTURE1D 2 +#define DDS_RESOURCE_DIMENSION_TEXTURE2D 3 +#define DDS_RESOURCE_DIMENSION_TEXTURE3D 4 +struct dds_header_dxt10 +{ + uint32_t dxgi_format; + uint32_t resource_dimension; + uint32_t misc_flags; + uint32_t array_size; + uint32_t misc_flags2; +}; + +static enum d3dx_resource_type dxt10_resource_dimension_to_d3dx_resource_type(uint32_t resource_dimension) +{ + switch (resource_dimension) + { + case DDS_RESOURCE_DIMENSION_TEXTURE1D: return D3DX_RESOURCE_TYPE_TEXTURE_1D; + case DDS_RESOURCE_DIMENSION_TEXTURE2D: return D3DX_RESOURCE_TYPE_TEXTURE_2D; + case DDS_RESOURCE_DIMENSION_TEXTURE3D: return D3DX_RESOURCE_TYPE_TEXTURE_3D; + + default: + break; + } + + FIXME("Unhandled DXT10 resource dimension value %u.\n", resource_dimension); + return D3DX_RESOURCE_TYPE_UNKNOWN; +} + +static BOOL has_extended_header(const struct dds_header *header) +{ + return (header->pixel_format.flags & DDS_PF_FOURCC) && + (header->pixel_format.fourcc == MAKEFOURCC('D', 'X', '1', '0')); +} + static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size, - struct d3dx_image *image, uint32_t starting_mip_level) + struct d3dx_image *image, uint32_t starting_mip_level, uint32_t flags) { uint32_t expected_src_data_size, header_size; const struct dds_header *header = src_data; @@ -1004,40 +1076,71 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src if (src_data_size < sizeof(*header) || header->pixel_format.size != sizeof(header->pixel_format)) return D3DXERR_INVALIDDATA;
- TRACE("File type is DDS.\n"); is_indexed_fmt = !!(header->pixel_format.flags & DDS_PF_INDEXED); header_size = is_indexed_fmt ? sizeof(*header) + DDS_PALETTE_SIZE : sizeof(*header);
set_volume_struct(&image->size, header->width, header->height, 1); image->mip_levels = header->miplevels ? header->miplevels : 1; - image->format = d3dx_pixel_format_id_from_dds_pixel_format(&header->pixel_format); - image->layer_count = 1; + if (has_extended_header(header) && (flags & D3DX_IMAGE_SUPPORT_DXT10)) + { + const struct dds_header_dxt10 *dxt10 = (const struct dds_header_dxt10 *)((uint8_t *)src_data + header_size);
- if (image->format == D3DX_PIXEL_FORMAT_COUNT) - return D3DXERR_INVALIDDATA; + header_size += sizeof(*dxt10); + if (src_data_size < header_size) + return D3DXERR_INVALIDDATA;
- TRACE("Pixel format is %#x.\n", image->format); - if (header->flags & DDS_DEPTH) - { - image->size.depth = max(header->depth, 1); - image->resource_type = D3DX_RESOURCE_TYPE_TEXTURE_3D; - } - else if (header->caps2 & DDS_CAPS2_CUBEMAP) - { - if ((header->caps2 & DDS_CAPS2_CUBEMAP_ALL_FACES) != DDS_CAPS2_CUBEMAP_ALL_FACES) + TRACE("File type is DXT10 DDS.\n"); + if ((image->format = d3dx_pixel_format_id_from_dxgi_format(dxt10->dxgi_format)) == D3DX_PIXEL_FORMAT_COUNT) + return D3DXERR_INVALIDDATA; + + if (dxt10->misc_flags2) { - WARN("Tried to load a partial cubemap DDS file.\n"); + ERR("Invalid misc_flags2 field %#x.\n", dxt10->misc_flags2); return D3DXERR_INVALIDDATA; }
- image->layer_count = 6; - image->resource_type = D3DX_RESOURCE_TYPE_CUBE_TEXTURE; + image->image_file_format = D3DX_IMAGE_FILE_FORMAT_DDS_DXT10; + image->size.depth = (header->flags & DDS_DEPTH) ? max(header->depth, 1) : 1; + image->layer_count = max(1, dxt10->array_size); + image->resource_type = dxt10_resource_dimension_to_d3dx_resource_type(dxt10->resource_dimension); + if (dxt10->misc_flags & DDS_RESOURCE_MISC_TEXTURECUBE) + { + if (image->resource_type != D3DX_RESOURCE_TYPE_TEXTURE_2D) + return D3DXERR_INVALIDDATA; + image->resource_type = D3DX_RESOURCE_TYPE_CUBE_TEXTURE; + image->layer_count *= 6; + } } else { - image->resource_type = D3DX_RESOURCE_TYPE_TEXTURE_2D; + TRACE("File type is DDS.\n"); + + if ((image->format = d3dx_pixel_format_id_from_dds_pixel_format(&header->pixel_format)) == D3DX_PIXEL_FORMAT_COUNT) + return D3DXERR_INVALIDDATA; + + image->image_file_format = D3DX_IMAGE_FILE_FORMAT_DDS; + image->layer_count = 1; + if (header->flags & DDS_DEPTH) + { + image->size.depth = max(header->depth, 1); + image->resource_type = D3DX_RESOURCE_TYPE_TEXTURE_3D; + } + else if (header->caps2 & DDS_CAPS2_CUBEMAP) + { + if ((header->caps2 & DDS_CAPS2_CUBEMAP_ALL_FACES) != DDS_CAPS2_CUBEMAP_ALL_FACES) + { + WARN("Tried to load a partial cubemap DDS file.\n"); + return D3DXERR_INVALIDDATA; + } + + image->layer_count = 6; + image->resource_type = D3DX_RESOURCE_TYPE_CUBE_TEXTURE; + } + else + image->resource_type = D3DX_RESOURCE_TYPE_TEXTURE_2D; }
+ TRACE("Pixel format is %#x.\n", image->format); image->layer_pitch = d3dx_calculate_layer_pixels_size(image->format, image->size.width, image->size.height, image->size.depth, image->mip_levels); if (!image->layer_pitch) @@ -1051,7 +1154,6 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
image->palette = (is_indexed_fmt) ? (PALETTEENTRY *)(((uint8_t *)src_data) + sizeof(*header)) : NULL; image->pixels = ((BYTE *)src_data) + header_size; - image->image_file_format = D3DX_IMAGE_FILE_FORMAT_DDS; if (starting_mip_level && (image->mip_levels > 1)) { uint32_t i, row_pitch, slice_pitch, initial_mip_levels; @@ -1650,7 +1752,7 @@ HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3d break;
case D3DX_IMAGE_FILE_FORMAT_DDS: - hr = d3dx_initialize_image_from_dds(src_data, src_data_size, image, starting_mip_level); + hr = d3dx_initialize_image_from_dds(src_data, src_data_size, image, starting_mip_level, flags); break;
case D3DX_IMAGE_FILE_FORMAT_PPM: diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index 0f440831259..a04290f44d5 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -149,11 +149,15 @@ enum d3dx_image_file_format D3DX_IMAGE_FILE_FORMAT_DIB = 6, D3DX_IMAGE_FILE_FORMAT_HDR = 7, D3DX_IMAGE_FILE_FORMAT_PFM = 8, + /* This is a Wine only file format value. */ + D3DX_IMAGE_FILE_FORMAT_DDS_DXT10 = 100, D3DX_IMAGE_FILE_FORMAT_FORCE_DWORD = 0x7fffffff };
enum d3dx_resource_type { + D3DX_RESOURCE_TYPE_UNKNOWN, + D3DX_RESOURCE_TYPE_TEXTURE_1D, D3DX_RESOURCE_TYPE_TEXTURE_2D, D3DX_RESOURCE_TYPE_TEXTURE_3D, D3DX_RESOURCE_TYPE_CUBE_TEXTURE, @@ -214,6 +218,15 @@ enum d3dx_pixel_format_id D3DX_PIXEL_FORMAT_COUNT, };
+/* These are aliases. */ +#define D3DX_PIXEL_FORMAT_R16G16B16A16_SNORM D3DX_PIXEL_FORMAT_U16V16W16Q16_SNORM +#define D3DX_PIXEL_FORMAT_R16G16_SNORM D3DX_PIXEL_FORMAT_U16V16_SNORM +#define D3DX_PIXEL_FORMAT_R8G8B8A8_SNORM D3DX_PIXEL_FORMAT_U8V8W8Q8_SNORM +#define D3DX_PIXEL_FORMAT_R8G8_SNORM D3DX_PIXEL_FORMAT_U8V8_SNORM +#define D3DX_PIXEL_FORMAT_BC1_UNORM D3DX_PIXEL_FORMAT_DXT1_UNORM +#define D3DX_PIXEL_FORMAT_BC2_UNORM D3DX_PIXEL_FORMAT_DXT3_UNORM +#define D3DX_PIXEL_FORMAT_BC3_UNORM D3DX_PIXEL_FORMAT_DXT5_UNORM + /* for internal use */ enum component_type { @@ -270,6 +283,7 @@ static inline void set_d3dx_pixels(struct d3dx_pixels *pixels, const void *data, }
#define D3DX_IMAGE_INFO_ONLY 1 +#define D3DX_IMAGE_SUPPORT_DXT10 2 struct d3dx_image { enum d3dx_resource_type resource_type;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 6 ++---- dlls/d3dx9_36/d3dx_helpers.c | 4 +++- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 3a5e6efd6e5..e6989f76916 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -3008,7 +3008,6 @@ static void test_legacy_dds_header_image_info(void) { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 1, (4 * 4), 3, 0, 0, { S_OK, 4, 4, 1, 1, 3, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, 0, - .todo_hr = TRUE }, /* Depth value set to 4, but no caps bits are set. Depth is ignored. */ { @@ -3108,7 +3107,7 @@ static void test_legacy_dds_header_image_info(void) ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
static void test_dxt10_dds_header_image_info(void) @@ -3147,7 +3146,6 @@ static void test_dxt10_dds_header_image_info(void) 0, 4, 4, 0, (4 * 4), 1, 0, 0, { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 0, }, { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, }, 0, - .todo_hr = TRUE }, /* * Setting the misc_flags2 field to anything other than 0 results in @@ -3275,7 +3273,7 @@ static void test_dxt10_dds_header_image_info(void) ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
static void test_get_image_info(void) diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 3574bc8324f..535461db599 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -1149,7 +1149,9 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src if (src_data_size < expected_src_data_size) { WARN("File is too short %u, expected at least %u bytes.\n", src_data_size, expected_src_data_size); - return D3DXERR_INVALIDDATA; + /* D3DX10/D3DX11 do not validate the size of the pixels, only the header. */ + if (!(flags & D3DX_IMAGE_SUPPORT_DXT10)) + return D3DXERR_INVALIDDATA; }
image->palette = (is_indexed_fmt) ? (PALETTEENTRY *)(((uint8_t *)src_data) + sizeof(*header)) : NULL;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 6 +++--- dlls/d3dx10_43/texture.c | 12 ++++++++++++ dlls/d3dx9_36/d3dx_helpers.c | 18 ++++++++++++++++++ dlls/d3dx9_36/d3dx_helpers.h | 18 ++++++++++++++++++ dlls/d3dx9_36/util.c | 6 +++++- 5 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index e6989f76916..4cfe16287c6 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -3459,9 +3459,9 @@ static void test_get_image_info(void) * These formats should map 1:1 from the DXT10 header, unlike legacy DDS * file equivalents. */ - check_dds_dxt10_format(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, TRUE); - check_dds_dxt10_format(DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, TRUE); - check_dds_dxt10_format(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, TRUE); + check_dds_dxt10_format(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, FALSE); + check_dds_dxt10_format(DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, FALSE); + check_dds_dxt10_format(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, FALSE); check_dds_dxt10_format(DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM, FALSE); check_dds_dxt10_format(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, FALSE);
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 0a65bfa8b73..379a2efc0ad 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -82,6 +82,10 @@ static DXGI_FORMAT dxgi_format_from_legacy_dds_d3dx_pixel_format_id(enum d3dx_pi case D3DX_PIXEL_FORMAT_DXT3_UNORM: return DXGI_FORMAT_BC2_UNORM; case D3DX_PIXEL_FORMAT_DXT4_UNORM: return DXGI_FORMAT_BC3_UNORM; case D3DX_PIXEL_FORMAT_DXT5_UNORM: return DXGI_FORMAT_BC3_UNORM; + case D3DX_PIXEL_FORMAT_BC4_UNORM: return DXGI_FORMAT_BC4_UNORM; + case D3DX_PIXEL_FORMAT_BC4_SNORM: return DXGI_FORMAT_BC4_SNORM; + case D3DX_PIXEL_FORMAT_BC5_UNORM: return DXGI_FORMAT_BC5_UNORM; + case D3DX_PIXEL_FORMAT_BC5_SNORM: return DXGI_FORMAT_BC5_SNORM;
/* These formats are known and explicitly unsupported on d3dx10+. */ case D3DX_PIXEL_FORMAT_U8V8W8Q8_SNORM: @@ -108,6 +112,9 @@ static DXGI_FORMAT dxgi_format_from_d3dx_pixel_format_id(enum d3dx_pixel_format_ case D3DX_PIXEL_FORMAT_B8G8R8X8_UNORM: return DXGI_FORMAT_B8G8R8X8_UNORM; case D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM: return DXGI_FORMAT_R10G10B10A2_UNORM; case D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; + case D3DX_PIXEL_FORMAT_R8_UNORM: return DXGI_FORMAT_R8_UNORM; + case D3DX_PIXEL_FORMAT_R8G8_UNORM: return DXGI_FORMAT_R8G8_UNORM; + case D3DX_PIXEL_FORMAT_R16_UNORM: return DXGI_FORMAT_R16_UNORM; case D3DX_PIXEL_FORMAT_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; case D3DX_PIXEL_FORMAT_A8_UNORM: return DXGI_FORMAT_A8_UNORM; case D3DX_PIXEL_FORMAT_R16_FLOAT: return DXGI_FORMAT_R16_FLOAT; @@ -115,12 +122,17 @@ static DXGI_FORMAT dxgi_format_from_d3dx_pixel_format_id(enum d3dx_pixel_format_ case D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; case D3DX_PIXEL_FORMAT_R32_FLOAT: return DXGI_FORMAT_R32_FLOAT; case D3DX_PIXEL_FORMAT_R32G32_FLOAT: return DXGI_FORMAT_R32G32_FLOAT; + case D3DX_PIXEL_FORMAT_R32G32B32_FLOAT: return DXGI_FORMAT_R32G32B32_FLOAT; case D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; case D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM: return DXGI_FORMAT_G8R8_G8B8_UNORM; case D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM: return DXGI_FORMAT_R8G8_B8G8_UNORM; case D3DX_PIXEL_FORMAT_BC1_UNORM: return DXGI_FORMAT_BC1_UNORM; case D3DX_PIXEL_FORMAT_BC2_UNORM: return DXGI_FORMAT_BC2_UNORM; case D3DX_PIXEL_FORMAT_BC3_UNORM: return DXGI_FORMAT_BC3_UNORM; + case D3DX_PIXEL_FORMAT_BC4_UNORM: return DXGI_FORMAT_BC4_UNORM; + case D3DX_PIXEL_FORMAT_BC4_SNORM: return DXGI_FORMAT_BC4_SNORM; + case D3DX_PIXEL_FORMAT_BC5_UNORM: return DXGI_FORMAT_BC5_UNORM; + case D3DX_PIXEL_FORMAT_BC5_SNORM: return DXGI_FORMAT_BC5_SNORM; case D3DX_PIXEL_FORMAT_R16G16B16A16_SNORM: return DXGI_FORMAT_R16G16B16A16_SNORM; case D3DX_PIXEL_FORMAT_R8G8B8A8_SNORM: return DXGI_FORMAT_R8G8B8A8_SNORM; case D3DX_PIXEL_FORMAT_R8G8_SNORM: return DXGI_FORMAT_R8G8_SNORM; diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 535461db599..b44ff3ce6c9 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -80,6 +80,9 @@ static const struct pixel_format_desc formats[] = {D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM, { 2, 10, 10, 10}, {30, 0, 10, 20}, 4, 1, 1, 4, CTYPE_UNORM, CTYPE_UNORM, 0 }, {D3DX_PIXEL_FORMAT_R16G16B16_UNORM, { 0, 16, 16, 16}, { 0, 0, 16, 32}, 6, 1, 1, 6, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_INTERNAL}, {D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM, {16, 16, 16, 16}, {48, 0, 16, 32}, 8, 1, 1, 8, CTYPE_UNORM, CTYPE_UNORM, 0 }, + {D3DX_PIXEL_FORMAT_R8_UNORM, { 0, 8, 0, 0}, { 0, 0, 0, 0}, 1, 1, 1, 1, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_R8G8_UNORM, { 0, 8, 8, 0}, { 0, 0, 8, 0}, 2, 1, 1, 2, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_R16_UNORM, { 0, 16, 0, 0}, { 0, 0, 0, 0}, 2, 1, 1, 2, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, {D3DX_PIXEL_FORMAT_R16G16_UNORM, { 0, 16, 16, 0}, { 0, 0, 16, 0}, 4, 1, 1, 4, CTYPE_EMPTY, CTYPE_UNORM, 0 }, {D3DX_PIXEL_FORMAT_A8_UNORM, { 8, 0, 0, 0}, { 0, 0, 0, 0}, 1, 1, 1, 1, CTYPE_UNORM, CTYPE_EMPTY, 0 }, {D3DX_PIXEL_FORMAT_L8A8_UNORM, { 8, 8, 0, 0}, { 8, 0, 0, 0}, 2, 1, 1, 2, CTYPE_UNORM, CTYPE_LUMA, 0 }, @@ -91,11 +94,16 @@ static const struct pixel_format_desc formats[] = {D3DX_PIXEL_FORMAT_DXT3_UNORM, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 16, CTYPE_UNORM, CTYPE_UNORM, FMT_FLAG_DXT}, {D3DX_PIXEL_FORMAT_DXT4_UNORM, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 16, CTYPE_UNORM, CTYPE_UNORM, FMT_FLAG_DXT}, {D3DX_PIXEL_FORMAT_DXT5_UNORM, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 16, CTYPE_UNORM, CTYPE_UNORM, FMT_FLAG_DXT}, + {D3DX_PIXEL_FORMAT_BC4_UNORM, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 8, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXT|FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_BC4_SNORM, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 8, CTYPE_EMPTY, CTYPE_SNORM, FMT_FLAG_DXT|FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_BC5_UNORM, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 16, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXT|FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_BC5_SNORM, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 16, CTYPE_EMPTY, CTYPE_SNORM, FMT_FLAG_DXT|FMT_FLAG_DXGI}, {D3DX_PIXEL_FORMAT_R16_FLOAT, { 0, 16, 0, 0}, { 0, 0, 0, 0}, 2, 1, 1, 2, CTYPE_EMPTY, CTYPE_FLOAT, 0 }, {D3DX_PIXEL_FORMAT_R16G16_FLOAT, { 0, 16, 16, 0}, { 0, 0, 16, 0}, 4, 1, 1, 4, CTYPE_EMPTY, CTYPE_FLOAT, 0 }, {D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT, {16, 16, 16, 16}, {48, 0, 16, 32}, 8, 1, 1, 8, CTYPE_FLOAT, CTYPE_FLOAT, 0 }, {D3DX_PIXEL_FORMAT_R32_FLOAT, { 0, 32, 0, 0}, { 0, 0, 0, 0}, 4, 1, 1, 4, CTYPE_EMPTY, CTYPE_FLOAT, 0 }, {D3DX_PIXEL_FORMAT_R32G32_FLOAT, { 0, 32, 32, 0}, { 0, 0, 32, 0}, 8, 1, 1, 8, CTYPE_EMPTY, CTYPE_FLOAT, 0 }, + {D3DX_PIXEL_FORMAT_R32G32B32_FLOAT, { 0, 32, 32, 32}, { 0, 0, 32, 64}, 12, 1, 1, 12, CTYPE_EMPTY, CTYPE_FLOAT, FMT_FLAG_DXGI}, {D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT, {32, 32, 32, 32}, {96, 0, 32, 64}, 16, 1, 1, 16, CTYPE_FLOAT, CTYPE_FLOAT, 0 }, {D3DX_PIXEL_FORMAT_P1_UINT, { 8, 8, 8, 8}, { 0, 0, 0, 0}, 1, 8, 1, 1, CTYPE_INDEX, CTYPE_INDEX, FMT_FLAG_INTERNAL}, {D3DX_PIXEL_FORMAT_P2_UINT, { 8, 8, 8, 8}, { 0, 0, 0, 0}, 1, 4, 1, 1, CTYPE_INDEX, CTYPE_INDEX, FMT_FLAG_INTERNAL}, @@ -217,6 +225,12 @@ static const struct { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','3') }, D3DX_PIXEL_FORMAT_DXT3_UNORM }, { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','4') }, D3DX_PIXEL_FORMAT_DXT4_UNORM }, { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','5') }, D3DX_PIXEL_FORMAT_DXT5_UNORM }, + { { 32, DDS_PF_FOURCC, MAKEFOURCC('B','C','4','U') }, D3DX_PIXEL_FORMAT_BC4_UNORM }, + { { 32, DDS_PF_FOURCC, MAKEFOURCC('B','C','4','S') }, D3DX_PIXEL_FORMAT_BC4_SNORM }, + /* ATI2 is treated identically to BC5U in d3dx10+. */ + { { 32, DDS_PF_FOURCC, MAKEFOURCC('A','T','I','2') }, D3DX_PIXEL_FORMAT_BC5_UNORM }, + { { 32, DDS_PF_FOURCC, MAKEFOURCC('B','C','5','U') }, D3DX_PIXEL_FORMAT_BC5_UNORM }, + { { 32, DDS_PF_FOURCC, MAKEFOURCC('B','C','5','S') }, D3DX_PIXEL_FORMAT_BC5_SNORM }, /* These aren't actually fourcc values, they're just D3DFMT values. */ { { 32, DDS_PF_FOURCC, 0x24 }, D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM }, { { 32, DDS_PF_FOURCC, 0x6e }, D3DX_PIXEL_FORMAT_U16V16W16Q16_SNORM }, @@ -375,6 +389,9 @@ static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(DXGI_FORM case DXGI_FORMAT_B4G4R4A4_UNORM: return D3DX_PIXEL_FORMAT_B4G4R4A4_UNORM; case DXGI_FORMAT_R10G10B10A2_UNORM: return D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM; case DXGI_FORMAT_R16G16B16A16_UNORM: return D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM; + case DXGI_FORMAT_R8_UNORM: return D3DX_PIXEL_FORMAT_R8_UNORM; + case DXGI_FORMAT_R8G8_UNORM: return D3DX_PIXEL_FORMAT_R8G8_UNORM; + case DXGI_FORMAT_R16_UNORM: return D3DX_PIXEL_FORMAT_R16_UNORM; case DXGI_FORMAT_R16G16_UNORM: return D3DX_PIXEL_FORMAT_R16G16_UNORM; case DXGI_FORMAT_A8_UNORM: return D3DX_PIXEL_FORMAT_A8_UNORM; case DXGI_FORMAT_R16_FLOAT: return D3DX_PIXEL_FORMAT_R16_FLOAT; @@ -382,6 +399,7 @@ static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(DXGI_FORM case DXGI_FORMAT_R16G16B16A16_FLOAT: return D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT; case DXGI_FORMAT_R32_FLOAT: return D3DX_PIXEL_FORMAT_R32_FLOAT; case DXGI_FORMAT_R32G32_FLOAT: return D3DX_PIXEL_FORMAT_R32G32_FLOAT; + case DXGI_FORMAT_R32G32B32_FLOAT: return D3DX_PIXEL_FORMAT_R32G32B32_FLOAT; case DXGI_FORMAT_R32G32B32A32_FLOAT: return D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT; case DXGI_FORMAT_G8R8_G8B8_UNORM: return D3DX_PIXEL_FORMAT_G8R8_G8B8_UNORM; case DXGI_FORMAT_R8G8_B8G8_UNORM: return D3DX_PIXEL_FORMAT_R8G8_B8G8_UNORM; diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index a04290f44d5..b7fc2186b35 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -183,6 +183,9 @@ enum d3dx_pixel_format_id D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM, D3DX_PIXEL_FORMAT_R16G16B16_UNORM, D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM, + D3DX_PIXEL_FORMAT_R8_UNORM, + D3DX_PIXEL_FORMAT_R8G8_UNORM, + D3DX_PIXEL_FORMAT_R16_UNORM, D3DX_PIXEL_FORMAT_R16G16_UNORM, D3DX_PIXEL_FORMAT_A8_UNORM, D3DX_PIXEL_FORMAT_L8A8_UNORM, @@ -194,11 +197,16 @@ enum d3dx_pixel_format_id D3DX_PIXEL_FORMAT_DXT3_UNORM, D3DX_PIXEL_FORMAT_DXT4_UNORM, D3DX_PIXEL_FORMAT_DXT5_UNORM, + D3DX_PIXEL_FORMAT_BC4_UNORM, + D3DX_PIXEL_FORMAT_BC4_SNORM, + D3DX_PIXEL_FORMAT_BC5_UNORM, + D3DX_PIXEL_FORMAT_BC5_SNORM, D3DX_PIXEL_FORMAT_R16_FLOAT, D3DX_PIXEL_FORMAT_R16G16_FLOAT, D3DX_PIXEL_FORMAT_R16G16B16A16_FLOAT, D3DX_PIXEL_FORMAT_R32_FLOAT, D3DX_PIXEL_FORMAT_R32G32_FLOAT, + D3DX_PIXEL_FORMAT_R32G32B32_FLOAT, D3DX_PIXEL_FORMAT_R32G32B32A32_FLOAT, D3DX_PIXEL_FORMAT_P1_UINT, D3DX_PIXEL_FORMAT_P2_UINT, @@ -244,6 +252,11 @@ enum format_flag FMT_FLAG_PACKED = 0x02, /* Internal only format, has no exact D3DFORMAT equivalent. */ FMT_FLAG_INTERNAL = 0x04, + /* + * For formats that only have a DXGI_FORMAT mapping, no D3DFORMAT + * equivalent. + */ + FMT_FLAG_DXGI = 0x08, };
struct pixel_format_desc { @@ -353,6 +366,11 @@ static inline BOOL is_internal_format(const struct pixel_format_desc *format) return !!(format->flags & FMT_FLAG_INTERNAL); }
+static inline BOOL is_dxgi_format(const struct pixel_format_desc *format) +{ + return !!(format->flags & FMT_FLAG_DXGI); +} + static inline BOOL is_conversion_from_supported(const struct pixel_format_desc *format) { return !is_packed_format(format) && !is_unknown_format(format); diff --git a/dlls/d3dx9_36/util.c b/dlls/d3dx9_36/util.c index 8a9aade34f8..dd2162d9f6e 100644 --- a/dlls/d3dx9_36/util.c +++ b/dlls/d3dx9_36/util.c @@ -71,9 +71,13 @@ D3DFORMAT d3dformat_from_d3dx_pixel_format_id(enum d3dx_pixel_format_id format) case D3DX_PIXEL_FORMAT_UYVY: return D3DFMT_UYVY; case D3DX_PIXEL_FORMAT_YUY2: return D3DFMT_YUY2; default: - if (!is_internal_format(get_d3dx_pixel_format_info(format))) + { + const struct pixel_format_desc *fmt_desc = get_d3dx_pixel_format_info(format); + + if (!is_internal_format(fmt_desc) && !is_dxgi_format(fmt_desc)) FIXME("Unknown d3dx_pixel_format_id %u.\n", format); return D3DFMT_UNKNOWN; + } } }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 36 +++++++------- dlls/d3dx10_43/texture.c | 93 ++++------------------------------- 2 files changed, 28 insertions(+), 101 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 4cfe16287c6..9e6ef2e4318 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -3055,7 +3055,7 @@ static void test_legacy_dds_header_image_info(void) { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 1, (4 * 4), 1, (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), (DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_POSITIVEX), - { E_FAIL, }, (64 * 6), .todo_hr = TRUE + { E_FAIL, }, (64 * 6) }, }; D3DX10_IMAGE_INFO info; @@ -3154,7 +3154,7 @@ static void test_dxt10_dds_header_image_info(void) { 0, 4, 4, 0, (4 * 4), 1, 0, 0, { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, 0, 1, 1, }, - { E_FAIL }, (4 * 4 * 4), .todo_hr = TRUE + { E_FAIL }, (4 * 4 * 4) }, /* * The misc_flags field isn't passed through directly, only the @@ -3169,7 +3169,7 @@ static void test_dxt10_dds_header_image_info(void) { 0, 4, 4, 0, (4 * 4), 1, 0, 0, { DXGI_FORMAT_R8G8B8A8_UNORM, 500, 0, 1, 0, }, - { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, 500, }, (4 * 4 * 4), .todo_info = TRUE + { S_OK, 4, 4, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, 500, }, (4 * 4 * 4), .todo_hr = TRUE }, /* Depth value of 2, but D3D10_RESOURCE_DIMENSION_TEXTURE2D. */ { @@ -3214,7 +3214,7 @@ static void test_dxt10_dds_header_image_info(void) { 0, 4, 4, 1, (4 * 4), 1, 0, 0, { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE3D, DDS_RESOURCE_MISC_TEXTURECUBE, 2, 0, }, - { E_FAIL }, (4 * 4 * 4 * 12), .todo_hr = TRUE + { E_FAIL }, (4 * 4 * 4 * 12) }, /* * 10. @@ -3223,7 +3223,7 @@ static void test_dxt10_dds_header_image_info(void) { 0, 4, 4, 1, (4 * 4), 1, 0, 0, { DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE1D, DDS_RESOURCE_MISC_TEXTURECUBE, 2, 0, }, - { E_FAIL }, (4 * 4 * 4 * 12), .todo_hr = TRUE + { E_FAIL }, (4 * 4 * 4 * 12) }, }; D3DX10_IMAGE_INFO info; @@ -3430,13 +3430,13 @@ static void test_get_image_info(void) check_dds_pixel_format(DDS_PF_FOURCC, 0x74, 0, 0, 0, 0, 0, DXGI_FORMAT_R32G32B32A32_FLOAT); /* D3DFMT_A32B32G32R32F */
/* Test for DDS pixel formats that are valid on d3dx9, but not d3dx10. */ - todo_wine check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('U','Y','V','Y'), 0, 0, 0, 0, 0, E_FAIL); - todo_wine check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0, E_FAIL); + check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('U','Y','V','Y'), 0, 0, 0, 0, 0, E_FAIL); + check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0, E_FAIL); /* Bumpmap formats aren't supported. */ - todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0, 0, E_FAIL); - todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, E_FAIL); - todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 32, 0xff, 0xff00, 0x00ff0000, 0xff000000, E_FAIL); - todo_wine check_dds_pixel_format_unsupported(DDS_PF_BUMPLUMINANCE, 0, 32, 0x0000ff, 0x00ff00, 0xff0000, 0, E_FAIL); + check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0, 0, E_FAIL); + check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, E_FAIL); + check_dds_pixel_format_unsupported(DDS_PF_BUMPDUDV, 0, 32, 0xff, 0xff00, 0x00ff0000, 0xff000000, E_FAIL); + check_dds_pixel_format_unsupported(DDS_PF_BUMPLUMINANCE, 0, 32, 0x0000ff, 0x00ff00, 0xff0000, 0, E_FAIL);
/* Newer fourCC formats. */ check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC4_UNORM); @@ -3444,16 +3444,16 @@ static void test_get_image_info(void) check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC4_SNORM); check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC5_SNORM); /* ATI1 is unsupported, but ATI2 is supported. */ - todo_wine check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('A','T','I','1'), 0, 0, 0, 0, 0, E_FAIL); + check_dds_pixel_format_unsupported(DDS_PF_FOURCC, MAKEFOURCC('A','T','I','1'), 0, 0, 0, 0, 0, E_FAIL); check_dds_pixel_format(DDS_PF_FOURCC, MAKEFOURCC('A','T','I','2'), 0, 0, 0, 0, 0, DXGI_FORMAT_BC5_UNORM);
- todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_B5G6R5_UNORM, E_FAIL); - todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_B5G5R5A1_UNORM, E_FAIL); + check_dds_dxt10_format_unsupported(DXGI_FORMAT_B5G6R5_UNORM, E_FAIL); + check_dds_dxt10_format_unsupported(DXGI_FORMAT_B5G5R5A1_UNORM, E_FAIL); /* Formats that are newer than d3d10. */ - todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC6H_UF16, E_FAIL); - todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC6H_SF16, E_FAIL); - todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC7_UNORM, E_FAIL); - todo_wine check_dds_dxt10_format_unsupported(DXGI_FORMAT_B4G4R4A4_UNORM, E_FAIL); + check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC6H_UF16, E_FAIL); + check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC6H_SF16, E_FAIL); + check_dds_dxt10_format_unsupported(DXGI_FORMAT_BC7_UNORM, E_FAIL); + check_dds_dxt10_format_unsupported(DXGI_FORMAT_B4G4R4A4_UNORM, E_FAIL);
/* * These formats should map 1:1 from the DXT10 header, unlike legacy DDS diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 379a2efc0ad..1f9998ad27a 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -235,22 +235,6 @@ static const GUID *dxgi_format_to_wic_guid(DXGI_FORMAT format) return NULL; }
-static D3D10_RESOURCE_DIMENSION wic_dimension_to_d3dx10_dimension(WICDdsDimension wic_dimension) -{ - switch (wic_dimension) - { - case WICDdsTexture1D: - return D3D10_RESOURCE_DIMENSION_TEXTURE1D; - case WICDdsTexture2D: - case WICDdsTextureCube: - return D3D10_RESOURCE_DIMENSION_TEXTURE2D; - case WICDdsTexture3D: - return D3D10_RESOURCE_DIMENSION_TEXTURE3D; - default: - return D3D10_RESOURCE_DIMENSION_UNKNOWN; - } -} - static unsigned int get_bpp_from_format(DXGI_FORMAT format) { switch (format) @@ -385,36 +369,6 @@ static unsigned int get_bpp_from_format(DXGI_FORMAT format) } }
-static DXGI_FORMAT get_d3dx10_dds_format(DXGI_FORMAT format) -{ - static const struct - { - DXGI_FORMAT src; - DXGI_FORMAT dst; - } - format_map[] = - { - {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}, - {DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM}, - }; - - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(format_map); ++i) - { - if (format == format_map[i].src) - return format_map[i].dst; - } - return format; -} - HRESULT WINAPI D3DX10GetImageInfoFromFileA(const char *src_file, ID3DX10ThreadPump *pump, D3DX10_IMAGE_INFO *info, HRESULT *result) { @@ -616,9 +570,7 @@ HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_inf { IWICBitmapFrameDecode *frame = NULL; IWICImagingFactory *factory = NULL; - IWICDdsDecoder *dds_decoder = NULL; IWICBitmapDecoder *decoder = NULL; - WICDdsParameters dds_params; IWICStream *stream = NULL; unsigned int frame_count; struct d3dx_image image; @@ -631,13 +583,7 @@ HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_inf if (SUCCEEDED(d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10)) && (image.image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS || (image.image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS_DXT10))) - { - if (SUCCEEDED(d3dx10_image_info_from_d3dx_image(img_info, &image))) - { - TRACE("Successfully retrieved image info from shared code.\n"); - return S_OK; - } - } + return d3dx10_image_info_from_d3dx_image(img_info, &image);
WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); IWICImagingFactory_CreateStream(factory, &stream); @@ -674,37 +620,18 @@ HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_inf
if (img_info->ImageFileFormat == D3DX10_IFF_DDS) { - hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICDdsDecoder, (void **)&dds_decoder); - if (FAILED(hr)) - goto end; - hr = IWICDdsDecoder_GetParameters(dds_decoder, &dds_params); - if (FAILED(hr)) - goto end; - img_info->ArraySize = dds_params.ArraySize; - img_info->Depth = dds_params.Depth; - img_info->MipLevels = dds_params.MipLevels; - img_info->ResourceDimension = wic_dimension_to_d3dx10_dimension(dds_params.Dimension); - img_info->Format = get_d3dx10_dds_format(dds_params.DxgiFormat); - img_info->MiscFlags = 0; - if (dds_params.Dimension == WICDdsTextureCube) - { - img_info->MiscFlags = D3D10_RESOURCE_MISC_TEXTURECUBE; - img_info->ArraySize *= 6; - } - } - else - { - img_info->ArraySize = 1; - img_info->Depth = 1; - img_info->MipLevels = 1; - img_info->ResourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; - img_info->Format = DXGI_FORMAT_R8G8B8A8_UNORM; - img_info->MiscFlags = 0; + hr = E_FAIL; + goto end; }
+ img_info->ArraySize = 1; + img_info->Depth = 1; + img_info->MipLevels = 1; + img_info->ResourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; + img_info->Format = DXGI_FORMAT_R8G8B8A8_UNORM; + img_info->MiscFlags = 0; + end: - if (dds_decoder) - IWICDdsDecoder_Release(dds_decoder); if (frame) IWICBitmapFrameDecode_Release(frame); if (decoder)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/texture.c | 40 +++++++++++++++++++++++++----------- dlls/d3dx9_36/d3dx_helpers.c | 18 ++++++++++++++++ dlls/d3dx9_36/d3dx_helpers.h | 4 ++++ 3 files changed, 50 insertions(+), 12 deletions(-)
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 1f9998ad27a..ed9cdd0e0f4 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -161,6 +161,9 @@ static D3DX10_IMAGE_FILE_FORMAT d3dx10_image_file_format_from_d3dx_image_file_fo case D3DX_IMAGE_FILE_FORMAT_JPG: return D3DX10_IFF_JPG; case D3DX_IMAGE_FILE_FORMAT_PNG: return D3DX10_IFF_PNG; case D3DX_IMAGE_FILE_FORMAT_DDS: return D3DX10_IFF_DDS; + case D3DX_IMAGE_FILE_FORMAT_TIFF: return D3DX10_IFF_TIFF; + case D3DX_IMAGE_FILE_FORMAT_GIF: return D3DX10_IFF_GIF; + case D3DX_IMAGE_FILE_FORMAT_WMP: return D3DX10_IFF_WMP; case D3DX_IMAGE_FILE_FORMAT_DDS_DXT10: return D3DX10_IFF_DDS; default: FIXME("No D3DX10_IMAGE_FILE_FORMAT for d3dx_image_file_format %d.\n", iff); @@ -522,20 +525,31 @@ static HRESULT d3dx10_image_info_from_d3dx_image(D3DX10_IMAGE_INFO *info, struct DXGI_FORMAT format;
memset(info, 0, sizeof(*info)); - if (image->image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS_DXT10) - format = dxgi_format_from_d3dx_pixel_format_id(image->format); - else - format = dxgi_format_from_legacy_dds_d3dx_pixel_format_id(image->format); + switch (image->image_file_format) + { + case D3DX_IMAGE_FILE_FORMAT_DDS_DXT10: + format = dxgi_format_from_d3dx_pixel_format_id(image->format); + break; + + case D3DX_IMAGE_FILE_FORMAT_DDS: + format = dxgi_format_from_legacy_dds_d3dx_pixel_format_id(image->format); + break; + + default: + if (iff == D3DX10_IFF_FORCE_DWORD) + return E_FAIL; + + /* All other image file formats use the default format. */ + format = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + }
if (format == DXGI_FORMAT_UNKNOWN) { - WARN("Tried to load DDS file with unsupported format %#x.\n", image->format); + WARN("Tried to load file with unsupported pixel format %#x.\n", image->format); return E_FAIL; }
- if (iff == D3DX10_IFF_FORCE_DWORD) - return E_FAIL; - switch (image->resource_type) { case D3DX_RESOURCE_TYPE_TEXTURE_2D: @@ -580,10 +594,12 @@ HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_inf if (!data || !size) return E_FAIL;
- if (SUCCEEDED(d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10)) - && (image.image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS - || (image.image_file_format == D3DX_IMAGE_FILE_FORMAT_DDS_DXT10))) - return d3dx10_image_info_from_d3dx_image(img_info, &image); + if (SUCCEEDED(d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10))) + { + hr = d3dx10_image_info_from_d3dx_image(img_info, &image); + if (SUCCEEDED(hr)) + return hr; + }
WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); IWICImagingFactory_CreateStream(factory, &stream); diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index b44ff3ce6c9..60394ca1d9b 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -526,6 +526,9 @@ static const GUID *wic_container_guid_from_d3dx_file_format(enum d3dx_image_file case D3DX_IMAGE_FILE_FORMAT_BMP: return &GUID_ContainerFormatBmp; case D3DX_IMAGE_FILE_FORMAT_JPG: return &GUID_ContainerFormatJpeg; case D3DX_IMAGE_FILE_FORMAT_PNG: return &GUID_ContainerFormatPng; + case D3DX_IMAGE_FILE_FORMAT_TIFF: return &GUID_ContainerFormatTiff; + case D3DX_IMAGE_FILE_FORMAT_GIF: return &GUID_ContainerFormatGif; + case D3DX_IMAGE_FILE_FORMAT_WMP: return &GUID_ContainerFormatWmp; default: assert(0 && "Unexpected file format."); return NULL; @@ -1002,6 +1005,12 @@ static const uint8_t ppm_raw_file_signature[] = { 'P', '6' }; static const uint8_t hdr_file_signature[] = { '#', '?', 'R', 'A', 'D', 'I', 'A', 'N', 'C', 'E', '\n' }; static const uint8_t pfm_color_file_signature[] = { 'P', 'F' }; static const uint8_t pfm_gray_file_signature[] = { 'P', 'f' }; +static const uint8_t tiff_le_file_signature[] = { 'I', 'I', 0x2a, 0x00 }; +static const uint8_t tiff_be_file_signature[] = { 'M', 'M', 0x00, 0x2a }; +static const uint8_t gif_87a_file_signature[] = { 'G', 'I', 'F', '8', '7', 'a' }; +static const uint8_t gif_89a_file_signature[] = { 'G', 'I', 'F', '8', '9', 'a' }; +static const uint8_t wmp_v0_file_signature[] = { 'I', 'I', 0xbc, 0x00 }; +static const uint8_t wmp_v1_file_signature[] = { 'I', 'I', 0xbc, 0x01 };
/* * If none of these match, the file is either DIB, TGA, or something we don't @@ -1025,6 +1034,12 @@ static const struct d3dx_file_format_signature file_format_signatures[] = { hdr_file_signature, sizeof(hdr_file_signature), D3DX_IMAGE_FILE_FORMAT_HDR }, { pfm_color_file_signature, sizeof(pfm_color_file_signature), D3DX_IMAGE_FILE_FORMAT_PFM }, { pfm_gray_file_signature, sizeof(pfm_gray_file_signature), D3DX_IMAGE_FILE_FORMAT_PFM }, + { tiff_le_file_signature, sizeof(tiff_le_file_signature), D3DX_IMAGE_FILE_FORMAT_TIFF }, + { tiff_be_file_signature, sizeof(tiff_be_file_signature), D3DX_IMAGE_FILE_FORMAT_TIFF }, + { gif_87a_file_signature, sizeof(gif_87a_file_signature), D3DX_IMAGE_FILE_FORMAT_GIF }, + { gif_89a_file_signature, sizeof(gif_89a_file_signature), D3DX_IMAGE_FILE_FORMAT_GIF }, + { wmp_v0_file_signature, sizeof(wmp_v0_file_signature), D3DX_IMAGE_FILE_FORMAT_WMP }, + { wmp_v1_file_signature, sizeof(wmp_v1_file_signature), D3DX_IMAGE_FILE_FORMAT_WMP }, };
static BOOL d3dx_get_image_file_format_from_file_signature(const void *src_data, uint32_t src_data_size, @@ -1768,6 +1783,9 @@ HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3d case D3DX_IMAGE_FILE_FORMAT_BMP: case D3DX_IMAGE_FILE_FORMAT_JPG: case D3DX_IMAGE_FILE_FORMAT_PNG: + case D3DX_IMAGE_FILE_FORMAT_TIFF: + case D3DX_IMAGE_FILE_FORMAT_GIF: + case D3DX_IMAGE_FILE_FORMAT_WMP: hr = d3dx_initialize_image_from_wic(src_data, src_data_size, image, iff, flags); break;
diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index b7fc2186b35..8263d832bfa 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -149,6 +149,10 @@ enum d3dx_image_file_format D3DX_IMAGE_FILE_FORMAT_DIB = 6, D3DX_IMAGE_FILE_FORMAT_HDR = 7, D3DX_IMAGE_FILE_FORMAT_PFM = 8, + /* TIFF/GIF/WMP are only available on D3DX10/D3DX11. */ + D3DX_IMAGE_FILE_FORMAT_TIFF = 10, + D3DX_IMAGE_FILE_FORMAT_GIF = 11, + D3DX_IMAGE_FILE_FORMAT_WMP = 12, /* This is a Wine only file format value. */ D3DX_IMAGE_FILE_FORMAT_DDS_DXT10 = 100, D3DX_IMAGE_FILE_FORMAT_FORCE_DWORD = 0x7fffffff
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 2 +- dlls/d3dx10_43/texture.c | 97 +---------------------------------- 2 files changed, 3 insertions(+), 96 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 9e6ef2e4318..b1342dabb15 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -3324,7 +3324,7 @@ static void test_get_image_info(void) /* 2 bpp is not a valid bit count. */ hr2 = 0xdeadbeef; hr = D3DX10GetImageInfoFromMemory(test_bmp_2bpp, sizeof(test_bmp_2bpp), NULL, &image_info, &hr2); - todo_wine ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); + ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr); ok(hr == hr2, "Got unexpected hr2 %#lx.\n", hr2);
for (i = 0; i < ARRAY_SIZE(test_image); ++i) diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index ed9cdd0e0f4..ab488dcfa2f 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -171,22 +171,6 @@ static D3DX10_IMAGE_FILE_FORMAT d3dx10_image_file_format_from_d3dx_image_file_fo } }
-static const struct -{ - const GUID *wic_container_guid; - D3DX10_IMAGE_FILE_FORMAT d3dx_file_format; -} -file_formats[] = -{ - { &GUID_ContainerFormatBmp, D3DX10_IFF_BMP }, - { &GUID_ContainerFormatJpeg, D3DX10_IFF_JPG }, - { &GUID_ContainerFormatPng, D3DX10_IFF_PNG }, - { &GUID_ContainerFormatDds, D3DX10_IFF_DDS }, - { &GUID_ContainerFormatTiff, D3DX10_IFF_TIFF }, - { &GUID_ContainerFormatGif, D3DX10_IFF_GIF }, - { &GUID_ContainerFormatWmp, D3DX10_IFF_WMP }, -}; - static const struct { const GUID *wic_guid; @@ -213,18 +197,6 @@ wic_pixel_formats[] = { &GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT } };
-static D3DX10_IMAGE_FILE_FORMAT wic_container_guid_to_file_format(GUID *container_format) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(file_formats); ++i) - { - if (IsEqualGUID(file_formats[i].wic_container_guid, container_format)) - return file_formats[i].d3dx_file_format; - } - return D3DX10_IFF_FORCE_DWORD; -} - static const GUID *dxgi_format_to_wic_guid(DXGI_FORMAT format) { unsigned int i; @@ -582,80 +554,15 @@ static HRESULT d3dx10_image_info_from_d3dx_image(D3DX10_IMAGE_INFO *info, struct
HRESULT get_image_info(const void *data, SIZE_T size, D3DX10_IMAGE_INFO *img_info) { - IWICBitmapFrameDecode *frame = NULL; - IWICImagingFactory *factory = NULL; - IWICBitmapDecoder *decoder = NULL; - IWICStream *stream = NULL; - unsigned int frame_count; struct d3dx_image image; - GUID container_format; HRESULT hr;
if (!data || !size) return E_FAIL;
- if (SUCCEEDED(d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10))) - { + hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10); + if (SUCCEEDED(hr)) hr = d3dx10_image_info_from_d3dx_image(img_info, &image); - if (SUCCEEDED(hr)) - return hr; - } - - WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); - IWICImagingFactory_CreateStream(factory, &stream); - hr = IWICStream_InitializeFromMemory(stream, (BYTE *)data, size); - if (FAILED(hr)) - { - WARN("Failed to initialize stream.\n"); - goto end; - } - hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder); - if (FAILED(hr)) - goto end; - - hr = IWICBitmapDecoder_GetContainerFormat(decoder, &container_format); - if (FAILED(hr)) - goto end; - img_info->ImageFileFormat = wic_container_guid_to_file_format(&container_format); - if (img_info->ImageFileFormat == D3DX10_IFF_FORCE_DWORD) - { - hr = E_FAIL; - WARN("Unsupported image file format %s.\n", debugstr_guid(&container_format)); - goto end; - } - - hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); - if (FAILED(hr) || !frame_count) - goto end; - hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); - if (FAILED(hr)) - goto end; - hr = IWICBitmapFrameDecode_GetSize(frame, &img_info->Width, &img_info->Height); - if (FAILED(hr)) - goto end; - - if (img_info->ImageFileFormat == D3DX10_IFF_DDS) - { - hr = E_FAIL; - goto end; - } - - img_info->ArraySize = 1; - img_info->Depth = 1; - img_info->MipLevels = 1; - img_info->ResourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; - img_info->Format = DXGI_FORMAT_R8G8B8A8_UNORM; - img_info->MiscFlags = 0; - -end: - if (frame) - IWICBitmapFrameDecode_Release(frame); - if (decoder) - IWICBitmapDecoder_Release(decoder); - if (stream) - IWICStream_Release(stream); - if (factory) - IWICImagingFactory_Release(factory);
if (hr != S_OK) {
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/tests/d3dx10.c:
}
}
+#define check_dds_pixel_format_unsupported(flags, fourcc, bpp, rmask, gmask, bmask, amask, expected_hr) \
check_dds_pixel_format_unsupported_(__LINE__, flags, fourcc, bpp, rmask, gmask, bmask, amask, expected_hr)
+static void check_dds_pixel_format_unsupported_(unsigned int line, DWORD flags, DWORD fourcc, DWORD bpp,
DWORD rmask, DWORD gmask, DWORD bmask, DWORD amask, HRESULT expected_hr)
Maybe it makes sense to move the bulk of `check_dds_pixel_format_unsupported_()` and `check_dds_pixel_format_()` to a separate test function taking both `expected_format` and `expected_hr` arguments and have both functions simply call into that with proper arguments?
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/tests/d3dx10.c:
- dds.header.pixel_format.flags = flags;
- dds.header.pixel_format.fourcc = fourcc;
- dds.header.pixel_format.bpp = bpp;
- dds.header.pixel_format.rmask = rmask;
- dds.header.pixel_format.gmask = gmask;
- dds.header.pixel_format.bmask = bmask;
- dds.header.pixel_format.amask = amask;
- memset(dds.data, 0, sizeof(dds.data));
- hr = D3DX10GetImageInfoFromMemory(&dds, sizeof(dds), NULL, &info, NULL);
- ok_(__FILE__, line)(hr == expected_hr, "Got unexpected hr %#lx, expected %#lx.\n", hr, expected_hr);
+}
+#define check_dds_dxt10_format(format, expected_format, wine_todo) \
check_dds_dxt10_format_(__LINE__, format, expected_format, wine_todo)
+static void check_dds_dxt10_format_(uint32_t line, DXGI_FORMAT format, DXGI_FORMAT expected_format, BOOL wine_todo)
Similarly here together with `check_dds_dxt10_format_unsupported_()`.
Not a ton of duplication but highlighting the actual test might be worth it.
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/tests/d3dx10.c:
DXGI_FORMAT format;
D3D10_RESOURCE_DIMENSION resource_dimension;
- };
- static const struct
- {
uint32_t flags;
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t row_pitch;
uint32_t mip_levels;
uint32_t caps;
uint32_t caps2;
struct expected expected;
uint32_t pixel_data_size;
BOOL todo_hr;
Kind of a nitpick and I could see arguments against it, but I'd put pixel_data_size (an input to `D3DX10GetImageInfoFromMemory()`) before the expected outputs.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/d3dx_helpers.c:
if (src_data_size < expected_src_data_size) { WARN("File is too short %u, expected at least %u bytes.\n", src_data_size, expected_src_data_size);
return D3DXERR_INVALIDDATA;
/* D3DX10/D3DX11 do not validate the size of the pixels, only the header. */
if (!(flags & D3DX_IMAGE_SUPPORT_DXT10))
return D3DXERR_INVALIDDATA;
Do we want to do this? It's the kind of bug-for-bug compatibility that I'm not sure we should replicate, at least until some application comes up needing it.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/d3dx_helpers.c:
{ { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','3') }, D3DX_PIXEL_FORMAT_DXT3_UNORM }, { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','4') }, D3DX_PIXEL_FORMAT_DXT4_UNORM }, { { 32, DDS_PF_FOURCC, MAKEFOURCC('D','X','T','5') }, D3DX_PIXEL_FORMAT_DXT5_UNORM },
- { { 32, DDS_PF_FOURCC, MAKEFOURCC('B','C','4','U') }, D3DX_PIXEL_FORMAT_BC4_UNORM },
- { { 32, DDS_PF_FOURCC, MAKEFOURCC('B','C','4','S') }, D3DX_PIXEL_FORMAT_BC4_SNORM },
- /* ATI2 is treated identically to BC5U in d3dx10+. */
- { { 32, DDS_PF_FOURCC, MAKEFOURCC('A','T','I','2') }, D3DX_PIXEL_FORMAT_BC5_UNORM },
I gather this is not supported on d3dx9? I don't see a test for it (although I wouldn't be surprised if I missed it in my cursory search).
This looks generally okay; I'm not approving right away only because of the question on patch 4/8.
On Fri Aug 8 10:20:16 2025 +0000, Matteo Bruni wrote:
I gather this is not supported on d3dx9? I don't see a test for it (although I wouldn't be surprised if I missed it in my cursory search).
I ran into an application that tried to load this format on d3dx9 and failed, which is what led me to write this test for d3dx10. It's not supported on d3dx9 at all, I tested all versions to make sure. It seemed odd to have a test for something that was obviously unsupported, but I can add one if you'd like. :)
On Fri Aug 8 10:20:16 2025 +0000, Matteo Bruni wrote:
Do we want to do this? It's the kind of bug-for-bug compatibility that I'm not sure we should replicate, at least until some application comes up needing it.
Hm. I guess it could in theory lead to us reading out of bounds? There are quite a few tests for file size validation in d3dx9, so I assumed it's probably something that has been encountered somewhere.
It might make sense to succeed in the image info case, but fail if an application tries to load it into a texture. Or fail in both cases, I don't have a strong opinion either way, and don't know of an application that relies upon this behavior.
On Fri Aug 8 14:37:07 2025 +0000, Connor McAdams wrote:
I ran into an application that tried to load this format on d3dx9 and failed, which is what led me to write this test for d3dx10. It's not supported on d3dx9 at all, I tested all versions to make sure. It seemed odd to have a test for something that was obviously unsupported, but I can add one if you'd like. :)
Well, the thing is, ATI2 was introduced during d3d9 times by AMD via a sort of "vendor hack" [https://aras-p.info/texts/D3D9GPUHacks.html]. It doesn't seem weird that d3dx only started supporting it after it was officially introduced in d3d10 as BC5, but it's not entirely a given either.
So I don't think a d3dx9 test checking that loading a ATI2 DDS fails would be a terrible idea. No particular rush either, though.
On Fri Aug 8 14:45:14 2025 +0000, Connor McAdams wrote:
Hm. I guess it could in theory lead to us reading out of bounds? There are quite a few tests for file size validation in d3dx9, so I assumed it's probably something that has been encountered somewhere. It might make sense to succeed in the image info case, but fail if an application tries to load it into a texture. Or fail in both cases, I don't have a strong opinion either way, and don't know of an application that relies upon this behavior.
Right, I guess it's more relevant for the texture load case. I guess it doesn't matter for now but I'd rather avoid potential out of bounds during texture loads until proven necessary (and the `WARN()` should hopefully help with spotting that).