From 67559215608eaf7338cbc7002ba3b74bf972a3a4 Mon Sep 17 00:00:00 2001 From: Simone Mario Lombardo Date: Wed, 9 Nov 2022 18:44:30 +0100 Subject: [PATCH] [DDRAW] Sync the fix for swap_interval from Wine (#4831) Sync the barebone fix from Wine (wine-7.19-557-g13cc08e32d6): https://source.winehq.org/git/wine.git/?a=search&h=HEAD&st=grep&s=ddraw_surface_update_frontbuffer%28 and https://source.winehq.org/git/wine.git/blob/13cc08e32d6c04f8f915d07cda39638ee99c3d43:/dlls/ddraw/surface.c - Added "swap_interval" argument to ddraw_surface_update_frontbuffer() - Added ddraw_swap_interval_from_flags() function for dispatching the integer type of required swap interval - Updated ddraw_surface_update_frontbuffer() function for managing the swap interval between backbuffer and frontbuffer (and relative flipping) - Updated the ddraw_surface7_Flip() function for relaying the swap interval to ddraw_surface_update_frontbuffer() function. - Added 0 value (as Wine) when the swap interval is not required This fixes empty white screen issue on rendering because of lacking swap interval for the software / games that use ddraw. CORE-18547 --- dll/directx/wine/ddraw/ddraw_private.h | 2 +- dll/directx/wine/ddraw/palette.c | 2 +- dll/directx/wine/ddraw/surface.c | 59 +++++++++++++++++++------- media/doc/WINESYNC.txt | 2 +- 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/dll/directx/wine/ddraw/ddraw_private.h b/dll/directx/wine/ddraw/ddraw_private.h index cac38c57e92..433bcd34a3d 100644 --- a/dll/directx/wine/ddraw/ddraw_private.h +++ b/dll/directx/wine/ddraw/ddraw_private.h @@ -218,7 +218,7 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN; HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, - const RECT *rect, BOOL read) DECLSPEC_HIDDEN; + const RECT *rect, BOOL read, unsigned int swap_interval) DECLSPEC_HIDDEN; static inline struct ddraw_surface *impl_from_IDirect3DTexture(IDirect3DTexture *iface) { diff --git a/dll/directx/wine/ddraw/palette.c b/dll/directx/wine/ddraw/palette.c index 5148832cab6..87aec96443a 100644 --- a/dll/directx/wine/ddraw/palette.c +++ b/dll/directx/wine/ddraw/palette.c @@ -176,7 +176,7 @@ static HRESULT WINAPI ddraw_palette_SetEntries(IDirectDrawPalette *iface, hr = wined3d_palette_set_entries(palette->wined3d_palette, flags, start, count, entries); if (SUCCEEDED(hr) && palette->flags & DDPCAPS_PRIMARYSURFACE) - ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE); + ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE, 0); wined3d_mutex_unlock(); diff --git a/dll/directx/wine/ddraw/surface.c b/dll/directx/wine/ddraw/surface.c index 11a0e6ba8db..c26cc76baab 100644 --- a/dll/directx/wine/ddraw/surface.c +++ b/dll/directx/wine/ddraw/surface.c @@ -40,8 +40,9 @@ static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDra * applications from drawing to the screen while we've locked the frontbuffer. * We'd like to do this in wined3d instead, but for that to work wined3d needs * to support windowless rendering first. */ -HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read) +HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read, unsigned int swap_interval) { + struct wined3d_texture *dst_texture; struct ddraw *ddraw = surface->ddraw; HDC surface_dc, screen_dc; int x, y, w, h; @@ -70,8 +71,18 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RE if (read) return DD_OK; - return wined3d_texture_blt(ddraw->wined3d_frontbuffer, 0, rect, - surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT); + if (swap_interval) + dst_texture = wined3d_swapchain_get_back_buffer(ddraw->wined3d_swapchain, 0); + else + dst_texture = ddraw->wined3d_frontbuffer; + + if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, + surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT))){ + hr = wined3d_swapchain_present(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0); + ddraw->flags |= DDRAW_GDI_FLIP; + } + + return hr; } if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc))) @@ -474,7 +485,7 @@ static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectD palette_impl->flags |= DDPCAPS_PRIMARYSURFACE; wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain, palette_impl ? palette_impl->wined3d_palette : NULL); - ddraw_surface_update_frontbuffer(surface, NULL, FALSE); + ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0); } if (palette_impl) IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface); @@ -990,7 +1001,7 @@ static HRESULT surface_lock(struct ddraw_surface *surface, } if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE); + hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0); if (SUCCEEDED(hr)) hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx, &map_desc, rect ? &box : NULL, @@ -1179,7 +1190,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface wined3d_mutex_lock(); hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx); if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE); + hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE, 0); wined3d_mutex_unlock(); return hr; @@ -1224,6 +1235,24 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL); } +static unsigned int ddraw_swap_interval_from_flags(DWORD flags) +{ + if (flags & DDFLIP_NOVSYNC) + return 0; + + switch (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) + { + case DDFLIP_INTERVAL2: + return 2; + case DDFLIP_INTERVAL3: + return 3; + case DDFLIP_INTERVAL4: + return 4; + default: + return 1; + } +} + static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *src, DWORD flags) { @@ -1347,7 +1376,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 } if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE); + hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE,ddraw_swap_interval_from_flags(flags)); else hr = DD_OK; @@ -1488,11 +1517,11 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (!dst_surface->clipper) { if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE); + hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE, 0); if (SUCCEEDED(hr)) hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter); if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) - hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE); + hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE, 0); return hr; } @@ -1535,7 +1564,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { - if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE))) + if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE, 0))) break; } } @@ -1546,7 +1575,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { - if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE))) + if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE, 0))) break; } } @@ -2219,7 +2248,7 @@ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc) if (surface->dc) hr = DDERR_DCALREADYCREATED; else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE); + hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0); if (SUCCEEDED(hr)) hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc); @@ -2323,7 +2352,7 @@ static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC h { surface->dc = NULL; if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE); + hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0); } wined3d_mutex_unlock(); @@ -4291,12 +4320,12 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurfac } if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE); + hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0); if (SUCCEEDED(hr)) hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect, src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT); if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) - hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE); + hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0); wined3d_mutex_unlock(); switch(hr) diff --git a/media/doc/WINESYNC.txt b/media/doc/WINESYNC.txt index 43def4ebffe..cb460336c0d 100644 --- a/media/doc/WINESYNC.txt +++ b/media/doc/WINESYNC.txt @@ -28,7 +28,7 @@ dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-4.18 dll/directx/wine/d3drm # Synced to WineStaging-4.18 dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-6.0-rc5 dll/directx/wine/d3dxof # Synced to WineStaging-4.18 -dll/directx/wine/ddraw # Synced to WineStaging-3.3 +dll/directx/wine/ddraw # Synced to WineStaging-3.3 (+ partial sync of ddraw_private.h, palette.c, and surface.c to wine-7.19-557-g13cc08e32d6) dll/directx/wine/devenum # Synced to WineStaging-4.18 dll/directx/wine/dinput # Synced to WineStaging-4.18 dll/directx/wine/dinput8 # Synced to WineStaging-4.18