This is the first step in moving the various D3DXCreateTextureFromFileInMemory functions over to using shared code.
-- v3: d3dx9: Add support for specifying which mip level to get pixel data from to d3dx_image_get_pixels(). d3dx9: Cleanup texture value argument handling in D3DXCreateTextureFromFileInMemoryEx(). d3dx9: Add support for specifying a starting mip level when initializing a d3dx_image structure. d3dx9: Use struct volume inside of struct d3dx_image for storing dimensions. d3dx9: Use d3dx_image structure inside of D3DXCreateTextureFromFileInMemoryEx(). d3dx9: Refactor texture creation and cleanup in D3DXCreateTextureFromFileInMemoryEx(). d3dx9/tests: Add more tests for loading files with multiple mip levels into textures. d3dx9/tests: Add tests for the source info argument of D3DXCreateTextureFromFileInMemoryEx().
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/texture.c | 132 ++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index b0dd3c0c6c3..463f0190bb6 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -24,6 +24,7 @@ #include "wine/test.h" #include "d3dx9tex.h" #include "resources.h" +#include <stdint.h>
static int has_2d_dxt1, has_2d_dxt3, has_2d_dxt5, has_cube_dxt5, has_3d_dxt3;
@@ -146,6 +147,92 @@ static inline void expect_vec4_(unsigned int line, const D3DXVECTOR4 *expected, got->x, got->y, got->z, got->w); }
+#define check_image_info(info, width, height, depth, mip_levels, format, resource_type, image_file_format, wine_todo) \ + check_image_info_(__LINE__, info, width, height, depth, mip_levels, format, resource_type, image_file_format, \ + wine_todo) +static inline void check_image_info_(uint32_t line, const D3DXIMAGE_INFO *info, uint32_t width, uint32_t height, + uint32_t depth, uint32_t mip_levels, D3DFORMAT format, D3DRESOURCETYPE resource_type, + D3DXIMAGE_FILEFORMAT image_file_format, BOOL wine_todo) +{ + const D3DXIMAGE_INFO expected_info = { width, height, depth, mip_levels, format, resource_type, 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->MipLevels != mip_levels) + ok_(__FILE__, line)(info->MipLevels == mip_levels, "Expected mip_levels %u, got %u.\n", mip_levels, + info->MipLevels); + ok_(__FILE__, line)(info->Format == format, "Expected texture format %d, got %d.\n", format, info->Format); + ok_(__FILE__, line)(info->ResourceType == resource_type, "Expected resource_type %d, got %d.\n", resource_type, + info->ResourceType); + ok_(__FILE__, line)(info->ImageFileFormat == image_file_format, "Expected image_file_format %d, got %d.\n", + image_file_format, info->ImageFileFormat); +} + +#define check_texture_level_desc(tex, level, format, usage, pool, multi_sample_type, multi_sample_quality, width, \ + height, wine_todo) \ + check_texture_level_desc_(__LINE__, tex, level, format, usage, pool, multi_sample_type, multi_sample_quality, \ + width, height, wine_todo) +static inline void check_texture_level_desc_(uint32_t line, IDirect3DTexture9 *tex, uint32_t level, D3DFORMAT format, + uint32_t usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multi_sample_type, + uint32_t multi_sample_quality, uint32_t width, uint32_t height, BOOL wine_todo) +{ + const D3DSURFACE_DESC expected_desc = { format, D3DRTYPE_SURFACE, usage, pool, multi_sample_type, + multi_sample_quality, width, height }; + D3DSURFACE_DESC desc; + BOOL matched; + HRESULT hr; + + hr = IDirect3DTexture9_GetLevelDesc(tex, level, &desc); + todo_wine_if(wine_todo && FAILED(hr)) + ok_(__FILE__, line)(hr == S_OK, "Failed to get texture level desc with hr %#lx.\n", hr); + if (FAILED(hr)) + return; + + matched = !memcmp(&expected_desc, &desc, sizeof(desc)); + todo_wine_if(wine_todo) ok_(__FILE__, line)(matched, "Got unexpected surface desc values.\n"); + if (matched) + return; + + todo_wine_if(wine_todo && desc.Format != format) + ok_(__FILE__, line)(desc.Format == format, "Expected surface format %d, got %d.\n", format, desc.Format); + ok_(__FILE__, line)(desc.Type == D3DRTYPE_SURFACE, "Expected D3DRTYPE_SURFACE, got %d.\n", desc.Type); + todo_wine_if(wine_todo && desc.Usage != usage) + ok_(__FILE__, line)(desc.Usage == usage, "Expected usage %u, got %lu.\n", usage, desc.Usage); + todo_wine_if(wine_todo && desc.Pool != pool) + ok_(__FILE__, line)(desc.Pool == pool, "Expected pool %d, got %d.\n", pool, desc.Pool); + todo_wine_if(wine_todo && desc.MultiSampleType != multi_sample_type) + ok_(__FILE__, line)(desc.MultiSampleType == multi_sample_type, "Expected multi sample type %d, got %d.\n", + multi_sample_type, desc.MultiSampleType); + todo_wine_if(wine_todo && desc.MultiSampleQuality != multi_sample_quality) + ok_(__FILE__, line)(desc.MultiSampleQuality == multi_sample_quality, "Expected multi sample quality %u, got %lu.\n", + multi_sample_quality, desc.MultiSampleQuality); + todo_wine_if(wine_todo && desc.Width != width) + ok_(__FILE__, line)(desc.Width == width, "Expected width %u, got %u.\n", width, desc.Width); + todo_wine_if(wine_todo && desc.Height != height) + ok_(__FILE__, line)(desc.Height == height, "Expected height %u, got %u.\n", height, desc.Height); +} + +#define check_texture_mip_levels(tex, expected_mip_levels, wine_todo) \ + check_texture_mip_levels_(__LINE__, ((IDirect3DBaseTexture9 *)tex), expected_mip_levels, wine_todo) +static inline void check_texture_mip_levels_(uint32_t line, IDirect3DBaseTexture9 *tex, uint32_t expected_mip_levels, + BOOL wine_todo) +{ + uint32_t mip_levels = IDirect3DBaseTexture9_GetLevelCount(tex); + + todo_wine_if(wine_todo) ok_(__FILE__, line)(mip_levels == expected_mip_levels, "Got miplevels %u, expected %u.\n", + mip_levels, expected_mip_levels); +} + static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) { unsigned int diff = x > y ? x - y : y - x; @@ -1936,6 +2023,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) IDirect3DTexture9 *texture; unsigned int miplevels; IDirect3DSurface9 *surface; + D3DXIMAGE_INFO img_info; D3DSURFACE_DESC desc;
hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, @@ -2056,6 +2144,50 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) ok(desc.Format == D3DFMT_L8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_L8); IDirect3DSurface9_Release(surface); IDirect3DTexture9_Release(texture); + + /* Test values returned in the D3DXIMAGE_INFO structure. */ + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(0, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + check_texture_mip_levels(texture, 2, FALSE); + check_image_info(&img_info, 2, 2, 1, 2, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE); + check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE); + check_texture_level_desc(texture, 1, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE); + + IDirect3DTexture9_Release(texture); + + /* + * The values returned in the D3DXIMAGE_INFO structure represent the mip + * level the texture data was retrieved from, i.e if we skip the first mip + * level, we will get the values of the second mip level. + */ + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(1, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + check_texture_mip_levels(texture, 1, FALSE); + check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, TRUE); + check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE); + + IDirect3DTexture9_Release(texture); + + /* + * Request skipping 3 mip levels in a file that only has 2 mip levels. In this + * case, it stops at the final mip level. + */ + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(3, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + check_texture_mip_levels(texture, 1, TRUE); + check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, TRUE); + check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, TRUE); + + IDirect3DTexture9_Release(texture); }
static void test_D3DXCreateCubeTextureFromFileInMemory(IDirect3DDevice9 *device)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/texture.c | 336 +++++++++++++++++++++++++++++++++- 1 file changed, 333 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 463f0190bb6..b099365150e 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -128,6 +128,91 @@ static const unsigned char png_grayscale[] = 0x60, 0x82 };
+/* + * 4x4x4 24-bit volume dds, 3 mipmaps. Level 0 is red, level 1 is green, level 2 is + * blue. + */ +static const BYTE dds_volume_24bit_4_4_4[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x0f,0x10,0x82,0x00,0x04,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, + 0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0x00 +}; + +/* + * 4x4x4 DXT3 volume dds. 3 mipmaps. Level 0 is red, level 1 is green, level 2 is + * blue. + */ +static const BYTE dds_volume_dxt3_4_4_4[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x8a,0x00,0x04,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, + 0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0x00,0xf8,0xaa,0xaa,0xaa,0xaa, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x07,0xe0,0x07,0xaa,0xaa,0xaa,0xaa, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x07,0xe0,0x07,0xaa,0xaa,0xaa,0xaa, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x1f,0x00,0xaa,0xaa,0xaa,0xaa, +}; + +/* + * 8x8 24-bit dds, 4 mipmaps. Level 0 is red, level 1 is green, level 2 is + * blue, and level 3 is black. + */ +static const BYTE dds_24bit_8_8[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x0a,0x00,0x08,0x00,0x00,0x00, + 0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff, + 0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00, + 0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00 +}; + #define ADMITTED_ERROR 0.0001f
static inline float relative_error(float expected, float got) @@ -248,6 +333,88 @@ static BOOL compare_color(DWORD c1, DWORD c2, BYTE max_diff) && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); }
+struct surface_readback +{ + IDirect3DSurface9 *surface; + D3DLOCKED_RECT locked_rect; +}; + +static uint32_t get_readback_color(struct surface_readback *rb, uint32_t x, uint32_t y) +{ + return rb->locked_rect.pBits + ? ((uint32_t *)rb->locked_rect.pBits)[y * rb->locked_rect.Pitch / sizeof(uint32_t) + x] : 0xdeadbeef; +} + +static void release_surface_readback(struct surface_readback *rb) +{ + HRESULT hr; + + if (!rb->surface) + return; + if (rb->locked_rect.pBits && FAILED(hr = IDirect3DSurface9_UnlockRect(rb->surface))) + trace("Can't unlock the readback surface, hr %#lx.\n", hr); + IDirect3DSurface9_Release(rb->surface); +} + +static void get_texture_surface_readback(IDirect3DDevice9 *device, IDirect3DTexture9 *texture, uint32_t mip_level, + struct surface_readback *rb) +{ + IDirect3DSurface9 *surface; + D3DSURFACE_DESC desc; + HRESULT hr; + + memset(rb, 0, sizeof(*rb)); + hr = IDirect3DTexture9_GetSurfaceLevel(texture, mip_level, &surface); + if (FAILED(hr)) + { + trace("Failed to get surface for mip level %d, hr %#lx.\n", mip_level, hr); + return; + } + + hr = IDirect3DSurface9_GetDesc(surface, &desc); + if (FAILED(hr)) + { + trace("Failed to get surface description, hr %#lx.\n", hr); + goto exit; + } + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, + &rb->surface, NULL); + if (FAILED(hr)) + { + trace("Can't create the readback surface, hr %#lx.\n", hr); + goto exit; + } + + hr = D3DXLoadSurfaceFromSurface(rb->surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_NONE, 0); + if (FAILED(hr)) + { + trace("Can't load the readback surface, hr %#lx.\n", hr); + goto exit; + } + + hr = IDirect3DSurface9_LockRect(rb->surface, &rb->locked_rect, NULL, D3DLOCK_READONLY); + if (FAILED(hr)) + trace("Can't lock the readback surface, hr %#lx.\n", hr); + +exit: + IDirect3DSurface9_Release(surface); + if (FAILED(hr)) + { + if (rb->surface) + IDirect3DSurface9_Release(rb->surface); + rb->surface = NULL; + } +} + +#define check_readback_pixel_4bpp(rb, x, y, color, todo) _check_readback_pixel_4bpp(__LINE__, rb, x, y, color, todo) +static inline void _check_readback_pixel_4bpp(uint32_t line, struct surface_readback *rb, uint32_t x, + uint32_t y, uint32_t expected_color, BOOL todo) +{ + uint32_t color = get_readback_color(rb, x, y); + todo_wine_if(todo) ok_(__FILE__, line)(color == expected_color, "Got color 0x%08x, expected 0x%08x.\n", color, expected_color); +} + static BOOL is_autogenmipmap_supported(IDirect3DDevice9 *device, D3DRESOURCETYPE resource_type) { HRESULT hr; @@ -1763,6 +1930,10 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; + static const uint32_t dds_volume_dxt3_4_4_4_expected_uncompressed[] = + { + 0xffff0000, 0xff00ff00, 0xff0000ff, + }; IDirect3DSurface9 *surface, *uncompressed_surface; IDirect3DTexture9 *texture; D3DLOCKED_RECT lock_rect; @@ -2012,16 +2183,69 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) ok(desc.Format == D3DFMT_A8R8G8B8, "Unexpected texture format %#x.\n", desc.Format); skip("D3DFMT_DXT3 volume textures are not supported, skipping a test.\n"); } - /* The lower texture levels are apparently generated by filtering the level 0 surface - * I.e. following levels from the file are ignored. */ + + IDirect3DTexture9_Release(texture); + + /* + * All mip levels are pulled from the texture file, even in the case of a + * volume texture file. + */ + hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_dxt3_4_4_4, sizeof(dds_volume_dxt3_4_4_4), &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + check_texture_mip_levels(texture, 3, TRUE); + if (has_2d_dxt3) + { + struct surface_readback surface_rb; + uint32_t mip_level; + + check_texture_level_desc(texture, 0, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 4, 4, FALSE); + check_texture_level_desc(texture, 1, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 2, 2, TRUE); + check_texture_level_desc(texture, 2, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 1, 1, TRUE); + for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level) + { + const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level]; + BOOL todo = !!mip_level; + uint32_t x, y; + + IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); + get_texture_surface_readback(device, texture, mip_level, &surface_rb); + for (y = 0; y < desc.Height; ++y) + { + for (x = 0; x < desc.Width; ++x) + { + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + } + } + release_surface_readback(&surface_rb); + } + } + else + { + check_texture_level_desc(texture, 0, D3DFMT_A8R8G8B8, 0, D3DPOOL_MANAGED, 0, 0, 4, 4, FALSE); + skip("D3DFMT_DXT3 textures are not supported, skipping a test.\n"); + } + IDirect3DTexture9_Release(texture); }
static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) { + static const uint32_t dds_24bit_8_8_expected[] = + { + 0xffff0000, 0xff00ff00, 0xff0000ff, 0xff000000, + }; + static const uint32_t dds_volume_24bit_4_4_4_expected[] = + { + 0xffff0000, 0xff00ff00, 0xff0000ff, + }; + static const uint32_t dds_volume_dxt3_4_4_4_expected_uncompressed[] = + { + 0xffff0000, 0xff00ff00, 0xff0000ff, + }; HRESULT hr; + struct surface_readback surface_rb; + uint32_t miplevels, mip_level; IDirect3DTexture9 *texture; - unsigned int miplevels; IDirect3DSurface9 *surface; D3DXIMAGE_INFO img_info; D3DSURFACE_DESC desc; @@ -2188,6 +2412,112 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, TRUE);
IDirect3DTexture9_Release(texture); + + /* + * Load multiple mip levels from a file and check the resulting pixel + * values. + */ + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + check_texture_mip_levels(texture, 4, FALSE); + check_image_info(&img_info, 8, 8, 1, 4, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE); + check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 8, 8, FALSE); + check_texture_level_desc(texture, 1, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE); + check_texture_level_desc(texture, 2, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE); + check_texture_level_desc(texture, 3, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE); + + for (mip_level = 0; mip_level < ARRAY_SIZE(dds_24bit_8_8_expected); ++mip_level) + { + const uint32_t expected_color = dds_24bit_8_8_expected[mip_level]; + uint32_t x, y; + + IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); + get_texture_surface_readback(device, texture, mip_level, &surface_rb); + for (y = 0; y < desc.Height; ++y) + { + for (x = 0; x < desc.Width; ++x) + { + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE); + } + } + release_surface_readback(&surface_rb); + } + + IDirect3DTexture9_Release(texture); + + /* Volume DDS with mips into regular texture tests. */ + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_volume_24bit_4_4_4, sizeof(dds_volume_24bit_4_4_4), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + check_texture_mip_levels(texture, 3, FALSE); + check_image_info(&img_info, 4, 4, 4, 3, D3DFMT_R8G8B8, D3DRTYPE_VOLUMETEXTURE, D3DXIFF_DDS, FALSE); + check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE); + check_texture_level_desc(texture, 1, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE); + check_texture_level_desc(texture, 2, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE); + + for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_24bit_4_4_4_expected); ++mip_level) + { + const uint32_t expected_color = dds_volume_24bit_4_4_4_expected[mip_level]; + BOOL todo = !!mip_level; + uint32_t x, y; + + IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); + get_texture_surface_readback(device, texture, mip_level, &surface_rb); + for (y = 0; y < desc.Height; ++y) + { + for (x = 0; x < desc.Width; ++x) + { + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + } + } + release_surface_readback(&surface_rb); + } + + IDirect3DTexture9_Release(texture); + + /* DXT3 volume DDS with mips into a regular texture. */ + if (has_2d_dxt3) + { + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_volume_dxt3_4_4_4, sizeof(dds_volume_dxt3_4_4_4), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + check_texture_mip_levels(texture, 3, TRUE); + check_image_info(&img_info, 4, 4, 4, 3, D3DFMT_DXT3, D3DRTYPE_VOLUMETEXTURE, D3DXIFF_DDS, FALSE); + check_texture_level_desc(texture, 0, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE); + check_texture_level_desc(texture, 1, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, TRUE); + check_texture_level_desc(texture, 2, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, TRUE); + + for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level) + { + const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level]; + BOOL todo = !!mip_level; + uint32_t x, y; + + IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); + get_texture_surface_readback(device, texture, mip_level, &surface_rb); + for (y = 0; y < desc.Height; ++y) + { + for (x = 0; x < desc.Width; ++x) + { + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + } + } + release_surface_readback(&surface_rb); + } + + IDirect3DTexture9_Release(texture); + } + else + { + skip("D3DFMT_DXT3 textures are not supported, skipping tests.\n"); + } }
static void test_D3DXCreateCubeTextureFromFileInMemory(IDirect3DDevice9 *device)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/texture.c | 67 +++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 52cfb1e8c34..a99a7b6252b 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -569,9 +569,8 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi { BOOL dynamic_texture, format_specified = FALSE; unsigned int loaded_miplevels, skip_levels; + IDirect3DTexture9 *staging_tex, *tex; IDirect3DSurface9 *surface; - IDirect3DTexture9 **texptr; - IDirect3DTexture9 *buftex; D3DXIMAGE_INFO imginfo; D3DCAPS9 caps; HRESULT hr; @@ -586,11 +585,11 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi if (!device || !texture || !srcdata || !srcdatasize) return D3DERR_INVALIDCALL;
+ staging_tex = tex = *texture = NULL; hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo); if (FAILED(hr)) { FIXME("Unrecognized file format, returning failure.\n"); - *texture = NULL; return hr; }
@@ -652,8 +651,7 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi if (FAILED(hr)) { FIXME("Couldn't find suitable texture parameters.\n"); - *texture = NULL; - return hr; + goto err; }
if (colorkey && !format_specified) @@ -667,79 +665,84 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi }
if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps))) - return D3DERR_INVALIDCALL; + { + hr = D3DERR_INVALIDCALL; + goto err; + }
/* Create the to-be-filled texture */ dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC); if (pool == D3DPOOL_DEFAULT && !dynamic_texture) { - hr = D3DXCreateTexture(device, width, height, miplevels, 0, format, D3DPOOL_SYSTEMMEM, &buftex); - texptr = &buftex; + TRACE("Creating staging texture.\n"); + hr = D3DXCreateTexture(device, width, height, miplevels, 0, format, D3DPOOL_SYSTEMMEM, &staging_tex); + tex = staging_tex; } else { - hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture); - texptr = texture; + hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, &tex); }
if (FAILED(hr)) { FIXME("Texture creation failed.\n"); - *texture = NULL; - return hr; + goto err; }
TRACE("Texture created correctly. Now loading the texture data into it.\n"); if (imginfo.ImageFileFormat != D3DXIFF_DDS) { - IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface); + IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surface); hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL); IDirect3DSurface9_Release(surface); - loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels); + loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(tex), imginfo.MipLevels); } else { - hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo, skip_levels, + hr = load_texture_from_dds(tex, srcdata, palette, filter, colorkey, &imginfo, skip_levels, &loaded_miplevels); }
if (FAILED(hr)) { FIXME("Texture loading failed.\n"); - IDirect3DTexture9_Release(*texptr); - *texture = NULL; - return hr; + goto err; }
- hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter); + hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)tex, palette, loaded_miplevels - 1, mipfilter); if (FAILED(hr)) { FIXME("Texture filtering failed.\n"); - IDirect3DTexture9_Release(*texptr); - *texture = NULL; - return hr; + goto err; }
/* Move the data to the actual texture if necessary */ - if (texptr == &buftex) + if (staging_tex) { hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture); - if (FAILED(hr)) - { - IDirect3DTexture9_Release(buftex); - *texture = NULL; - return hr; - } + goto err;
- IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture)); - IDirect3DTexture9_Release(buftex); + IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)staging_tex, (IDirect3DBaseTexture9 *)(*texture)); + IDirect3DTexture9_Release(staging_tex); + } + else + { + *texture = tex; }
if (srcinfo) *srcinfo = imginfo;
- return D3D_OK; + return hr; + +err: + if (staging_tex) + IDirect3DTexture9_Release(staging_tex); + else if (tex) + IDirect3DTexture9_Release(tex); + + return hr; }
HRESULT WINAPI D3DXCreateTextureFromFileInMemory(struct IDirect3DDevice9 *device,
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 5 +++++ dlls/d3dx9_36/surface.c | 9 ++++----- dlls/d3dx9_36/texture.c | 17 +++++++++++++++-- 3 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 001a7f26f4f..5c9d1a0ddad 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -122,6 +122,11 @@ struct d3dx_image D3DXIMAGE_FILEFORMAT image_file_format; };
+HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t flags); +void d3dx_image_cleanup(struct d3dx_image *image); +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels); +void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image); + struct d3dx_include_from_file { ID3DXInclude ID3DXInclude_iface; diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index dd84528a0d5..69eb9d3058b 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1132,8 +1132,7 @@ exit: return hr; }
-static HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, - struct d3dx_image *image, uint32_t flags) +HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t flags) { if (!src_data || !src_data_size || !image) return D3DERR_INVALIDCALL; @@ -1145,13 +1144,13 @@ static HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, return d3dx_initialize_image_from_wic(src_data, src_data_size, image, flags); }
-static void d3dx_image_cleanup(struct d3dx_image *image) +void d3dx_image_cleanup(struct d3dx_image *image) { free(image->image_buf); free(image->palette); }
-static HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels) +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels) { uint32_t row_pitch, slice_pitch; RECT unaligned_rect; @@ -1168,7 +1167,7 @@ static HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixel return D3D_OK; }
-static void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image) +void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image) { info->ImageFileFormat = image->image_file_format; info->Width = image->width; diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index a99a7b6252b..0755e7cf4f6 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -571,6 +571,7 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi unsigned int loaded_miplevels, skip_levels; IDirect3DTexture9 *staging_tex, *tex; IDirect3DSurface9 *surface; + struct d3dx_image image; D3DXIMAGE_INFO imginfo; D3DCAPS9 caps; HRESULT hr; @@ -586,13 +587,15 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi return D3DERR_INVALIDCALL;
staging_tex = tex = *texture = NULL; - hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo); + hr = d3dx_image_init(srcdata, srcdatasize, &image, 0); if (FAILED(hr)) { FIXME("Unrecognized file format, returning failure.\n"); return hr; }
+ d3dximage_info_from_d3dx_image(&imginfo, &image); + /* handle default values */ if (width == 0 || width == D3DX_DEFAULT_NONPOW2) width = imginfo.Width; @@ -692,8 +695,16 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi TRACE("Texture created correctly. Now loading the texture data into it.\n"); if (imginfo.ImageFileFormat != D3DXIFF_DDS) { + const RECT src_rect = { 0, 0, imginfo.Width, imginfo.Height }; + struct d3dx_pixels pixels; + + hr = d3dx_image_get_pixels(&image, &pixels); + if (FAILED(hr)) + goto err; + IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surface); - hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL); + hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels.data, imginfo.Format, + pixels.row_pitch, pixels.palette, &src_rect, filter, colorkey); IDirect3DSurface9_Release(surface); loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(tex), imginfo.MipLevels); } @@ -731,12 +742,14 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi *texture = tex; }
+ d3dx_image_cleanup(&image); if (srcinfo) *srcinfo = imginfo;
return hr;
err: + d3dx_image_cleanup(&image); if (staging_tex) IDirect3DTexture9_Release(staging_tex); else if (tex)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 4 +--- dlls/d3dx9_36/surface.c | 36 +++++++++++++++++------------------ 2 files changed, 18 insertions(+), 22 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 5c9d1a0ddad..52475aa3025 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -104,9 +104,7 @@ struct d3dx_image D3DRESOURCETYPE resource_type; D3DFORMAT format;
- uint32_t width; - uint32_t height; - uint32_t depth; + struct volume size; uint32_t mip_levels;
BYTE *pixels; diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 69eb9d3058b..5fe0d0416c1 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -743,9 +743,7 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src return D3DXERR_INVALIDDATA;
TRACE("File type is DDS.\n"); - image->width = header->width; - image->height = header->height; - image->depth = 1; + set_volume_struct(&image->size, header->width, header->height, 1); image->mip_levels = header->miplevels ? header->miplevels : 1; image->format = dds_pixel_format_to_d3dformat(&header->pixel_format);
@@ -755,7 +753,7 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src TRACE("Pixel format is %#x.\n", image->format); if (header->caps2 & DDS_CAPS2_VOLUME) { - image->depth = header->depth; + image->size.depth = header->depth; image->resource_type = D3DRTYPE_VOLUMETEXTURE; } else if (header->caps2 & DDS_CAPS2_CUBEMAP) @@ -773,8 +771,8 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src else image->resource_type = D3DRTYPE_TEXTURE;
- expected_src_data_size = calculate_dds_file_size(image->format, image->width, image->height, - image->depth, image->mip_levels, faces); + expected_src_data_size = calculate_dds_file_size(image->format, image->size.width, image->size.height, + image->size.depth, image->mip_levels, faces); 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); @@ -863,18 +861,18 @@ static BOOL image_is_argb(IWICBitmapFrameDecode *frame, struct d3dx_image *image && image->image_file_format != D3DXIFF_TGA)) return FALSE;
- size = image->width * image->height * 4; + size = image->size.width * image->size.height * 4; if (!(buffer = malloc(size))) return FALSE;
- if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, image->width * 4, size, buffer))) + if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, image->size.width * 4, size, buffer))) { ERR("Failed to copy pixels, hr %#lx.\n", hr); free(buffer); return FALSE; }
- for (i = 0; i < image->width * image->height; ++i) + for (i = 0; i < image->size.width * image->size.height; ++i) { if (buffer[i * 4 + 3]) { @@ -952,7 +950,7 @@ static HRESULT d3dx_image_wic_frame_decode(struct d3dx_image *image, HRESULT hr;
fmt_desc = get_format_info(image->format); - hr = d3dx_calculate_pixels_size(image->format, image->width, image->height, &row_pitch, &slice_pitch); + hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch); if (FAILED(hr)) return hr;
@@ -1088,7 +1086,7 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src if (FAILED(hr)) goto exit;
- hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &image->width, &image->height); + hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &image->size.width, &image->size.height); if (FAILED(hr)) goto exit;
@@ -1113,7 +1111,7 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src goto exit; }
- image->depth = 1; + image->size.depth = 1; image->mip_levels = 1; image->resource_type = D3DRTYPE_TEXTURE;
@@ -1156,13 +1154,13 @@ HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixe RECT unaligned_rect; HRESULT hr = S_OK;
- hr = d3dx_calculate_pixels_size(image->format, image->width, image->height, &row_pitch, &slice_pitch); + hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch); if (FAILED(hr)) return hr;
- SetRect(&unaligned_rect, 0, 0, image->width, image->height); - set_d3dx_pixels(pixels, image->pixels, row_pitch, slice_pitch, image->palette, image->width, image->height, - image->depth, &unaligned_rect); + SetRect(&unaligned_rect, 0, 0, image->size.width, image->size.height); + set_d3dx_pixels(pixels, image->pixels, row_pitch, slice_pitch, image->palette, image->size.width, image->size.height, + image->size.depth, &unaligned_rect);
return D3D_OK; } @@ -1170,9 +1168,9 @@ HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixe void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image) { info->ImageFileFormat = image->image_file_format; - info->Width = image->width; - info->Height = image->height; - info->Depth = image->depth; + info->Width = image->size.width; + info->Height = image->size.height; + info->Depth = image->size.depth; info->MipLevels = image->mip_levels; info->Format = image->format; info->ResourceType = image->resource_type;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 8 +-- dlls/d3dx9_36/surface.c | 101 +++++++++++++++++++--------------- dlls/d3dx9_36/tests/texture.c | 11 ++-- dlls/d3dx9_36/texture.c | 20 +------ 4 files changed, 70 insertions(+), 70 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 52475aa3025..07b4aff5137 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -120,7 +120,8 @@ struct d3dx_image D3DXIMAGE_FILEFORMAT image_file_format; };
-HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t flags); +HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, + uint32_t starting_mip_level, uint32_t flags); void d3dx_image_cleanup(struct d3dx_image *image); HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels); void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image); @@ -171,9 +172,8 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette);
-HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette, - DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels, - unsigned int *loaded_miplevels); +HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, + const struct d3dx_image *image, unsigned int *loaded_miplevels); HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info); HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 5fe0d0416c1..45277e28109 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -437,6 +437,20 @@ static HRESULT d3dformat_to_dds_pixel_format(struct dds_pixel_format *pixel_form return E_NOTIMPL; }
+static void d3dx_get_next_mip_level_size(struct volume *size) +{ + size->width = max(size->width / 2, 1); + size->height = max(size->height / 2, 1); + size->depth = max(size->depth / 2, 1); +} + +static const char *debug_volume(const struct volume *volume) +{ + if (!volume) + return "(null)"; + return wine_dbg_sprintf("(%ux%ux%u)", volume->width, volume->height, volume->depth); +} + static HRESULT d3dx_calculate_pixels_size(D3DFORMAT format, uint32_t width, uint32_t height, uint32_t *pitch, uint32_t *size) { @@ -570,9 +584,8 @@ HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *d row_pitch, slice_pitch, NULL, src_box, filter, color_key); }
-HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette, - DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels, - unsigned int *loaded_miplevels) +HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, + const struct d3dx_image *image, unsigned int *loaded_miplevels) { HRESULT hr; RECT src_rect; @@ -580,49 +593,29 @@ HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, UINT mip_level; UINT mip_levels; UINT mip_level_size; - UINT width, height; IDirect3DSurface9 *surface; - const struct dds_header *header = src_data; - const BYTE *pixels = (BYTE *)(header + 1); - - /* Loading a cube texture as a simple texture is also supported - * (only first face texture is taken). Same with volume textures. */ - if ((src_info->ResourceType != D3DRTYPE_TEXTURE) - && (src_info->ResourceType != D3DRTYPE_CUBETEXTURE) - && (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE)) - { - WARN("Trying to load a %u resource as a 2D texture, returning failure.\n", src_info->ResourceType); - return D3DXERR_INVALIDDATA; - } + const BYTE *pixels = image->pixels; + struct volume mip_size = image->size;
- width = src_info->Width; - height = src_info->Height; - mip_levels = min(src_info->MipLevels, IDirect3DTexture9_GetLevelCount(texture)); - if (src_info->ResourceType == D3DRTYPE_VOLUMETEXTURE) - mip_levels = 1; - for (mip_level = 0; mip_level < mip_levels + skip_levels; ++mip_level) + mip_levels = min(image->mip_levels, IDirect3DTexture9_GetLevelCount(texture)); + for (mip_level = 0; mip_level < mip_levels; ++mip_level) { - hr = d3dx_calculate_pixels_size(src_info->Format, width, height, &src_pitch, &mip_level_size); + hr = d3dx_calculate_pixels_size(image->format, mip_size.width, mip_size.height, &src_pitch, &mip_level_size); if (FAILED(hr)) return hr;
- if (mip_level >= skip_levels) - { - SetRect(&src_rect, 0, 0, width, height); - - IDirect3DTexture9_GetSurfaceLevel(texture, mip_level - skip_levels, &surface); - hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, src_info->Format, src_pitch, - NULL, &src_rect, filter, color_key); - IDirect3DSurface9_Release(surface); - if (FAILED(hr)) - return hr; - } + SetRect(&src_rect, 0, 0, mip_size.width, mip_size.height); + IDirect3DTexture9_GetSurfaceLevel(texture, mip_level, &surface); + hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, image->format, src_pitch, + NULL, &src_rect, filter, color_key); + IDirect3DSurface9_Release(surface); + if (FAILED(hr)) + return hr;
- pixels += mip_level_size; - width = max(1, width / 2); - height = max(1, height / 2); + pixels += mip_level_size * mip_size.depth; + d3dx_get_next_mip_level_size(&mip_size); }
- *loaded_miplevels = mip_levels - skip_levels; + *loaded_miplevels = mip_levels;
return D3D_OK; } @@ -733,7 +726,7 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co }
static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size, - struct d3dx_image *image) + struct d3dx_image *image, uint32_t starting_mip_level) { const struct dds_header *header = src_data; uint32_t expected_src_data_size; @@ -781,6 +774,27 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
image->pixels = ((BYTE *)src_data) + sizeof(*header); image->image_file_format = D3DXIFF_DDS; + if (starting_mip_level && (image->mip_levels > 1)) + { + uint32_t i, row_pitch, slice_pitch, initial_mip_levels; + const struct volume initial_size = image->size; + + initial_mip_levels = image->mip_levels; + for (i = 0; i < starting_mip_level; i++) + { + d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch); + + image->pixels += slice_pitch * image->size.depth; + d3dx_get_next_mip_level_size(&image->size); + if (--image->mip_levels == 1) + break; + } + + TRACE("Requested starting mip level %u, actual starting mip level is %u (of %u total in image).\n", + starting_mip_level, (initial_mip_levels - image->mip_levels), initial_mip_levels); + TRACE("Original dimensions %s, new dimensions %s.\n", debug_volume(&initial_size), debug_volume(&image->size)); + } + return D3D_OK; }
@@ -1130,14 +1144,15 @@ exit: return hr; }
-HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t flags) +HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, + uint32_t starting_mip_level, uint32_t flags) { if (!src_data || !src_data_size || !image) return D3DERR_INVALIDCALL;
memset(image, 0, sizeof(*image)); if ((src_data_size >= 4) && !memcmp(src_data, "DDS ", 4)) - return d3dx_initialize_image_from_dds(src_data, src_data_size, image); + return d3dx_initialize_image_from_dds(src_data, src_data_size, image, starting_mip_level);
return d3dx_initialize_image_from_wic(src_data, src_data_size, image, flags); } @@ -1210,7 +1225,7 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, if (!info) return D3D_OK;
- hr = d3dx_image_init(data, datasize, &image, D3DX_IMAGE_INFO_ONLY); + hr = d3dx_image_init(data, datasize, &image, 0, D3DX_IMAGE_INFO_ONLY); if (FAILED(hr)) { TRACE("Invalid or unsupported image file\n"); return D3DXERR_INVALIDDATA; @@ -1359,7 +1374,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, if (!pDestSurface || !pSrcData || !SrcDataSize) return D3DERR_INVALIDCALL;
- hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0); + hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0, 0); if (FAILED(hr)) return D3DXERR_INVALIDDATA;
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index b099365150e..04dab09c33c 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2393,7 +2393,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
check_texture_mip_levels(texture, 1, FALSE); - check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, TRUE); + check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE); check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
IDirect3DTexture9_Release(texture); @@ -2407,9 +2407,9 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(3, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
- check_texture_mip_levels(texture, 1, TRUE); - check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, TRUE); - check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, TRUE); + check_texture_mip_levels(texture, 1, FALSE); + check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE); + check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
IDirect3DTexture9_Release(texture);
@@ -2463,7 +2463,6 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_24bit_4_4_4_expected); ++mip_level) { const uint32_t expected_color = dds_volume_24bit_4_4_4_expected[mip_level]; - BOOL todo = !!mip_level; uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2472,7 +2471,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE); } } release_surface_readback(&surface_rb); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 0755e7cf4f6..f20a4b7c3db 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -587,7 +587,8 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi return D3DERR_INVALIDCALL;
staging_tex = tex = *texture = NULL; - hr = d3dx_image_init(srcdata, srcdatasize, &image, 0); + skip_levels = mipfilter != D3DX_DEFAULT ? mipfilter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0; + hr = d3dx_image_init(srcdata, srcdatasize, &image, skip_levels, 0); if (FAILED(hr)) { FIXME("Unrecognized file format, returning failure.\n"); @@ -634,20 +635,6 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi miplevels = imginfo.MipLevels; }
- skip_levels = mipfilter != D3DX_DEFAULT ? mipfilter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0; - if (skip_levels && imginfo.MipLevels > skip_levels) - { - TRACE("Skipping the first %u (of %u) levels of a DDS mipmapped texture.\n", - skip_levels, imginfo.MipLevels); - TRACE("Texture level 0 dimensions are %ux%u.\n", imginfo.Width, imginfo.Height); - width >>= skip_levels; - height >>= skip_levels; - miplevels -= skip_levels; - } - else - { - skip_levels = 0; - }
/* Fix up texture creation parameters. */ hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool); @@ -710,8 +697,7 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi } else { - hr = load_texture_from_dds(tex, srcdata, palette, filter, colorkey, &imginfo, skip_levels, - &loaded_miplevels); + hr = load_texture_from_dds(tex, palette, filter, colorkey, &image, &loaded_miplevels); }
if (FAILED(hr))
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/texture.c | 42 +++++++---------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-)
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index f20a4b7c3db..d7d61d1f36c 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -598,43 +598,15 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi d3dximage_info_from_d3dx_image(&imginfo, &image);
/* handle default values */ - if (width == 0 || width == D3DX_DEFAULT_NONPOW2) - width = imginfo.Width; - - if (height == 0 || height == D3DX_DEFAULT_NONPOW2) - height = imginfo.Height; - - if (width == D3DX_DEFAULT) - width = make_pow2(imginfo.Width); - - if (height == D3DX_DEFAULT) - height = make_pow2(imginfo.Height); - - if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) - format = imginfo.Format; - else - format_specified = TRUE; - - if (width == D3DX_FROM_FILE) - { - width = imginfo.Width; - } + if (!width || width == D3DX_DEFAULT_NONPOW2 || width == D3DX_FROM_FILE || width == D3DX_DEFAULT) + width = (width == D3DX_DEFAULT) ? make_pow2(imginfo.Width) : imginfo.Width; + if (!height || height == D3DX_DEFAULT_NONPOW2 || height == D3DX_FROM_FILE || height == D3DX_DEFAULT) + height = (height == D3DX_DEFAULT) ? make_pow2(imginfo.Height) : imginfo.Height;
- if (height == D3DX_FROM_FILE) - { - height = imginfo.Height; - } - - if (format == D3DFMT_FROM_FILE) - { + format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT); + if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) format = imginfo.Format; - } - - if (miplevels == D3DX_FROM_FILE) - { - miplevels = imginfo.MipLevels; - } - + miplevels = (miplevels == D3DX_FROM_FILE) ? imginfo.MipLevels : miplevels;
/* Fix up texture creation parameters. */ hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 4 +- dlls/d3dx9_36/surface.c | 72 +++++++++++++---------------------- dlls/d3dx9_36/tests/texture.c | 20 +++++----- dlls/d3dx9_36/texture.c | 48 ++++++++++++----------- 4 files changed, 62 insertions(+), 82 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 07b4aff5137..701afffd046 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -123,7 +123,7 @@ struct d3dx_image HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t starting_mip_level, uint32_t flags); void d3dx_image_cleanup(struct d3dx_image *image); -HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels); +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels); void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image);
struct d3dx_include_from_file @@ -172,8 +172,6 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette);
-HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, - const struct d3dx_image *image, unsigned int *loaded_miplevels); HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info); HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 45277e28109..949e2d629cc 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -584,42 +584,6 @@ HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *d row_pitch, slice_pitch, NULL, src_box, filter, color_key); }
-HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, - const struct d3dx_image *image, unsigned int *loaded_miplevels) -{ - HRESULT hr; - RECT src_rect; - UINT src_pitch; - UINT mip_level; - UINT mip_levels; - UINT mip_level_size; - IDirect3DSurface9 *surface; - const BYTE *pixels = image->pixels; - struct volume mip_size = image->size; - - mip_levels = min(image->mip_levels, IDirect3DTexture9_GetLevelCount(texture)); - for (mip_level = 0; mip_level < mip_levels; ++mip_level) - { - hr = d3dx_calculate_pixels_size(image->format, mip_size.width, mip_size.height, &src_pitch, &mip_level_size); - if (FAILED(hr)) return hr; - - SetRect(&src_rect, 0, 0, mip_size.width, mip_size.height); - IDirect3DTexture9_GetSurfaceLevel(texture, mip_level, &surface); - hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, image->format, src_pitch, - NULL, &src_rect, filter, color_key); - IDirect3DSurface9_Release(surface); - if (FAILED(hr)) - return hr; - - pixels += mip_level_size * mip_size.depth; - d3dx_get_next_mip_level_size(&mip_size); - } - - *loaded_miplevels = mip_levels; - - return D3D_OK; -} - HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info) { @@ -1163,19 +1127,37 @@ void d3dx_image_cleanup(struct d3dx_image *image) free(image->palette); }
-HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels) +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels) { - uint32_t row_pitch, slice_pitch; + const BYTE *pixels_ptr = image->pixels; + struct volume mip_size = image->size; + uint32_t row_pitch, slice_pitch, i; RECT unaligned_rect; HRESULT hr = S_OK;
- hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch); - if (FAILED(hr)) - return hr; + if (mip_level >= image->mip_levels) + { + ERR("Tried to retrieve mip level %u, but image only has %u mip levels.\n", mip_level, image->mip_levels); + return E_FAIL; + } + + slice_pitch = row_pitch = 0; + for (i = 0; i < image->mip_levels; i++) + { + hr = d3dx_calculate_pixels_size(image->format, mip_size.width, mip_size.height, &row_pitch, &slice_pitch); + if (FAILED(hr)) + return hr; + + if (i == mip_level) + break; + + pixels_ptr += slice_pitch * mip_size.depth; + d3dx_get_next_mip_level_size(&mip_size); + }
- SetRect(&unaligned_rect, 0, 0, image->size.width, image->size.height); - set_d3dx_pixels(pixels, image->pixels, row_pitch, slice_pitch, image->palette, image->size.width, image->size.height, - image->size.depth, &unaligned_rect); + SetRect(&unaligned_rect, 0, 0, mip_size.width, mip_size.height); + set_d3dx_pixels(pixels, pixels_ptr, row_pitch, slice_pitch, image->palette, mip_size.width, mip_size.height, + mip_size.depth, &unaligned_rect);
return D3D_OK; } @@ -1384,7 +1366,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, else SetRect(&src_rect, 0, 0, img_info.Width, img_info.Height);
- hr = d3dx_image_get_pixels(&image, &pixels); + hr = d3dx_image_get_pixels(&image, 0, &pixels); if (FAILED(hr)) goto exit;
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 04dab09c33c..4da8f56f834 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2158,7 +2158,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) type = IDirect3DTexture9_GetType(texture); ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected %u.\n", type, D3DRTYPE_TEXTURE); level_count = IDirect3DBaseTexture9_GetLevelCount((IDirect3DBaseTexture9 *)texture); - todo_wine ok(level_count == 3, "Texture has %lu mip levels, 3 expected.\n", level_count); + ok(level_count == 3, "Texture has %lu mip levels, 3 expected.\n", level_count); hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#lx, expected %#lx.\n", hr, D3D_OK); ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width); @@ -2192,19 +2192,18 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) */ hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_dxt3_4_4_4, sizeof(dds_volume_dxt3_4_4_4), &texture); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - check_texture_mip_levels(texture, 3, TRUE); + check_texture_mip_levels(texture, 3, FALSE); if (has_2d_dxt3) { struct surface_readback surface_rb; uint32_t mip_level;
check_texture_level_desc(texture, 0, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 4, 4, FALSE); - check_texture_level_desc(texture, 1, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 2, 2, TRUE); - check_texture_level_desc(texture, 2, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 1, 1, TRUE); + check_texture_level_desc(texture, 1, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 2, 2, FALSE); + check_texture_level_desc(texture, 2, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 1, 1, FALSE); for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level) { const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level]; - BOOL todo = !!mip_level; uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2213,7 +2212,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE); } } release_surface_readback(&surface_rb); @@ -2487,16 +2486,15 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
- check_texture_mip_levels(texture, 3, TRUE); + check_texture_mip_levels(texture, 3, FALSE); check_image_info(&img_info, 4, 4, 4, 3, D3DFMT_DXT3, D3DRTYPE_VOLUMETEXTURE, D3DXIFF_DDS, FALSE); check_texture_level_desc(texture, 0, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE); - check_texture_level_desc(texture, 1, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, TRUE); - check_texture_level_desc(texture, 2, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, TRUE); + check_texture_level_desc(texture, 1, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE); + check_texture_level_desc(texture, 2, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level) { const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level]; - BOOL todo = !!mip_level; uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2505,7 +2503,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE); } } release_surface_readback(&surface_rb); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index d7d61d1f36c..bf4a9e816fd 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -567,10 +567,10 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo, PALETTEENTRY *palette, struct IDirect3DTexture9 **texture) { + const struct pixel_format_desc *src_fmt_desc, *dst_fmt_desc; BOOL dynamic_texture, format_specified = FALSE; - unsigned int loaded_miplevels, skip_levels; + uint32_t loaded_miplevels, skip_levels, i; IDirect3DTexture9 *staging_tex, *tex; - IDirect3DSurface9 *surface; struct d3dx_image image; D3DXIMAGE_INFO imginfo; D3DCAPS9 caps; @@ -619,13 +619,6 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi if (colorkey && !format_specified) format = get_alpha_replacement_format(format);
- if (imginfo.ResourceType == D3DRTYPE_VOLUMETEXTURE - && D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5 && miplevels > 1) - { - FIXME("Generation of mipmaps for compressed volume textures is not implemented yet.\n"); - miplevels = 1; - } - if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps))) { hr = D3DERR_INVALIDCALL; @@ -652,24 +645,33 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi }
TRACE("Texture created correctly. Now loading the texture data into it.\n"); - if (imginfo.ImageFileFormat != D3DXIFF_DDS) + dst_fmt_desc = get_format_info(format); + src_fmt_desc = get_format_info(imginfo.Format); + loaded_miplevels = min(imginfo.MipLevels, IDirect3DTexture9_GetLevelCount(tex)); + for (i = 0; i < loaded_miplevels; i++) { - const RECT src_rect = { 0, 0, imginfo.Width, imginfo.Height }; - struct d3dx_pixels pixels; + struct d3dx_pixels src_pixels, dst_pixels; + D3DSURFACE_DESC dst_surface_desc; + D3DLOCKED_RECT dst_locked_rect; + RECT dst_rect;
- hr = d3dx_image_get_pixels(&image, &pixels); + hr = d3dx_image_get_pixels(&image, i, &src_pixels); if (FAILED(hr)) - goto err; + break;
- IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surface); - hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels.data, imginfo.Format, - pixels.row_pitch, pixels.palette, &src_rect, filter, colorkey); - IDirect3DSurface9_Release(surface); - loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(tex), imginfo.MipLevels); - } - else - { - hr = load_texture_from_dds(tex, palette, filter, colorkey, &image, &loaded_miplevels); + hr = IDirect3DTexture9_LockRect(tex, i, &dst_locked_rect, NULL, 0); + if (FAILED(hr)) + break; + + IDirect3DTexture9_GetLevelDesc(tex, i, &dst_surface_desc); + SetRect(&dst_rect, 0, 0, dst_surface_desc.Width, dst_surface_desc.Height); + set_d3dx_pixels(&dst_pixels, dst_locked_rect.pBits, dst_locked_rect.Pitch, 0, palette, + dst_surface_desc.Width, dst_surface_desc.Height, 1, &dst_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_fmt_desc, &src_pixels, src_fmt_desc, filter, colorkey); + IDirect3DTexture9_UnlockRect(tex, i); + if (FAILED(hr)) + break; }
if (FAILED(hr))
On Thu Jun 13 12:14:16 2024 +0000, Connor McAdams wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/5801/diffs?diff_id=117721&start_sha=479c94a2ea058f883a11a7a84b06f736a99451fa#d291f1fc6edcbc5e0c592d8a4adc268488525828_251_251)
Fixed in the current revision.
On Thu Jun 13 12:14:16 2024 +0000, Connor McAdams wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/5801/diffs?diff_id=117721&start_sha=479c94a2ea058f883a11a7a84b06f736a99451fa#d291f1fc6edcbc5e0c592d8a4adc268488525828_2358_2375)
Fixed in the current revision.
On Thu Jun 13 12:15:49 2024 +0000, Matteo Bruni wrote:
I think it's level 0 red, level 1 green, level 2 blue.
Don't know how this happened, but I fixed it in the current revision. Nice catch :)
On Thu Jun 13 12:14:19 2024 +0000, Connor McAdams wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/5801/diffs?diff_id=117721&start_sha=479c94a2ea058f883a11a7a84b06f736a99451fa#d291f1fc6edcbc5e0c592d8a4adc268488525828_2201_2206)
Changed in the current revision.
On Thu Jun 13 12:14:20 2024 +0000, Connor McAdams wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/5801/diffs?diff_id=117721&start_sha=479c94a2ea058f883a11a7a84b06f736a99451fa#62f9751cd03c180393d0d62f4051f132128d50f3_637_632)
I had considered renaming/calling this a staging texture, but I was a bit hesitant as I wasn't sure if that was a D3D10-11ism and they were considered to be "buffers" for d3d9. Fixed in the current revision. :)
On Wed Jun 12 17:22:54 2024 +0000, Matteo Bruni wrote:
This is fine. I wonder, though, if it wouldn't be nicer to keep a separate path for the error case and avoid those `AddRef()`s. Something like:
return hr; err: if (buf_tex) IDirect3DTexture9_Release(buf_tex); if (tex) IDirect3DTexture9_Release(tex); return hr;
This would require duplicating the `d3dx_image_cleanup(&image);` in both exit paths in the next patch, but maybe that's still nicer overall?
I've changed it to be more in line with what you've posted here, let me know if it's better. :)
On Thu Jun 13 12:14:22 2024 +0000, Connor McAdams wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/5801/diffs?diff_id=117721&start_sha=479c94a2ea058f883a11a7a84b06f736a99451fa#e5891b30c0f0a0d106394089d61a67281f349564_123_123)
I've changed a few different instances of mip/mips with mip_level/mip_levels. Hopefully it's better now.