From 291a9c2f9a616b9f53254c3dd2931bb23f010793 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 9 Dec 2018 14:23:36 +0100 Subject: [PATCH] Fixed various multi-monitor display issues --- DDrawCompat/D3dDdi/Hooks.cpp | 4 +- DDrawCompat/D3dDdi/Hooks.h | 2 +- DDrawCompat/D3dDdi/KernelModeThunks.cpp | 43 +++++++++++--- DDrawCompat/D3dDdi/KernelModeThunks.h | 2 +- DDrawCompat/DDraw/DirectDraw.cpp | 16 ----- DDrawCompat/DDraw/DirectDraw.h | 3 - DDrawCompat/DDraw/DirectDrawClipper.cpp | 34 +++++++++-- DDrawCompat/DDraw/DirectDrawClipper.h | 4 ++ DDrawCompat/DDraw/DirectDrawSurface.cpp | 2 +- DDrawCompat/DDraw/RealPrimarySurface.cpp | 16 ++++- .../DDraw/Surfaces/PrimarySurfaceImpl.cpp | 58 +++++++++++++++++++ DDrawCompat/DDraw/Surfaces/Surface.cpp | 2 +- DDrawCompat/Dll/DllMain.cpp | 2 +- DDrawCompat/Gdi/Dc.cpp | 13 +++-- DDrawCompat/Gdi/Region.cpp | 5 ++ DDrawCompat/Gdi/Region.h | 1 + DDrawCompat/Gdi/TitleBar.cpp | 8 ++- DDrawCompat/Gdi/VirtualScreen.cpp | 8 ++- 18 files changed, 172 insertions(+), 51 deletions(-) diff --git a/DDrawCompat/D3dDdi/Hooks.cpp b/DDrawCompat/D3dDdi/Hooks.cpp index c62b2b8..0c1daeb 100644 --- a/DDrawCompat/D3dDdi/Hooks.cpp +++ b/DDrawCompat/D3dDdi/Hooks.cpp @@ -81,9 +81,9 @@ namespace D3dDdi return g_ddiVersion; } - void installHooks() + void installHooks(HMODULE origDDrawModule) { - KernelModeThunks::installHooks(); + KernelModeThunks::installHooks(origDDrawModule); } void onUmdFileNameQueried(const std::wstring& umdFileName) diff --git a/DDrawCompat/D3dDdi/Hooks.h b/DDrawCompat/D3dDdi/Hooks.h index 12eaeff..7c59d82 100644 --- a/DDrawCompat/D3dDdi/Hooks.h +++ b/DDrawCompat/D3dDdi/Hooks.h @@ -5,7 +5,7 @@ namespace D3dDdi { UINT getDdiVersion(); - void installHooks(); + void installHooks(HMODULE origDDrawModule); void onUmdFileNameQueried(const std::wstring& umdFileName); void uninstallHooks(); } diff --git a/DDrawCompat/D3dDdi/KernelModeThunks.cpp b/DDrawCompat/D3dDdi/KernelModeThunks.cpp index f7958a6..b998858 100644 --- a/DDrawCompat/D3dDdi/KernelModeThunks.cpp +++ b/DDrawCompat/D3dDdi/KernelModeThunks.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -34,6 +35,7 @@ namespace std::map g_contexts; AdapterInfo g_gdiAdapterInfo = {}; AdapterInfo g_lastOpenAdapterInfo = {}; + std::string g_lastDDrawCreateDcDevice; UINT g_lastFlipInterval = 0; UINT g_flipIntervalOverride = 0; D3DKMT_HANDLE g_lastPresentContext = 0; @@ -108,6 +110,13 @@ namespace return LOG_RESULT(result); } + HDC WINAPI ddrawCreateDcA(LPCSTR pwszDriver, LPCSTR pwszDevice, LPCSTR pszPort, const DEVMODEA* pdm) + { + LOG_FUNC("ddrawCreateDCA", pwszDriver, pwszDevice, pszPort, pdm); + g_lastDDrawCreateDcDevice = pwszDevice ? pwszDevice : std::string(); + return LOG_RESULT(CALL_ORIG_FUNC(CreateDCA)(pwszDriver, pwszDevice, pszPort, pdm)); + } + NTSTATUS APIENTRY destroyContext(const D3DKMT_DESTROYCONTEXT* pData) { LOG_FUNC("D3DKMTDestroyContext", pData); @@ -123,18 +132,35 @@ namespace return LOG_RESULT(result); } + BOOL CALLBACK findDDrawMonitorRect(HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT /*lprcMonitor*/, LPARAM dwData) + { + MONITORINFOEX mi = {}; + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + if (g_lastDDrawCreateDcDevice == mi.szDevice) + { + *reinterpret_cast(dwData) = mi.rcMonitor; + return FALSE; + } + return TRUE; + } + AdapterInfo getAdapterInfo(const D3DKMT_OPENADAPTERFROMHDC& data) { AdapterInfo adapterInfo = {}; adapterInfo.adapter = data.hAdapter; adapterInfo.vidPnSourceId = data.VidPnSourceId; - POINT p = {}; - GetDCOrgEx(data.hDc, &p); - MONITORINFO mi = {}; - mi.cbSize = sizeof(mi); - GetMonitorInfo(MonitorFromPoint(p, MONITOR_DEFAULTTOPRIMARY), &mi); - adapterInfo.monitorRect = mi.rcMonitor; + EnumDisplayMonitors(nullptr, nullptr, findDDrawMonitorRect, + reinterpret_cast(&adapterInfo.monitorRect)); + + if (IsRectEmpty(&adapterInfo.monitorRect)) + { + MONITORINFO mi = {}; + mi.cbSize = sizeof(mi); + GetMonitorInfo(MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY), &mi); + adapterInfo.monitorRect = mi.rcMonitor; + } return adapterInfo; } @@ -282,7 +308,7 @@ namespace D3dDdi { lastDisplaySettingsUniqueness = currentDisplaySettingsUniqueness; CompatPtr ddUnk; - primary->GetDDInterface(primary, reinterpret_cast(&ddUnk.getRef())); + primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast(&ddUnk.getRef())); CompatPtr dd7(ddUnk); DDDEVICEIDENTIFIER2 di = {}; @@ -297,7 +323,7 @@ namespace D3dDdi return g_qpcLastVerticalBlank; } - void installHooks() + void installHooks(HMODULE origDDrawModule) { HOOK_FUNCTION(gdi32, D3DKMTCloseAdapter, closeAdapter); HOOK_FUNCTION(gdi32, D3DKMTCreateContext, createContext); @@ -308,6 +334,7 @@ namespace D3dDdi HOOK_FUNCTION(gdi32, D3DKMTQueryAdapterInfo, queryAdapterInfo); HOOK_FUNCTION(gdi32, D3DKMTPresent, present); HOOK_FUNCTION(gdi32, D3DKMTSetQueuedLimit, setQueuedLimit); + Compat::hookIatFunction(origDDrawModule, "gdi32.dll", "CreateDCA", ddrawCreateDcA); // Functions not available in Windows Vista Compat::hookFunction("gdi32", "D3DKMTCreateContextVirtual", diff --git a/DDrawCompat/D3dDdi/KernelModeThunks.h b/DDrawCompat/D3dDdi/KernelModeThunks.h index d56553f..dfd91eb 100644 --- a/DDrawCompat/D3dDdi/KernelModeThunks.h +++ b/DDrawCompat/D3dDdi/KernelModeThunks.h @@ -13,7 +13,7 @@ namespace D3dDdi UINT getLastSubmittedFrameCount(); RECT getMonitorRect(); long long getQpcLastVerticalBlank(); - void installHooks(); + void installHooks(HMODULE origDDrawModule); void setFlipIntervalOverride(UINT flipInterval); void waitForVerticalBlank(); } diff --git a/DDrawCompat/DDraw/DirectDraw.cpp b/DDrawCompat/DDraw/DirectDraw.cpp index 85a6e45..cd589ec 100644 --- a/DDrawCompat/DDraw/DirectDraw.cpp +++ b/DDrawCompat/DDraw/DirectDraw.cpp @@ -28,22 +28,6 @@ namespace namespace DDraw { - CompatPtr createCompatibleSurface(DWORD bpp) - { - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT; - desc.dwWidth = 1; - desc.dwHeight = 1; - desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - desc.ddpfPixelFormat = getRgbPixelFormat(bpp); - - CompatPtr surface; - auto dd = DDraw::Repository::getDirectDraw(); - dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); - return surface; - } - template void* getDdObject(TDirectDraw& dd) { diff --git a/DDrawCompat/DDraw/DirectDraw.h b/DDrawCompat/DDraw/DirectDraw.h index b9562ce..401cc70 100644 --- a/DDrawCompat/DDraw/DirectDraw.h +++ b/DDrawCompat/DDraw/DirectDraw.h @@ -2,7 +2,6 @@ #include -#include "Common/CompatPtr.h" #include "Common/CompatRef.h" #include "Common/CompatVtable.h" #include "DDraw/Visitors/DirectDrawVtblVisitor.h" @@ -10,8 +9,6 @@ namespace DDraw { - CompatPtr createCompatibleSurface(DWORD bpp); - template void* getDdObject(TDirectDraw& dd); diff --git a/DDrawCompat/DDraw/DirectDrawClipper.cpp b/DDrawCompat/DDraw/DirectDrawClipper.cpp index 4191b5e..a8cd068 100644 --- a/DDrawCompat/DDraw/DirectDrawClipper.cpp +++ b/DDrawCompat/DDraw/DirectDrawClipper.cpp @@ -2,8 +2,10 @@ #include #include "Common/CompatRef.h" +#include "D3dDdi/KernelModeThunks.h" #include "DDraw/DirectDrawClipper.h" #include "Gdi/Gdi.h" +#include "Gdi/Region.h" namespace { @@ -28,9 +30,16 @@ namespace void updateWindowClipList(CompatRef clipper, ClipperData& data) { HDC dc = GetDC(data.hwnd); - HRGN rgn = CreateRectRgn(0, 0, 0, 0); - + Gdi::Region rgn; GetRandomRgn(dc, rgn, SYSRGN); + CALL_ORIG_FUNC(ReleaseDC)(data.hwnd, dc); + + RECT primaryRect = D3dDdi::KernelModeThunks::getMonitorRect(); + if (0 != primaryRect.left || 0 != primaryRect.top) + { + rgn.offset(-primaryRect.left, -primaryRect.top); + } + DWORD rgnSize = GetRegionData(rgn, 0, nullptr); std::vector rgnData(rgnSize); GetRegionData(rgn, rgnSize, reinterpret_cast(rgnData.data())); @@ -40,9 +49,6 @@ namespace { clipper->SetHWnd(&clipper, 0, data.hwnd); } - - DeleteObject(rgn); - CALL_ORIG_FUNC(ReleaseDC)(data.hwnd, dc); } HRESULT STDMETHODCALLTYPE GetHWnd(IDirectDrawClipper* This, HWND* lphWnd) @@ -115,6 +121,24 @@ namespace namespace DDraw { + HRGN DirectDrawClipper::getClipRgn(CompatRef clipper) + { + std::vector rgnData; + DWORD size = 0; + clipper->GetClipList(&clipper, nullptr, nullptr, &size); + rgnData.resize(size); + clipper->GetClipList(&clipper, nullptr, reinterpret_cast(rgnData.data()), &size); + return ExtCreateRegion(nullptr, size, reinterpret_cast(rgnData.data())); + } + + HRESULT DirectDrawClipper::setClipRgn(CompatRef clipper, HRGN rgn) + { + std::vector rgnData; + rgnData.resize(GetRegionData(rgn, 0, nullptr)); + GetRegionData(rgn, rgnData.size(), reinterpret_cast(rgnData.data())); + return clipper->SetClipList(&clipper, reinterpret_cast(rgnData.data()), 0); + } + void DirectDrawClipper::setCompatVtable(IDirectDrawClipperVtbl& vtable) { vtable.GetHWnd = &GetHWnd; diff --git a/DDrawCompat/DDraw/DirectDrawClipper.h b/DDrawCompat/DDraw/DirectDrawClipper.h index 63ac12e..5430647 100644 --- a/DDrawCompat/DDraw/DirectDrawClipper.h +++ b/DDrawCompat/DDraw/DirectDrawClipper.h @@ -1,5 +1,6 @@ #pragma once +#include "Common/CompatRef.h" #include "Common/CompatVtable.h" #include "DDraw/Visitors/DirectDrawClipperVtblVisitor.h" @@ -8,6 +9,9 @@ namespace DDraw class DirectDrawClipper : public CompatVtable { public: + static HRGN getClipRgn(CompatRef clipper); + static HRESULT setClipRgn(CompatRef clipper, HRGN rgn); + static void setCompatVtable(IDirectDrawClipperVtbl& vtable); }; } diff --git a/DDrawCompat/DDraw/DirectDrawSurface.cpp b/DDrawCompat/DDraw/DirectDrawSurface.cpp index b912b8c..3ad0878 100644 --- a/DDrawCompat/DDraw/DirectDrawSurface.cpp +++ b/DDrawCompat/DDraw/DirectDrawSurface.cpp @@ -12,7 +12,7 @@ namespace HRESULT STDMETHODCALLTYPE callImpl(TSurface* This, Params... params) { DDraw::Surface* surface = This ? DDraw::Surface::getSurface(*This) : nullptr; - if (!surface) + if (!surface || !(surface->getImpl())) { return (CompatVtable>::s_origVtable.*origMethod)(This, params...); } diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index e02d7da..c16e87f 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -78,6 +78,7 @@ namespace void bltToWindowViaGdi(Gdi::Region* primaryRegion) { std::unique_ptr virtualScreenDc(nullptr, &Gdi::VirtualScreen::deleteDc); + RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds(); for (auto windowPair : Gdi::Window::getWindows()) { @@ -110,12 +111,14 @@ namespace } } - Gdi::GdiAccessGuard gdiAccessGuard(Gdi::ACCESS_READ); + Gdi::GdiAccessGuard gdiAccessGuard(Gdi::ACCESS_READ, !primaryRegion); HWND presentationWindow = windowPair.second->getPresentationWindow(); HDC dc = GetWindowDC(presentationWindow); RECT rect = windowPair.second->getWindowRect(); - CALL_ORIG_FUNC(BitBlt)(dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, - virtualScreenDc.get(), rect.left, rect.top, SRCCOPY); + visibleRegion.offset(-rect.left, -rect.top); + SelectClipRgn(dc, visibleRegion); + CALL_ORIG_FUNC(BitBlt)(dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, virtualScreenDc.get(), + rect.left - virtualScreenBounds.left, rect.top - virtualScreenBounds.top, SRCCOPY); CALL_ORIG_FUNC(ReleaseDC)(presentationWindow, dc); } } @@ -138,6 +141,7 @@ namespace HDC backBufferDc = nullptr; backBuffer->GetDC(backBuffer, &backBufferDc); + RECT ddrawMonitorRect = D3dDdi::KernelModeThunks::getMonitorRect(); for (auto it = visibleLayeredWindows.rbegin(); it != visibleLayeredWindows.rend(); ++it) { @@ -145,6 +149,12 @@ namespace HRGN rgn = Gdi::getVisibleWindowRgn(*it); RECT wr = {}; GetWindowRect(*it, &wr); + + if (0 != ddrawMonitorRect.left || 0 != ddrawMonitorRect.top) + { + OffsetRect(&wr, -ddrawMonitorRect.left, -ddrawMonitorRect.top); + OffsetRgn(rgn, -ddrawMonitorRect.left, -ddrawMonitorRect.top); + } SelectClipRgn(backBufferDc, rgn); CALL_ORIG_FUNC(BitBlt)(backBufferDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp index ec4d9d1..992c078 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp @@ -1,12 +1,69 @@ +#include "Common/CompatPtr.h" +#include "D3dDdi/KernelModeThunks.h" +#include "DDraw/DirectDrawClipper.h" #include "DDraw/DirectDrawPalette.h" #include "DDraw/DirectDrawSurface.h" #include "DDraw/RealPrimarySurface.h" #include "DDraw/Surfaces/PrimarySurface.h" #include "DDraw/Surfaces/PrimarySurfaceImpl.h" +#include "Dll/Procs.h" #include "Gdi/Gdi.h" +#include "Gdi/Region.h" +#include "Gdi/VirtualScreen.h" namespace { + template + void bltToGdi(TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, + DWORD dwFlags, LPDDBLTFX lpDDBltFx) + { + if (!lpDestRect) + { + return; + } + + CompatPtr clipper; + CompatVtable>::s_origVtable.GetClipper(This, &clipper.getRef()); + if (!clipper) + { + return; + } + + Gdi::Region clipRgn(DDraw::DirectDrawClipper::getClipRgn(*clipper)); + RECT monitorRect = D3dDdi::KernelModeThunks::getMonitorRect(); + RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds(); + clipRgn.offset(monitorRect.left, monitorRect.top); + clipRgn &= virtualScreenBounds; + clipRgn -= monitorRect; + if (clipRgn.isEmpty()) + { + return; + } + + auto gdiSurface(Gdi::VirtualScreen::createSurface(virtualScreenBounds)); + if (!gdiSurface) + { + return; + } + + CompatPtr gdiClipper; + CALL_ORIG_PROC(DirectDrawCreateClipper, 0, &gdiClipper.getRef(), nullptr); + if (!gdiClipper) + { + return; + } + + RECT dstRect = *lpDestRect; + OffsetRect(&dstRect, monitorRect.left - virtualScreenBounds.left, monitorRect.top - virtualScreenBounds.top); + clipRgn.offset(-virtualScreenBounds.left, -virtualScreenBounds.top); + DDraw::DirectDrawClipper::setClipRgn(*gdiClipper, clipRgn); + + auto srcSurface(CompatPtr::from(lpDDSrcSurface)); + gdiSurface->SetClipper(gdiSurface, gdiClipper); + gdiSurface->Blt(gdiSurface, &dstRect, srcSurface, lpSrcRect, dwFlags, lpDDBltFx); + gdiSurface->SetClipper(gdiSurface, nullptr); + } + void restorePrimaryCaps(DWORD& caps) { caps &= ~DDSCAPS_OFFSCREENPLAIN; @@ -41,6 +98,7 @@ namespace DDraw HRESULT result = m_impl.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); if (SUCCEEDED(result)) { + bltToGdi(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); RealPrimarySurface::update(); } return result; diff --git a/DDrawCompat/DDraw/Surfaces/Surface.cpp b/DDrawCompat/DDraw/Surfaces/Surface.cpp index 860775a..6dcc430 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.cpp +++ b/DDrawCompat/DDraw/Surfaces/Surface.cpp @@ -122,7 +122,7 @@ namespace DDraw privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER))) { CompatPtr dd; - dds->GetDDInterface(&dds, reinterpret_cast(&dd.getRef())); + dds.get().lpVtbl->GetDDInterface(&dds, reinterpret_cast(&dd.getRef())); privateData->createImpl(); privateData->m_impl->m_data = privateData.get(); diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index 1c9299b..4ca498f 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -39,7 +39,7 @@ namespace Compat::Log() << "Installing registry hooks"; Win32::Registry::installHooks(); Compat::Log() << "Installing Direct3D driver hooks"; - D3dDdi::installHooks(); + D3dDdi::installHooks(g_origDDrawModule); Compat::Log() << "Installing display mode hooks"; Win32::DisplayMode::installHooks(g_origDDrawModule); Gdi::VirtualScreen::init(); diff --git a/DDrawCompat/Gdi/Dc.cpp b/DDrawCompat/Gdi/Dc.cpp index 2f634b1..5a1d164 100644 --- a/DDrawCompat/Gdi/Dc.cpp +++ b/DDrawCompat/Gdi/Dc.cpp @@ -111,13 +111,15 @@ namespace } } - void setClippingRegion(const CompatDc& compatDc, std::shared_ptr rootWindow, const POINT& origin) + void setClippingRegion(const CompatDc& compatDc, std::shared_ptr rootWindow, + const POINT& origin, const RECT& virtualScreenBounds) { if (rootWindow) { Gdi::Region sysRgn; CALL_ORIG_FUNC(GetRandomRgn)(compatDc.origDc, sysRgn, SYSRGN); sysRgn &= rootWindow->getVisibleRegion(); + OffsetRgn(sysRgn, -virtualScreenBounds.left, -virtualScreenBounds.top); SelectClipRgn(compatDc.dc, sysRgn); } else @@ -206,15 +208,18 @@ namespace Gdi POINT origin = {}; GetDCOrgEx(origDc, &origin); RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds(); - origin.x -= virtualScreenBounds.left; - origin.y -= virtualScreenBounds.top; + if (wnd && GetDesktopWindow() != wnd) + { + origin.x -= virtualScreenBounds.left; + origin.y -= virtualScreenBounds.top; + } compatDc.refCount = 1; compatDc.origDc = origDc; compatDc.threadId = GetCurrentThreadId(); compatDc.savedState = useMetaRgn ? SaveDC(compatDc.dc) : 0; copyDcAttributes(compatDc, origDc, origin); - setClippingRegion(compatDc, rootWindow, origin); + setClippingRegion(compatDc, rootWindow, origin, virtualScreenBounds); g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc)); diff --git a/DDrawCompat/Gdi/Region.cpp b/DDrawCompat/Gdi/Region.cpp index 0279b51..cad3b65 100644 --- a/DDrawCompat/Gdi/Region.cpp +++ b/DDrawCompat/Gdi/Region.cpp @@ -14,6 +14,11 @@ namespace namespace Gdi { + Region::Region(HRGN rgn) + : m_region(rgn) + { + } + Region::Region(const RECT& rect) : m_region(CreateRectRgnIndirect(&rect)) { diff --git a/DDrawCompat/Gdi/Region.h b/DDrawCompat/Gdi/Region.h index eb5529a..7eaeb12 100644 --- a/DDrawCompat/Gdi/Region.h +++ b/DDrawCompat/Gdi/Region.h @@ -9,6 +9,7 @@ namespace Gdi class Region { public: + Region(HRGN rgn); Region(const RECT& rect = RECT{ 0, 0, 0, 0 }); ~Region(); Region(const Region& other); diff --git a/DDrawCompat/Gdi/TitleBar.cpp b/DDrawCompat/Gdi/TitleBar.cpp index dc97433..52eeb61 100644 --- a/DDrawCompat/Gdi/TitleBar.cpp +++ b/DDrawCompat/Gdi/TitleBar.cpp @@ -1,7 +1,9 @@ #include "Common/Hook.h" #include "DDraw/Surfaces/PrimarySurface.h" #include "Gdi/Gdi.h" +#include "Gdi/Region.h" #include "Gdi/TitleBar.h" +#include "Gdi/VirtualScreen.h" namespace { @@ -101,11 +103,11 @@ namespace Gdi flags |= DC_GRADIENT; } + RECT virtualScreenBounds = VirtualScreen::getBounds(); RECT clipRect = m_tbi.rcTitleBar; - OffsetRect(&clipRect, m_windowRect.left, m_windowRect.top); - HRGN clipRgn = CreateRectRgnIndirect(&clipRect); + OffsetRect(&clipRect, m_windowRect.left - virtualScreenBounds.left, m_windowRect.top - virtualScreenBounds.top); + Region clipRgn(clipRect); SelectClipRgn(m_compatDc, clipRgn); - DeleteObject(clipRgn); RECT textRect = m_tbi.rcTitleBar; if (m_hasIcon) diff --git a/DDrawCompat/Gdi/VirtualScreen.cpp b/DDrawCompat/Gdi/VirtualScreen.cpp index dfe55f4..06f7255 100644 --- a/DDrawCompat/Gdi/VirtualScreen.cpp +++ b/DDrawCompat/Gdi/VirtualScreen.cpp @@ -1,8 +1,8 @@ #include #include "DDraw/DirectDraw.h" -#include "DDraw/Repository.h" #include "DDraw/ScopedThreadLock.h" +#include "DDraw/Surfaces/PrimarySurface.h" #include "Gdi/Gdi.h" #include "Gdi/Region.h" #include "Gdi/VirtualScreen.h" @@ -134,8 +134,12 @@ namespace Gdi (rect.top - g_bounds.top) * g_pitch + (rect.left - g_bounds.left) * g_bpp / 8; + auto primary(DDraw::PrimarySurface::getPrimary()); + CompatPtr ddUnk; + primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast(&ddUnk.getRef())); + CompatPtr dd(ddUnk); + CompatPtr surface; - auto dd(DDraw::Repository::getDirectDraw()); dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); return surface; }