mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Handle DisplayResolution scaling in windowed mode
This commit is contained in:
parent
fc16184256
commit
5ce5ea0668
@ -387,20 +387,19 @@ namespace D3dDdi
|
||||
void fixPresent(D3DKMT_PRESENT& data)
|
||||
{
|
||||
static RECT rect = {};
|
||||
if (DDraw::RealPrimarySurface::isFullscreen())
|
||||
HWND devicePresentationWindow = DDraw::RealPrimarySurface::getDevicePresentationWindow();
|
||||
HWND presentationWindow = DDraw::RealPrimarySurface::getPresentationWindow();
|
||||
if (devicePresentationWindow && devicePresentationWindow == data.hWindow ||
|
||||
presentationWindow && presentationWindow == data.hWindow)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 = ▭
|
||||
}
|
||||
data.pSrcSubRects = ▭
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,16 +131,7 @@ namespace D3dDdi
|
||||
|
||||
if (m_origData.Flags.MatchGdiPrimary)
|
||||
{
|
||||
g_presentationRect = calculatePresentationRect();
|
||||
auto& si = m_origData.pSurfList[0];
|
||||
RECT primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
|
||||
|
||||
Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect());
|
||||
if (!EqualRect(&g_presentationRect, &primaryRect))
|
||||
{
|
||||
Gdi::Cursor::setEmulated(true);
|
||||
}
|
||||
Gdi::VirtualScreen::setFullscreenMode(true);
|
||||
setFullscreenMode(true);
|
||||
}
|
||||
|
||||
fixResourceData();
|
||||
@ -180,9 +171,7 @@ namespace D3dDdi
|
||||
{
|
||||
if (m_origData.Flags.MatchGdiPrimary)
|
||||
{
|
||||
Gdi::VirtualScreen::setFullscreenMode(false);
|
||||
Gdi::Cursor::setEmulated(false);
|
||||
Gdi::Cursor::setMonitorClipRect({});
|
||||
setFullscreenMode(false);
|
||||
}
|
||||
|
||||
if (m_msaaSurface.surface || m_msaaResolvedSurface.surface || m_lockRefSurface.surface)
|
||||
@ -1036,6 +1025,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Resource::presentationBlt(D3DDDIARG_BLT data, Resource* srcResource)
|
||||
{
|
||||
LOG_FUNC("Resource::presentationBlt", data, *srcResource);
|
||||
if (srcResource->m_lockResource)
|
||||
{
|
||||
if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
|
||||
@ -1066,7 +1056,7 @@ namespace D3dDdi
|
||||
srcResource = repo.getTempTexture(srcWidth, srcHeight, getPixelFormat(srcResource->m_fixedData.Format)).resource;
|
||||
if (!srcResource)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
return LOG_RESULT(E_OUTOFMEMORY);
|
||||
}
|
||||
copySubResourceRegion(*srcResource, 0, data.SrcRect, data.hSrcResource, data.SrcSubResourceIndex, data.SrcRect);
|
||||
}
|
||||
@ -1103,7 +1093,7 @@ namespace D3dDdi
|
||||
|
||||
if (!rtSurface.resource)
|
||||
{
|
||||
return S_OK;
|
||||
return LOG_RESULT(S_OK);
|
||||
}
|
||||
|
||||
const LONG dstWidth = data.DstRect.right - data.DstRect.left;
|
||||
@ -1147,7 +1137,7 @@ namespace D3dDdi
|
||||
}
|
||||
|
||||
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
|
||||
return S_OK;
|
||||
return LOG_RESULT(S_OK);
|
||||
}
|
||||
|
||||
void Resource::presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect)
|
||||
@ -1244,6 +1234,35 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
|
||||
void Resource::setFullscreenMode(bool isFullscreen)
|
||||
{
|
||||
if (!IsRectEmpty(&g_presentationRect) == isFullscreen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFullscreen)
|
||||
{
|
||||
g_presentationRect = calculatePresentationRect();
|
||||
auto& si = m_origData.pSurfList[0];
|
||||
RECT primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
|
||||
|
||||
Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect());
|
||||
if (!EqualRect(&g_presentationRect, &primaryRect))
|
||||
{
|
||||
Gdi::Cursor::setEmulated(true);
|
||||
}
|
||||
Gdi::VirtualScreen::setFullscreenMode(m_origData.Flags.MatchGdiPrimary);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_presentationRect = {};
|
||||
Gdi::VirtualScreen::setFullscreenMode(false);
|
||||
Gdi::Cursor::setEmulated(false);
|
||||
Gdi::Cursor::setMonitorClipRect({});
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Resource::shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource)
|
||||
{
|
||||
LOG_FUNC("Resource::shaderBlt", data, srcResource);
|
||||
|
@ -49,6 +49,7 @@ namespace D3dDdi
|
||||
void scaleRect(RECT& rect);
|
||||
void setAsGdiResource(bool isGdiResource);
|
||||
void setAsPrimary();
|
||||
void setFullscreenMode(bool isFullscreen);
|
||||
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
||||
void updateConfig();
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/Palette.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Gdi/Window.h>
|
||||
#include <Gdi/WinProc.h>
|
||||
@ -62,6 +63,7 @@ namespace
|
||||
HWND g_devicePresentationWindow = nullptr;
|
||||
HWND g_deviceWindow = nullptr;
|
||||
HWND* g_deviceWindowPtr = nullptr;
|
||||
HWND g_presentationWindow = nullptr;
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
||||
CompatPtr<IDirectDrawSurface7> getLastSurface();
|
||||
@ -195,6 +197,16 @@ namespace
|
||||
{
|
||||
LOG_FUNC("RealPrimarySurface::onRelease");
|
||||
|
||||
if (g_presentationWindow)
|
||||
{
|
||||
auto resource = D3dDdi::Device::findResource(
|
||||
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
|
||||
resource->setFullscreenMode(false);
|
||||
|
||||
Gdi::GuiThread::destroyWindow(g_presentationWindow);
|
||||
g_presentationWindow = nullptr;
|
||||
}
|
||||
|
||||
g_frontBuffer = nullptr;
|
||||
g_lastFlipSurface = nullptr;
|
||||
g_windowedBackBuffer.release();
|
||||
@ -296,6 +308,44 @@ namespace
|
||||
g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + 1;
|
||||
}
|
||||
|
||||
void updatePresentationWindowPos()
|
||||
{
|
||||
if (!g_presentationWindow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool isFullscreen = false;
|
||||
if (SUCCEEDED(g_frontBuffer->IsLost(g_frontBuffer)))
|
||||
{
|
||||
HWND foregroundWindow = GetForegroundWindow();
|
||||
if (foregroundWindow)
|
||||
{
|
||||
DWORD pid = 0;
|
||||
GetWindowThreadProcessId(foregroundWindow, &pid);
|
||||
isFullscreen = GetCurrentProcessId() == pid && Gdi::Window::hasFullscreenWindow();
|
||||
}
|
||||
}
|
||||
|
||||
auto resource = D3dDdi::Device::findResource(
|
||||
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
|
||||
resource->setFullscreenMode(isFullscreen);
|
||||
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
if (isFullscreen)
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_presentationWindow, 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 if (IsWindowVisible(g_presentationWindow))
|
||||
{
|
||||
ShowWindow(g_presentationWindow, SW_HIDE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/)
|
||||
{
|
||||
int msUntilUpdateReady = 0;
|
||||
@ -311,6 +361,7 @@ namespace
|
||||
}
|
||||
|
||||
DDraw::ScopedThreadLock lock;
|
||||
updatePresentationWindowPos();
|
||||
msUntilUpdateReady = DDraw::RealPrimarySurface::flush();
|
||||
}
|
||||
}
|
||||
@ -363,9 +414,19 @@ namespace DDraw
|
||||
g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier,
|
||||
&g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER);
|
||||
|
||||
g_deviceWindowPtr = DDraw::DirectDraw::getDeviceWindowPtr(dd.get());
|
||||
g_deviceWindowPtr = (0 != desc.dwBackBufferCount) ? DDraw::DirectDraw::getDeviceWindowPtr(dd.get()) : nullptr;
|
||||
g_deviceWindow = g_deviceWindowPtr ? *g_deviceWindowPtr : nullptr;
|
||||
g_devicePresentationWindow = Gdi::Window::getPresentationWindow(g_deviceWindow);
|
||||
g_devicePresentationWindow = g_deviceWindow ? Gdi::Window::getPresentationWindow(g_deviceWindow) : nullptr;
|
||||
|
||||
if (0 == desc.dwBackBufferCount)
|
||||
{
|
||||
auto mr = DDraw::PrimarySurface::getMonitorRect();
|
||||
if (!EqualRect(&mr, &g_monitorRect))
|
||||
{
|
||||
g_presentationWindow = Gdi::PresentationWindow::create(nullptr);
|
||||
updatePresentationWindowPos();
|
||||
}
|
||||
}
|
||||
|
||||
onRestore();
|
||||
updateDevicePresentationWindowPos();
|
||||
@ -484,6 +545,11 @@ namespace DDraw
|
||||
return g_monitorRect;
|
||||
}
|
||||
|
||||
HWND RealPrimarySurface::getPresentationWindow()
|
||||
{
|
||||
return g_presentationWindow;
|
||||
}
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> RealPrimarySurface::getSurface()
|
||||
{
|
||||
return g_frontBuffer;
|
||||
@ -495,6 +561,10 @@ namespace DDraw
|
||||
{
|
||||
return g_devicePresentationWindow;
|
||||
}
|
||||
if (g_presentationWindow && IsWindowVisible(g_presentationWindow))
|
||||
{
|
||||
return g_presentationWindow;
|
||||
}
|
||||
return HWND_TOPMOST;
|
||||
}
|
||||
|
||||
@ -576,7 +646,7 @@ namespace DDraw
|
||||
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
if (g_isFullscreen && IsWindowVisible(g_deviceWindow) && !IsIconic(g_deviceWindow))
|
||||
if (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,
|
||||
|
@ -18,6 +18,7 @@ namespace DDraw
|
||||
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
|
||||
static int flush();
|
||||
static HWND getDevicePresentationWindow();
|
||||
static HWND getPresentationWindow();
|
||||
static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
|
||||
static RECT getMonitorRect();
|
||||
static CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <D3dDdi/KernelModeThunks.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
@ -419,6 +420,26 @@ namespace Gdi
|
||||
return layeredWindows;
|
||||
}
|
||||
|
||||
bool hasFullscreenWindow()
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
RECT mr = DDraw::PrimarySurface::getMonitorRect();
|
||||
for (auto& window : g_windows)
|
||||
{
|
||||
if (!window.second.isLayered &&
|
||||
window.second.windowRect.left <= mr.left &&
|
||||
window.second.windowRect.top <= mr.top &&
|
||||
window.second.windowRect.right >= mr.right &&
|
||||
window.second.windowRect.bottom >= mr.bottom &&
|
||||
IsWindowVisible(window.first) &&
|
||||
!IsIconic(window.first))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isTopLevelWindow(HWND hwnd)
|
||||
{
|
||||
return GetDesktopWindow() == GetAncestor(hwnd, GA_PARENT);
|
||||
@ -492,6 +513,14 @@ namespace Gdi
|
||||
CompatRef<IDirectDrawClipper> clipper)
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
auto presentationWindow = DDraw::RealPrimarySurface::getPresentationWindow();
|
||||
if (presentationWindow && IsWindowVisible(presentationWindow))
|
||||
{
|
||||
clipper->SetHWnd(&clipper, 0, presentationWindow);
|
||||
dst->Blt(&dst, nullptr, &src, nullptr, DDBLT_WAIT, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto window : g_windowZOrder)
|
||||
{
|
||||
if (window->presentationWindow && !window->visibleRegion.isEmpty())
|
||||
|
@ -19,6 +19,7 @@ namespace Gdi
|
||||
|
||||
HWND getPresentationWindow(HWND hwnd);
|
||||
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
||||
bool hasFullscreenWindow();
|
||||
bool isTopLevelWindow(HWND hwnd);
|
||||
void onStyleChanged(HWND hwnd, WPARAM wParam);
|
||||
void onSyncPaint(HWND hwnd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user