1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00
DDrawCompat/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp
narzoul 5195a5e4b4 Minimize GDI redraws on window position changes
When the display mode changes in full screen mode, DirectDraw resets
the main window to topmost after a short delay, generating a
WM_WINDOWPOSCHANGED message. This could cause an unnecessary repainting
of the window, erasing the background even if nothing needed to be updated.

Now only the regions that change during window repositioning are redrawn.

Fixes the black flashing in Rogue Spear's menus after display mode changes,
mentioned in issue #2.
2017-05-28 12:43:43 +02:00

244 lines
6.0 KiB
C++

#include "DDraw/DirectDrawPalette.h"
#include "DDraw/RealPrimarySurface.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "DDraw/Surfaces/PrimarySurfaceImpl.h"
#include "Gdi/Gdi.h"
namespace
{
void restorePrimaryCaps(DWORD& caps)
{
caps &= ~DDSCAPS_OFFSCREENPLAIN;
caps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE;
}
}
namespace DDraw
{
template <typename TSurface>
PrimarySurfaceImpl<TSurface>::PrimarySurfaceImpl(SurfaceImpl& impl) : m_impl(impl)
{
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Blt(
TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
DWORD dwFlags, LPDDBLTFX lpDDBltFx)
{
if (RealPrimarySurface::isLost())
{
return DDERR_SURFACELOST;
}
HRESULT result = m_impl.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
if (SUCCEEDED(result))
{
RealPrimarySurface::invalidate(lpDestRect);
RealPrimarySurface::update();
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::BltFast(
TSurface* This, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans)
{
if (RealPrimarySurface::isLost())
{
return DDERR_SURFACELOST;
}
HRESULT result = m_impl.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
if (SUCCEEDED(result))
{
const LONG x = dwX;
const LONG y = dwY;
RECT destRect = { x, y, x, y };
if (lpSrcRect)
{
destRect.right += lpSrcRect->right - lpSrcRect->left;
destRect.bottom += lpSrcRect->bottom - lpSrcRect->top;
}
else
{
TSurfaceDesc desc = {};
desc.dwSize = sizeof(desc);
CompatVtable<Vtable<TSurface>>::s_origVtable.GetSurfaceDesc(lpDDSrcSurface, &desc);
destRect.right += desc.dwWidth;
destRect.bottom += desc.dwHeight;
}
RealPrimarySurface::invalidate(&destRect);
RealPrimarySurface::update();
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags)
{
if (RealPrimarySurface::isLost())
{
return DDERR_SURFACELOST;
}
HRESULT result = m_impl.Flip(This, lpDDSurfaceTargetOverride, dwFlags);
if (SUCCEEDED(result))
{
result = RealPrimarySurface::flip(dwFlags);
if (SUCCEEDED(result))
{
static_cast<PrimarySurface*>(m_data)->updateGdiSurfacePtr(
CompatPtr<IDirectDrawSurface>::from(lpDDSurfaceTargetOverride));
}
else
{
undoFlip(This, lpDDSurfaceTargetOverride);
}
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::GetCaps(TSurface* This, TDdsCaps* lpDDSCaps)
{
HRESULT result = m_impl.GetCaps(This, lpDDSCaps);
if (SUCCEEDED(result))
{
restorePrimaryCaps(lpDDSCaps->dwCaps);
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc)
{
HRESULT result = m_impl.GetSurfaceDesc(This, lpDDSurfaceDesc);
if (SUCCEEDED(result))
{
restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps.dwCaps);
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::IsLost(TSurface* This)
{
HRESULT result = m_impl.IsLost(This);
if (SUCCEEDED(result))
{
result = RealPrimarySurface::isLost() ? DDERR_SURFACELOST : DD_OK;
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Lock(
TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc,
DWORD dwFlags, HANDLE hEvent)
{
if (RealPrimarySurface::isLost())
{
return DDERR_SURFACELOST;
}
HRESULT result = m_impl.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
if (SUCCEEDED(result))
{
RealPrimarySurface::invalidate(lpDestRect);
restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps.dwCaps);
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::QueryInterface(TSurface* This, REFIID riid, LPVOID* obp)
{
if (riid == IID_IDirectDrawGammaControl)
{
auto realPrimary(RealPrimarySurface::getSurface());
return realPrimary->QueryInterface(realPrimary, riid, obp);
}
return m_impl.QueryInterface(This, riid, obp);
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::ReleaseDC(TSurface* This, HDC hDC)
{
HRESULT result = m_impl.ReleaseDC(This, hDC);
if (SUCCEEDED(result))
{
RealPrimarySurface::invalidate(nullptr);
RealPrimarySurface::update();
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Restore(TSurface* This)
{
HRESULT result = IsLost(This);
if (FAILED(result))
{
result = RealPrimarySurface::restore();
if (SUCCEEDED(result))
{
result = m_impl.Restore(This);
if (SUCCEEDED(result))
{
Gdi::redraw(nullptr);
}
}
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper)
{
HRESULT result = m_impl.SetClipper(This, lpDDClipper);
if (SUCCEEDED(result))
{
RealPrimarySurface::setClipper(lpDDClipper);
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette)
{
if (lpDDPalette)
{
DirectDrawPalette::waitForNextUpdate();
}
if (lpDDPalette == PrimarySurface::s_palette)
{
return DD_OK;
}
HRESULT result = m_impl.SetPalette(This, lpDDPalette);
if (SUCCEEDED(result))
{
PrimarySurface::s_palette = lpDDPalette;
RealPrimarySurface::setPalette();
}
return result;
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
{
HRESULT result = m_impl.Unlock(This, lpRect);
if (SUCCEEDED(result))
{
RealPrimarySurface::update();
}
return result;
}
template PrimarySurfaceImpl<IDirectDrawSurface>;
template PrimarySurfaceImpl<IDirectDrawSurface2>;
template PrimarySurfaceImpl<IDirectDrawSurface3>;
template PrimarySurfaceImpl<IDirectDrawSurface4>;
template PrimarySurfaceImpl<IDirectDrawSurface7>;
}