mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added FullscreenMode setting
This commit is contained in:
parent
fb9f28456e
commit
55eab96f78
@ -11,6 +11,7 @@ namespace Config
|
||||
Settings::DisplayRefreshRate displayRefreshRate;
|
||||
Settings::DisplayResolution displayResolution;
|
||||
Settings::ForceD3D9On12 forceD3D9On12;
|
||||
Settings::FullscreenMode fullscreenMode;
|
||||
Settings::RenderColorDepth renderColorDepth;
|
||||
Settings::ResolutionScale resolutionScale;
|
||||
Settings::SpriteDetection spriteDetection;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <Config/Settings/DisplayRefreshRate.h>
|
||||
#include <Config/Settings/DisplayResolution.h>
|
||||
#include <Config/Settings/ForceD3D9On12.h>
|
||||
#include <Config/Settings/FullscreenMode.h>
|
||||
#include <Config/Settings/RenderColorDepth.h>
|
||||
#include <Config/Settings/ResolutionScale.h>
|
||||
#include <Config/Settings/SpriteDetection.h>
|
||||
@ -32,6 +33,7 @@ namespace Config
|
||||
extern Settings::DisplayRefreshRate displayRefreshRate;
|
||||
extern Settings::DisplayResolution displayResolution;
|
||||
extern Settings::ForceD3D9On12 forceD3D9On12;
|
||||
extern Settings::FullscreenMode fullscreenMode;
|
||||
extern Settings::RenderColorDepth renderColorDepth;
|
||||
extern Settings::ResolutionScale resolutionScale;
|
||||
extern Settings::SpriteDetection spriteDetection;
|
||||
|
21
DDrawCompat/Config/Settings/FullscreenMode.h
Normal file
21
DDrawCompat/Config/Settings/FullscreenMode.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <Config/MappedSetting.h>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
namespace Settings
|
||||
{
|
||||
class FullscreenMode : public MappedSetting<UINT>
|
||||
{
|
||||
public:
|
||||
static const UINT BORDERLESS = 0;
|
||||
static const UINT EXCLUSIVE = 1;
|
||||
|
||||
FullscreenMode()
|
||||
: MappedSetting("FullscreenMode", "borderless", { {"borderless", BORDERLESS}, {"exclusive", EXCLUSIVE} })
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,6 +1,10 @@
|
||||
#include <functional>
|
||||
#include <set>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include <d3dkmthk.h>
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <D3dDdi/Adapter.h>
|
||||
@ -9,6 +13,7 @@
|
||||
#include <D3dDdi/Hooks.h>
|
||||
#include <D3dDdi/KernelModeThunks.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
#include <D3dDdi/Log/KernelModeThunksLog.h>
|
||||
#include <Dll/Dll.h>
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_OPENADAPTER& data)
|
||||
@ -28,26 +33,36 @@ namespace
|
||||
|
||||
typedef HRESULT(APIENTRY* PFND3D9ON12_OPENADAPTER)(
|
||||
D3DDDIARG_OPENADAPTER* pOpenAdapter, LUID* pLUID, D3D9ON12_CREATE_DEVICE_ARGS* pArgs);
|
||||
typedef HRESULT(APIENTRY* PFND3D9ON12_KMTPRESENT)(
|
||||
HANDLE hDevice, D3DKMT_PRESENT* pKMTArgs);
|
||||
|
||||
struct D3D9ON12_PRIVATE_DDI_TABLE
|
||||
{
|
||||
PFND3D9ON12_OPENADAPTER pfnOpenAdapter;
|
||||
FARPROC pfnGetSharedGDIHandle;
|
||||
FARPROC pfnCreateSharedNTHandle;
|
||||
FARPROC pfnGetDeviceState;
|
||||
PFND3D9ON12_KMTPRESENT pfnKMTPresent;
|
||||
};
|
||||
|
||||
void APIENTRY getPrivateDdiTable(D3D9ON12_PRIVATE_DDI_TABLE* pPrivateDDITable);
|
||||
HRESULT APIENTRY kmtPresent(HANDLE hDevice, D3DKMT_PRESENT* pKMTArgs);
|
||||
HRESULT APIENTRY openAdapter(D3DDDIARG_OPENADAPTER* pOpenData);
|
||||
HRESULT APIENTRY openAdapterPrivate(D3DDDIARG_OPENADAPTER* pOpenData, LUID* pLUID, D3D9ON12_CREATE_DEVICE_ARGS* pArgs);
|
||||
|
||||
decltype(&getPrivateDdiTable) g_origGetPrivateDdiTable = nullptr;
|
||||
PFND3DDDI_OPENADAPTER g_origOpenAdapter = nullptr;
|
||||
PFND3D9ON12_OPENADAPTER g_origOpenAdapterPrivate = nullptr;
|
||||
PFND3D9ON12_KMTPRESENT g_origKmtPresent = nullptr;
|
||||
|
||||
void APIENTRY getPrivateDdiTable(D3D9ON12_PRIVATE_DDI_TABLE* pPrivateDDITable)
|
||||
{
|
||||
LOG_FUNC("GetPrivateDDITable", pPrivateDDITable);
|
||||
g_origGetPrivateDdiTable(pPrivateDDITable);
|
||||
g_origOpenAdapterPrivate = pPrivateDDITable->pfnOpenAdapter;
|
||||
g_origKmtPresent = pPrivateDDITable->pfnKMTPresent;
|
||||
pPrivateDDITable->pfnOpenAdapter = &openAdapterPrivate;
|
||||
pPrivateDDITable->pfnKMTPresent = &kmtPresent;
|
||||
}
|
||||
|
||||
FARPROC WINAPI getProcAddress(HMODULE hModule, LPCSTR lpProcName)
|
||||
@ -84,6 +99,13 @@ namespace
|
||||
return LOG_RESULT(CALL_ORIG_FUNC(GetProcAddress)(hModule, lpProcName));
|
||||
}
|
||||
|
||||
HRESULT APIENTRY kmtPresent(HANDLE hDevice, D3DKMT_PRESENT* pKMTArgs)
|
||||
{
|
||||
LOG_FUNC("KMTPresent", hDevice, pKMTArgs);
|
||||
D3dDdi::KernelModeThunks::fixPresent(*pKMTArgs);
|
||||
return LOG_RESULT(g_origKmtPresent(hDevice, pKMTArgs));
|
||||
}
|
||||
|
||||
HRESULT openAdapterCommon(D3DDDIARG_OPENADAPTER* pOpenData, std::function<HRESULT()> origOpenAdapter)
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <DDraw/ScopedThreadLock.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <Gdi/Palette.h>
|
||||
#include <Gdi/Window.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
@ -28,6 +29,8 @@ namespace
|
||||
D3dDdi::KernelModeThunks::AdapterInfo g_lastOpenAdapterInfo = {};
|
||||
Compat::SrwLock g_adapterInfoSrwLock;
|
||||
std::string g_lastDDrawDeviceName;
|
||||
decltype(&D3DKMTSubmitPresentBltToHwQueue) g_origSubmitPresentBltToHwQueue = nullptr;
|
||||
decltype(&D3DKMTSubmitPresentToHwQueue) g_origSubmitPresentToHwQueue = nullptr;
|
||||
|
||||
long long g_qpcLastVsync = 0;
|
||||
UINT g_vsyncCounter = 0;
|
||||
@ -199,6 +202,13 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS APIENTRY present(D3DKMT_PRESENT* pData)
|
||||
{
|
||||
LOG_FUNC("D3DKMTPresent", pData);
|
||||
D3dDdi::KernelModeThunks::fixPresent(*pData);
|
||||
return LOG_RESULT(D3DKMTPresent(pData));
|
||||
}
|
||||
|
||||
NTSTATUS APIENTRY queryAdapterInfo(const D3DKMT_QUERYADAPTERINFO* pData)
|
||||
{
|
||||
LOG_FUNC("D3DKMTQueryAdapterInfo", pData);
|
||||
@ -251,6 +261,20 @@ namespace
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
|
||||
NTSTATUS APIENTRY submitPresentToHwQueue(D3DKMT_SUBMITPRESENTTOHWQUEUE* pData)
|
||||
{
|
||||
LOG_FUNC("D3DKMTSubmitPresentToHwQueue", pData);
|
||||
D3dDdi::KernelModeThunks::fixPresent(pData->PrivatePresentData);
|
||||
return LOG_RESULT(g_origSubmitPresentToHwQueue(pData));
|
||||
}
|
||||
|
||||
NTSTATUS APIENTRY submitPresentBltToHwQueue(const D3DKMT_SUBMITPRESENTBLTTOHWQUEUE* pData)
|
||||
{
|
||||
LOG_FUNC("D3DKMTSubmitPresentBltToHwQueue", pData);
|
||||
D3dDdi::KernelModeThunks::fixPresent(const_cast<D3DKMT_PRESENT&>(pData->PrivatePresentData));
|
||||
return LOG_RESULT(g_origSubmitPresentBltToHwQueue(pData));
|
||||
}
|
||||
|
||||
void updateGdiAdapterInfo()
|
||||
{
|
||||
static auto lastDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness() - 1;
|
||||
@ -331,6 +355,27 @@ namespace D3dDdi
|
||||
{
|
||||
namespace KernelModeThunks
|
||||
{
|
||||
void fixPresent(D3DKMT_PRESENT& data)
|
||||
{
|
||||
static RECT rect = {};
|
||||
if (DDraw::RealPrimarySurface::isFullscreen())
|
||||
{
|
||||
HWND devicePresentationWindow = DDraw::RealPrimarySurface::getDevicePresentationWindow();
|
||||
if (devicePresentationWindow && devicePresentationWindow == data.hWindow)
|
||||
{
|
||||
rect = DDraw::RealPrimarySurface::getMonitorRect();
|
||||
OffsetRect(&rect, -rect.left, -rect.top);
|
||||
data.SrcRect = rect;
|
||||
data.DstRect.right = data.DstRect.left + rect.right;
|
||||
data.DstRect.bottom = data.DstRect.top + rect.bottom;
|
||||
if (1 == data.SubRectCnt)
|
||||
{
|
||||
data.pSrcSubRects = ▭
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AdapterInfo getAdapterInfo(CompatRef<IDirectDraw7> dd)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
@ -359,12 +404,19 @@ namespace D3dDdi
|
||||
|
||||
void installHooks()
|
||||
{
|
||||
g_origSubmitPresentBltToHwQueue = reinterpret_cast<decltype(&D3DKMTSubmitPresentBltToHwQueue)>(
|
||||
GetProcAddress(GetModuleHandle("gdi32"), "D3DKMTSubmitPresentBltToHwQueue"));
|
||||
g_origSubmitPresentToHwQueue = reinterpret_cast<decltype(&D3DKMTSubmitPresentToHwQueue)>(
|
||||
GetProcAddress(GetModuleHandle("gdi32"), "D3DKMTSubmitPresentToHwQueue"));
|
||||
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "CreateDCA", ddrawCreateDcA);
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCloseAdapter", closeAdapter);
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCreateDCFromMemory", createDcFromMemory);
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTOpenAdapterFromHdc", openAdapterFromHdc);
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTPresent", present);
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTQueryAdapterInfo", queryAdapterInfo);
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTSetGammaRamp", setGammaRamp);
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTSubmitPresentToHwQueue", submitPresentToHwQueue);
|
||||
|
||||
Dll::createThread(&vsyncThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include <d3dkmthk.h>
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include <Common/CompatRef.h>
|
||||
@ -16,6 +20,7 @@ namespace D3dDdi
|
||||
MONITORINFOEXW monitorInfo;
|
||||
};
|
||||
|
||||
void fixPresent(D3DKMT_PRESENT& data);
|
||||
AdapterInfo getAdapterInfo(CompatRef<IDirectDraw7> dd);
|
||||
AdapterInfo getLastOpenAdapterInfo();
|
||||
long long getQpcLastVsync();
|
||||
|
@ -163,3 +163,18 @@ std::ostream& operator<<(std::ostream& os, const D3DKMT_SETVIDPNSOURCEOWNER1& da
|
||||
<< data.Version0
|
||||
<< Compat::hex(data.Flags.Value);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const D3DKMT_SUBMITPRESENTTOHWQUEUE& data)
|
||||
{
|
||||
return Compat::LogStruct(os)
|
||||
<< Compat::array(data.hHwQueues, data.PrivatePresentData.BroadcastContextCount + 1)
|
||||
<< data.PrivatePresentData;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const D3DKMT_SUBMITPRESENTBLTTOHWQUEUE& data)
|
||||
{
|
||||
return Compat::LogStruct(os)
|
||||
<< Compat::hex(data.hHwQueue)
|
||||
<< Compat::hex(data.HwQueueProgressFenceId)
|
||||
<< data.PrivatePresentData;
|
||||
}
|
||||
|
@ -23,3 +23,5 @@ std::ostream& operator<<(std::ostream& os, const D3DKMT_SETGAMMARAMP& data);
|
||||
std::ostream& operator<<(std::ostream& os, const D3DKMT_SETQUEUEDLIMIT& data);
|
||||
std::ostream& operator<<(std::ostream& os, const D3DKMT_SETVIDPNSOURCEOWNER& data);
|
||||
std::ostream& operator<<(std::ostream& os, const D3DKMT_SETVIDPNSOURCEOWNER1& data);
|
||||
std::ostream& operator<<(std::ostream& os, const D3DKMT_SUBMITPRESENTTOHWQUEUE& data);
|
||||
std::ostream& operator<<(std::ostream& os, const D3DKMT_SUBMITPRESENTBLTTOHWQUEUE& data);
|
||||
|
@ -126,7 +126,7 @@ namespace D3dDdi
|
||||
throw HResultException(E_FAIL);
|
||||
}
|
||||
|
||||
if (m_origData.Flags.Primary)
|
||||
if (m_origData.Flags.MatchGdiPrimary)
|
||||
{
|
||||
g_presentationRect = calculatePresentationRect();
|
||||
auto& si = m_origData.pSurfList[0];
|
||||
@ -175,7 +175,7 @@ namespace D3dDdi
|
||||
|
||||
Resource::~Resource()
|
||||
{
|
||||
if (m_origData.Flags.Primary)
|
||||
if (m_origData.Flags.MatchGdiPrimary)
|
||||
{
|
||||
Gdi::VirtualScreen::setFullscreenMode(false);
|
||||
Gdi::Cursor::setEmulated(false);
|
||||
@ -215,7 +215,7 @@ namespace D3dDdi
|
||||
|
||||
if (srcResource)
|
||||
{
|
||||
if (m_fixedData.Flags.Primary)
|
||||
if (m_fixedData.Flags.MatchGdiPrimary)
|
||||
{
|
||||
return presentationBlt(data, srcResource);
|
||||
}
|
||||
@ -486,7 +486,7 @@ namespace D3dDdi
|
||||
|
||||
void Resource::fixResourceData()
|
||||
{
|
||||
if (m_fixedData.Flags.Primary)
|
||||
if (m_fixedData.Flags.MatchGdiPrimary)
|
||||
{
|
||||
RECT r = DDraw::RealPrimarySurface::getMonitorRect();
|
||||
if (!IsRectEmpty(&r))
|
||||
@ -538,7 +538,7 @@ namespace D3dDdi
|
||||
|
||||
D3DDDIFORMAT Resource::getFormatConfig()
|
||||
{
|
||||
if (m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Primary && D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
|
||||
if (m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.MatchGdiPrimary && D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
|
||||
(D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format))
|
||||
{
|
||||
switch (Config::renderColorDepth.get())
|
||||
@ -552,7 +552,7 @@ namespace D3dDdi
|
||||
|
||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Resource::getMultisampleConfig()
|
||||
{
|
||||
if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.Primary ||
|
||||
if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.MatchGdiPrimary ||
|
||||
m_fixedData.Flags.ZBuffer) &&
|
||||
D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool)
|
||||
{
|
||||
@ -570,7 +570,7 @@ namespace D3dDdi
|
||||
SIZE Resource::getScaledSize()
|
||||
{
|
||||
SIZE size = { static_cast<LONG>(m_fixedData.pSurfList[0].Width), static_cast<LONG>(m_fixedData.pSurfList[0].Height) };
|
||||
if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.Primary ||
|
||||
if ((m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.Texture && !m_fixedData.Flags.MatchGdiPrimary ||
|
||||
m_fixedData.Flags.ZBuffer) &&
|
||||
D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool)
|
||||
{
|
||||
|
@ -15,9 +15,9 @@ namespace DDraw
|
||||
void suppressEmulatedDirectDraw(GUID*& guid);
|
||||
|
||||
template <typename TDirectDraw>
|
||||
HWND getDeviceWindow(TDirectDraw& dd)
|
||||
HWND* getDeviceWindowPtr(TDirectDraw& dd)
|
||||
{
|
||||
return reinterpret_cast<HWND**>(&dd)[1][8];
|
||||
return &reinterpret_cast<HWND**>(&dd)[1][8];
|
||||
}
|
||||
|
||||
template <typename Vtable>
|
||||
|
@ -45,6 +45,9 @@ namespace
|
||||
std::atomic<long long> g_qpcLastUpdate = 0;
|
||||
UINT g_flipEndVsyncCount = 0;
|
||||
UINT g_presentEndVsyncCount = 0;
|
||||
HWND g_devicePresentationWindow = nullptr;
|
||||
HWND g_deviceWindow = nullptr;
|
||||
HWND* g_deviceWindowPtr = nullptr;
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
||||
CompatPtr<IDirectDrawSurface7> getLastSurface();
|
||||
@ -128,6 +131,11 @@ namespace
|
||||
g_isFullscreen = false;
|
||||
g_waitingForPrimaryUnlock = false;
|
||||
g_surfaceDesc = {};
|
||||
|
||||
DDraw::RealPrimarySurface::updateDevicePresentationWindowPos();
|
||||
g_devicePresentationWindow = nullptr;
|
||||
g_deviceWindow = nullptr;
|
||||
g_deviceWindowPtr = nullptr;
|
||||
g_monitorRect = {};
|
||||
}
|
||||
|
||||
@ -200,9 +208,11 @@ namespace
|
||||
g_isUpdatePending = false;
|
||||
g_waitingForPrimaryUnlock = false;
|
||||
|
||||
if (g_isFullscreen)
|
||||
if (g_isFullscreen && g_devicePresentationWindow)
|
||||
{
|
||||
*g_deviceWindowPtr = g_devicePresentationWindow;
|
||||
g_frontBuffer->Flip(g_frontBuffer, getBackBuffer(), DDFLIP_WAIT);
|
||||
*g_deviceWindowPtr = g_deviceWindow;
|
||||
}
|
||||
g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + max(flipInterval, 1);
|
||||
}
|
||||
@ -296,7 +306,13 @@ namespace DDraw
|
||||
g_frontBuffer = CompatPtr<IDirectDrawSurface7>::from(surface.get()).detach();
|
||||
g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier,
|
||||
&g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER);
|
||||
|
||||
g_deviceWindowPtr = DDraw::DirectDraw::getDeviceWindowPtr(dd.get());
|
||||
g_deviceWindow = g_deviceWindowPtr ? *g_deviceWindowPtr : nullptr;
|
||||
g_devicePresentationWindow = Gdi::Window::getPresentationWindow(g_deviceWindow);
|
||||
|
||||
onRestore();
|
||||
updateDevicePresentationWindowPos();
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
@ -354,6 +370,11 @@ namespace DDraw
|
||||
}
|
||||
}
|
||||
|
||||
HWND RealPrimarySurface::getDevicePresentationWindow()
|
||||
{
|
||||
return g_devicePresentationWindow;
|
||||
}
|
||||
|
||||
HRESULT RealPrimarySurface::getGammaRamp(DDGAMMARAMP* rampData)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
@ -376,6 +397,15 @@ namespace DDraw
|
||||
return g_frontBuffer;
|
||||
}
|
||||
|
||||
HWND RealPrimarySurface::getTopmost()
|
||||
{
|
||||
if (g_isFullscreen && g_devicePresentationWindow)
|
||||
{
|
||||
return g_devicePresentationWindow;
|
||||
}
|
||||
return HWND_TOPMOST;
|
||||
}
|
||||
|
||||
void RealPrimarySurface::init()
|
||||
{
|
||||
Dll::createThread(&updateThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
@ -438,6 +468,28 @@ namespace DDraw
|
||||
}
|
||||
}
|
||||
|
||||
void RealPrimarySurface::updateDevicePresentationWindowPos()
|
||||
{
|
||||
if (!g_devicePresentationWindow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
if (g_isFullscreen && IsWindowVisible(g_deviceWindow) && !IsIconic(g_deviceWindow))
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_devicePresentationWindow, HWND_TOPMOST, g_monitorRect.left, g_monitorRect.top,
|
||||
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top,
|
||||
SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
Gdi::Window::updatePresentationWindowPos(g_devicePresentationWindow, g_deviceWindow);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool RealPrimarySurface::waitForFlip(Surface* surface)
|
||||
{
|
||||
auto primary(DDraw::PrimarySurface::getPrimary());
|
||||
|
@ -17,9 +17,11 @@ namespace DDraw
|
||||
|
||||
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
|
||||
static void flush();
|
||||
static HWND getDevicePresentationWindow();
|
||||
static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
|
||||
static RECT getMonitorRect();
|
||||
static CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
||||
static HWND getTopmost();
|
||||
static void init();
|
||||
static bool isFullscreen();
|
||||
static bool isLost();
|
||||
@ -28,6 +30,7 @@ namespace DDraw
|
||||
static void scheduleUpdate();
|
||||
static HRESULT setGammaRamp(DDGAMMARAMP* rampData);
|
||||
static void update();
|
||||
static void updateDevicePresentationWindowPos();
|
||||
static bool waitForFlip(Surface* surface);
|
||||
};
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ namespace DDraw
|
||||
}
|
||||
|
||||
g_origCaps = origCaps;
|
||||
g_deviceWindow = DDraw::DirectDraw::getDeviceWindow(dd.get());
|
||||
g_deviceWindow = *DDraw::DirectDraw::getDeviceWindowPtr(dd.get());
|
||||
|
||||
if (desc.ddpfPixelFormat.dwRGBBitCount <= 8)
|
||||
{
|
||||
|
@ -226,6 +226,7 @@
|
||||
<ClInclude Include="Config\Settings\DisplayRefreshRate.h" />
|
||||
<ClInclude Include="Config\Settings\DisplayResolution.h" />
|
||||
<ClInclude Include="Config\Settings\ForceD3D9On12.h" />
|
||||
<ClInclude Include="Config\Settings\FullscreenMode.h" />
|
||||
<ClInclude Include="Config\Settings\RenderColorDepth.h" />
|
||||
<ClInclude Include="Config\Settings\ResolutionScale.h" />
|
||||
<ClInclude Include="Config\Settings\SpriteDetection.h" />
|
||||
|
@ -540,6 +540,9 @@
|
||||
<ClInclude Include="Config\Settings\ForceD3D9On12.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Config\Settings\FullscreenMode.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
|
@ -239,8 +239,11 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
Time::init();
|
||||
Win32::Thread::applyConfig();
|
||||
|
||||
const DWORD disableMaxWindowedMode = 12;
|
||||
CALL_ORIG_PROC(SetAppCompatData)(disableMaxWindowedMode, 0);
|
||||
if (Config::Settings::FullscreenMode::EXCLUSIVE == Config::fullscreenMode.get())
|
||||
{
|
||||
const DWORD disableMaxWindowedMode = 12;
|
||||
CALL_ORIG_PROC(SetAppCompatData)(disableMaxWindowedMode, 0);
|
||||
}
|
||||
|
||||
Compat::Log() << "DDrawCompat loaded successfully";
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <Gdi/TitleBar.h>
|
||||
#include <Gdi/User32WndProcs.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Gdi/Window.h>
|
||||
#include <Gdi/WinProc.h>
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const MENUITEMINFOW& val)
|
||||
@ -249,6 +250,21 @@ namespace
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_SETREDRAW:
|
||||
{
|
||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
BOOL isVisible = IsWindowVisible(hwnd);
|
||||
auto result = origDefWindowProc(hwnd, msg, wParam, lParam);
|
||||
if (isVisible != IsWindowVisible(hwnd))
|
||||
{
|
||||
Gdi::Window::updateAll();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return defPaintProc(hwnd, msg, wParam, lParam, origDefWindowProc);
|
||||
|
@ -38,7 +38,6 @@ namespace
|
||||
std::map<HWND, WindowProc> g_windowProc;
|
||||
|
||||
WindowProc getWindowProc(HWND hwnd);
|
||||
bool isTopLevelWindow(HWND hwnd);
|
||||
bool isUser32ScrollBar(HWND hwnd);
|
||||
void onDestroyWindow(HWND hwnd);
|
||||
void onGetMinMaxInfo(MINMAXINFO& mmi);
|
||||
@ -72,7 +71,7 @@ namespace
|
||||
break;
|
||||
|
||||
case WM_SYNCPAINT:
|
||||
if (isTopLevelWindow(hwnd))
|
||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
Gdi::Window::onSyncPaint(hwnd);
|
||||
return 0;
|
||||
@ -124,7 +123,7 @@ namespace
|
||||
break;
|
||||
|
||||
case WM_STYLECHANGED:
|
||||
if (isTopLevelWindow(hwnd))
|
||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
Gdi::Window::onStyleChanged(hwnd, wParam);
|
||||
}
|
||||
@ -181,11 +180,6 @@ namespace
|
||||
return g_windowProc[hwnd];
|
||||
}
|
||||
|
||||
bool isTopLevelWindow(HWND hwnd)
|
||||
{
|
||||
return GetDesktopWindow() == GetAncestor(hwnd, GA_PARENT);
|
||||
}
|
||||
|
||||
bool isUser32ScrollBar(HWND hwnd)
|
||||
{
|
||||
WNDCLASS wc = {};
|
||||
@ -207,7 +201,7 @@ namespace
|
||||
|
||||
void onDestroyWindow(HWND hwnd)
|
||||
{
|
||||
if (isTopLevelWindow(hwnd))
|
||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
Gdi::Window::updateAll();
|
||||
return;
|
||||
@ -272,7 +266,7 @@ namespace
|
||||
notifyFunc();
|
||||
}
|
||||
|
||||
if (isTopLevelWindow(hwnd))
|
||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
Gdi::Window::updateAll();
|
||||
}
|
||||
@ -286,7 +280,7 @@ namespace
|
||||
|
||||
void onWindowPosChanging(HWND hwnd, WINDOWPOS& wp)
|
||||
{
|
||||
if (isTopLevelWindow(hwnd))
|
||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
wp.flags |= SWP_NOREDRAW;
|
||||
}
|
||||
@ -499,7 +493,7 @@ namespace Gdi
|
||||
setWindowProc(hwnd, ddcWindowProcA, ddcWindowProcW);
|
||||
}
|
||||
|
||||
if (!isTopLevelWindow(hwnd))
|
||||
if (!Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -355,36 +355,15 @@ namespace
|
||||
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
|
||||
}
|
||||
|
||||
WINDOWPOS wp = {};
|
||||
wp.flags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING;
|
||||
if (isVisible)
|
||||
const HWND devicePresentationWindow = DDraw::RealPrimarySurface::getDevicePresentationWindow();
|
||||
if (DDraw::RealPrimarySurface::isFullscreen() && devicePresentationWindow == it->second.presentationWindow)
|
||||
{
|
||||
wp.hwndInsertAfter = GetWindow(hwnd, GW_HWNDPREV);
|
||||
if (!wp.hwndInsertAfter)
|
||||
{
|
||||
wp.hwndInsertAfter = (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP;
|
||||
}
|
||||
else if (wp.hwndInsertAfter == it->second.presentationWindow)
|
||||
{
|
||||
wp.flags |= SWP_NOZORDER;
|
||||
}
|
||||
|
||||
wp.x = it->second.windowRect.left;
|
||||
wp.y = it->second.windowRect.top;
|
||||
wp.cx = it->second.windowRect.right - it->second.windowRect.left;
|
||||
wp.cy = it->second.windowRect.bottom - it->second.windowRect.top;
|
||||
wp.flags |= SWP_SHOWWINDOW;
|
||||
DDraw::RealPrimarySurface::updateDevicePresentationWindowPos();
|
||||
}
|
||||
else
|
||||
{
|
||||
wp.flags |= SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
|
||||
Gdi::Window::updatePresentationWindowPos(it->second.presentationWindow, hwnd);
|
||||
}
|
||||
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(it->second.presentationWindow,
|
||||
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
|
||||
});
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
@ -395,6 +374,56 @@ namespace Gdi
|
||||
{
|
||||
namespace Window
|
||||
{
|
||||
HWND getPresentationWindow(HWND hwnd)
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
auto it = g_windows.find(hwnd);
|
||||
return it != g_windows.end() ? it->second.presentationWindow : nullptr;
|
||||
}
|
||||
|
||||
std::vector<LayeredWindow> getVisibleLayeredWindows()
|
||||
{
|
||||
std::vector<LayeredWindow> layeredWindows;
|
||||
for (auto it = g_windowZOrder.rbegin(); it != g_windowZOrder.rend(); ++it)
|
||||
{
|
||||
auto& window = **it;
|
||||
if (window.isLayered && !window.visibleRegion.isEmpty())
|
||||
{
|
||||
layeredWindows.push_back({ window.hwnd, window.windowRect, window.visibleRegion });
|
||||
}
|
||||
}
|
||||
|
||||
RECT wr = {};
|
||||
auto configWindow = GuiThread::getConfigWindow();
|
||||
if (configWindow && configWindow->isVisible())
|
||||
{
|
||||
GetWindowRect(configWindow->getWindow(), &wr);
|
||||
auto visibleRegion(getWindowRegion(configWindow->getWindow()));
|
||||
visibleRegion.offset(wr.left, wr.top);
|
||||
layeredWindows.push_back({ configWindow->getWindow(), wr, visibleRegion });
|
||||
auto capture = Input::getCaptureWindow();
|
||||
if (capture && capture != configWindow)
|
||||
{
|
||||
GetWindowRect(capture->getWindow(), &wr);
|
||||
layeredWindows.push_back({ capture->getWindow(), wr, nullptr });
|
||||
}
|
||||
}
|
||||
|
||||
HWND cursorWindow = Input::getCursorWindow();
|
||||
if (cursorWindow)
|
||||
{
|
||||
GetWindowRect(cursorWindow, &wr);
|
||||
layeredWindows.push_back({ cursorWindow, wr, nullptr });
|
||||
}
|
||||
|
||||
return layeredWindows;
|
||||
}
|
||||
|
||||
bool isTopLevelWindow(HWND hwnd)
|
||||
{
|
||||
return GetDesktopWindow() == GetAncestor(hwnd, GA_PARENT);
|
||||
}
|
||||
|
||||
void onStyleChanged(HWND hwnd, WPARAM wParam)
|
||||
{
|
||||
if (GWL_EXSTYLE == wParam)
|
||||
@ -516,44 +545,6 @@ namespace Gdi
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LayeredWindow> getVisibleLayeredWindows()
|
||||
{
|
||||
std::vector<LayeredWindow> layeredWindows;
|
||||
for (auto it = g_windowZOrder.rbegin(); it != g_windowZOrder.rend(); ++it)
|
||||
{
|
||||
auto& window = **it;
|
||||
if (window.isLayered && !window.visibleRegion.isEmpty())
|
||||
{
|
||||
layeredWindows.push_back({ window.hwnd, window.windowRect, window.visibleRegion });
|
||||
}
|
||||
}
|
||||
|
||||
RECT wr = {};
|
||||
auto configWindow = GuiThread::getConfigWindow();
|
||||
if (configWindow && configWindow->isVisible())
|
||||
{
|
||||
GetWindowRect(configWindow->getWindow(), &wr);
|
||||
auto visibleRegion(getWindowRegion(configWindow->getWindow()));
|
||||
visibleRegion.offset(wr.left, wr.top);
|
||||
layeredWindows.push_back({ configWindow->getWindow(), wr, visibleRegion });
|
||||
auto capture = Input::getCaptureWindow();
|
||||
if (capture && capture != configWindow)
|
||||
{
|
||||
GetWindowRect(capture->getWindow(), &wr);
|
||||
layeredWindows.push_back({ capture->getWindow(), wr, nullptr });
|
||||
}
|
||||
}
|
||||
|
||||
HWND cursorWindow = Input::getCursorWindow();
|
||||
if (cursorWindow)
|
||||
{
|
||||
GetWindowRect(cursorWindow, &wr);
|
||||
layeredWindows.push_back({ cursorWindow, wr, nullptr });
|
||||
}
|
||||
|
||||
return layeredWindows;
|
||||
}
|
||||
|
||||
void updateAll()
|
||||
{
|
||||
LOG_FUNC("Window::updateAll");
|
||||
@ -603,5 +594,44 @@ namespace Gdi
|
||||
SendNotifyMessage(hwnd, WM_SYNCPAINT, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePresentationWindowPos(HWND presentationWindow, HWND owner)
|
||||
{
|
||||
const bool isOwnerVisible = IsWindowVisible(owner) && !IsIconic(owner);
|
||||
|
||||
WINDOWPOS wp = {};
|
||||
wp.flags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING;
|
||||
if (isOwnerVisible)
|
||||
{
|
||||
wp.hwndInsertAfter = GetWindow(owner, GW_HWNDPREV);
|
||||
if (!wp.hwndInsertAfter)
|
||||
{
|
||||
wp.hwndInsertAfter = (GetWindowLong(owner, GWL_EXSTYLE) & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP;
|
||||
}
|
||||
else if (wp.hwndInsertAfter == presentationWindow)
|
||||
{
|
||||
wp.flags |= SWP_NOZORDER;
|
||||
}
|
||||
|
||||
RECT wr = {};
|
||||
GetWindowRect(owner, &wr);
|
||||
|
||||
wp.x = wr.left;
|
||||
wp.y = wr.top;
|
||||
wp.cx = wr.right - wr.left;
|
||||
wp.cy = wr.bottom - wr.top;
|
||||
wp.flags |= SWP_SHOWWINDOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
wp.flags |= SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
|
||||
}
|
||||
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(presentationWindow,
|
||||
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,15 @@ namespace Gdi
|
||||
Gdi::Region region;
|
||||
};
|
||||
|
||||
HWND getPresentationWindow(HWND hwnd);
|
||||
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
||||
bool isTopLevelWindow(HWND hwnd);
|
||||
void onStyleChanged(HWND hwnd, WPARAM wParam);
|
||||
void onSyncPaint(HWND hwnd);
|
||||
void present(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
CompatRef<IDirectDrawClipper> clipper);
|
||||
void present(Gdi::Region excludeRegion);
|
||||
void updateAll();
|
||||
void updatePresentationWindowPos(HWND presentationWindow, HWND owner);
|
||||
}
|
||||
}
|
||||
|
@ -285,8 +285,9 @@ namespace Input
|
||||
CALL_ORIG_FUNC(SetLayeredWindowAttributes)(g_cursorWindow, RGB(0xFF, 0xFF, 0xFF), 0, LWA_COLORKEY);
|
||||
|
||||
g_cursorPos = { (g_monitorRect.left + g_monitorRect.right) / 2, (g_monitorRect.top + g_monitorRect.bottom) / 2 };
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_cursorWindow, HWND_TOPMOST, g_cursorPos.x, g_cursorPos.y,
|
||||
g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_cursorWindow, DDraw::RealPrimarySurface::getTopmost(),
|
||||
g_cursorPos.x, g_cursorPos.y, g_bmpArrowSize.cx, g_bmpArrowSize.cy,
|
||||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
g_capture->onMouseMove(getRelativeCursorPos());
|
||||
|
||||
resetMouseHook();
|
||||
@ -305,8 +306,9 @@ namespace Input
|
||||
{
|
||||
Gdi::GuiThread::execute([]()
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_cursorWindow, HWND_TOPMOST, g_cursorPos.x, g_cursorPos.y,
|
||||
g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING);
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_cursorWindow, DDraw::RealPrimarySurface::getTopmost(),
|
||||
g_cursorPos.x, g_cursorPos.y, g_bmpArrowSize.cx, g_bmpArrowSize.cy,
|
||||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,6 @@ namespace Overlay
|
||||
if (m_style & WS_VISIBLE)
|
||||
{
|
||||
updatePos();
|
||||
ShowWindow(m_hwnd, SW_SHOWNA);
|
||||
Input::setCapture(this);
|
||||
}
|
||||
else
|
||||
@ -214,8 +213,10 @@ namespace Overlay
|
||||
m_rect = calculateRect({ monitorRect.left / m_scaleFactor, monitorRect.top / m_scaleFactor,
|
||||
monitorRect.right / m_scaleFactor, monitorRect.bottom / m_scaleFactor });
|
||||
|
||||
CALL_ORIG_FUNC(SetWindowPos)(m_hwnd, HWND_TOPMOST, m_rect.left * m_scaleFactor, m_rect.top * m_scaleFactor,
|
||||
(m_rect.right - m_rect.left) * m_scaleFactor, (m_rect.bottom - m_rect.top) * m_scaleFactor, SWP_NOACTIVATE);
|
||||
CALL_ORIG_FUNC(SetWindowPos)(m_hwnd, DDraw::RealPrimarySurface::getTopmost(),
|
||||
m_rect.left * m_scaleFactor, m_rect.top * m_scaleFactor,
|
||||
(m_rect.right - m_rect.left) * m_scaleFactor, (m_rect.bottom - m_rect.top) * m_scaleFactor,
|
||||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
|
||||
if (Input::getCaptureWindow() == this)
|
||||
{
|
||||
@ -230,7 +231,10 @@ namespace Overlay
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_DISPLAYCHANGE:
|
||||
updatePos();
|
||||
if (m_style & WS_VISIBLE)
|
||||
{
|
||||
updatePos();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user