This is the first step in moving the various D3DXCreateTextureFromFileInMemory functions over to using shared code.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/texture.c | 131 ++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index b0dd3c0c6c3..06fdb130fd1 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,91 @@ 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_(unsigned int 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 %d, got %d.\n", width, info->Width); + todo_wine_if(wine_todo && info->Height != height) + ok_(__FILE__, line)(info->Height == height, "Expected height %d, got %d.\n", height, info->Height); + todo_wine_if(wine_todo && info->Depth != depth) + ok_(__FILE__, line)(info->Depth == depth, "Expected depth %d, got %d.\n", depth, info->Depth); + todo_wine_if(wine_todo && info->MipLevels != mip_levels) + ok_(__FILE__, line)(info->MipLevels == mip_levels, "Expected mip_levels %d, got %d.\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_(unsigned int 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 %d, got %d.\n", width, desc.Width); + todo_wine_if(wine_todo && desc.Height != height) + ok_(__FILE__, line)(desc.Height == height, "Expected height %d, got %d.\n", height, desc.Height); +} + +#define check_texture_mips(tex, expected_mips, wine_todo) \ + check_texture_mips_(__LINE__, ((IDirect3DBaseTexture9 *)tex), expected_mips, wine_todo) +static inline void check_texture_mips_(unsigned int line, IDirect3DBaseTexture9 *tex, uint32_t expected_mips, BOOL wine_todo) +{ + uint32_t mips = IDirect3DBaseTexture9_GetLevelCount(tex); + + todo_wine_if(wine_todo) ok_(__FILE__, line)(mips == expected_mips, "Got miplevels %u, expected %u.\n", mips, + expected_mips); +} + 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 +2022,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 +2143,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, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); + + check_texture_mips(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. + */ + 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, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); + + check_texture_mips(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 mips. In this + * case, it stops at the final mip. + */ + 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, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); + + check_texture_mips(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 | 320 +++++++++++++++++++++++++++++++++- 1 file changed, 317 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 06fdb130fd1..7685992f2b7 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 blue, level 2 is + * green. + */ +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 blue, level 2 is + * green. + */ +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) @@ -247,6 +332,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(unsigned int 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; @@ -2011,16 +2178,57 @@ 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, "D3DXCreateTextureFromFileInMemory returned %#lx, expected %#lx.\n", hr, D3D_OK); + check_texture_mips(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 < 3; ++mip_level) + { + const uint32_t expected_color[3] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; + 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[mip_level], 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) { 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; @@ -2187,6 +2395,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, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); + + check_texture_mips(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 < 4; ++mip_level) + { + const uint32_t expected_color[4] = { 0xffff0000, 0xff00ff00, 0xff0000ff, 0xff000000 }; + 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[mip_level], 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, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); + + check_texture_mips(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 < 3; ++mip_level) + { + const uint32_t expected_color[3] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; + 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[mip_level], 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, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); + + check_texture_mips(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 < 3; ++mip_level) + { + const uint32_t expected_color[3] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; + 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[mip_level], 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..075c45da6ad 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 *buf_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;
+ buf_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 exit; }
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 exit; + }
/* 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; + hr = D3DXCreateTexture(device, width, height, miplevels, 0, format, D3DPOOL_SYSTEMMEM, &buf_tex); + if (SUCCEEDED(hr)) + { + tex = buf_tex; + IDirect3DTexture9_AddRef(buf_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 exit; }
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 exit; }
- 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 exit; }
/* Move the data to the actual texture if necessary */ - if (texptr == &buftex) + if (buf_tex) { hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture); - if (FAILED(hr)) - { - IDirect3DTexture9_Release(buftex); - *texture = NULL; - return hr; - } + goto exit;
- IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture)); - IDirect3DTexture9_Release(buftex); + IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buf_tex, (IDirect3DBaseTexture9 *)(*texture)); + } + else + { + *texture = tex; + IDirect3DTexture9_AddRef(tex); }
if (srcinfo) *srcinfo = imginfo; +exit: + if (buf_tex) + IDirect3DTexture9_Release(buf_tex); + if (tex) + IDirect3DTexture9_Release(tex);
- return D3D_OK; + 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 | 16 ++++++++++++++-- 3 files changed, 23 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 075c45da6ad..021281474e4 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 *buf_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;
buf_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; @@ -695,8 +698,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 exit; + 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); } @@ -737,6 +748,7 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi if (srcinfo) *srcinfo = imginfo; exit: + d3dx_image_cleanup(&image); if (buf_tex) IDirect3DTexture9_Release(buf_tex); if (tex)
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..9b7b6d566a9 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, + 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..97624fec3ba 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -570,9 +570,22 @@ 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) +static void d3dx_get_next_mip_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); +} + +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_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) { 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 && (image->mip_levels > 1)) + { + uint32_t i, row_pitch, slice_pitch, initial_mips; + const struct volume initial_size = image->size; + + initial_mips = image->mip_levels; + for (i = 0; i < starting_mip; 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_size(&image->size); + if (--image->mip_levels == 1) + break; + } + + TRACE("Requested starting mip %u, actual starting mip is %u (of %u total in image).\n", + starting_mip, (initial_mips - image->mip_levels), initial_mips); + 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, + 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);
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 7685992f2b7..b083d5c6151 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2376,7 +2376,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK);
check_texture_mips(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); @@ -2390,9 +2390,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, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK);
- check_texture_mips(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_mips(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);
@@ -2446,7 +2446,6 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) for (mip_level = 0; mip_level < 3; ++mip_level) { const uint32_t expected_color[3] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; - BOOL todo = !!mip_level; uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2455,7 +2454,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color[mip_level], todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color[mip_level], FALSE); } } release_surface_readback(&surface_rb); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 021281474e4..f2175e9a741 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;
buf_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); @@ -713,8 +700,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/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/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 f2175e9a741..88d766d2b01 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 9b7b6d566a9..cec203806e0 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, 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 97624fec3ba..63e7ca38aba 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -584,42 +584,6 @@ static const char *debug_volume(const struct volume *volume) return wine_dbg_sprintf("(%ux%ux%u)", volume->width, volume->height, volume->depth); }
-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_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_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 b083d5c6151..38cf5221652 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2153,7 +2153,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); @@ -2187,19 +2187,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, "D3DXCreateTextureFromFileInMemory returned %#lx, expected %#lx.\n", hr, D3D_OK); - check_texture_mips(texture, 3, TRUE); + check_texture_mips(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 < 3; ++mip_level) { const uint32_t expected_color[3] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; - BOOL todo = !!mip_level; uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2208,7 +2207,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color[mip_level], todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color[mip_level], FALSE); } } release_surface_readback(&surface_rb); @@ -2470,16 +2469,15 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture); ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK);
- check_texture_mips(texture, 3, TRUE); + check_texture_mips(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 < 3; ++mip_level) { const uint32_t expected_color[3] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; - BOOL todo = !!mip_level; uint32_t x, y;
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2488,7 +2486,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color[mip_level], todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color[mip_level], FALSE); } } release_surface_readback(&surface_rb); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 88d766d2b01..ea8e7635c9c 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 *buf_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; @@ -655,24 +648,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 exit; + 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))