-- v3: d3dx9: Validate filter argument in texture from file functions. d3dx9: Validate filter argument in D3DXLoadSurfaceFrom{Surface,FileInMemory,Memory}(). d3dx9: Validate filter argument in D3DXLoadVolumeFrom{Volume,FileInMemory,Memory}(). d3dx9: Further validate filter argument passed to D3DXFilterTexture(). d3dx9: Introduce helper function for retrieving the mip filter value in texture from file functions. 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..8bc60ec443f 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, FALSE); + 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 | 24 +++- dlls/d3dx9_36/tests/surface.c | 30 +++++ dlls/d3dx9_36/tests/texture.c | 162 +++++++++++++++++++++++- dlls/d3dx9_36/tests/volume.c | 26 +++- 4 files changed, 237 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..5ac14eb3eb4 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,26 @@ #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 }, + /* Any unused filter bits being set results in failure. */ + { 0xff800001, 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..ffc03a4d37e 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,44 @@ 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(); + } + + /* Mip skip bits are 30-26, 25-23 are unused, setting them does nothing. */ + texture = NULL; + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), 32, 32, 6, + 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, 0x03800001, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (texture) + IDirect3DTexture9_Release(texture); + 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 +2539,51 @@ 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(); + } + + /* Mip skip bits are 30-26, 25-23 are unused, setting them does nothing. */ + 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, 0x03800001, + 0, NULL, NULL, &cube_texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (cube_texture) + IDirect3DCubeTexture9_Release(cube_texture); + if (!is_autogenmipmap_supported(device, D3DRTYPE_CUBETEXTURE)) { skip("No D3DUSAGE_AUTOGENMIPMAP support for cube textures\n"); @@ -2708,7 +2825,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 +2849,47 @@ 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(); + } + + /* Mip skip bits are 30-26, 25-23 are unused, setting them does nothing. */ + 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, 0x03800001, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (texture) + IDirect3DVolumeTexture9_Release(texture); + 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 | 2 ++ dlls/d3dx9_36/tests/texture.c | 6 +++--- dlls/d3dx9_36/texture.c | 20 ++++++++++++++------ 3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 248b6a69b00..3065752a36d 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -33,6 +33,8 @@
#define FOURCC_TX_1 0x54580100
+#define D3DX9_FILTER_INVALID_BITS 0xff80fff8 + struct vec4 { float x, y, z, w; diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index ffc03a4d37e..b58dd104760 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2186,7 +2186,7 @@ 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); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); if (texture) IDirect3DTexture9_Release(texture);
@@ -2568,7 +2568,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, 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); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); if (cube_texture) IDirect3DCubeTexture9_Release(cube_texture);
@@ -2874,7 +2874,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, 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); + ok(hr == D3D_OK, "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 a65a955cebf..93ab7142ab7 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)) { @@ -1115,8 +1125,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)) { @@ -1397,8 +1406,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)) {
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 7 +++++++ dlls/d3dx9_36/tests/d3dx9_test_images.h | 5 ++--- dlls/d3dx9_36/tests/texture.c | 9 +++------ dlls/d3dx9_36/texture.c | 4 ++-- 4 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 3065752a36d..ac7c06e73f6 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -34,6 +34,13 @@ #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 { diff --git a/dlls/d3dx9_36/tests/d3dx9_test_images.h b/dlls/d3dx9_36/tests/d3dx9_test_images.h index 5ac14eb3eb4..605e4a0b860 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,11 +35,11 @@ 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 }, /* Any unused filter bits being set results in failure. */ - { 0xff800001, D3DERR_INVALIDCALL, .d3dx_filter_texture_todo = TRUE }, + { 0xff800001, D3DERR_INVALIDCALL }, };
/* 1x1 bmp (1 bpp) */ diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index b58dd104760..e4baf3f5858 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(); } @@ -1176,8 +1174,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/texture.c b/dlls/d3dx9_36/texture.c index 93ab7142ab7..b3fed65244e 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -59,8 +59,8 @@ HRESULT WINAPI D3DXFilterTexture(IDirect3DBaseTexture9 *texture, if (!texture) return D3DERR_INVALIDCALL;
- if ((filter & 0xFFFF) > D3DX_FILTER_BOX && filter != D3DX_DEFAULT) - return D3DERR_INVALIDCALL; + if (filter != D3DX_DEFAULT && FAILED(hr = d3dx9_validate_filter(filter))) + return hr;
if (srclevel == D3DX_DEFAULT) srclevel = 0;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 8 ++++++++ dlls/d3dx9_36/tests/volume.c | 6 ++---- dlls/d3dx9_36/volume.c | 10 ++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index ac7c06e73f6..bf16b3a7590 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -42,6 +42,14 @@ static inline HRESULT d3dx9_validate_filter(uint32_t filter) return D3D_OK; }
+static inline HRESULT d3dx9_handle_load_filter(DWORD *filter) +{ + if (*filter == D3DX_DEFAULT) + *filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + + return d3dx9_validate_filter(*filter); +} + struct vec4 { float x, y, z, w; 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..ae14e47b8b6 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -108,8 +108,8 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, || src_box->Front >= src_box->Back) return E_FAIL;
- if (filter == D3DX_DEFAULT) - filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + if (FAILED(hr = d3dx9_handle_load_filter(&filter))) + return hr;
src_format_desc = get_format_info(src_format); if (src_format_desc->type == FORMAT_UNKNOWN) @@ -180,6 +180,9 @@ HRESULT WINAPI D3DXLoadVolumeFromFileInMemory(IDirect3DVolume9 *dst_volume, cons if (!dst_volume || !src_data || !src_data_size) return D3DERR_INVALIDCALL;
+ if (FAILED(hr = d3dx9_handle_load_filter(&filter))) + return hr; + hr = d3dx_image_init(src_data, src_data_size, &image, 0, 0); if (FAILED(hr)) return D3DXERR_INVALIDDATA; @@ -231,6 +234,9 @@ HRESULT WINAPI D3DXLoadVolumeFromVolume(IDirect3DVolume9 *dst_volume, const PALE
if (!dst_volume || !src_volume) return D3DERR_INVALIDCALL;
+ if (FAILED(hr = d3dx9_handle_load_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 | 10 ++++++++-- dlls/d3dx9_36/tests/surface.c | 9 +++------ 2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 8bc60ec443f..4413a3c4dec 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1258,6 +1258,9 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, if (!pDestSurface || !pSrcData || !SrcDataSize) return D3DERR_INVALIDCALL;
+ if (FAILED(hr = d3dx9_handle_load_filter(&dwFilter))) + return hr; + hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0, 0); if (FAILED(hr)) return D3DXERR_INVALIDDATA; @@ -2205,8 +2208,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, } }
- if (filter == D3DX_DEFAULT) - filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER; + if (FAILED(hr = d3dx9_handle_load_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 +2280,9 @@ HRESULT WINAPI D3DXLoadSurfaceFromSurface(IDirect3DSurface9 *dst_surface, if (!dst_surface || !src_surface) return D3DERR_INVALIDCALL;
+ if (FAILED(hr = d3dx9_handle_load_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/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(); }
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/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 e4baf3f5858..8e299a61360 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);
@@ -2548,8 +2547,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);
@@ -2854,8 +2852,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 b3fed65244e..2820857230d 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -597,6 +597,9 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi if (!device || !texture || !srcdata || !srcdatasize) return D3DERR_INVALIDCALL;
+ if (FAILED(hr = d3dx9_handle_load_filter(&filter))) + return hr; + staging_tex = tex = *texture = NULL; mipfilter = d3dx9_get_mip_filter_value(mipfilter, &skip_levels); hr = d3dx_image_init(srcdata, srcdatasize, &image, skip_levels, 0); @@ -1124,6 +1127,9 @@ HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic if (!device || !data || !data_size || !volume_texture) return D3DERR_INVALIDCALL;
+ if (FAILED(hr = d3dx9_handle_load_filter(&filter))) + return hr; + staging_tex = tex = *volume_texture = NULL; mip_filter = d3dx9_get_mip_filter_value(mip_filter, &skip_levels); hr = d3dx_image_init(data, data_size, &image, skip_levels, 0); @@ -1405,6 +1411,9 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, if (!device || !cube_texture || !src_data || !src_data_size) return D3DERR_INVALIDCALL;
+ if (FAILED(hr = d3dx9_handle_load_filter(&filter))) + return hr; + staging_tex = tex = *cube_texture = NULL; mip_filter = d3dx9_get_mip_filter_value(mip_filter, &skip_levels); hr = d3dx_image_init(src_data, src_data_size, &image, skip_levels, 0);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147541
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000057200DE, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
On Mon Aug 5 10:55:42 2024 +0000, Matteo Bruni wrote:
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?)
Yeah, the mip skip bits are only valid in the `mipfilter` argument. I've removed these from this structure, and added them as a separate test for the `mipfilter` argument only.
On Mon Aug 5 10:54:27 2024 +0000, Connor McAdams wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/6157/diffs?diff_id=125029&start_sha=03b7073a4863c51180ecc52a56b4e64efa0354c7#8fffeae09861a99974e55842964630933974cdc8_2235_2231)
Yeah, there's no need to update the surface in the event of failure. Changed in the current revision.
On Fri Aug 2 21:07:38 2024 +0000, Matteo Bruni wrote:
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);`
Changed this in the current revision. There's no `D3DX_FILTER` type, so I've just used `DWORD` which is what all the filter values are.
I've also re-ordered the patches a bit due to the introduction of this separate helper. Let me know if this is better. :)
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/texture.c:
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();
- }
- /* Mip skip bits are 30-26, 25-23 are unused, setting them does nothing. */
- texture = NULL;
- hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), 32, 32, 6,
0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, 0x03800001, 0, NULL, NULL, &texture);
- ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
- if (texture)
This `if` is unnecessary, here and below for the cube and volume cases.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/texture.c:
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);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); if (texture)
Now this `if` also becomes unnecessary; similarly below.
This merge request was approved by Matteo Bruni.