From 2fe2e0345570eadae008c501bbaf94818bcece72 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 28 Apr 2024 16:21:49 +0200 Subject: [PATCH] Fixed windowed presentation See issue #298. --- DDrawCompat/D3dDdi/Resource.cpp | 9 +++++++ DDrawCompat/DDraw/RealPrimarySurface.cpp | 30 +++++++++++++++++++----- DDrawCompat/Gdi/Window.cpp | 19 ++++++++++++++- DDrawCompat/Gdi/Window.h | 5 ++++ DDrawCompat/Win32/DisplayMode.cpp | 21 ++++++++++++----- 5 files changed, 71 insertions(+), 13 deletions(-) diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 96c5ba9..f99fe23 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -1675,6 +1675,15 @@ namespace D3dDdi return true; } + if (m_isPrimary) + { + auto origCaps = DDraw::PrimarySurface::getOrigCaps(); + if ((origCaps & DDSCAPS_SYSTEMMEMORY) && !(origCaps & DDSCAPS_FLIP)) + { + return true; + } + } + if (m_lockData.empty() || !m_lockData[data.DstSubResourceIndex].isSysMemUpToDate || Time::qpcToMs(Time::queryPerformanceCounter() - m_lockData[data.DstSubResourceIndex].qpcLastCpuAccess) > 200) diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 386b7a5..47ae808 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -242,8 +242,9 @@ namespace Input::updateCursor(); }); - if (src ? !g_isFullscreen : !g_presentationWindow) + if (!src && !g_presentationWindow) { + LOG_DEBUG << "Present mode: windowed GDI"; Gdi::Window::present(nullptr); return; } @@ -277,7 +278,7 @@ namespace D3dDdi::SurfaceRepository* repo = nullptr; if (src) { - repo = DDraw::DirectDrawSurface::getSurfaceRepository(*frontBuffer); + repo = DDraw::DirectDrawSurface::getSurfaceRepository(*g_tagSurface->getDDS()); } else { @@ -300,15 +301,21 @@ namespace Gdi::Region excludeRegion(mi.rcEmulated); Gdi::Window::present(excludeRegion); - presentationBlt(*backBuffer, *src); + if (backBuffer) + { + presentationBlt(*backBuffer, *src); + } + if (useFlip) { if (g_isExclusiveFullscreen) { + LOG_DEBUG << "Present mode: exclusive fullscreen flip"; frontBuffer->Flip(frontBuffer, backBuffer, DDFLIP_WAIT); } else { + LOG_DEBUG << "Present mode: borderless fullscreen flip"; *g_deviceWindowPtr = g_presentationWindow; frontBuffer->Flip(frontBuffer, nullptr, DDFLIP_WAIT); *g_deviceWindowPtr = g_deviceWindow; @@ -320,12 +327,23 @@ namespace { CALL_ORIG_PROC(DirectDrawCreateClipper)(0, &g_clipper.getRef(), nullptr); } - g_clipper->SetHWnd(g_clipper, 0, g_presentationWindow); frontBuffer->SetClipper(frontBuffer, g_clipper); - frontBuffer->Blt(frontBuffer, nullptr, backBuffer, nullptr, DDBLT_WAIT, nullptr); + + if (g_presentationWindow) + { + LOG_DEBUG << "Present mode: windowed fullscreen blt"; + g_clipper->SetHWnd(g_clipper, 0, g_presentationWindow); + frontBuffer->Blt(frontBuffer, nullptr, backBuffer, nullptr, DDBLT_WAIT, nullptr); + } + else + { + LOG_DEBUG << "Present mode: windowed blt"; + Gdi::Window::present(*frontBuffer, *src, *g_clipper); + } } else { + LOG_DEBUG << "Present mode: windowed fullscreen GDI"; HDC dstDc = GetWindowDC(g_presentationWindow); HDC srcDc = nullptr; D3dDdi::Resource::setReadOnlyLock(true); @@ -346,6 +364,7 @@ namespace void updateNow(CompatWeakPtr src, bool isOverlayOnly) { + updatePresentationParams(); present(src, isOverlayOnly); { @@ -545,7 +564,6 @@ namespace DDraw if (vsyncCount != lastOverlayCheckVsyncCount) { updatePresentationParams(); - setPresentationWindowTopmost(); Gdi::Cursor::update(); Gdi::Caret::blink(); auto statsWindow = Gdi::GuiThread::getStatsWindow(); diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp index c90cecb..b96e4a0 100644 --- a/DDrawCompat/Gdi/Window.cpp +++ b/DDrawCompat/Gdi/Window.cpp @@ -554,15 +554,32 @@ namespace Gdi RedrawWindow(hwnd, &emptyRect, nullptr, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ERASENOW); } + void present(CompatRef dst, CompatRef src, + CompatRef clipper) + { + D3dDdi::ScopedCriticalSection lock; + auto mr = DDraw::PrimarySurface::getMonitorInfo().rcEmulated; + for (auto window : g_windowZOrder) + { + if (window->presentationWindow && !window->visibleRegion.isEmpty()) + { + clipper->SetHWnd(&clipper, 0, window->presentationWindow); + dst->Blt(&dst, &mr, &src, nullptr, DDBLT_WAIT, nullptr); + } + } + } + void present(Gdi::Region excludeRegion) { D3dDdi::ScopedCriticalSection lock; std::unique_ptr virtualScreenDc(nullptr, &Gdi::VirtualScreen::deleteDc); RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds(); + auto fsPresentationWindow = DDraw::RealPrimarySurface::getPresentationWindow(); for (auto window : g_windowZOrder) { - if (!window->presentationWindow) + if (!window->presentationWindow || + window->presentationWindow == fsPresentationWindow) { continue; } diff --git a/DDrawCompat/Gdi/Window.h b/DDrawCompat/Gdi/Window.h index 5120c1c..0e2a8ed 100644 --- a/DDrawCompat/Gdi/Window.h +++ b/DDrawCompat/Gdi/Window.h @@ -1,5 +1,8 @@ #pragma once +#include + +#include #include namespace Gdi @@ -27,6 +30,8 @@ namespace Gdi bool isTopLevelWindow(HWND hwnd); void onStyleChanged(HWND hwnd, WPARAM wParam); void onSyncPaint(HWND hwnd); + void present(CompatRef dst, CompatRef src, + CompatRef clipper); void present(Gdi::Region excludeRegion); void setDpiAwareness(HWND hwnd, bool dpiAware); void updateAll(); diff --git a/DDrawCompat/Win32/DisplayMode.cpp b/DDrawCompat/Win32/DisplayMode.cpp index a2e1574..6808f8b 100644 --- a/DDrawCompat/Win32/DisplayMode.cpp +++ b/DDrawCompat/Win32/DisplayMode.cpp @@ -228,8 +228,11 @@ namespace Compat::ScopedCriticalSection lock(g_cs); if (lpDevMode) { - g_emulatedDisplayMode.width = emulatedResolution.cx; - g_emulatedDisplayMode.height = emulatedResolution.cy; + if (lpDevMode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) + { + g_emulatedDisplayMode.width = emulatedResolution.cx; + g_emulatedDisplayMode.height = emulatedResolution.cy; + } if (lpDevMode->dmFields & DM_BITSPERPEL) { g_emulatedDisplayMode.bpp = lpDevMode->dmBitsPerPel; @@ -322,8 +325,11 @@ namespace if (getDeviceName(lpszDeviceName) == g_emulatedDisplayMode.deviceName) { lpDevMode->dmBitsPerPel = g_emulatedDisplayMode.bpp; - lpDevMode->dmPelsWidth = g_emulatedDisplayMode.width; - lpDevMode->dmPelsHeight = g_emulatedDisplayMode.height; + if (0 != g_emulatedDisplayMode.width) + { + lpDevMode->dmPelsWidth = g_emulatedDisplayMode.width; + lpDevMode->dmPelsHeight = g_emulatedDisplayMode.height; + } } else { @@ -694,8 +700,11 @@ namespace mi.rcEmulated = mi.rcMonitor; if (g_emulatedDisplayMode.deviceName == mi.szDevice) { - mi.rcEmulated.right = mi.rcEmulated.left + g_emulatedDisplayMode.width; - mi.rcEmulated.bottom = mi.rcEmulated.top + g_emulatedDisplayMode.height; + if (0 != g_emulatedDisplayMode.width) + { + mi.rcEmulated.right = mi.rcEmulated.left + g_emulatedDisplayMode.width; + mi.rcEmulated.bottom = mi.rcEmulated.top + g_emulatedDisplayMode.height; + } mi.bpp = g_emulatedDisplayMode.bpp; mi.isEmulated = true; }