Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48923
Fixes a regression triggered by 530a3d94de949030f8d74bacd6c20986b32f1a31.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - Fix test failure with 'gdi' renderer.
dlls/ddraw/ddraw.c | 2 +- dlls/ddraw/ddraw_private.h | 9 +++++++ dlls/ddraw/surface.c | 12 ++++++++- dlls/ddraw/tests/ddraw7.c | 54 +++++++++++++++++++++++++++++++++++--- 4 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 95e9fba901..2a4900ea7b 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -4899,7 +4899,7 @@ void ddraw_update_lost_surfaces(struct ddraw *ddraw)
LIST_FOR_EACH_ENTRY(surface, &ddraw->surface_list, struct ddraw_surface, surface_list_entry) { - surface->is_lost = TRUE; + surface->is_lost = ddraw_surface_can_be_lost(surface); } ddraw->device_state = DDRAW_DEVICE_STATE_OK; } diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 83e3ee10c0..c82dce542f 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -221,6 +221,7 @@ struct ddraw_texture struct wined3d_device *wined3d_device;
void *texture_memory; + BOOL sysmem_fallback; };
HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc, @@ -637,6 +638,14 @@ static inline BOOL format_is_paletteindexed(const DDPIXELFORMAT *fmt) return !!(fmt->dwFlags & flags); }
+static inline BOOL ddraw_surface_can_be_lost(const struct ddraw_surface *surface) +{ + if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) + return TRUE; + + return ((const struct ddraw_texture *)wined3d_texture_get_parent(surface->wined3d_texture))->sysmem_fallback; +} + /* Used for generic dumping */ struct flag_info { diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 20143891d3..e159a671de 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -35,7 +35,8 @@ static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDra
static BOOL ddraw_surface_is_lost(const struct ddraw_surface *surface) { - return surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost; + return ddraw_surface_can_be_lost(surface) + && (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost); }
/* This is slow, of course. Also, in case of locks, we can't prevent other @@ -5891,6 +5892,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ struct wined3d_display_mode mode; DDSURFACEDESC2 *desc, *mip_desc; struct ddraw_texture *texture; + BOOL sysmem_fallback = FALSE; unsigned int layers = 1; unsigned int pitch = 0; BOOL reserve_memory; @@ -6213,9 +6215,14 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ if (!(ddraw->flags & DDRAW_NO3D) && SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, ddraw->wined3d_adapter, WINED3D_DEVICE_TYPE_HAL, mode.format_id, usage, bind_flags, WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format))) + { desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + } else + { desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + sysmem_fallback = TRUE; + } } else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) { @@ -6371,6 +6378,8 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ layers = 6; }
+ texture->sysmem_fallback = sysmem_fallback; + /* Some applications assume surfaces will always be mapped at the same * address. Some of those also assume that this address is valid even when * the surface isn't mapped, and that updates done this way will be @@ -6498,6 +6507,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ }
texture->texture_memory = NULL; + texture->sysmem_fallback = sysmem_fallback; texture->version = version; texture->surface_desc = root->surface_desc; desc = &texture->surface_desc; diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index e942f44f29..82162bafdc 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -9269,6 +9269,7 @@ static void test_vb_writeonly(void) static void test_lost_device(void) { IDirectDrawSurface7 *surface, *back_buffer; + IDirectDrawSurface7 *sysmem_surface; DDSURFACEDESC2 surface_desc; HWND window1, window2; IDirectDraw7 *ddraw; @@ -9284,7 +9285,7 @@ static void test_lost_device(void) ddraw = create_ddraw(); ok(!!ddraw, "Failed to create a ddraw object.\n"); hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); - ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
memset(&surface_desc, 0, sizeof(surface_desc)); surface_desc.dwSize = sizeof(surface_desc); @@ -9292,7 +9293,16 @@ static void test_lost_device(void) surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; U5(surface_desc).dwBackBufferCount = 1; hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); - ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + surface_desc.dwWidth = 100; + surface_desc.dwHeight = 100; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_TestCooperativeLevel(ddraw); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9300,6 +9310,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
ret = SetForegroundWindow(GetDesktopWindow()); ok(ret, "Failed to set foreground window.\n"); @@ -9309,6 +9321,8 @@ static void test_lost_device(void) ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
ret = SetForegroundWindow(window1); ok(ret, "Failed to set foreground window.\n"); @@ -9318,6 +9332,8 @@ static void test_lost_device(void) ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_RestoreAllSurfaces(ddraw); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9327,6 +9343,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9336,6 +9354,8 @@ static void test_lost_device(void) todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
/* Trying to restore the primary will crash, probably because flippable * surfaces can't exist in DDSCL_NORMAL. */ @@ -9345,12 +9365,16 @@ static void test_lost_device(void) surface_desc.dwFlags = DDSD_CAPS; surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); - ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_TestCooperativeLevel(ddraw); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_IsLost(surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
ret = SetForegroundWindow(GetDesktopWindow()); ok(ret, "Failed to set foreground window.\n"); @@ -9358,6 +9382,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_IsLost(surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
ret = SetForegroundWindow(window1); ok(ret, "Failed to set foreground window.\n"); @@ -9365,6 +9391,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_IsLost(surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9372,6 +9400,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_IsLost(surface); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_RestoreAllSurfaces(ddraw); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9379,6 +9409,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_IsLost(surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
IDirectDrawSurface7_Release(surface); memset(&surface_desc, 0, sizeof(surface_desc)); @@ -9387,7 +9419,7 @@ static void test_lost_device(void) surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; U5(surface_desc).dwBackBufferCount = 1; hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); - ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9397,6 +9429,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9406,6 +9440,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9415,6 +9451,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9424,6 +9462,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9433,6 +9473,8 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); @@ -9442,6 +9484,8 @@ static void test_lost_device(void) ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
memset(&caps, 0, sizeof(caps)); caps.dwCaps = DDSCAPS_FLIP; @@ -9454,8 +9498,10 @@ static void test_lost_device(void) ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_IsLost(back_buffer); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + IDirectDrawSurface7_Release(back_buffer);
+ IDirectDrawSurface7_Release(sysmem_surface); IDirectDrawSurface7_Release(surface); refcount = IDirectDraw7_Release(ddraw); ok(!refcount, "Got unexpected refcount %u.\n", refcount);