From ac9dbc72def1c89675266fd5c33d0fdd45f67fe5 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 10 Apr 2016 17:12:36 +0200 Subject: [PATCH] Update only the dirty rectangle on the real primary surface --- DDrawCompat/CompatDirectDrawSurface.cpp | 20 ++++++++++++ DDrawCompat/CompatGdi.cpp | 1 + DDrawCompat/RealPrimarySurface.cpp | 42 +++++++++++++++++++------ DDrawCompat/RealPrimarySurface.h | 1 + 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/DDrawCompat/CompatDirectDrawSurface.cpp b/DDrawCompat/CompatDirectDrawSurface.cpp index aedf7d0..8d2e163 100644 --- a/DDrawCompat/CompatDirectDrawSurface.cpp +++ b/DDrawCompat/CompatDirectDrawSurface.cpp @@ -431,6 +431,7 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Blt( if (This == s_compatPrimarySurface && SUCCEEDED(result)) { + RealPrimarySurface::invalidate(lpDestRect); RealPrimarySurface::update(); } @@ -455,6 +456,23 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::BltFast( HRESULT result = s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); if (This == s_compatPrimarySurface && 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); + s_origVtable.GetSurfaceDesc(lpDDSrcSurface, &desc); + destRect.right += desc.dwWidth; + destRect.bottom += desc.dwHeight; + } + RealPrimarySurface::invalidate(&destRect); RealPrimarySurface::update(); } return result; @@ -531,6 +549,7 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Lock( HRESULT result = s_origVtable.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent); if (SUCCEEDED(result) && g_lockingPrimary && lpDDSurfaceDesc) { + RealPrimarySurface::invalidate(lpDestRect); restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps); } else if (DDERR_SURFACELOST == result) @@ -574,6 +593,7 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::ReleaseDC(TSurface* HRESULT result = s_origVtable.ReleaseDC(This, hDC); if (This == s_compatPrimarySurface && SUCCEEDED(result)) { + RealPrimarySurface::invalidate(nullptr); RealPrimarySurface::update(); } return result; diff --git a/DDrawCompat/CompatGdi.cpp b/DDrawCompat/CompatGdi.cpp index c5a6193..5fd70e0 100644 --- a/DDrawCompat/CompatGdi.cpp +++ b/DDrawCompat/CompatGdi.cpp @@ -117,6 +117,7 @@ namespace GdiFlush(); CompatDirectDrawSurface::s_origVtable.Unlock( CompatPrimarySurface::surface, nullptr); + RealPrimarySurface::invalidate(nullptr); RealPrimarySurface::update(); Compat::origProcs.ReleaseDDThreadLock(); diff --git a/DDrawCompat/RealPrimarySurface.cpp b/DDrawCompat/RealPrimarySurface.cpp index 71eee3c..21049ed 100644 --- a/DDrawCompat/RealPrimarySurface.cpp +++ b/DDrawCompat/RealPrimarySurface.cpp @@ -24,6 +24,7 @@ namespace HANDLE g_updateThread = nullptr; HANDLE g_updateEvent = nullptr; + RECT g_updateRect = {}; bool g_isFlipEvent = false; LARGE_INTEGER g_lastUpdateTime = {}; LARGE_INTEGER g_qpcFrequency = {}; @@ -52,14 +53,14 @@ namespace IDirectDrawSurface7* converterSurface = CompatPaletteConverter::lockSurface(); HDC converterDc = CompatPaletteConverter::lockDc(); - origVtable.Blt(converterSurface, nullptr, CompatPrimarySurface::surface, nullptr, - DDBLT_WAIT, nullptr); + origVtable.Blt(converterSurface, &g_updateRect, + CompatPrimarySurface::surface, &g_updateRect, DDBLT_WAIT, nullptr); HDC destDc = nullptr; origVtable.GetDC(dest, &destDc); - result = TRUE == CALL_ORIG_FUNC(BitBlt)(destDc, 0, 0, - RealPrimarySurface::s_surfaceDesc.dwWidth, RealPrimarySurface::s_surfaceDesc.dwHeight, - converterDc, 0, 0, SRCCOPY); + result = TRUE == CALL_ORIG_FUNC(BitBlt)(destDc, g_updateRect.left, g_updateRect.top, + g_updateRect.right - g_updateRect.left, g_updateRect.bottom - g_updateRect.top, + converterDc, g_updateRect.left, g_updateRect.top, SRCCOPY); origVtable.ReleaseDC(dest, destDc); CompatPaletteConverter::unlockDc(); @@ -75,8 +76,13 @@ namespace } else { - result = SUCCEEDED(origVtable.Blt( - dest, nullptr, CompatPrimarySurface::surface, nullptr, DDBLT_WAIT, nullptr)); + result = SUCCEEDED(origVtable.Blt(dest, &g_updateRect, + CompatPrimarySurface::surface, &g_updateRect, DDBLT_WAIT, nullptr)); + } + + if (result) + { + SetRectEmpty(&g_updateRect); } Compat::LogLeave("RealPrimarySurface::compatBlt", dest); @@ -232,6 +238,7 @@ HRESULT RealPrimarySurface::flip(DWORD flags) return DDERR_NOTFLIPPABLE; } + invalidate(nullptr); compatBlt(g_backBuffer); if (flags & DDFLIP_DONOTWAIT) { @@ -253,6 +260,19 @@ IDirectDrawSurface7* RealPrimarySurface::getSurface() return g_frontBuffer; } +void RealPrimarySurface::invalidate(const RECT* rect) +{ + if (rect) + { + UnionRect(&g_updateRect, &g_updateRect, rect); + } + else + { + SetRect(&g_updateRect, 0, 0, + CompatPrimarySurface::displayMode.width, CompatPrimarySurface::displayMode.height); + } +} + bool RealPrimarySurface::isFullScreen() { return g_isFullScreen; @@ -306,13 +326,17 @@ void RealPrimarySurface::setPalette() void RealPrimarySurface::update() { - g_isFlipEvent = false; - SetEvent(g_updateEvent); + if (!IsRectEmpty(&g_updateRect)) + { + g_isFlipEvent = false; + SetEvent(g_updateEvent); + } } void RealPrimarySurface::updatePalette(DWORD startingEntry, DWORD count) { CompatPaletteConverter::setPrimaryPalette(startingEntry, count); CompatGdi::updatePalette(startingEntry, count); + invalidate(nullptr); updateNow(); } diff --git a/DDrawCompat/RealPrimarySurface.h b/DDrawCompat/RealPrimarySurface.h index e8a9239..61ca2b2 100644 --- a/DDrawCompat/RealPrimarySurface.h +++ b/DDrawCompat/RealPrimarySurface.h @@ -12,6 +12,7 @@ public: static HRESULT flip(DWORD flags); static IDirectDrawSurface7* getSurface(); + static void invalidate(const RECT* rect); static bool isFullScreen(); static bool isLost(); static void release();