From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/tests/ddraw2.c | 90 +++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw4.c | 93 +++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw7.c | 83 ++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 3d4a0a26522..79ffe51a6f8 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -16631,6 +16631,95 @@ static void test_multiple_devices(void) DestroyWindow(window); }
+static void test_d3d_state_reset(void) +{ + struct find_different_mode_param param; + IDirect3DViewport2 *viewport; + IDirectDrawSurface *surface; + IDirect3DDevice2 *device; + D3DVIEWPORT2 vp1, vp2; + IDirectDraw2 *ddraw; + DDSURFACEDESC ddsd; + DWORD state; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0); + + window = create_window(); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + + if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))) + { + skip("Failed to create 3D device.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x00282828); + ok(hr == DD_OK, "got %#lx.\n", hr); + hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, TRUE); + ok(hr == DD_OK, "got %#lx.\n", hr); + + memset(¶m, 0, sizeof(param)); + hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, ¶m, find_different_mode_callback); + ok(hr == DD_OK, "got %#lx.\n", hr); + + viewport = create_viewport(device, 0, 0, param.old_width, param.old_height); + ok(hr == DD_OK, "got %#lx.\n", hr); + + vp1.dwSize = sizeof(vp1); + vp2.dwSize = sizeof(vp2); + + hr = IDirect3DDevice2_SetCurrentViewport(device, viewport); + ok(hr == DD_OK, "got %#lx.\n", hr); + hr = IDirect3DViewport2_GetViewport2(viewport, &vp1); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = set_display_mode(ddraw, param.new_width, param.new_height); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirect3DViewport2_GetViewport2(viewport, &vp2); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); + ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(ddsd.dwWidth == param.new_width, "got %ld, expected %d.\n", ddsd.dwWidth, param.new_width); + ok(ddsd.dwHeight == param.new_height, "got %ld, expected %d.\n", ddsd.dwHeight, param.new_height); + + hr = IDirect3DViewport2_GetViewport2(viewport, &vp2); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); + ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight); + + hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_FOGCOLOR, &state); + ok(hr == DD_OK, "got %#lx.\n", hr); + todo_wine ok(state == 0x00282828, "got %#lx.\n", state); + hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &state); + ok(hr == DD_OK, "got %#lx.\n", hr); + todo_wine ok(state == TRUE, "got %#lx.\n", state); + + hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + IDirect3DViewport2_Release(viewport); + IDirectDrawSurface_Release(surface); + IDirectDraw2_Release(ddraw); + IDirect3DDevice2_Release(device); + DestroyWindow(window); +} + START_TEST(ddraw2) { DDDEVICEIDENTIFIER identifier; @@ -16757,4 +16846,5 @@ START_TEST(ddraw2) test_filling_convention(); test_enum_devices(); test_multiple_devices(); + test_d3d_state_reset(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index a0e4fe18c31..278d2b21da0 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -19733,6 +19733,98 @@ static void test_vb_desc(void) ok(!refcount, "Device has %lu references left.\n", refcount); }
+static void test_d3d_state_reset(void) +{ + struct find_different_mode_param param; + IDirect3DViewport3 *viewport; + IDirectDrawSurface4 *surface; + IDirect3DDevice3 *device; + D3DVIEWPORT2 vp1, vp2; + IDirectDraw4 *ddraw; + DDSURFACEDESC2 ddsd; + IDirect3D3 *d3d; + DWORD state; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0); + + if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))) + { + skip("Failed to create 3D device.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice3_GetDirect3D(device, &d3d); + ok(hr == DD_OK, "got %#lx.\n", hr); + hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x00282828); + ok(hr == DD_OK, "got %#lx.\n", hr); + hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, TRUE); + ok(hr == DD_OK, "got %#lx.\n", hr); + + memset(¶m, 0, sizeof(param)); + hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, ¶m, find_different_mode_callback); + ok(hr == DD_OK, "got %#lx.\n", hr); + + viewport = create_viewport(device, 0, 0, param.old_width, param.old_height); + ok(hr == DD_OK, "got %#lx.\n", hr); + + vp1.dwSize = sizeof(vp1); + vp2.dwSize = sizeof(vp2); + + hr = IDirect3DDevice3_SetCurrentViewport(device, viewport); + ok(hr == DD_OK, "got %#lx.\n", hr); + hr = IDirect3DViewport3_GetViewport2(viewport, &vp1); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = set_display_mode(ddraw, param.new_width, param.new_height); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirect3DViewport3_GetViewport2(viewport, &vp2); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); + ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(ddsd.dwWidth == param.new_width, "got %ld, expected %d.\n", ddsd.dwWidth, param.new_width); + ok(ddsd.dwHeight == param.new_height, "got %ld, expected %d.\n", ddsd.dwHeight, param.new_height); + + hr = IDirect3DViewport3_GetViewport2(viewport, &vp2); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); + ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight); + + hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_FOGCOLOR, &state); + ok(hr == DD_OK, "got %#lx.\n", hr); + todo_wine ok(state == 0x00282828, "got %#lx.\n", state); + hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &state); + ok(hr == DD_OK, "got %#lx.\n", hr); + todo_wine ok(state == TRUE, "got %#lx.\n", state); + + hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + IDirect3DViewport3_Release(viewport); + IDirectDrawSurface4_Release(surface); + IDirectDraw4_Release(ddraw); + IDirect3D3_Release(d3d); + IDirect3DDevice3_Release(device); + DestroyWindow(window); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -19876,4 +19968,5 @@ START_TEST(ddraw4) test_enum_devices(); test_multiple_devices(); test_vb_desc(); + test_d3d_state_reset(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index e222e798ffe..709030ecdbe 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -20189,6 +20189,88 @@ static void test_vb_desc(void) ok(!refcount, "Device has %lu references left.\n", refcount); }
+static void test_d3d_state_reset(void) +{ + struct find_different_mode_param param; + IDirectDrawSurface7 *surface; + IDirect3DDevice7 *device; + D3DVIEWPORT7 vp1, vp2; + IDirectDraw7 *ddraw; + DDSURFACEDESC2 ddsd; + IDirect3D7 *d3d; + DWORD state; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0); + + if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))) + { + skip("Failed to create 3D device.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice7_GetDirect3D(device, &d3d); + ok(hr == DD_OK, "got %#lx.\n", hr); + hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x00282828); + ok(hr == DD_OK, "got %#lx.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, TRUE); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirect3DDevice7_GetViewport(device, &vp1); + ok(hr == DD_OK, "got %#lx.\n", hr); + + memset(¶m, 0, sizeof(param)); + hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, ¶m, find_different_mode_callback); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = set_display_mode(ddraw, param.new_width, param.new_height); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirect3DDevice7_GetViewport(device, &vp2); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); + ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(ddsd.dwWidth == param.new_width, "got %ld, expected %d.\n", ddsd.dwWidth, param.new_width); + ok(ddsd.dwHeight == param.new_height, "got %ld, expected %d.\n", ddsd.dwHeight, param.new_height); + + hr = IDirect3DDevice7_GetViewport(device, &vp2); + ok(hr == DD_OK, "got %#lx.\n", hr); + todo_wine ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); + todo_wine ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight); + + hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_FOGCOLOR, &state); + ok(hr == DD_OK, "got %#lx.\n", hr); + todo_wine ok(state == 0x00282828, "got %#lx.\n", state); + hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &state); + ok(hr == DD_OK, "got %#lx.\n", hr); + todo_wine ok(state == TRUE, "got %#lx.\n", state); + + hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + IDirectDrawSurface7_Release(surface); + IDirectDraw7_Release(ddraw); + IDirect3D7_Release(d3d); + IDirect3DDevice7_Release(device); + DestroyWindow(window); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -20366,4 +20448,5 @@ START_TEST(ddraw7) test_flip_3d(); test_multiple_devices(); test_vb_desc(); + test_d3d_state_reset(); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/surface.c | 20 ++++++++++++++++++-- dlls/ddraw/tests/ddraw2.c | 4 ++-- dlls/ddraw/tests/ddraw4.c | 4 ++-- dlls/ddraw/tests/ddraw7.c | 8 ++++---- 4 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 71179b01a0b..6a7b5bdb680 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -6780,6 +6780,22 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) { + if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, + device->state, WINED3D_SBT_ALL, &device->saved_state))) + { + struct list *entry; + + ERR("Failed to create stateblock, hr %#lx.\n", hr); + entry = &device->ddraw_entry; + while ((entry = list_prev(&ddraw->d3ddevice_list, entry))) + { + device = LIST_ENTRY(entry, struct d3d_device, ddraw_entry); + wined3d_stateblock_decref(device->saved_state); + device->saved_state = NULL; + } + free(texture); + return E_OUTOFMEMORY; + } if (device->recording) wined3d_stateblock_decref(device->recording); device->recording = NULL; @@ -6797,8 +6813,8 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) { - wined3d_stateblock_set_render_state(device->state, WINED3D_RS_ZENABLE, - !!swapchain_desc.enable_auto_depth_stencil); + wined3d_stateblock_apply(device->saved_state, device->state); + device->saved_state = NULL; } } } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 79ffe51a6f8..66fceafbc8d 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -16705,10 +16705,10 @@ static void test_d3d_state_reset(void)
hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_FOGCOLOR, &state); ok(hr == DD_OK, "got %#lx.\n", hr); - todo_wine ok(state == 0x00282828, "got %#lx.\n", state); + ok(state == 0x00282828, "got %#lx.\n", state); hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &state); ok(hr == DD_OK, "got %#lx.\n", hr); - todo_wine ok(state == TRUE, "got %#lx.\n", state); + ok(state == TRUE, "got %#lx.\n", state);
hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL); ok(hr == DD_OK, "got %#lx.\n", hr); diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 278d2b21da0..a952eb683a5 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -19809,10 +19809,10 @@ static void test_d3d_state_reset(void)
hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_FOGCOLOR, &state); ok(hr == DD_OK, "got %#lx.\n", hr); - todo_wine ok(state == 0x00282828, "got %#lx.\n", state); + ok(state == 0x00282828, "got %#lx.\n", state); hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &state); ok(hr == DD_OK, "got %#lx.\n", hr); - todo_wine ok(state == TRUE, "got %#lx.\n", state); + ok(state == TRUE, "got %#lx.\n", state);
hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL); ok(hr == DD_OK, "got %#lx.\n", hr); diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 709030ecdbe..04fe5a2049b 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -20251,15 +20251,15 @@ static void test_d3d_state_reset(void)
hr = IDirect3DDevice7_GetViewport(device, &vp2); ok(hr == DD_OK, "got %#lx.\n", hr); - todo_wine ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); - todo_wine ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight); + ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth); + ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight);
hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_FOGCOLOR, &state); ok(hr == DD_OK, "got %#lx.\n", hr); - todo_wine ok(state == 0x00282828, "got %#lx.\n", state); + ok(state == 0x00282828, "got %#lx.\n", state); hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &state); ok(hr == DD_OK, "got %#lx.\n", hr); - todo_wine ok(state == TRUE, "got %#lx.\n", state); + ok(state == TRUE, "got %#lx.\n", state);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL); ok(hr == DD_OK, "got %#lx.\n", hr);
The Bright Star Of Seraph-Katis depends on that. Specifically on not resetting the viewport. The game uses an own render target surface which is not primary surface for the d3d device and it is more apparent that nothing should change in d3d state in that case but the tests added in the MR suggest that even with a default render target viewport is not reset.
I need to do some research; there may be a better way to solve this problem.
I need to do some research; there may be a better way to solve this problem.
Well, if it's purely about not resetting state, wined3d_device_reset() has a "reset_state" parameter that can be set to FALSE. The reason it's currently set to TRUE is mostly because the wined3d_device_reset() call was introduced before the "reset_state" parameter, and TRUE matches the previous behaviour.