-- v2: d3dx9: Introduce helper function for retrieving the mip filter value in texture from file functions. d3dx9: Validate filter argument value in texture from file functions. d3dx9: Handle default filter value in texture from file functions. d3dx9: Validate filter argument in D3DXLoadSurfaceFrom{Surface,FileInMemory,Memory}(). d3dx9: Validate filter argument in D3DXLoadVolumeFrom{Volume,FileInMemory,Memory}(). d3dx9/tests: Add d3dx filter argument value tests. d3dx9: Return failure from D3DXLoadSurfaceFromMemory() if d3dx_load_pixels_from_pixels() fails. d3dx9: Return success in D3DXLoadSurfaceFromMemory() for multisampled destination surfaces. d3dx9/tests: Add tests for D3DXLoadSurfaceFromMemory() with a multisampled surface.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 75 +++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 8 deletions(-)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 1d60f9c46aa..44f5b2d2cad 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -56,32 +56,32 @@ static void release_surface_readback(struct surface_readback *rb) IDirect3DSurface9_Release(rb->surface); }
-static void get_surface_decompressed_readback(IDirect3DDevice9 *device, IDirect3DSurface9 *compressed_surface, +static void get_surface_readback(IDirect3DDevice9 *device, IDirect3DSurface9 *src_surface, D3DFORMAT rb_format, struct surface_readback *rb) { D3DSURFACE_DESC desc; HRESULT hr;
memset(rb, 0, sizeof(*rb)); - hr = IDirect3DSurface9_GetDesc(compressed_surface, &desc); + hr = IDirect3DSurface9_GetDesc(src_surface, &desc); if (FAILED(hr)) { - trace("Failed to get compressed surface description, hr %#lx.\n", hr); + trace("Failed to get source surface description, hr %#lx.\n", hr); return; }
- hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, desc.Width, desc.Height, rb_format, D3DPOOL_SYSTEMMEM, &rb->surface, NULL); if (FAILED(hr)) { - trace("Can't create the decompressed surface, hr %#lx.\n", hr); + trace("Can't create the readback surface, hr %#lx.\n", hr); return; }
- hr = D3DXLoadSurfaceFromSurface(rb->surface, NULL, NULL, compressed_surface, NULL, NULL, D3DX_FILTER_NONE, 0); + hr = D3DXLoadSurfaceFromSurface(rb->surface, NULL, NULL, src_surface, NULL, NULL, D3DX_FILTER_NONE, 0); if (FAILED(hr)) { - trace("Can't load the decompressed surface, hr %#lx.\n", hr); + trace("Can't load the readback surface, hr %#lx.\n", hr); IDirect3DSurface9_Release(rb->surface); rb->surface = NULL; return; @@ -96,6 +96,12 @@ static void get_surface_decompressed_readback(IDirect3DDevice9 *device, IDirect3 } }
+static void get_surface_decompressed_readback(IDirect3DDevice9 *device, IDirect3DSurface9 *compressed_surface, + struct surface_readback *rb) +{ + return get_surface_readback(device, compressed_surface, D3DFMT_A8R8G8B8, rb); +} + static HRESULT create_file(const char *filename, const unsigned char *data, const unsigned int size) { DWORD received; @@ -771,6 +777,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) static const DWORD pixdata_g16r16[] = { 0x07d23fbe, 0xdc7f44a4, 0xe4d8976b, 0x9a84fe89 }; static const DWORD pixdata_a8b8g8r8[] = { 0xc3394cf0, 0x235ae892, 0x09b197fd, 0x8dc32bf6 }; static const DWORD pixdata_a2r10g10b10[] = { 0x57395aff, 0x5b7668fd, 0xb0d856b5, 0xff2c61d6 }; + static const uint32_t pixdata_a8r8g8b8[] = { 0x00102030, 0x40506070, 0x8090a0b0, 0xc0d0e0ff }; BYTE buffer[4 * 8 * 4];
hr = create_file("testdummy.bmp", noimage, sizeof(noimage)); /* invalid image */ @@ -933,9 +940,61 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &newsurf, NULL); if (SUCCEEDED(hr)) { - hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0); + struct surface_readback surface_rb; + + /* D3DXLoadSurfaceFromMemory should return success with a multisampled render target. */ + SetRect(&rect, 0, 0, 2, 2); + hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, &rect, pixdata_a8r8g8b8, D3DFMT_A8R8G8B8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + /* The call succeeds, but the surface isn't actually written to. */ + get_surface_readback(device, newsurf, D3DFMT_A8R8G8B8, &surface_rb); + check_readback_pixel_4bpp(&surface_rb, 0, 0, 0x00000000, FALSE); + check_readback_pixel_4bpp(&surface_rb, 1, 0, 0x00000000, FALSE); + check_readback_pixel_4bpp(&surface_rb, 0, 1, 0x00000000, FALSE); + check_readback_pixel_4bpp(&surface_rb, 1, 1, 0x00000000, FALSE); + release_surface_readback(&surface_rb); + + /* + * Load the data into our non-multisampled render target, then load + * that into the multisampled render target. + */ + SetRect(&rect, 0, 0, 2, 2); + hr = D3DXLoadSurfaceFromMemory(surf, NULL, &rect, pixdata_a8r8g8b8, D3DFMT_A8R8G8B8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + get_surface_readback(device, surf, D3DFMT_A8R8G8B8, &surface_rb); + check_readback_pixel_4bpp(&surface_rb, 0, 0, pixdata_a8r8g8b8[0], FALSE); + check_readback_pixel_4bpp(&surface_rb, 1, 0, pixdata_a8r8g8b8[1], FALSE); + check_readback_pixel_4bpp(&surface_rb, 0, 1, pixdata_a8r8g8b8[2], FALSE); + check_readback_pixel_4bpp(&surface_rb, 1, 1, pixdata_a8r8g8b8[3], FALSE); + release_surface_readback(&surface_rb); + + /* + * Loading from a non-multisampled surface into a multisampled surface + * does change the surface contents. + */ + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, &rect, surf, NULL, &rect, D3DX_FILTER_NONE, 0); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
+ get_surface_readback(device, newsurf, D3DFMT_A8R8G8B8, &surface_rb); + check_readback_pixel_4bpp(&surface_rb, 0, 0, pixdata_a8r8g8b8[0], TRUE); + check_readback_pixel_4bpp(&surface_rb, 1, 0, pixdata_a8r8g8b8[1], TRUE); + check_readback_pixel_4bpp(&surface_rb, 0, 1, pixdata_a8r8g8b8[2], TRUE); + check_readback_pixel_4bpp(&surface_rb, 1, 1, pixdata_a8r8g8b8[3], TRUE); + release_surface_readback(&surface_rb); + + /* Contents of the multisampled surface are preserved. */ + hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, 8, NULL, &rect, D3DX_FILTER_POINT, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + get_surface_readback(device, newsurf, D3DFMT_A8R8G8B8, &surface_rb); + check_readback_pixel_4bpp(&surface_rb, 0, 0, pixdata_a8r8g8b8[0], TRUE); + check_readback_pixel_4bpp(&surface_rb, 1, 0, pixdata_a8r8g8b8[1], TRUE); + check_readback_pixel_4bpp(&surface_rb, 0, 1, pixdata_a8r8g8b8[2], TRUE); + check_readback_pixel_4bpp(&surface_rb, 1, 1, pixdata_a8r8g8b8[3], TRUE); + release_surface_readback(&surface_rb); + IDirect3DSurface9_Release(newsurf); } else
From: Connor McAdams cmcadams@codeweavers.com
Tests show that nothing is written to multisampled destination surfaces, so just return success early.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 6 ++++++ dlls/d3dx9_36/tests/surface.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 344a491765e..62ca72de665 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -2174,6 +2174,12 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, }
IDirect3DSurface9_GetDesc(dst_surface, &surfdesc); + if (surfdesc.MultiSampleType != D3DMULTISAMPLE_NONE) + { + TRACE("Multisampled destination surface, doing nothing.\n"); + return D3D_OK; + } + destformatdesc = get_format_info(surfdesc.Format); if (!dst_rect) { diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 44f5b2d2cad..cd31a024f73 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -945,7 +945,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) /* D3DXLoadSurfaceFromMemory should return success with a multisampled render target. */ SetRect(&rect, 0, 0, 2, 2); hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, &rect, pixdata_a8r8g8b8, D3DFMT_A8R8G8B8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
/* The call succeeds, but the surface isn't actually written to. */ get_surface_readback(device, newsurf, D3DFMT_A8R8G8B8, &surface_rb); @@ -986,7 +986,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
/* Contents of the multisampled surface are preserved. */ hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, 8, NULL, &rect, D3DX_FILTER_POINT, 0); - todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
get_surface_readback(device, newsurf, D3DFMT_A8R8G8B8, &surface_rb); check_readback_pixel_4bpp(&surface_rb, 0, 0, pixdata_a8r8g8b8[0], TRUE);
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 62ca72de665..e3a5b69e41d 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -2218,13 +2218,16 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lockrect, &surface, TRUE))) return hr;
- set_d3dx_pixels(&dst_pixels, lockrect.pBits, lockrect.Pitch, 0, dst_palette, (dst_rect_aligned.right - dst_rect_aligned.left), (dst_rect_aligned.bottom - dst_rect_aligned.top), 1, dst_rect); OffsetRect(&dst_pixels.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top);
- d3dx_load_pixels_from_pixels(&dst_pixels, destformatdesc, &src_pixels, srcformatdesc, filter, color_key); + if (FAILED(hr = d3dx_load_pixels_from_pixels(&dst_pixels, destformatdesc, &src_pixels, srcformatdesc, filter, color_key))) + { + unlock_surface(dst_surface, &dst_rect_aligned, surface, TRUE); + return hr; + }
return unlock_surface(dst_surface, &dst_rect_aligned, surface, TRUE); }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/d3dx9_test_images.h | 29 ++++- dlls/d3dx9_36/tests/surface.c | 30 ++++++ dlls/d3dx9_36/tests/texture.c | 136 +++++++++++++++++++++++- dlls/d3dx9_36/tests/volume.c | 26 ++++- 4 files changed, 216 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/tests/d3dx9_test_images.h b/dlls/d3dx9_36/tests/d3dx9_test_images.h index 655d9a87fde..8dabd8c2f84 100644 --- a/dlls/d3dx9_36/tests/d3dx9_test_images.h +++ b/dlls/d3dx9_36/tests/d3dx9_test_images.h @@ -1,6 +1,6 @@ /* - * Test images and functions used across the surface, texture and volume - * test files. + * Test images, functions and values used across the surface, texture and + * volume test files. * * Copyright 2024 Connor McAdams for CodeWeavers * @@ -23,6 +23,31 @@ #define COBJMACROS #include "d3dx9tex.h"
+static const struct +{ + uint32_t filter; + HRESULT expected_hr; + BOOL d3dx_filter_texture_todo; +} +test_filter_values[] = +{ + { D3DX_DEFAULT, D3D_OK }, + /* Any combo of MIRROR/DITHER/SRGB bits are valid. */ + { 0x007f0001, D3D_OK }, + { D3DX_DEFAULT_NONPOW2, D3DERR_INVALIDCALL }, + { D3DX_FROM_FILE, D3DERR_INVALIDCALL }, + { 0, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, + { D3DX_FILTER_BOX + 1, D3DERR_INVALIDCALL }, + { 0x0000ffff, D3DERR_INVALIDCALL }, + { 0x7c000001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, + { 0x80000001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, + /* + * Mip skip bits are 30-26, 25-23 are unused, but setting them results in + * failure. + */ + { 0x03800001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, +}; + /* 1x1 bmp (1 bpp) */ static const uint8_t bmp_1bpp[] = { diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index cd31a024f73..c29f61a8e7d 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -779,6 +779,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) static const DWORD pixdata_a2r10g10b10[] = { 0x57395aff, 0x5b7668fd, 0xb0d856b5, 0xff2c61d6 }; static const uint32_t pixdata_a8r8g8b8[] = { 0x00102030, 0x40506070, 0x8090a0b0, 0xc0d0e0ff }; BYTE buffer[4 * 8 * 4]; + uint32_t i;
hr = create_file("testdummy.bmp", noimage, sizeof(noimage)); /* invalid image */ testdummy_ok = SUCCEEDED(hr); @@ -1053,6 +1054,17 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, &destrect, D3DX_FILTER_NONE, 0); ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#lx, expected %#lx.\n", hr, D3D_OK);
+ for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, test_filter_values[i].filter, 0); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + winetest_pop_context(); + } + IDirect3DSurface9_Release(newsurf);
check_release((IUnknown*)surf, 0); @@ -1213,6 +1225,24 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) hr = IDirect3DSurface9_UnlockRect(surf); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx\n", hr);
+ SetRect(&rect, 0, 0, 2, 2); + for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, dds_24bit, sizeof(dds_24bit), NULL, + test_filter_values[i].filter, 0, NULL); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, D3DFMT_A8B8G8R8, 8, NULL, &rect, + test_filter_values[i].filter, 0); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + winetest_pop_context(); + } + check_release((IUnknown*)surf, 0); }
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index bbfae36b4e9..495e9055f1e 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -1047,6 +1047,7 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) IDirect3DCubeTexture9 *cubetex; IDirect3DVolumeTexture9 *voltex; HRESULT hr; + uint32_t i;
hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 5, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex, NULL);
@@ -1058,6 +1059,17 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_NONE); ok(hr == D3D_OK, "D3DXFilterTexture returned %#lx, expected %#lx\n", hr, D3D_OK);
+ for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)tex, NULL, 0, test_filter_values[i].filter); + todo_wine_if(test_filter_values[i].d3dx_filter_texture_todo) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + winetest_pop_context(); + } + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_BOX + 1); /* Invalid filter */ ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#lx, expected %#lx\n", hr, D3DERR_INVALIDCALL);
@@ -1126,6 +1138,17 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) hr = D3DXFilterTexture((IDirect3DBaseTexture9*) cubetex, NULL, 0, D3DX_FILTER_BOX + 1); /* Invalid filter */ ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#lx, expected %#lx\n", hr, D3DERR_INVALIDCALL);
+ for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)cubetex, NULL, 0, test_filter_values[i].filter); + todo_wine_if(test_filter_values[i].d3dx_filter_texture_todo) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + winetest_pop_context(); + } + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) cubetex, NULL, 5, D3DX_FILTER_NONE); /* Invalid miplevel */ ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#lx, expected %#lx\n", hr, D3DERR_INVALIDCALL); IDirect3DCubeTexture9_Release(cubetex); @@ -1148,6 +1171,17 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) hr = D3DXFilterTexture((IDirect3DBaseTexture9*) voltex, NULL, 0, D3DX_FILTER_BOX); ok(hr == D3D_OK, "D3DXFilterTexture returned %#lx, expected %#lx\n", hr, D3D_OK);
+ for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)voltex, NULL, 0, test_filter_values[i].filter); + todo_wine_if(test_filter_values[i].d3dx_filter_texture_todo) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + winetest_pop_context(); + } + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) voltex, NULL, level_count - 1, D3DX_DEFAULT); ok(hr == D3D_OK, "D3DXFilterTexture returned %#lx, expected %#lx\n", hr, D3D_OK);
@@ -2118,7 +2152,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) }; HRESULT hr; struct surface_readback surface_rb; - uint32_t miplevels, mip_level; + uint32_t miplevels, mip_level, i; IDirect3DTexture9 *texture; IDirect3DSurface9 *surface; D3DXIMAGE_INFO img_info; @@ -2129,6 +2163,36 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); IDirect3DTexture9_Release(texture);
+ for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + texture = NULL; + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, test_filter_values[i].filter, D3DX_DEFAULT, 0, NULL, NULL, &texture); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + if (texture) + IDirect3DTexture9_Release(texture); + + winetest_pop_context(); + } + + /* Mip filter argument values never cause failure. */ + for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Mip filter %d (%#x)", i, test_filter_values[i].filter); + + texture = NULL; + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), 32, 32, 6, + 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, test_filter_values[i].filter, 0, NULL, NULL, &texture); + todo_wine_if(FAILED(hr)) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (texture) + IDirect3DTexture9_Release(texture); + + winetest_pop_context(); + } + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#lx, expected %#lx\n", hr, D3D_OK); @@ -2467,6 +2531,42 @@ static void test_D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); IDirect3DCubeTexture9_Release(cube_texture);
+ hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, dds_cube_map, sizeof(dds_cube_map), D3DX_DEFAULT, + D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &cube_texture); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + IDirect3DCubeTexture9_Release(cube_texture); + for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + cube_texture = NULL; + hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, dds_cube_map, sizeof(dds_cube_map), D3DX_DEFAULT, + D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, test_filter_values[i].filter, D3DX_DEFAULT, + 0, NULL, NULL, &cube_texture); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + if (cube_texture) + IDirect3DCubeTexture9_Release(cube_texture); + + winetest_pop_context(); + } + + /* Mip filter argument values never cause failure. */ + for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Mip filter %d (%#x)", i, test_filter_values[i].filter); + + cube_texture = NULL; + hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, dds_cube_map, sizeof(dds_cube_map), D3DX_DEFAULT, + D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, test_filter_values[i].filter, + 0, NULL, NULL, &cube_texture); + todo_wine_if(FAILED(hr)) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (cube_texture) + IDirect3DCubeTexture9_Release(cube_texture); + + winetest_pop_context(); + } + if (!is_autogenmipmap_supported(device, D3DRTYPE_CUBETEXTURE)) { skip("No D3DUSAGE_AUTOGENMIPMAP support for cube textures\n"); @@ -2708,7 +2808,7 @@ static void test_D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *dev }; IDirect3DVolumeTexture9 *volume_texture, *texture; struct volume_readback volume_rb; - uint32_t mip_level, x, y, z; + uint32_t mip_level, x, y, z, i; D3DXIMAGE_INFO img_info; D3DVOLUME_DESC desc; HRESULT hr; @@ -2732,6 +2832,38 @@ static void test_D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *dev check_image_info(&img_info, 8, 8, 1, 4, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE); IDirect3DVolumeTexture9_Release(texture);
+ for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + texture = NULL; + hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + test_filter_values[i].filter, D3DX_DEFAULT, 0, NULL, NULL, &texture); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + if (texture) + IDirect3DVolumeTexture9_Release(texture); + + winetest_pop_context(); + } + + /* Mip filter argument values never cause failure. */ + for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Mip filter %d (%#x)", i, test_filter_values[i].filter); + + texture = NULL; + hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, test_filter_values[i].filter, 0, NULL, NULL, &texture); + todo_wine_if(FAILED(hr)) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (texture) + IDirect3DVolumeTexture9_Release(texture); + + winetest_pop_context(); + } + hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), D3DX_DEFAULT, 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); diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index c0bad638597..c961120eb0d 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -191,6 +191,18 @@ static void test_D3DXLoadVolumeFromMemory(IDirect3DDevice9 *device) hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 32, NULL, &src_box, D3DX_DEFAULT, 0); ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#lx, expected %#lx\n", hr, D3D_OK);
+ for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 32, NULL, &src_box, + test_filter_values[i].filter, 0); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + winetest_pop_context(); + } + IDirect3DVolume9_Release(volume); IDirect3DVolumeTexture9_Release(volume_texture); } @@ -199,7 +211,7 @@ static void test_D3DXLoadVolumeFromFileInMemory(IDirect3DDevice9 *device) { HRESULT hr; D3DBOX src_box; - uint32_t x, y, z; + uint32_t x, y, z, i; D3DVOLUME_DESC desc; D3DXIMAGE_INFO img_info; IDirect3DVolume9 *volume; @@ -260,6 +272,18 @@ static void test_D3DXLoadVolumeFromFileInMemory(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume); + for (i = 0; i < ARRAY_SIZE(test_filter_values); ++i) + { + winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter); + + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_24bit_8_8, sizeof(dds_24bit_8_8), NULL, + test_filter_values[i].filter, 0, NULL); + todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, + "Unexpected hr %#lx.\n", hr); + + winetest_pop_context(); + } + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_24bit_8_8, sizeof(dds_24bit_8_8), NULL, D3DX_FILTER_POINT, 0, &img_info); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 9 +++++++++ dlls/d3dx9_36/tests/texture.c | 3 +-- dlls/d3dx9_36/tests/volume.c | 6 ++---- dlls/d3dx9_36/volume.c | 15 +++++++++++++++ 4 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 248b6a69b00..ac7c06e73f6 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -33,6 +33,15 @@
#define FOURCC_TX_1 0x54580100
+#define D3DX9_FILTER_INVALID_BITS 0xff80fff8 +static inline HRESULT d3dx9_validate_filter(uint32_t filter) +{ + if ((filter & D3DX9_FILTER_INVALID_BITS) || !(filter & 0x7) || ((filter & 0x7) > D3DX_FILTER_BOX)) + return D3DERR_INVALIDCALL; + + return D3D_OK; +} + struct vec4 { float x, y, z, w; diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 495e9055f1e..0c02a9e7c65 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -1176,8 +1176,7 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter);
hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)voltex, NULL, 0, test_filter_values[i].filter); - todo_wine_if(test_filter_values[i].d3dx_filter_texture_todo) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
winetest_pop_context(); } diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index c961120eb0d..68eca7c531b 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -197,8 +197,7 @@ static void test_D3DXLoadVolumeFromMemory(IDirect3DDevice9 *device)
hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 32, NULL, &src_box, test_filter_values[i].filter, 0); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
winetest_pop_context(); } @@ -278,8 +277,7 @@ static void test_D3DXLoadVolumeFromFileInMemory(IDirect3DDevice9 *device)
hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_24bit_8_8, sizeof(dds_24bit_8_8), NULL, test_filter_values[i].filter, 0, NULL); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
winetest_pop_context(); } diff --git a/dlls/d3dx9_36/volume.c b/dlls/d3dx9_36/volume.c index 2088b70ed4c..a69588a4f37 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -111,6 +111,9 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
+ if (FAILED(hr = d3dx9_validate_filter(filter))) + return hr; + src_format_desc = get_format_info(src_format); if (src_format_desc->type == FORMAT_UNKNOWN) return E_NOTIMPL; @@ -180,6 +183,12 @@ HRESULT WINAPI D3DXLoadVolumeFromFileInMemory(IDirect3DVolume9 *dst_volume, cons if (!dst_volume || !src_data || !src_data_size) return D3DERR_INVALIDCALL;
+ if (filter == D3DX_DEFAULT) + filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + + if (FAILED(hr = d3dx9_validate_filter(filter))) + return hr; + hr = d3dx_image_init(src_data, src_data_size, &image, 0, 0); if (FAILED(hr)) return D3DXERR_INVALIDDATA; @@ -231,6 +240,12 @@ HRESULT WINAPI D3DXLoadVolumeFromVolume(IDirect3DVolume9 *dst_volume, const PALE
if (!dst_volume || !src_volume) return D3DERR_INVALIDCALL;
+ if (filter == D3DX_DEFAULT) + filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + + if (FAILED(hr = d3dx9_validate_filter(filter))) + return hr; + IDirect3DVolume9_GetDesc(src_volume, &desc);
if (!src_box)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 12 ++++++++++++ dlls/d3dx9_36/tests/d3dx9_test_images.h | 9 ++++----- dlls/d3dx9_36/tests/surface.c | 9 +++------ dlls/d3dx9_36/tests/texture.c | 6 ++---- 4 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index e3a5b69e41d..b524a2e2716 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1258,6 +1258,11 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, if (!pDestSurface || !pSrcData || !SrcDataSize) return D3DERR_INVALIDCALL;
+ if (dwFilter == D3DX_DEFAULT) + dwFilter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + if (FAILED(hr = d3dx9_validate_filter(dwFilter))) + return hr; + hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0, 0); if (FAILED(hr)) return D3DXERR_INVALIDDATA; @@ -2207,6 +2212,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + if (FAILED(hr = d3dx9_validate_filter(filter))) + return hr;
hr = d3dx_pixels_init(src_memory, src_pitch, 0, src_palette, srcformatdesc->format, src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_pixels); @@ -2277,6 +2284,11 @@ HRESULT WINAPI D3DXLoadSurfaceFromSurface(IDirect3DSurface9 *dst_surface, if (!dst_surface || !src_surface) return D3DERR_INVALIDCALL;
+ if (filter == D3DX_DEFAULT) + filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + if (FAILED(hr = d3dx9_validate_filter(filter))) + return hr; + IDirect3DSurface9_GetDesc(src_surface, &src_desc); src_format_desc = get_format_info(src_desc.Format); if (!src_rect) diff --git a/dlls/d3dx9_36/tests/d3dx9_test_images.h b/dlls/d3dx9_36/tests/d3dx9_test_images.h index 8dabd8c2f84..256897d37b9 100644 --- a/dlls/d3dx9_36/tests/d3dx9_test_images.h +++ b/dlls/d3dx9_36/tests/d3dx9_test_images.h @@ -27,7 +27,6 @@ static const struct { uint32_t filter; HRESULT expected_hr; - BOOL d3dx_filter_texture_todo; } test_filter_values[] = { @@ -36,16 +35,16 @@ test_filter_values[] = { 0x007f0001, D3D_OK }, { D3DX_DEFAULT_NONPOW2, D3DERR_INVALIDCALL }, { D3DX_FROM_FILE, D3DERR_INVALIDCALL }, - { 0, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, + { 0, D3DERR_INVALIDCALL }, { D3DX_FILTER_BOX + 1, D3DERR_INVALIDCALL }, { 0x0000ffff, D3DERR_INVALIDCALL }, - { 0x7c000001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, - { 0x80000001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, + { 0x7c000001, D3DERR_INVALIDCALL }, + { 0x80000001, D3DERR_INVALIDCALL }, /* * Mip skip bits are 30-26, 25-23 are unused, but setting them results in * failure. */ - { 0x03800001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, + { 0x03800001, D3DERR_INVALIDCALL }, };
/* 1x1 bmp (1 bpp) */ diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index c29f61a8e7d..e2ea26cbd0c 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -1059,8 +1059,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter);
hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, test_filter_values[i].filter, 0); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
winetest_pop_context(); } @@ -1232,13 +1231,11 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, dds_24bit, sizeof(dds_24bit), NULL, test_filter_values[i].filter, 0, NULL); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, D3DFMT_A8B8G8R8, 8, NULL, &rect, test_filter_values[i].filter, 0); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
winetest_pop_context(); } diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 0c02a9e7c65..35303faf625 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -1064,8 +1064,7 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter);
hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)tex, NULL, 0, test_filter_values[i].filter); - todo_wine_if(test_filter_values[i].d3dx_filter_texture_todo) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
winetest_pop_context(); } @@ -1143,8 +1142,7 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) winetest_push_context("Filter %d (%#x)", i, test_filter_values[i].filter);
hr = D3DXFilterTexture((IDirect3DBaseTexture9 *)cubetex, NULL, 0, test_filter_values[i].filter); - todo_wine_if(test_filter_values[i].d3dx_filter_texture_todo) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr);
winetest_pop_context(); }
From: Connor McAdams cmcadams@codeweavers.com
This used to be handled by the calls to D3DXLoad{Surface,Volume}FromMemory(), but now it needs to be handled inside of the texture from file functions themselves.
Fixes: 1215ee024148952525317cc104ce91e650f21ca3 Fixes: c9e6f6f84f661bdd190f4475296a7ce1d3885516 Fixes: f023fd35cefe6d46849a4a9336905410b4991ac4 Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/texture.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index a65a955cebf..3c0264cc6ce 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -603,6 +603,8 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi 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 (filter == D3DX_DEFAULT) + filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT); if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) @@ -1133,6 +1135,8 @@ HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic height = (height == D3DX_DEFAULT) ? make_pow2(image_info.Height) : image_info.Height; if (!depth || depth == D3DX_DEFAULT_NONPOW2 || depth == D3DX_FROM_FILE || depth == D3DX_DEFAULT) depth = (depth == D3DX_DEFAULT) ? make_pow2(image_info.Depth) : image_info.Depth; + if (filter == D3DX_DEFAULT) + filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT); if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) @@ -1418,6 +1422,8 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, size = max(img_info.Width, img_info.Height); else if (size == D3DX_DEFAULT) size = make_pow2(max(img_info.Width, img_info.Height)); + if (filter == D3DX_DEFAULT) + filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT); if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/texture.c | 9 +++------ dlls/d3dx9_36/texture.c | 9 +++++++++ 2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 35303faf625..9955d971cef 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2167,8 +2167,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) texture = NULL; hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, test_filter_values[i].filter, D3DX_DEFAULT, 0, NULL, NULL, &texture); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr); if (texture) IDirect3DTexture9_Release(texture);
@@ -2540,8 +2539,7 @@ static void test_D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, dds_cube_map, sizeof(dds_cube_map), D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, test_filter_values[i].filter, D3DX_DEFAULT, 0, NULL, NULL, &cube_texture); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr); if (cube_texture) IDirect3DCubeTexture9_Release(cube_texture);
@@ -2837,8 +2835,7 @@ static void test_D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *dev hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, test_filter_values[i].filter, D3DX_DEFAULT, 0, NULL, NULL, &texture); - todo_wine_if(FAILED(test_filter_values[i].expected_hr)) ok(hr == test_filter_values[i].expected_hr, - "Unexpected hr %#lx.\n", hr); + ok(hr == test_filter_values[i].expected_hr, "Unexpected hr %#lx.\n", hr); if (texture) IDirect3DVolumeTexture9_Release(texture);
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 3c0264cc6ce..1487258d96a 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -606,6 +606,9 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
+ if (FAILED(hr = d3dx9_validate_filter(filter))) + goto err; + format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT); if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) format = imginfo.Format; @@ -1138,6 +1141,9 @@ HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
+ if (FAILED(hr = d3dx9_validate_filter(filter))) + goto err; + format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT); if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) format = image_info.Format; @@ -1425,6 +1431,9 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
+ if (FAILED(hr = d3dx9_validate_filter(filter))) + goto err; + format_specified = (format != D3DFMT_UNKNOWN && format != D3DX_DEFAULT); if (format == D3DFMT_FROM_FILE || format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) format = img_info.Format;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/texture.c | 15 ++++++--------- dlls/d3dx9_36/texture.c | 20 ++++++++++++++------ 2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 9955d971cef..636dd3c7a08 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2182,9 +2182,8 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) texture = NULL; hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), 32, 32, 6, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, test_filter_values[i].filter, 0, NULL, NULL, &texture); - todo_wine_if(FAILED(hr)) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (texture) - IDirect3DTexture9_Release(texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + IDirect3DTexture9_Release(texture);
winetest_pop_context(); } @@ -2555,9 +2554,8 @@ static void test_D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, dds_cube_map, sizeof(dds_cube_map), D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, test_filter_values[i].filter, 0, NULL, NULL, &cube_texture); - todo_wine_if(FAILED(hr)) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (cube_texture) - IDirect3DCubeTexture9_Release(cube_texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + IDirect3DCubeTexture9_Release(cube_texture);
winetest_pop_context(); } @@ -2851,9 +2849,8 @@ static void test_D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *dev hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, dds_24bit_8_8, sizeof(dds_24bit_8_8), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, test_filter_values[i].filter, 0, NULL, NULL, &texture); - todo_wine_if(FAILED(hr)) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (texture) - IDirect3DVolumeTexture9_Release(texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + IDirect3DVolumeTexture9_Release(texture);
winetest_pop_context(); } diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 1487258d96a..9ed83c184ae 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -562,6 +562,17 @@ static D3DFORMAT get_alpha_replacement_format(D3DFORMAT format) return format; }
+static uint32_t d3dx9_get_mip_filter_value(uint32_t mip_filter, uint32_t *skip_levels) +{ + uint32_t filter = (mip_filter == D3DX_DEFAULT) ? D3DX_FILTER_BOX : mip_filter & ~D3DX9_FILTER_INVALID_BITS; + + *skip_levels = mip_filter != D3DX_DEFAULT ? mip_filter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0; + *skip_levels &= D3DX_SKIP_DDS_MIP_LEVELS_MASK; + if (!(filter & 0x7) || (filter & 0x7) > D3DX_FILTER_BOX) + filter = (filter & 0x007f0000) | D3DX_FILTER_BOX; + return filter; +} + HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *device, const void *srcdata, UINT srcdatasize, UINT width, UINT height, UINT miplevels, DWORD usage, D3DFORMAT format, D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo, @@ -587,8 +598,7 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi return D3DERR_INVALIDCALL;
staging_tex = tex = *texture = NULL; - skip_levels = mipfilter != D3DX_DEFAULT ? mipfilter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0; - skip_levels &= D3DX_SKIP_DDS_MIP_LEVELS_MASK; + mipfilter = d3dx9_get_mip_filter_value(mipfilter, &skip_levels); hr = d3dx_image_init(srcdata, srcdatasize, &image, skip_levels, 0); if (FAILED(hr)) { @@ -1120,8 +1130,7 @@ HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic return D3DERR_INVALIDCALL;
staging_tex = tex = *volume_texture = NULL; - skip_levels = mip_filter != D3DX_DEFAULT ? mip_filter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0; - skip_levels &= D3DX_SKIP_DDS_MIP_LEVELS_MASK; + mip_filter = d3dx9_get_mip_filter_value(mip_filter, &skip_levels); hr = d3dx_image_init(data, data_size, &image, skip_levels, 0); if (FAILED(hr)) { @@ -1407,8 +1416,7 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, return D3DERR_INVALIDCALL;
staging_tex = tex = *cube_texture = NULL; - skip_levels = mip_filter != D3DX_DEFAULT ? mip_filter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0; - skip_levels &= D3DX_SKIP_DDS_MIP_LEVELS_MASK; + mip_filter = d3dx9_get_mip_filter_value(mip_filter, &skip_levels); hr = d3dx_image_init(src_data, src_data_size, &image, skip_levels, 0); if (FAILED(hr)) {
On Thu Aug 1 13:02:10 2024 +0000, Matteo Bruni wrote:
Nitpick, just `..., "Unexpected hr %#lx.\n", hr);` It would be interesting to also check the loaded surface contents.
Added readback tests, and changed these error messages in the current revision.
On Thu Aug 1 13:01:09 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/6157/diffs?diff_id=124641&start_sha=4ae32fd3259080a42e4c959f827de0b63064a246#8fffeae09861a99974e55842964630933974cdc8_290_281)
I thought the source needed to be a render target as well, but that wasn't the case. Either way, turns out nothing gets written to the surface anyways, so this code is no longer necessary in the current revision. :)
On Sun Jul 28 19:26:13 2024 +0000, Matteo Bruni wrote:
So this is effectively a `Fixes: 1215ee024148952525317cc104ce91e650f21ca3`, right? I'd make use of this occasion to introduce a tiny helper like `d3dx9_validate_filter()` for this, even if it's just two lines (but copied around now a handful of times). Also, while thinking of a name for the helper, I started to wonder whether we should actually validate the `filter` value. As it turns out, that's very much the case (e.g. try to use `6`.) Actual validation should be its own patch, probably, but I guess this is one more reason for introducing the helper.
Added a helper for this, and a lot more tests generally for filter argument value validation. I might have gone a bit overboard, but it's probably better to just get it all out of the way now to avoid any potential issues in the future. :)
On Thu Aug 1 13:07:24 2024 +0000, Matteo Bruni wrote:
While reviewing I found that some d3dx9 tests spuriously fail with traces enabled. I'll send an MR for it, probably tomorrow at this point...
Thanks for doing that. :) I encountered those spurious failures awhile ago and had local patches for them at some point, but I forgot about it being an issue.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lockrect, &surface, TRUE))) return hr;
set_d3dx_pixels(&dst_pixels, lockrect.pBits, lockrect.Pitch, 0, dst_palette, (dst_rect_aligned.right - dst_rect_aligned.left), (dst_rect_aligned.bottom - dst_rect_aligned.top), 1, dst_rect); OffsetRect(&dst_pixels.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top);
d3dx_load_pixels_from_pixels(&dst_pixels, destformatdesc, &src_pixels, srcformatdesc, filter, color_key);
- if (FAILED(hr = d3dx_load_pixels_from_pixels(&dst_pixels, destformatdesc, &src_pixels, srcformatdesc, filter, color_key)))
- {
unlock_surface(dst_surface, &dst_rect_aligned, surface, TRUE);
A bit of an academic question, but: should we rather call `unlock_surface(..., FALSE);` in error paths?
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/d3dx9_test_images.h:
+{
- { D3DX_DEFAULT, D3D_OK },
- /* Any combo of MIRROR/DITHER/SRGB bits are valid. */
- { 0x007f0001, D3D_OK },
- { D3DX_DEFAULT_NONPOW2, D3DERR_INVALIDCALL },
- { D3DX_FROM_FILE, D3DERR_INVALIDCALL },
- { 0, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE },
- { D3DX_FILTER_BOX + 1, D3DERR_INVALIDCALL },
- { 0x0000ffff, D3DERR_INVALIDCALL },
- { 0x7c000001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE },
- { 0x80000001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE },
- /*
* Mip skip bits are 30-26, 25-23 are unused, but setting them results in
* failure.
*/
- { 0x03800001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE },
Technically, mip skip bits should only apply to the `mipfilter` argument, not `filter`. Is there any validation for those in `filter` arguments (i.e. are otherwise valid "mip skip" values in `filter` rejected?)
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/volume.c:
if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
- if (FAILED(hr = d3dx9_validate_filter(filter)))
return hr;
Sooo, when I proposed this in the previous review I was figuring that `D3DX_DEFAULT` handling could go in the helper as well, although I didn't exactly consider that `D3DXFilterTexture()` has its own different interpretation of `D3DX_DEFAULT`.
What do you think about introducing yet another helper to be used in everything-but-`D3DXFilterTexture()` which does D3DX_DEFAULT handling and also calls `d3dx9_validate_filter()`? E.g. something like `HRESULT d3dx9_handle_load_filter(D3DX_FILTER *filter);`