1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Emulate flip when the primary surface is requested in system memory

When the primary surface chain is requested to be created in system memory,
flip should be emulated (copy from back buffer to front buffer) to be
consistent with legacy DirectDraw behavior.

Fixes flashing graphical artifacts in Carmageddon (Win95 version) menus
when exiting from a race, mentioned in issue #3.
This commit is contained in:
narzoul 2017-07-25 21:27:40 +02:00
parent b78446c16f
commit 947bb41bf3
5 changed files with 39 additions and 17 deletions

View File

@ -122,20 +122,14 @@ namespace DDraw
return s_origVtable.CreateSurface(This, lpDDSurfaceDesc, lplpDDSurface, pUnkOuter);
}
HRESULT result = DD_OK;
const bool isPrimary = 0 != (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
if (isPrimary)
if (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
{
result = PrimarySurface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface);
return PrimarySurface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface);
}
else
{
result = Surface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface);
return Surface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface);
}
return result;
}
template <typename TDirectDraw>

View File

@ -10,6 +10,7 @@ namespace
DDSURFACEDESC2 g_primarySurfaceDesc = {};
CompatWeakPtr<IDirectDrawSurface> g_gdiSurface = nullptr;
CompatWeakPtr<IDirectDrawSurface> g_primarySurface = nullptr;
bool g_isFlipEmulated = false;
}
namespace DDraw
@ -25,6 +26,7 @@ namespace DDraw
g_gdiSurface = nullptr;
g_primarySurface = nullptr;
g_isFlipEmulated = false;
s_palette = nullptr;
s_surfaceBuffers.clear();
ZeroMemory(&s_paletteEntries, sizeof(s_paletteEntries));
@ -67,6 +69,7 @@ namespace DDraw
CompatPtr<IDirectDrawSurface> surface1(Compat::queryInterface<IDirectDrawSurface>(surface));
g_gdiSurface = surface1;
g_primarySurface = surface1;
g_isFlipEmulated = 0 != (desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc));
g_primarySurfaceDesc.dwSize = sizeof(g_primarySurfaceDesc);
@ -127,6 +130,11 @@ namespace DDraw
Compat::queryInterface<IDirectDrawSurface7>(g_primarySurface.get()));
}
bool PrimarySurface::isFlipEmulated()
{
return g_isFlipEmulated;
}
void PrimarySurface::resizeBuffers(CompatRef<IDirectDrawSurface7> surface)
{
DDSCAPS2 flipCaps = {};

View File

@ -20,6 +20,7 @@ namespace DDraw
static const DDSURFACEDESC2& getDesc();
static CompatPtr<IDirectDrawSurface7> getGdiSurface();
static CompatPtr<IDirectDrawSurface7> getPrimary();
static bool isFlipEmulated();
void updateGdiSurfacePtr(IDirectDrawSurface* flipTargetOverride);

View File

@ -80,19 +80,38 @@ namespace DDraw
}
HRESULT result = m_impl.Flip(This, lpDDSurfaceTargetOverride, dwFlags);
if (SUCCEEDED(result))
if (FAILED(result))
{
result = RealPrimarySurface::flip(dwFlags);
if (SUCCEEDED(result))
return result;
}
result = RealPrimarySurface::flip(dwFlags);
if (SUCCEEDED(result) && !PrimarySurface::isFlipEmulated())
{
static_cast<PrimarySurface*>(m_data)->updateGdiSurfacePtr(
CompatPtr<IDirectDrawSurface>::from(lpDDSurfaceTargetOverride));
return DD_OK;
}
undoFlip(This, lpDDSurfaceTargetOverride);
if (SUCCEEDED(result) && PrimarySurface::isFlipEmulated())
{
if (lpDDSurfaceTargetOverride)
{
static_cast<PrimarySurface*>(m_data)->updateGdiSurfacePtr(
CompatPtr<IDirectDrawSurface>::from(lpDDSurfaceTargetOverride));
s_origVtable.BltFast(This, 0, 0, lpDDSurfaceTargetOverride, nullptr, DDBLTFAST_WAIT);
}
else
{
undoFlip(This, lpDDSurfaceTargetOverride);
TDdsCaps caps = {};
caps.dwCaps = DDSCAPS_BACKBUFFER;
CompatPtr<TSurface> backBuffer;
s_origVtable.GetAttachedSurface(This, &caps, &backBuffer.getRef());
s_origVtable.BltFast(This, 0, 0, backBuffer, nullptr, DDBLTFAST_WAIT);
}
}
return result;
}

View File

@ -56,6 +56,8 @@ namespace DDraw
protected:
void undoFlip(TSurface* This, TSurface* targetOverride);
static const Vtable<TSurface>& s_origVtable;
private:
bool bltRetry(TSurface*& dstSurface, RECT*& dstRect,
TSurface*& srcSurface, RECT*& srcRect, bool isTransparentBlt,
@ -63,7 +65,5 @@ namespace DDraw
bool prepareBltRetrySurface(TSurface*& surface, RECT*& rect,
const TSurfaceDesc& desc, bool isTransparentBlt, bool isCopyNeeded);
void replaceWithVidMemSurface(TSurface*& surface, RECT*& rect, const TSurfaceDesc& desc);
static const Vtable<TSurface>& s_origVtable;
};
}