mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Updated windowed mode presentation to use multiple window-clipped blits
Windowed mode presentation is changed to use a series of blits clipped to each top level window to work around performance issues when a clipper uses a clip list instead of a window. Otherwise DirectDraw uses StretchBlt rather than the driver Present call even if the clip list is a single rectangle matching the window client area. Fixes a performance issue reported in issue #24.
This commit is contained in:
parent
46f71be51a
commit
3f1fa0fae1
@ -45,7 +45,6 @@ namespace DDraw
|
||||
SET_COMPAT_METHOD(Lock);
|
||||
SET_COMPAT_METHOD(ReleaseDC);
|
||||
SET_COMPAT_METHOD(Restore);
|
||||
SET_COMPAT_METHOD(SetClipper);
|
||||
SET_COMPAT_METHOD(SetPalette);
|
||||
SET_COMPAT_METHOD(Unlock);
|
||||
|
||||
|
@ -20,6 +20,7 @@ namespace
|
||||
void onRelease();
|
||||
DWORD WINAPI updateThreadProc(LPVOID lpParameter);
|
||||
|
||||
DWORD g_primaryThreadId = 0;
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_backBuffer;
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_paletteConverter;
|
||||
@ -39,9 +40,28 @@ namespace
|
||||
|
||||
std::atomic<bool> g_isFullScreen(false);
|
||||
|
||||
bool compatBlt(CompatRef<IDirectDrawSurface7> dest)
|
||||
BOOL CALLBACK bltToWindow(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
Compat::LogEnter("RealPrimarySurface::compatBlt", dest);
|
||||
g_clipper->SetHWnd(g_clipper, 0, hwnd);
|
||||
auto src = reinterpret_cast<IDirectDrawSurface7*>(lParam);
|
||||
g_frontBuffer->Blt(g_frontBuffer, nullptr, src, nullptr, DDBLT_WAIT, nullptr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HRESULT bltToPrimaryChain(CompatRef<IDirectDrawSurface7> src)
|
||||
{
|
||||
if (g_isFullScreen)
|
||||
{
|
||||
return g_backBuffer->Blt(g_backBuffer, nullptr, &src, nullptr, DDBLT_WAIT, nullptr);
|
||||
}
|
||||
|
||||
EnumThreadWindows(g_primaryThreadId, bltToWindow, reinterpret_cast<LPARAM>(&src));
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
bool compatBlt()
|
||||
{
|
||||
Compat::LogEnter("RealPrimarySurface::compatBlt");
|
||||
|
||||
bool result = false;
|
||||
|
||||
@ -64,16 +84,15 @@ namespace
|
||||
|
||||
if (result)
|
||||
{
|
||||
result = SUCCEEDED(dest->Blt(
|
||||
&dest, nullptr, g_paletteConverter, nullptr, DDBLT_WAIT, nullptr));
|
||||
result = SUCCEEDED(bltToPrimaryChain(*g_paletteConverter));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = SUCCEEDED(dest->Blt(&dest, nullptr, primary, nullptr, DDBLT_WAIT, nullptr));
|
||||
result = SUCCEEDED(bltToPrimaryChain(*primary));
|
||||
}
|
||||
|
||||
Compat::LogLeave("RealPrimarySurface::compatBlt", dest) << result;
|
||||
Compat::LogLeave("RealPrimarySurface::compatBlt") << result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -124,6 +143,11 @@ namespace
|
||||
backBufferCaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
surface->GetAttachedSurface(surface, &backBufferCaps, &backBuffer.getRef());
|
||||
}
|
||||
else
|
||||
{
|
||||
CALL_ORIG_PROC(DirectDrawCreateClipper, 0, &g_clipper.getRef(), nullptr);
|
||||
surface->SetClipper(surface, g_clipper);
|
||||
}
|
||||
|
||||
g_qpcFlipModeTimeout = Time::g_qpcFrequency / Config::minExpectedFlipsPerSec;
|
||||
g_qpcLastFlip = Time::queryPerformanceCounter() - g_qpcFlipModeTimeout;
|
||||
@ -156,6 +180,7 @@ namespace
|
||||
g_backBuffer = backBuffer;
|
||||
g_surfaceDesc = desc;
|
||||
g_isFullScreen = isFlippable;
|
||||
g_primaryThreadId = GetCurrentThreadId();
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
@ -184,7 +209,7 @@ namespace
|
||||
ResetEvent(g_updateEvent);
|
||||
g_frontBuffer = nullptr;
|
||||
g_backBuffer = nullptr;
|
||||
g_clipper = nullptr;
|
||||
g_clipper.release();
|
||||
g_isFullScreen = false;
|
||||
g_paletteConverter.release();
|
||||
|
||||
@ -197,13 +222,7 @@ namespace
|
||||
{
|
||||
ResetEvent(g_updateEvent);
|
||||
|
||||
if (!g_isFullScreen)
|
||||
{
|
||||
compatBlt(*g_frontBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (compatBlt(*g_backBuffer))
|
||||
if (compatBlt() && g_isFullScreen)
|
||||
{
|
||||
D3dDdi::KernelModeThunks::overrideFlipInterval(
|
||||
Time::queryPerformanceCounter() - g_qpcLastFlip >= g_qpcFlipModeTimeout
|
||||
@ -262,13 +281,11 @@ namespace DDraw
|
||||
CompatPtr<typename Types<DirectDraw>::TCreatedSurface> surface;
|
||||
result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
|
||||
|
||||
bool isFlippable = true;
|
||||
if (DDERR_NOEXCLUSIVEMODE == result)
|
||||
{
|
||||
desc.dwFlags = DDSD_CAPS;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||||
desc.dwBackBufferCount = 0;
|
||||
isFlippable = false;
|
||||
result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
|
||||
}
|
||||
|
||||
@ -316,7 +333,7 @@ namespace DDraw
|
||||
g_isUpdateSuspended = false;
|
||||
|
||||
g_qpcLastFlip = Time::queryPerformanceCounter();
|
||||
compatBlt(*g_backBuffer);
|
||||
compatBlt();
|
||||
HRESULT result = g_frontBuffer->Flip(g_frontBuffer, nullptr, flags);
|
||||
g_qpcNextUpdate = Time::queryPerformanceCounter();
|
||||
return result;
|
||||
@ -377,22 +394,6 @@ namespace DDraw
|
||||
return g_frontBuffer->Restore(g_frontBuffer);
|
||||
}
|
||||
|
||||
void RealPrimarySurface::setClipper(CompatWeakPtr<IDirectDrawClipper> clipper)
|
||||
{
|
||||
if (g_backBuffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT result = g_frontBuffer->SetClipper(g_frontBuffer, clipper);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed to set clipper on the real primary surface: " << result);
|
||||
return;
|
||||
}
|
||||
g_clipper = clipper;
|
||||
}
|
||||
|
||||
HRESULT RealPrimarySurface::setGammaRamp(DDGAMMARAMP* rampData)
|
||||
{
|
||||
auto gammaControl(CompatPtr<IDirectDrawGammaControl>::from(g_frontBuffer.get()));
|
||||
@ -416,7 +417,7 @@ namespace DDraw
|
||||
|
||||
void RealPrimarySurface::update()
|
||||
{
|
||||
if (g_isUpdateSuspended || !(g_isFullScreen || g_clipper))
|
||||
if (g_isUpdateSuspended)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace DDraw
|
||||
static void release();
|
||||
static void removeUpdateThread();
|
||||
static HRESULT restore();
|
||||
static void setClipper(CompatWeakPtr<IDirectDrawClipper> clipper);
|
||||
static HRESULT setGammaRamp(DDGAMMARAMP* rampData);
|
||||
static void setPalette();
|
||||
static void update();
|
||||
|
@ -204,17 +204,6 @@ namespace DDraw
|
||||
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)
|
||||
{
|
||||
|
@ -29,7 +29,6 @@ namespace DDraw
|
||||
DWORD dwFlags, HANDLE hEvent) override;
|
||||
virtual HRESULT ReleaseDC(TSurface* This, HDC hDC) override;
|
||||
virtual HRESULT Restore(TSurface* This) override;
|
||||
virtual HRESULT SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper) override;
|
||||
virtual HRESULT SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette) override;
|
||||
virtual HRESULT Unlock(TSurface* This, TUnlockParam lpRect) override;
|
||||
|
||||
|
@ -273,12 +273,6 @@ namespace DDraw
|
||||
return s_origVtable.Restore(This);
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper)
|
||||
{
|
||||
return s_origVtable.SetClipper(This, lpDDClipper);
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette)
|
||||
{
|
||||
|
@ -49,7 +49,6 @@ namespace DDraw
|
||||
DWORD dwFlags, HANDLE hEvent);
|
||||
virtual HRESULT ReleaseDC(TSurface* This, HDC hDC);
|
||||
virtual HRESULT Restore(TSurface* This);
|
||||
virtual HRESULT SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper);
|
||||
virtual HRESULT SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette);
|
||||
virtual HRESULT Unlock(TSurface* This, TUnlockParam lpRect);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user