From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/d3dx9_test_images.h | 56 +++++++- dlls/d3dx9_36/tests/texture.c | 31 ----- dlls/d3dx9_36/tests/volume.c | 175 ++++++++++++++++++++++++ 3 files changed, 230 insertions(+), 32 deletions(-)
diff --git a/dlls/d3dx9_36/tests/d3dx9_test_images.h b/dlls/d3dx9_36/tests/d3dx9_test_images.h index ca20ed6954d..1034700c22e 100644 --- a/dlls/d3dx9_36/tests/d3dx9_test_images.h +++ b/dlls/d3dx9_36/tests/d3dx9_test_images.h @@ -1,5 +1,6 @@ /* - * Test images used across the surface, texture and volume test files. + * Test images and functions used across the surface, texture and volume + * test files. * * Copyright 2024 Connor McAdams for CodeWeavers * @@ -80,6 +81,28 @@ static const uint8_t bmp_32bpp_argb[] = 0xc2,0x00,0xa3,0xb3,0xc3,0x01 };
+/* + * 4x4 bmp (32 bpp ARGB) four 2x2 blocks: + * +-----+-----+ + * |Red |Green| + * | | | + * +-----+-----+ + * |Blue |Black| + * | | | + * +-----+-----+ + */ +static const uint8_t bmp_32bpp_4_4_argb[] = +{ + 0x42,0x4d,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00, + 0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x00, + 0x00,0x00,0x40,0x00,0x00,0x00,0x24,0x16,0x00,0x00,0x24,0x16,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0x00, + 0x00,0xff,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0x00, + 0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff, +}; + static const uint8_t png_grayscale[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, @@ -379,3 +402,34 @@ static const uint8_t dds_24bit_8_8[] = 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 check_image_info(info, width, height, depth, mip_levels, format, resource_type, image_file_format, wine_todo) \ + check_image_info_(__FILE__, __LINE__, info, width, height, depth, mip_levels, format, resource_type, \ + image_file_format, wine_todo) +static inline void check_image_info_(const char *file, 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); +} diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index f32aa4eaad9..847d55bafea 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -48,37 +48,6 @@ 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, \ diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index 0c101157d30..83d832b08c7 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -23,6 +23,106 @@ #include "d3dx9tex.h" #include "d3dx9_test_images.h"
+struct volume_readback +{ + IDirect3DVolume9 *volume; + D3DLOCKED_BOX locked_box; +}; + +static inline uint32_t get_volume_readback_color(struct volume_readback *rb, uint32_t x, uint32_t y, uint32_t z) +{ + const uint32_t *pixels = rb->locked_box.pBits; + const D3DLOCKED_BOX *box = &rb->locked_box; + + if (!box->pBits) + return 0xdeadbeef; + return pixels[(z * (box->SlicePitch / sizeof(uint32_t)) + (y * (box->RowPitch / sizeof(uint32_t))) + x)]; +} + +#define release_volume_readback(rb) release_volume_readback_(__FILE__, __LINE__, rb) +static inline void release_volume_readback_(const char *file, uint32_t line, struct volume_readback *rb) +{ + HRESULT hr; + + if (!rb->volume) + return; + if (rb->locked_box.pBits && FAILED(hr = IDirect3DVolume9_UnlockBox(rb->volume))) + trace_(file, line)("Can't unlock the readback volume, hr %#lx.\n", hr); + IDirect3DVolume9_Release(rb->volume); +} + +#define get_texture_volume_readback(device, volume_tex, mip_level, rb) \ + get_texture_volume_readback_(__FILE__, __LINE__, device, volume_tex, mip_level, rb) +static inline void get_texture_volume_readback_(const char *file, uint32_t line, IDirect3DDevice9 *device, + IDirect3DVolumeTexture9 *volume_tex, uint32_t mip_level, struct volume_readback *rb) +{ + IDirect3DVolumeTexture9 *rb_tex; + IDirect3DVolume9 *volume = NULL; + D3DVOLUME_DESC desc; + HRESULT hr; + + memset(rb, 0, sizeof(*rb)); + hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_tex, mip_level, &desc); + if (FAILED(hr)) + { + trace_(file, line)("Failed to get volume description for mip level %d, hr %#lx.\n", mip_level, hr); + return; + } + + hr = IDirect3DDevice9_CreateVolumeTexture(device, desc.Width, desc.Height, desc.Depth, 1, 0, D3DFMT_A8R8G8B8, + D3DPOOL_SYSTEMMEM, &rb_tex, NULL); + if (FAILED(hr)) + { + trace_(file, line)("Can't create the readback volume texture, hr %#lx.\n", hr); + return; + } + + hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_tex, mip_level, &volume); + if (FAILED(hr)) + { + trace_(file, line)("Failed to get the volume for mip_level %d, hr %#lx.\n", mip_level, hr); + goto exit; + } + + hr = IDirect3DVolumeTexture9_GetVolumeLevel(rb_tex, 0, &rb->volume); + if (FAILED(hr)) + { + trace_(file, line)("Failed to get readback volume, hr %#lx.\n", hr); + goto exit; + } + + hr = D3DXLoadVolumeFromVolume(rb->volume, NULL, NULL, volume, NULL, NULL, D3DX_FILTER_NONE, 0); + if (FAILED(hr)) + { + trace_(file, line)("Can't load the source volume into the readback, hr %#lx.\n", hr); + goto exit; + } + + hr = IDirect3DVolume9_LockBox(rb->volume, &rb->locked_box, NULL, D3DLOCK_READONLY); + if (FAILED(hr)) + trace_(file, line)("Can't lock the readback volume, hr %#lx.\n", hr); + +exit: + IDirect3DVolumeTexture9_Release(rb_tex); + if (volume) + IDirect3DVolume9_Release(volume); + if (FAILED(hr)) + { + if (rb->volume) + IDirect3DVolume9_Release(rb->volume); + rb->volume = NULL; + } +} + +#define check_volume_readback_pixel_4bpp(rb, x, y, z, color, todo) \ + _check_volume_readback_pixel_4bpp(__FILE__, __LINE__, rb, x, y, z, color, todo) +static inline void _check_volume_readback_pixel_4bpp(const char *file, uint32_t line, struct volume_readback *rb, + uint32_t x, uint32_t y, uint32_t z, uint32_t expected_color, BOOL todo) +{ + uint32_t color = get_volume_readback_color(rb, x, y, z); + todo_wine_if(todo) ok_(file, line)(color == expected_color, "Got color 0x%08x, expected 0x%08x.\n", color, expected_color); +} + #define check_pixel_4bpp(box, x, y, z, color) _check_pixel_4bpp(__LINE__, box, x, y, z, color) static inline void _check_pixel_4bpp(unsigned int line, const D3DLOCKED_BOX *box, int x, int y, int z, DWORD expected_color) { @@ -199,8 +299,16 @@ static void test_D3DXLoadVolumeFromFileInMemory(IDirect3DDevice9 *device) { HRESULT hr; D3DBOX src_box; + uint32_t x, y, z; + D3DVOLUME_DESC desc; + D3DXIMAGE_INFO img_info; IDirect3DVolume9 *volume; + struct volume_readback volume_rb; IDirect3DVolumeTexture9 *volume_texture; + static const uint32_t bmp_32bpp_4_4_argb_expected[] = + { + 0xffff0000, 0xff00ff00, 0xff0000ff, 0xff000000, + };
hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, D3DUSAGE_DYNAMIC, D3DFMT_DXT3, D3DPOOL_DEFAULT, &volume_texture, NULL); @@ -245,6 +353,73 @@ static void test_D3DXLoadVolumeFromFileInMemory(IDirect3DDevice9 *device)
IDirect3DVolume9_Release(volume); IDirect3DVolumeTexture9_Release(volume_texture); + + /* Load 2D DDS image into a volume. */ + hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 8, 8, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, + &volume_texture, NULL); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume); + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_24bit_8_8, sizeof(dds_24bit_8_8), NULL, + D3DX_FILTER_POINT, 0, &img_info); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + check_image_info(&img_info, 8, 8, 1, 4, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE); + + IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &desc); + get_texture_volume_readback(device, volume_texture, 0, &volume_rb); + for (z = 0; z < desc.Depth; ++z) + { + for (y = 0; y < desc.Height; ++y) + { + for (x = 0; x < desc.Width; ++x) + { + check_volume_readback_pixel_4bpp(&volume_rb, x, y, z, 0xffff0000, FALSE); + } + } + } + release_volume_readback(&volume_rb); + } + + IDirect3DVolume9_Release(volume); + IDirect3DVolumeTexture9_Release(volume_texture); + + /* Load a BMP image into a volume. */ + hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, + &volume_texture, NULL); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume); + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, bmp_32bpp_4_4_argb, sizeof(bmp_32bpp_4_4_argb), NULL, + D3DX_FILTER_POINT, 0, &img_info); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + check_image_info(&img_info, 4, 4, 1, 1, D3DFMT_A8R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_BMP, FALSE); + + IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &desc); + get_texture_volume_readback(device, volume_texture, 0, &volume_rb); + for (z = 0; z < desc.Depth; ++z) + { + for (y = 0; y < desc.Height; ++y) + { + const uint32_t *expected_color = &bmp_32bpp_4_4_argb_expected[(y < (desc.Height / 2)) ? 0 : 2]; + + for (x = 0; x < desc.Width; ++x) + { + if (x < (desc.Width / 2)) + check_volume_readback_pixel_4bpp(&volume_rb, x, y, z, expected_color[0], FALSE); + else + check_volume_readback_pixel_4bpp(&volume_rb, x, y, z, expected_color[1], FALSE); + } + } + } + release_volume_readback(&volume_rb); + } + + IDirect3DVolume9_Release(volume); + IDirect3DVolumeTexture9_Release(volume_texture); }
START_TEST(volume)