diff --git a/DDrawCompat/D3dDdi/DeviceFuncs.cpp b/DDrawCompat/D3dDdi/DeviceFuncs.cpp index b405ca5..86f4a81 100644 --- a/DDrawCompat/D3dDdi/DeviceFuncs.cpp +++ b/DDrawCompat/D3dDdi/DeviceFuncs.cpp @@ -3,6 +3,7 @@ #include "D3dDdi/DeviceFuncs.h" #include "D3dDdi/LockResource.h" +#include "D3dDdi/KernelModeThunks.h" namespace { @@ -11,6 +12,7 @@ namespace HANDLE device; HANDLE resource; + Resource() : device(nullptr), resource(nullptr) {} Resource(HANDLE device, HANDLE resource) : device(device), resource(resource) {} bool operator<(const Resource& rhs) const @@ -41,6 +43,7 @@ namespace std::map g_lockResources; std::map g_renderTargets; + Resource g_sharedPrimary; const UINT g_resourceTypeFlags = getResourceTypeFlags().Value; ResourceReplacer::ResourceReplacer(HANDLE device, const HANDLE& resource, UINT subResourceIndex) @@ -208,6 +211,13 @@ namespace HRESULT APIENTRY destroyResource(HANDLE hDevice, HANDLE hResource) { + const bool isSharedPrimary = + hDevice == g_sharedPrimary.device && hResource == g_sharedPrimary.resource; + if (isSharedPrimary) + { + D3dDdi::KernelModeThunks::releaseVidPnSources(); + } + HRESULT result = getOrigVtable(hDevice).pfnDestroyResource(hDevice, hResource); if (SUCCEEDED(result)) { @@ -224,6 +234,11 @@ namespace getOrigVtable(hDevice).pfnDestroyResource(hDevice, it->second.getHandle()); g_lockResources.erase(it); } + + if (isSharedPrimary) + { + g_sharedPrimary = {}; + } } return result; } @@ -251,6 +266,16 @@ namespace return getOrigVtable(hDevice).pfnLock(hDevice, pData); } + HRESULT APIENTRY openResource(HANDLE hDevice, D3DDDIARG_OPENRESOURCE* pResource) + { + HRESULT result = getOrigVtable(hDevice).pfnOpenResource(hDevice, pResource); + if (SUCCEEDED(result) && pResource->Flags.Fullscreen) + { + g_sharedPrimary = Resource(hDevice, pResource->hResource); + } + return result; + } + HRESULT APIENTRY present(HANDLE hDevice, const D3DDDIARG_PRESENT* pData) { auto it = g_lockResources.find(Resource(hDevice, pData->hSrcResource)); @@ -334,6 +359,7 @@ namespace D3dDdi vtable.pfnDrawRectPatch = &RENDER_FUNC(pfnDrawRectPatch); vtable.pfnDrawTriPatch = &RENDER_FUNC(pfnDrawTriPatch); vtable.pfnLock = &lock; + vtable.pfnOpenResource = &openResource; vtable.pfnPresent = &present; vtable.pfnPresent1 = &present1; vtable.pfnSetRenderTarget = &setRenderTarget; diff --git a/DDrawCompat/D3dDdi/KernelModeThunks.cpp b/DDrawCompat/D3dDdi/KernelModeThunks.cpp index 416ea44..76c9f5d 100644 --- a/DDrawCompat/D3dDdi/KernelModeThunks.cpp +++ b/DDrawCompat/D3dDdi/KernelModeThunks.cpp @@ -230,5 +230,18 @@ namespace D3dDdi HOOK_FUNCTION(gdi32, D3DKMTSetVidPnSourceOwner, setVidPnSourceOwner); HOOK_FUNCTION(gdi32, D3DKMTSetVidPnSourceOwner1, setVidPnSourceOwner1); } + + void releaseVidPnSources() + { + for (auto it : g_devices) + { + if (D3DDDI_ID_UNINITIALIZED != it.second.vidPnSourceId) + { + D3DKMT_SETVIDPNSOURCEOWNER vidPnSourceOwner = {}; + vidPnSourceOwner.hDevice = it.first; + D3DKMTSetVidPnSourceOwner(&vidPnSourceOwner); + } + } + } } } diff --git a/DDrawCompat/D3dDdi/KernelModeThunks.h b/DDrawCompat/D3dDdi/KernelModeThunks.h index 9c49692..607d4e2 100644 --- a/DDrawCompat/D3dDdi/KernelModeThunks.h +++ b/DDrawCompat/D3dDdi/KernelModeThunks.h @@ -7,5 +7,6 @@ namespace D3dDdi namespace KernelModeThunks { void installHooks(); + void releaseVidPnSources(); } } diff --git a/DDrawCompat/DDraw/ActivateAppHandler.cpp b/DDrawCompat/DDraw/ActivateAppHandler.cpp index 250a80b..6e611af 100644 --- a/DDrawCompat/DDraw/ActivateAppHandler.cpp +++ b/DDrawCompat/DDraw/ActivateAppHandler.cpp @@ -1,116 +1,64 @@ -#include "Common/CompatPtr.h" -#include "Common/CompatRef.h" -#include "Common/Log.h" +#define CINTERFACE + +#include + +#include "Common/Hook.h" #include "DDraw/ActivateAppHandler.h" -#include "DDraw/DirectDraw.h" -#include "DDraw/DisplayMode.h" -#include "DDraw/Surfaces/PrimarySurface.h" -#include "DDraw/Surfaces/SurfaceImpl.h" #include "Gdi/Gdi.h" #include "Win32/FontSmoothing.h" -extern HWND g_mainWindow; - namespace { - bool g_isActive = true; - HWND g_fullScreenCooperativeWindow = nullptr; - DWORD g_fullScreenCooperativeFlags = 0; Win32::FontSmoothing::SystemSettings g_fontSmoothingSettings = {}; - HHOOK g_callWndProcHook = nullptr; + WNDPROC g_origDdWndProc = nullptr; - void handleActivateApp(bool isActivated); - - void activateApp(CompatRef dd) + void activateApp() { - if (!(g_fullScreenCooperativeFlags & DDSCL_NOWINDOWCHANGES)) - { - ShowWindow(g_fullScreenCooperativeWindow, SW_RESTORE); - HWND lastActivePopup = GetLastActivePopup(g_fullScreenCooperativeWindow); - if (lastActivePopup && lastActivePopup != g_fullScreenCooperativeWindow) - { - BringWindowToTop(lastActivePopup); - } - } - - dd->SetCooperativeLevel(&dd, g_fullScreenCooperativeWindow, g_fullScreenCooperativeFlags); - auto dm = DDraw::DisplayMode::getDisplayMode(dd); - dd->SetDisplayMode(&dd, dm.dwWidth, dm.dwHeight, 32, dm.dwRefreshRate, 0); - - auto primary(DDraw::PrimarySurface::getPrimary()); - if (primary && SUCCEEDED(primary->Restore(primary))) - { - DDraw::SurfaceImpl::fixSurfacePtrs(*primary); - Gdi::invalidate(nullptr); - } - + Gdi::enableEmulation(); Win32::FontSmoothing::setSystemSettings(g_fontSmoothingSettings); } - void deactivateApp(CompatRef dd) + void deactivateApp() { - dd->RestoreDisplayMode(&dd); - dd->SetCooperativeLevel(&dd, g_fullScreenCooperativeWindow, DDSCL_NORMAL); - - if (!(g_fullScreenCooperativeFlags & DDSCL_NOWINDOWCHANGES)) - { - ShowWindow(g_fullScreenCooperativeWindow, SW_SHOWMINNOACTIVE); - } - + Gdi::disableEmulation(); g_fontSmoothingSettings = Win32::FontSmoothing::getSystemSettings(); Win32::FontSmoothing::setSystemSettings(Win32::FontSmoothing::g_origSystemSettings); } - LRESULT CALLBACK callWndProc(int nCode, WPARAM wParam, LPARAM lParam) + LRESULT CALLBACK ddWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - auto ret = reinterpret_cast(lParam); - Compat::LogEnter("callWndProc", nCode, wParam, ret); + static bool isDisplayChangeNotificationEnabled = true; - if (HC_ACTION == nCode && WM_ACTIVATEAPP == ret->message) + switch (uMsg) { - const bool isActivated = TRUE == ret->wParam; - handleActivateApp(isActivated); - } - - LRESULT result = CallNextHookEx(nullptr, nCode, wParam, lParam); - Compat::LogLeave("callWndProc", nCode, wParam, ret) << result; - return result; - } - - void handleActivateApp(bool isActivated) - { - Compat::LogEnter("handleActivateApp", isActivated); - - if (isActivated == g_isActive) + case WM_ACTIVATEAPP: { - return; - } - g_isActive = isActivated; - - if (!isActivated) - { - Gdi::disableEmulation(); - } - - auto dd(DDraw::getFullScreenDirectDraw()); - if (dd) - { - if (isActivated) + isDisplayChangeNotificationEnabled = false; + if (TRUE == wParam) { - activateApp(*dd); + activateApp(); } else { - deactivateApp(*dd); + deactivateApp(); } + LRESULT result = g_origDdWndProc(hwnd, uMsg, wParam, lParam); + isDisplayChangeNotificationEnabled = true; + return result; } - if (isActivated) + case WM_DISPLAYCHANGE: { - Gdi::enableEmulation(); + // Fix for alt-tabbing in Commandos 2 + if (!isDisplayChangeNotificationEnabled) + { + return 0; + } + break; + } } - Compat::LogLeave("handleActivateApp", isActivated); + return g_origDdWndProc(hwnd, uMsg, wParam, lParam); } } @@ -118,26 +66,15 @@ namespace DDraw { namespace ActivateAppHandler { - void installHooks() + void setCooperativeLevel(HWND hwnd, DWORD flags) { - const DWORD threadId = GetCurrentThreadId(); - g_callWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, callWndProc, nullptr, threadId); - } - - bool isActive() - { - return g_isActive; - } - - void setFullScreenCooperativeLevel(HWND hwnd, DWORD flags) - { - g_fullScreenCooperativeWindow = hwnd; - g_fullScreenCooperativeFlags = flags; - } - - void uninstallHooks() - { - UnhookWindowsHookEx(g_callWndProcHook); + static bool isDdWndProcHooked = false; + if ((flags & DDSCL_FULLSCREEN) && !isDdWndProcHooked) + { + g_origDdWndProc = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_WNDPROC)); + Compat::hookFunction(reinterpret_cast(g_origDdWndProc), ddWndProc); + isDdWndProcHooked = true; + } } } } diff --git a/DDrawCompat/DDraw/ActivateAppHandler.h b/DDrawCompat/DDraw/ActivateAppHandler.h index 580f52d..df0ce9f 100644 --- a/DDrawCompat/DDraw/ActivateAppHandler.h +++ b/DDrawCompat/DDraw/ActivateAppHandler.h @@ -8,9 +8,6 @@ namespace DDraw { namespace ActivateAppHandler { - void installHooks(); - bool isActive(); - void setFullScreenCooperativeLevel(HWND hwnd, DWORD flags); - void uninstallHooks(); + void setCooperativeLevel(HWND hwnd, DWORD flags); } } diff --git a/DDrawCompat/DDraw/DirectDraw.cpp b/DDrawCompat/DDraw/DirectDraw.cpp index 4760e81..f6c62e2 100644 --- a/DDrawCompat/DDraw/DirectDraw.cpp +++ b/DDrawCompat/DDraw/DirectDraw.cpp @@ -1,17 +1,12 @@ #include "Common/CompatPtr.h" -#include "Common/CompatRef.h" #include "DDraw/ActivateAppHandler.h" #include "DDraw/DirectDraw.h" -#include "DDraw/DirectDrawSurface.h" #include "DDraw/DisplayMode.h" #include "DDraw/Surfaces/TagSurface.h" #include "DDraw/Surfaces/PrimarySurface.h" -#include "DDraw/Surfaces/Surface.h" namespace DDraw { - TagSurface* g_fullScreenTagSurface = nullptr; - template void* getDdObject(TDirectDraw& dd) { @@ -23,19 +18,6 @@ namespace DDraw template void* getDdObject(IDirectDraw4&); template void* getDdObject(IDirectDraw7&); - CompatPtr getFullScreenDirectDraw() - { - return g_fullScreenTagSurface ? g_fullScreenTagSurface->getDirectDraw() : nullptr; - } - - void onRelease(TagSurface& dd) - { - if (&dd == g_fullScreenTagSurface) - { - g_fullScreenTagSurface = nullptr; - } - } - template void DirectDraw::setCompatVtable(Vtable& vtable) { @@ -130,11 +112,6 @@ namespace DDraw HRESULT STDMETHODCALLTYPE DirectDraw::SetCooperativeLevel( TDirectDraw* This, HWND hWnd, DWORD dwFlags) { - if ((dwFlags & DDSCL_FULLSCREEN) && !ActivateAppHandler::isActive()) - { - return DDERR_EXCLUSIVEMODEALREADYSET; - } - HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags); if (SUCCEEDED(result)) { @@ -147,18 +124,7 @@ namespace DDraw tagSurface = TagSurface::get(ddObject); } - if (tagSurface) - { - if (dwFlags & DDSCL_FULLSCREEN) - { - g_fullScreenTagSurface = tagSurface; - ActivateAppHandler::setFullScreenCooperativeLevel(hWnd, dwFlags); - } - else if ((dwFlags & DDSCL_NORMAL) && tagSurface == g_fullScreenTagSurface) - { - g_fullScreenTagSurface = nullptr; - } - } + ActivateAppHandler::setCooperativeLevel(hWnd, dwFlags); } return result; } diff --git a/DDrawCompat/DDraw/DirectDraw.h b/DDrawCompat/DDraw/DirectDraw.h index e9300e4..89186fb 100644 --- a/DDrawCompat/DDraw/DirectDraw.h +++ b/DDrawCompat/DDraw/DirectDraw.h @@ -1,20 +1,14 @@ #pragma once -#include "Common/CompatPtr.h" #include "Common/CompatVtable.h" #include "DDraw/Visitors/DirectDrawVtblVisitor.h" #include "DDraw/Types.h" namespace DDraw { - class TagSurface; - template void* getDdObject(TDirectDraw& dd); - CompatPtr getFullScreenDirectDraw(); - void onRelease(TagSurface& dd); - template class DirectDraw: public CompatVtable> { diff --git a/DDrawCompat/DDraw/DisplayMode.cpp b/DDrawCompat/DDraw/DisplayMode.cpp index 4eb15f0..8fad834 100644 --- a/DDrawCompat/DDraw/DisplayMode.cpp +++ b/DDrawCompat/DDraw/DisplayMode.cpp @@ -40,11 +40,16 @@ namespace targetDevMode.dmDisplayFrequency == currentDevMode.dmDisplayFrequency && targetDevMode.dmDisplayFlags == currentDevMode.dmDisplayFlags) { - HANDLE dwmDxFullScreenTransitionEvent = OpenEventW( - EVENT_MODIFY_STATE, FALSE, L"DWM_DX_FULLSCREEN_TRANSITION_EVENT"); - SetEvent(dwmDxFullScreenTransitionEvent); - CloseHandle(dwmDxFullScreenTransitionEvent); - return DISP_CHANGE_SUCCESSFUL; + LONG result = origChangeDisplaySettings( + lpszDeviceName, lpDevMode, hwnd, dwflags, lParam); + if (SUCCEEDED(result)) + { + HANDLE dwmDxFullScreenTransitionEvent = OpenEventW( + EVENT_MODIFY_STATE, FALSE, L"DWM_DX_FULLSCREEN_TRANSITION_EVENT"); + SetEvent(dwmDxFullScreenTransitionEvent); + CloseHandle(dwmDxFullScreenTransitionEvent); + } + return result; } } diff --git a/DDrawCompat/DDraw/Hooks.cpp b/DDrawCompat/DDraw/Hooks.cpp index 8d2f97e..a4a5aa3 100644 --- a/DDrawCompat/DDraw/Hooks.cpp +++ b/DDrawCompat/DDraw/Hooks.cpp @@ -108,13 +108,10 @@ namespace DDraw hookDirectDraw(*dd7); hookDirectDrawSurface(*dd7); hookDirectDrawPalette(*dd7); - - ActivateAppHandler::installHooks(); } void uninstallHooks() { RealPrimarySurface::removeUpdateThread(); - ActivateAppHandler::uninstallHooks(); } } diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index bc49532..f699743 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -129,7 +129,7 @@ namespace timeBeginPeriod(1); g_frontBuffer = surface.detach(); - g_backBuffer = backBuffer.detach(); + g_backBuffer = backBuffer; g_surfaceDesc = desc; g_isFullScreen = isFlippable; @@ -149,7 +149,7 @@ namespace ResetEvent(g_updateEvent); timeEndPeriod(1); g_frontBuffer = nullptr; - g_backBuffer.release(); + g_backBuffer = nullptr; g_clipper = nullptr; g_isFullScreen = false; DDraw::PaletteConverter::release(); diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp index 87974e9..7742e54 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp @@ -145,6 +145,7 @@ namespace DDraw while (SUCCEEDED(result) && next.get() != g_gdiSurface.get() && next.get() != primary) { current = next; + next.reset(); result = current->GetAttachedSurface(current, &caps, &next.getRef()); } diff --git a/DDrawCompat/DDraw/Surfaces/TagSurface.cpp b/DDrawCompat/DDraw/Surfaces/TagSurface.cpp index 77bf177..3a4303c 100644 --- a/DDrawCompat/DDraw/Surfaces/TagSurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/TagSurface.cpp @@ -3,7 +3,6 @@ #include "DDraw/DirectDraw.h" #include "DDraw/Repository.h" -#include "DDraw/Surfaces/SurfaceImpl.h" #include "DDraw/Surfaces/TagSurface.h" namespace @@ -15,9 +14,6 @@ namespace DDraw { TagSurface::~TagSurface() { - std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(), - [=](auto& i) { return i.second == this; })->second; - onRelease(*this); Repository::onRelease(m_ddObject); g_tagSurfaces.erase(std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(), [=](auto& i) { return i.second == this; }));