[PATCH v8 0/3] MR10874: wined3d: Disallow locking of multisampled back buffers.
-- v8: wined3d: Disallow locking of multisampled back buffers. d3d9/tests: Test multisampled back buffer locking. d3d8/tests: Test multisampled back buffer locking. https://gitlab.winehq.org/wine/wine/-/merge_requests/10874
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/d3d8/tests/device.c | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index 02383233cff..82a4bcaee2f 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -9341,6 +9341,7 @@ static void test_lockable_backbuffer(void) { D3DPRESENT_PARAMETERS present_parameters = {0}; struct device_desc device_desc; + IDirect3DSwapChain8 *swapchain; IDirect3DSurface8 *surface; IDirect3DDevice8 *device; D3DLOCKED_RECT lockrect; @@ -9415,6 +9416,51 @@ static void test_lockable_backbuffer(void) IDirect3DSurface8_Release(surface); refcount = IDirect3DDevice8_Release(device); ok(!refcount, "Device has %lu references left.\n", refcount); + + if (SUCCEEDED(IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES))) + { + /* Multisampling is allowed. */ + present_parameters.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES; + hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device); + ok(hr == D3D_OK, "Failed to create device, hr %#lx.\n", hr); + + hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface); + ok(hr == D3D_OK, "Failed to get backbuffer, hr %#lx.\n", hr); + + /* But locking multisampled is not allowed. */ + hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + IDirect3DSurface8_UnlockRect(surface); + + IDirect3DSurface8_Release(surface); + + present_parameters.hDeviceWindow = NULL; + hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &present_parameters, &swapchain); + ok(hr == D3D_OK, "Failed to create swapchain, hr %#lx.\n", hr); + + hr = IDirect3DSwapChain8_GetBackBuffer(swapchain, 0, 0, &surface); + ok(hr == D3D_OK, "Failed to get backbuffer, hr %#lx.\n", hr); + + hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + IDirect3DSurface8_UnlockRect(surface); + + IDirect3DSurface8_Release(surface); + IDirect3DSwapChain8_Release(swapchain); + + IDirect3DDevice8_Release(device); + } + else + { + skip("Multisampling not supported for D3DFMT_A8R8G8B8.\n"); + } + IDirect3D8_Release(d3d); DestroyWindow(window); } @@ -9507,7 +9553,9 @@ static void test_clip_planes_limits(void) static void test_swapchain_multisample_reset(void) { D3DPRESENT_PARAMETERS present_parameters; + IDirect3DSurface8 *surface; IDirect3DDevice8 *device; + D3DLOCKED_RECT lr; IDirect3D8 *d3d; ULONG refcount; HWND window; @@ -9552,6 +9600,23 @@ static void test_swapchain_multisample_reset(void) hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); ok(hr == D3D_OK, "Failed to clear, hr %#lx.\n", hr); + /* Lockable back buffer flag is allowed. */ + present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + hr = IDirect3DDevice8_Reset(device, &present_parameters); + ok(hr == D3D_OK, "Failed to reset device, hr %#lx.\n", hr); + + hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface); + ok(hr == D3D_OK, "Failed to get backbuffer, hr %#lx.\n", hr); + + /* But locking is not allowed. */ + hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + IDirect3DSurface8_UnlockRect(surface); + + IDirect3DSurface8_Release(surface); + refcount = IDirect3DDevice8_Release(device); ok(!refcount, "Device has %lu references left.\n", refcount); IDirect3D8_Release(d3d); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10874
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/d3d9/tests/device.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 3dc9bff4dc2..cb14f3f1de1 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -13047,6 +13047,7 @@ static void test_lockable_backbuffer(void) { D3DPRESENT_PARAMETERS present_parameters = {0}; struct device_desc device_desc; + IDirect3DSwapChain9 *swapchain; IDirect3DSurface9 *surface; IDirect3DDevice9 *device; D3DLOCKED_RECT lockrect; @@ -13125,8 +13126,26 @@ static void test_lockable_backbuffer(void) ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#lx.\n", hr); IDirect3DSurface9_Release(surface); + + present_parameters.hDeviceWindow = NULL; + present_parameters.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES; + hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &present_parameters, &swapchain); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + IDirect3DSwapChain9_Release(swapchain); + refcount = IDirect3DDevice9_Release(device); ok(!refcount, "Device has %lu references left.\n", refcount); + + present_parameters.hDeviceWindow = window; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d); DestroyWindow(window); } @@ -13269,6 +13288,15 @@ static void test_swapchain_multisample_reset(void) hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); ok(hr == D3D_OK, "Failed to clear, hr %#lx.\n", hr); + /* Lockable back buffer flag is not allowed. */ + d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + hr = IDirect3DDevice9_Reset(device, &d3dpp); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); + hr = IDirect3DDevice9_TestCooperativeLevel(device); + todo_wine + ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned hr %#lx.\n", hr); + refcount = IDirect3DDevice9_Release(device); ok(!refcount, "Device has %lu references left.\n", refcount); IDirect3D9_Release(d3d); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10874
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/d3d8/device.c | 3 ++- dlls/d3d8/tests/device.c | 9 --------- dlls/d3d9/tests/device.c | 8 -------- dlls/wined3d/device.c | 5 ++++- dlls/wined3d/swapchain.c | 15 ++++++++++++++- dlls/wined3d/wined3d_private.h | 2 ++ include/wine/wined3d.h | 2 ++ 7 files changed, 24 insertions(+), 20 deletions(-) diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 036c60edc37..c04283c1ad4 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -308,7 +308,8 @@ static BOOL wined3d_swapchain_desc_from_d3d8(struct wined3d_swapchain_desc *swap swapchain_desc->auto_depth_stencil_format = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat); swapchain_desc->flags - = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) | WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; + = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) | WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH + | WINED3D_SWAPCHAIN_ALLOW_MS_LOCKABLE_BACKBUFFER; swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz; swapchain_desc->auto_restore_display_mode = TRUE; diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index 82a4bcaee2f..fed5923ca5d 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -9431,10 +9431,7 @@ static void test_lockable_backbuffer(void) /* But locking multisampled is not allowed. */ hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - IDirect3DSurface8_UnlockRect(surface); IDirect3DSurface8_Release(surface); @@ -9446,10 +9443,7 @@ static void test_lockable_backbuffer(void) ok(hr == D3D_OK, "Failed to get backbuffer, hr %#lx.\n", hr); hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - IDirect3DSurface8_UnlockRect(surface); IDirect3DSurface8_Release(surface); IDirect3DSwapChain8_Release(swapchain); @@ -9610,10 +9604,7 @@ static void test_swapchain_multisample_reset(void) /* But locking is not allowed. */ hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - IDirect3DSurface8_UnlockRect(surface); IDirect3DSurface8_Release(surface); diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index cb14f3f1de1..24c02ea6b68 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -13130,10 +13130,7 @@ static void test_lockable_backbuffer(void) present_parameters.hDeviceWindow = NULL; present_parameters.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES; hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &present_parameters, &swapchain); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - IDirect3DSwapChain9_Release(swapchain); refcount = IDirect3DDevice9_Release(device); ok(!refcount, "Device has %lu references left.\n", refcount); @@ -13141,10 +13138,7 @@ static void test_lockable_backbuffer(void) present_parameters.hDeviceWindow = window; hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - IDirect3DDevice9_Release(device); IDirect3D9_Release(d3d); DestroyWindow(window); @@ -13291,10 +13285,8 @@ static void test_swapchain_multisample_reset(void) /* Lockable back buffer flag is not allowed. */ d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; hr = IDirect3DDevice9_Reset(device, &d3dpp); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr); hr = IDirect3DDevice9_TestCooperativeLevel(device); - todo_wine ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned hr %#lx.\n", hr); refcount = IDirect3DDevice9_Release(device); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index e754cc633b7..8f195c6dee4 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4987,7 +4987,7 @@ static void update_swapchain_flags(struct wined3d_texture *texture) { unsigned int flags = texture->swapchain->state.desc.flags; - if (flags & WINED3D_SWAPCHAIN_LOCKABLE_BACKBUFFER) + if (flags & WINED3D_SWAPCHAIN_LOCKABLE_BACKBUFFER && !texture->swapchain->state.desc.multisample_type) texture->resource.access |= WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; else texture->resource.access &= ~(WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W); @@ -5082,6 +5082,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, TRACE("refresh_rate %u\n", swapchain_desc->refresh_rate); TRACE("auto_restore_display_mode %#x\n", swapchain_desc->auto_restore_display_mode); + if (FAILED(hr = wined3d_swapchain_desc_validate_flags(swapchain_desc))) + return hr; + if (swapchain_desc->backbuffer_bind_flags && swapchain_desc->backbuffer_bind_flags != WINED3D_BIND_RENDER_TARGET) FIXME("Got unexpected backbuffer bind flags %#x.\n", swapchain_desc->backbuffer_bind_flags); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 2bc544c1213..c26df770cdb 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -1506,7 +1506,7 @@ static HRESULT swapchain_create_texture(struct wined3d_swapchain *swapchain, texture_desc.access = WINED3D_RESOURCE_ACCESS_CPU; else texture_desc.access = WINED3D_RESOURCE_ACCESS_GPU; - if (!depth && (swapchain_desc->flags & WINED3D_SWAPCHAIN_LOCKABLE_BACKBUFFER)) + if (!depth && (swapchain_desc->flags & WINED3D_SWAPCHAIN_LOCKABLE_BACKBUFFER) && !swapchain_desc->multisample_type) texture_desc.access |= WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; texture_desc.width = swapchain_desc->backbuffer_width; texture_desc.height = swapchain_desc->backbuffer_height; @@ -1536,6 +1536,16 @@ static HRESULT swapchain_create_texture(struct wined3d_swapchain *swapchain, return S_OK; } +HRESULT wined3d_swapchain_desc_validate_flags(const struct wined3d_swapchain_desc *desc) +{ + /* d3d8 allows the lockable flag even though the backbuffer is not lockable. */ + if ((desc->flags & WINED3D_SWAPCHAIN_LOCKABLE_BACKBUFFER) && desc->multisample_type + && !(desc->flags & WINED3D_SWAPCHAIN_ALLOW_MS_LOCKABLE_BACKBUFFER)) + return WINED3DERR_INVALIDCALL; + + return WINED3D_OK; +} + static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device, const struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops, @@ -1554,6 +1564,9 @@ static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struc && desc->swap_effect != WINED3D_SWAP_EFFECT_COPY) FIXME("Unimplemented swap effect %#x.\n", desc->swap_effect); + if (FAILED(hr = wined3d_swapchain_desc_validate_flags(desc))) + return hr; + window = desc->device_window ? desc->device_window : device->create_parms.focus_window; TRACE("Using target window %p.\n", window); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index fa758c53cc1..f8e367b2637 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4062,6 +4062,8 @@ struct wined3d_decoder_output_view void wined3d_decoder_output_view_cleanup(struct wined3d_decoder_output_view *view); +HRESULT wined3d_swapchain_desc_validate_flags(const struct wined3d_swapchain_desc *desc); + struct wined3d_swapchain_state { struct wined3d *wined3d; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index cfb098adfb0..355140043db 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -920,6 +920,8 @@ enum wined3d_memory_segment_group #define WINED3D_SWAPCHAIN_NO_WINDOW_CHANGES 0x00040000u #define WINED3D_SWAPCHAIN_RESTORE_WINDOW_STATE 0x00080000u #define WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER 0x00100000u +/* Allow the swapchain flag, but not actual locking */ +#define WINED3D_SWAPCHAIN_ALLOW_MS_LOCKABLE_BACKBUFFER 0x00200000u #define WINED3DDP_MAXTEXCOORD 8 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10874
Looks good to me like this. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10874#note_141983
This merge request was approved by Henri Verbeet. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10874
This merge request was approved by Elizabeth Figura. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10874
participants (4)
-
Conor McCarthy -
Conor McCarthy (@cmccarthy) -
Elizabeth Figura (@zfigura) -
Henri Verbeet (@hverbeet)