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); return s_origVtable.CreateSurface(This, lpDDSurfaceDesc, lplpDDSurface, pUnkOuter);
} }
HRESULT result = DD_OK; if (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
const bool isPrimary = 0 != (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
if (isPrimary)
{ {
result = PrimarySurface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface); return PrimarySurface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface);
} }
else else
{ {
result = Surface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface); return Surface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface);
} }
return result;
} }
template <typename TDirectDraw> template <typename TDirectDraw>

View File

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

View File

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

View File

@ -80,19 +80,38 @@ namespace DDraw
} }
HRESULT result = m_impl.Flip(This, lpDDSurfaceTargetOverride, dwFlags); HRESULT result = m_impl.Flip(This, lpDDSurfaceTargetOverride, dwFlags);
if (SUCCEEDED(result)) if (FAILED(result))
{ {
result = RealPrimarySurface::flip(dwFlags); return result;
if (SUCCEEDED(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( s_origVtable.BltFast(This, 0, 0, lpDDSurfaceTargetOverride, nullptr, DDBLTFAST_WAIT);
CompatPtr<IDirectDrawSurface>::from(lpDDSurfaceTargetOverride));
} }
else 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; return result;
} }

View File

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