2018-07-17 20:46:38 +02:00
|
|
|
#include <memory>
|
2018-03-17 21:40:00 +01:00
|
|
|
#include <vector>
|
2015-12-31 00:01:28 +01:00
|
|
|
|
2021-06-15 23:14:33 +02:00
|
|
|
#include <Common/Comparison.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <Common/CompatPtr.h>
|
|
|
|
#include <Common/Hook.h>
|
2022-04-15 23:49:46 +02:00
|
|
|
#include <Common/ScopedCriticalSection.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <Common/Time.h>
|
|
|
|
#include <Config/Config.h>
|
|
|
|
#include <D3dDdi/Device.h>
|
|
|
|
#include <D3dDdi/KernelModeThunks.h>
|
2022-06-05 15:08:53 +02:00
|
|
|
#include <D3dDdi/Resource.h>
|
|
|
|
#include <D3dDdi/ScopedCriticalSection.h>
|
|
|
|
#include <D3dDdi/SurfaceRepository.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <DDraw/DirectDraw.h>
|
|
|
|
#include <DDraw/DirectDrawSurface.h>
|
|
|
|
#include <DDraw/IReleaseNotifier.h>
|
|
|
|
#include <DDraw/RealPrimarySurface.h>
|
|
|
|
#include <DDraw/ScopedThreadLock.h>
|
|
|
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
2022-06-05 15:08:53 +02:00
|
|
|
#include <DDraw/Surfaces/TagSurface.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <DDraw/Types.h>
|
|
|
|
#include <Gdi/Caret.h>
|
2021-06-15 23:14:33 +02:00
|
|
|
#include <Gdi/Cursor.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <Gdi/Gdi.h>
|
2022-02-06 23:56:59 +01:00
|
|
|
#include <Gdi/GuiThread.h>
|
2021-06-15 23:14:33 +02:00
|
|
|
#include <Gdi/Palette.h>
|
2022-06-06 21:52:39 +02:00
|
|
|
#include <Gdi/PresentationWindow.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <Gdi/VirtualScreen.h>
|
|
|
|
#include <Gdi/Window.h>
|
2021-06-20 14:32:19 +02:00
|
|
|
#include <Gdi/WinProc.h>
|
2022-02-06 23:56:59 +01:00
|
|
|
#include <Overlay/ConfigWindow.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <Win32/DisplayMode.h>
|
2015-12-25 01:57:44 +01:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
const unsigned DELAYED_FLIP_MODE_TIMEOUT_MS = 200;
|
|
|
|
|
2015-12-25 01:57:44 +01:00
|
|
|
void onRelease();
|
|
|
|
|
2022-06-07 15:46:38 +02:00
|
|
|
CompatWeakPtr<IDirectDraw7> g_defaultPrimaryDD;
|
|
|
|
CompatWeakPtr<IDirectDrawSurface7> g_defaultPrimary;
|
|
|
|
|
2016-05-16 18:16:13 +02:00
|
|
|
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
|
2022-06-05 15:08:53 +02:00
|
|
|
CompatWeakPtr<IDirectDrawSurface7> g_windowedBackBuffer;
|
2016-05-16 22:31:58 +02:00
|
|
|
CompatWeakPtr<IDirectDrawClipper> g_clipper;
|
2021-06-12 20:49:36 +02:00
|
|
|
RECT g_monitorRect = {};
|
2016-05-16 18:16:13 +02:00
|
|
|
DDSURFACEDESC2 g_surfaceDesc = {};
|
2016-08-27 22:39:28 +02:00
|
|
|
DDraw::IReleaseNotifier g_releaseNotifier(onRelease);
|
2015-12-25 01:57:44 +01:00
|
|
|
|
2021-06-21 23:15:25 +02:00
|
|
|
bool g_isFullscreen = false;
|
2018-10-03 20:49:50 +02:00
|
|
|
DDraw::Surface* g_lastFlipSurface = nullptr;
|
2020-07-13 23:44:05 +02:00
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
Compat::CriticalSection g_presentCs;
|
|
|
|
bool g_isDelayedFlipPending = false;
|
2020-07-13 23:44:05 +02:00
|
|
|
bool g_isUpdatePending = false;
|
2022-04-15 23:49:46 +02:00
|
|
|
bool g_isUpdateReady = false;
|
|
|
|
DWORD g_lastUpdateThreadId = 0;
|
|
|
|
long long g_qpcLastUpdate = 0;
|
|
|
|
long long g_qpcUpdateStart = 0;
|
|
|
|
|
|
|
|
long long g_qpcDelayedFlipEnd = 0;
|
2020-07-13 23:44:05 +02:00
|
|
|
UINT g_flipEndVsyncCount = 0;
|
|
|
|
UINT g_presentEndVsyncCount = 0;
|
2022-04-15 23:49:46 +02:00
|
|
|
|
2022-04-08 16:13:31 +02:00
|
|
|
HWND g_devicePresentationWindow = nullptr;
|
|
|
|
HWND g_deviceWindow = nullptr;
|
|
|
|
HWND* g_deviceWindowPtr = nullptr;
|
2022-06-06 21:52:39 +02:00
|
|
|
HWND g_presentationWindow = nullptr;
|
2018-10-03 20:49:50 +02:00
|
|
|
|
|
|
|
CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
|
|
|
CompatPtr<IDirectDrawSurface7> getLastSurface();
|
2015-12-31 00:01:28 +01:00
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
void bltToPrimaryChain(CompatRef<IDirectDrawSurface7> src)
|
2017-11-12 16:12:58 +01:00
|
|
|
{
|
2021-06-21 23:15:25 +02:00
|
|
|
if (!g_isFullscreen)
|
2015-12-25 01:57:44 +01:00
|
|
|
{
|
2022-06-05 15:08:53 +02:00
|
|
|
{
|
|
|
|
D3dDdi::ScopedCriticalSection lock;
|
|
|
|
auto srcResource = D3dDdi::Device::findResource(
|
|
|
|
DDraw::DirectDrawSurface::getDriverResourceHandle(src.get()));
|
|
|
|
auto bbResource = D3dDdi::Device::findResource(
|
|
|
|
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
|
|
|
|
|
|
|
|
D3DDDIARG_BLT blt = {};
|
|
|
|
blt.hSrcResource = *srcResource;
|
|
|
|
blt.SrcSubResourceIndex = DDraw::DirectDrawSurface::getSubResourceIndex(src.get());
|
|
|
|
blt.SrcRect = DDraw::PrimarySurface::getMonitorRect();
|
|
|
|
blt.hDstResource = *bbResource;
|
|
|
|
blt.DstSubResourceIndex = 0;
|
|
|
|
blt.DstRect = g_monitorRect;
|
|
|
|
bbResource->presentationBlt(blt, srcResource);
|
|
|
|
}
|
|
|
|
|
|
|
|
Gdi::Window::present(*g_frontBuffer, *g_windowedBackBuffer, *g_clipper);
|
2018-10-03 20:49:50 +02:00
|
|
|
return;
|
2015-12-25 01:57:44 +01:00
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
auto backBuffer(getBackBuffer());
|
|
|
|
if (backBuffer)
|
2018-03-17 21:40:00 +01:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
backBuffer->Blt(backBuffer, nullptr, &src, nullptr, DDBLT_WAIT, nullptr);
|
2018-03-17 21:40:00 +01:00
|
|
|
}
|
2016-12-19 19:25:15 +01:00
|
|
|
}
|
|
|
|
|
2022-06-07 15:46:38 +02:00
|
|
|
BOOL WINAPI createDefaultPrimaryEnum(
|
|
|
|
GUID* lpGUID, LPSTR /*lpDriverDescription*/, LPSTR lpDriverName, LPVOID lpContext, HMONITOR /*hm*/)
|
|
|
|
{
|
|
|
|
auto& deviceName = *static_cast<std::wstring*>(lpContext);
|
|
|
|
if (deviceName != std::wstring(lpDriverName, lpDriverName + strlen(lpDriverName)))
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CompatPtr<IDirectDraw7> dd;
|
|
|
|
if (FAILED(CALL_ORIG_PROC(DirectDrawCreateEx)(
|
|
|
|
lpGUID, reinterpret_cast<void**>(&dd.getRef()), IID_IDirectDraw7, nullptr)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CompatPtr<IDirectDrawSurface7> primary;
|
|
|
|
DDSURFACEDESC2 desc = {};
|
|
|
|
desc.dwSize = sizeof(desc);
|
|
|
|
desc.dwFlags = DDSD_CAPS;
|
|
|
|
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
|
|
if (FAILED(dd.get()->lpVtbl->CreateSurface(dd, &desc, &primary.getRef(), nullptr)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_defaultPrimary = primary.detach();
|
|
|
|
g_defaultPrimaryDD = dd.detach();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void createDefaultPrimary()
|
|
|
|
{
|
|
|
|
if (g_frontBuffer || g_defaultPrimary && SUCCEEDED(g_defaultPrimary->IsLost(g_defaultPrimary)))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DDraw::RealPrimarySurface::destroyDefaultPrimary();
|
|
|
|
|
|
|
|
if (DDraw::TagSurface::doesFullscreenDirectDrawExist())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto dm = Win32::DisplayMode::getEmulatedDisplayMode();
|
|
|
|
if (0 == dm.diff.cx && 0 == dm.diff.cy)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CALL_ORIG_PROC(DirectDrawEnumerateExA)(createDefaultPrimaryEnum, &dm.deviceName, DDENUM_ATTACHEDSECONDARYDEVICES);
|
|
|
|
}
|
|
|
|
|
2022-06-05 15:08:53 +02:00
|
|
|
CompatPtr<IDirectDrawSurface7> createWindowedBackBuffer(DDRAWI_DIRECTDRAW_LCL* ddLcl, DWORD width, DWORD height)
|
|
|
|
{
|
|
|
|
if (!ddLcl)
|
|
|
|
{
|
|
|
|
LOG_INFO << "ERROR: createWindowedBackBuffer: ddLcl is null";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto tagSurface = DDraw::TagSurface::get(ddLcl);
|
|
|
|
if (!tagSurface)
|
|
|
|
{
|
|
|
|
LOG_INFO << "ERROR: createWindowedBackBuffer: TagSurface not found";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto resource = DDraw::DirectDrawSurface::getDriverResourceHandle(*tagSurface->getDDS());
|
|
|
|
if (!resource)
|
|
|
|
{
|
|
|
|
LOG_INFO << "ERROR: createWindowedBackBuffer: driver resource handle not found";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto device = D3dDdi::Device::findDeviceByResource(resource);
|
|
|
|
if (!device)
|
|
|
|
{
|
|
|
|
LOG_INFO << "ERROR: createWindowedBackBuffer: device not found";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto& repo = D3dDdi::SurfaceRepository::get(device->getAdapter());
|
|
|
|
D3dDdi::SurfaceRepository::Surface surface = {};
|
|
|
|
repo.getSurface(surface, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
|
|
|
|
DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY);
|
|
|
|
if (!surface.surface)
|
|
|
|
{
|
|
|
|
LOG_INFO << "ERROR: createWindowedBackBuffer: surface creation failed";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return surface.surface;
|
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
CompatPtr<IDirectDrawSurface7> getBackBuffer()
|
2016-05-16 18:16:13 +02:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
DDSCAPS2 caps = {};
|
|
|
|
caps.dwCaps = DDSCAPS_BACKBUFFER;
|
2016-05-22 11:09:44 +02:00
|
|
|
CompatPtr<IDirectDrawSurface7> backBuffer;
|
2018-10-03 20:49:50 +02:00
|
|
|
if (g_frontBuffer)
|
2016-05-16 18:16:13 +02:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
g_frontBuffer->GetAttachedSurface(g_frontBuffer, &caps, &backBuffer.getRef());
|
2016-05-16 18:16:13 +02:00
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
return backBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
CompatPtr<IDirectDrawSurface7> getLastSurface()
|
|
|
|
{
|
|
|
|
DDSCAPS2 caps = {};
|
|
|
|
caps.dwCaps = DDSCAPS_FLIP;;
|
|
|
|
CompatPtr<IDirectDrawSurface7> backBuffer(getBackBuffer());
|
|
|
|
CompatPtr<IDirectDrawSurface7> lastSurface;
|
|
|
|
if (backBuffer)
|
2017-11-12 16:12:58 +01:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
backBuffer->GetAttachedSurface(backBuffer, &caps, &lastSurface.getRef());
|
2017-11-12 16:12:58 +01:00
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
return lastSurface;
|
|
|
|
}
|
2016-05-16 18:16:13 +02:00
|
|
|
|
2020-07-13 23:44:05 +02:00
|
|
|
UINT getFlipInterval(DWORD flags)
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2022-04-16 18:56:44 +02:00
|
|
|
auto vSync = Config::vSync.get();
|
|
|
|
if (Config::Settings::VSync::APP != vSync)
|
|
|
|
{
|
|
|
|
return Config::Settings::VSync::OFF == vSync ? 0 : Config::vSync.getParam();
|
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
if (flags & DDFLIP_NOVSYNC)
|
2017-05-17 20:41:05 +02:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2020-07-13 23:44:05 +02:00
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
if (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
|
|
|
|
{
|
|
|
|
UINT flipInterval = (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) >> 24;
|
|
|
|
if (flipInterval < 2 || flipInterval > 4)
|
|
|
|
{
|
|
|
|
flipInterval = 1;
|
|
|
|
}
|
|
|
|
return flipInterval;
|
2017-05-17 20:41:05 +02:00
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
return 1;
|
|
|
|
}
|
2016-05-16 18:16:13 +02:00
|
|
|
|
2015-12-25 01:57:44 +01:00
|
|
|
void onRelease()
|
|
|
|
{
|
2018-11-03 01:36:38 +01:00
|
|
|
LOG_FUNC("RealPrimarySurface::onRelease");
|
2015-12-29 15:40:28 +01:00
|
|
|
|
2022-06-06 21:52:39 +02:00
|
|
|
if (g_presentationWindow)
|
|
|
|
{
|
|
|
|
auto resource = D3dDdi::Device::findResource(
|
|
|
|
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
|
|
|
|
resource->setFullscreenMode(false);
|
|
|
|
|
|
|
|
Gdi::GuiThread::destroyWindow(g_presentationWindow);
|
|
|
|
g_presentationWindow = nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-25 01:57:44 +01:00
|
|
|
g_frontBuffer = nullptr;
|
2022-04-15 23:49:46 +02:00
|
|
|
g_lastFlipSurface = nullptr;
|
2022-06-05 15:08:53 +02:00
|
|
|
g_windowedBackBuffer.release();
|
2017-11-12 16:12:58 +01:00
|
|
|
g_clipper.release();
|
2021-06-21 23:15:25 +02:00
|
|
|
g_isFullscreen = false;
|
2018-10-03 20:49:50 +02:00
|
|
|
g_surfaceDesc = {};
|
2022-04-08 16:13:31 +02:00
|
|
|
|
|
|
|
DDraw::RealPrimarySurface::updateDevicePresentationWindowPos();
|
|
|
|
g_devicePresentationWindow = nullptr;
|
|
|
|
g_deviceWindow = nullptr;
|
|
|
|
g_deviceWindowPtr = nullptr;
|
2021-06-12 20:49:36 +02:00
|
|
|
g_monitorRect = {};
|
2015-12-25 01:57:44 +01:00
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
void onRestore()
|
2016-04-15 00:08:22 +02:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
DDSURFACEDESC2 desc = {};
|
|
|
|
desc.dwSize = sizeof(desc);
|
|
|
|
g_frontBuffer->GetSurfaceDesc(g_frontBuffer, &desc);
|
2016-04-15 00:08:22 +02:00
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
g_clipper.release();
|
2022-01-08 14:17:21 +01:00
|
|
|
CALL_ORIG_PROC(DirectDrawCreateClipper)(0, &g_clipper.getRef(), nullptr);
|
|
|
|
g_frontBuffer->SetClipper(g_frontBuffer, g_clipper);
|
2018-10-03 20:49:50 +02:00
|
|
|
|
|
|
|
const bool isFlippable = 0 != (desc.ddsCaps.dwCaps & DDSCAPS_FLIP);
|
|
|
|
g_surfaceDesc = desc;
|
2021-06-21 23:15:25 +02:00
|
|
|
g_isFullscreen = isFlippable;
|
2018-10-03 20:49:50 +02:00
|
|
|
|
|
|
|
if (isFlippable)
|
2017-05-17 20:41:05 +02:00
|
|
|
{
|
2020-07-13 23:44:05 +02:00
|
|
|
g_frontBuffer->Flip(g_frontBuffer, getLastSurface(), DDFLIP_WAIT);
|
2022-04-15 23:49:46 +02:00
|
|
|
D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1);
|
2016-04-15 00:08:22 +02:00
|
|
|
}
|
2022-04-15 23:49:46 +02:00
|
|
|
|
2022-06-05 15:08:53 +02:00
|
|
|
if (g_windowedBackBuffer)
|
|
|
|
{
|
|
|
|
g_windowedBackBuffer->Restore(g_windowedBackBuffer);
|
|
|
|
}
|
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
Compat::ScopedCriticalSection lock(g_presentCs);
|
|
|
|
g_isUpdatePending = false;
|
|
|
|
g_isUpdateReady = false;
|
|
|
|
g_qpcLastUpdate = Time::queryPerformanceCounter() - Time::msToQpc(DELAYED_FLIP_MODE_TIMEOUT_MS);
|
|
|
|
g_qpcUpdateStart = g_qpcLastUpdate;
|
|
|
|
g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter();
|
|
|
|
g_flipEndVsyncCount = g_presentEndVsyncCount;
|
2015-12-25 01:57:44 +01:00
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
void presentToPrimaryChain(CompatWeakPtr<IDirectDrawSurface7> src)
|
2015-12-25 01:57:44 +01:00
|
|
|
{
|
2019-07-19 19:56:21 +02:00
|
|
|
LOG_FUNC("RealPrimarySurface::presentToPrimaryChain", src);
|
2018-10-03 20:49:50 +02:00
|
|
|
|
|
|
|
Gdi::VirtualScreen::update();
|
|
|
|
|
2022-02-06 23:56:59 +01:00
|
|
|
Gdi::GuiThread::execute([]()
|
|
|
|
{
|
|
|
|
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
|
|
|
if (configWindow)
|
|
|
|
{
|
|
|
|
configWindow->update();
|
|
|
|
}
|
|
|
|
|
2022-02-08 23:38:06 +01:00
|
|
|
auto capture = Input::getCaptureWindow();
|
2022-02-06 23:56:59 +01:00
|
|
|
if (capture)
|
|
|
|
{
|
|
|
|
capture->update();
|
|
|
|
}
|
|
|
|
|
|
|
|
Input::updateCursor();
|
|
|
|
});
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
if (!g_frontBuffer || !src || DDraw::RealPrimarySurface::isLost())
|
2015-12-25 01:57:44 +01:00
|
|
|
{
|
2020-12-27 17:08:44 +01:00
|
|
|
Gdi::Window::present(nullptr);
|
2018-10-03 20:49:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-06-12 20:49:36 +02:00
|
|
|
Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect());
|
2020-12-27 17:08:44 +01:00
|
|
|
Gdi::Window::present(excludeRegion);
|
2021-01-16 12:42:56 +01:00
|
|
|
bltToPrimaryChain(*src);
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
void updateNow(CompatWeakPtr<IDirectDrawSurface7> src)
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
{
|
|
|
|
Compat::ScopedCriticalSection lock(g_presentCs);
|
|
|
|
g_isUpdatePending = false;
|
|
|
|
g_isUpdateReady = false;
|
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
presentToPrimaryChain(src);
|
|
|
|
|
2022-04-08 16:13:31 +02:00
|
|
|
if (g_isFullscreen && g_devicePresentationWindow)
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2022-04-08 16:13:31 +02:00
|
|
|
*g_deviceWindowPtr = g_devicePresentationWindow;
|
2020-07-13 23:44:05 +02:00
|
|
|
g_frontBuffer->Flip(g_frontBuffer, getBackBuffer(), DDFLIP_WAIT);
|
2022-04-08 16:13:31 +02:00
|
|
|
*g_deviceWindowPtr = g_deviceWindow;
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
2022-04-15 23:49:46 +02:00
|
|
|
g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + 1;
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
|
|
|
|
2022-06-06 21:52:39 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-02-28 22:34:47 +01:00
|
|
|
unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/)
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
int msUntilUpdateReady = 0;
|
2021-03-01 22:59:07 +01:00
|
|
|
while (true)
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
if (msUntilUpdateReady > 0)
|
2015-12-28 13:54:11 +01:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
Sleep(1);
|
2015-12-28 13:54:11 +01:00
|
|
|
}
|
2022-04-15 23:49:46 +02:00
|
|
|
else
|
2021-06-15 23:14:33 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1);
|
2021-06-15 23:14:33 +02:00
|
|
|
}
|
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
DDraw::ScopedThreadLock lock;
|
2022-06-07 15:46:38 +02:00
|
|
|
createDefaultPrimary();
|
2022-06-06 21:52:39 +02:00
|
|
|
updatePresentationWindowPos();
|
2022-04-15 23:49:46 +02:00
|
|
|
msUntilUpdateReady = DDraw::RealPrimarySurface::flush();
|
2015-12-25 01:57:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-27 22:39:28 +02:00
|
|
|
namespace DDraw
|
2015-12-25 01:57:44 +01:00
|
|
|
{
|
2016-08-27 22:39:28 +02:00
|
|
|
template <typename DirectDraw>
|
|
|
|
HRESULT RealPrimarySurface::create(CompatRef<DirectDraw> dd)
|
|
|
|
{
|
2022-06-07 15:46:38 +02:00
|
|
|
LOG_FUNC("RealPrimarySurface::create", &dd);
|
2018-10-03 20:49:50 +02:00
|
|
|
DDraw::ScopedThreadLock lock;
|
2021-06-12 20:49:36 +02:00
|
|
|
g_monitorRect = D3dDdi::KernelModeThunks::getAdapterInfo(*CompatPtr<IDirectDraw7>::from(&dd)).monitorInfo.rcMonitor;
|
2016-12-19 19:25:15 +01:00
|
|
|
|
2016-08-27 22:39:28 +02:00
|
|
|
typename Types<DirectDraw>::TSurfaceDesc desc = {};
|
|
|
|
desc.dwSize = sizeof(desc);
|
|
|
|
desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
2021-06-02 00:34:50 +02:00
|
|
|
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
|
2018-10-03 20:49:50 +02:00
|
|
|
desc.dwBackBufferCount = 2;
|
2016-08-27 22:39:28 +02:00
|
|
|
|
|
|
|
CompatPtr<typename Types<DirectDraw>::TCreatedSurface> surface;
|
2021-01-16 12:42:56 +01:00
|
|
|
HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
|
2016-08-27 22:39:28 +02:00
|
|
|
|
|
|
|
if (DDERR_NOEXCLUSIVEMODE == result)
|
|
|
|
{
|
|
|
|
desc.dwFlags = DDSD_CAPS;
|
|
|
|
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
|
|
desc.dwBackBufferCount = 0;
|
|
|
|
result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
|
|
|
|
}
|
2015-12-25 01:57:44 +01:00
|
|
|
|
2016-08-27 22:39:28 +02:00
|
|
|
if (FAILED(result))
|
|
|
|
{
|
2022-05-22 18:39:04 +02:00
|
|
|
LOG_INFO << "ERROR: Failed to create the real primary surface: " << Compat::hex(result);
|
2021-06-12 20:49:36 +02:00
|
|
|
g_monitorRect = {};
|
2016-08-27 22:39:28 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-06-05 15:08:53 +02:00
|
|
|
if (0 == desc.dwBackBufferCount)
|
|
|
|
{
|
|
|
|
g_windowedBackBuffer = createWindowedBackBuffer(DDraw::DirectDraw::getInt(dd.get()).lpLcl,
|
|
|
|
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top).detach();
|
|
|
|
if (!g_windowedBackBuffer)
|
|
|
|
{
|
|
|
|
g_monitorRect = {};
|
|
|
|
return DDERR_GENERIC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
g_frontBuffer = CompatPtr<IDirectDrawSurface7>::from(surface.get()).detach();
|
|
|
|
g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier,
|
|
|
|
&g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER);
|
2022-04-08 16:13:31 +02:00
|
|
|
|
2022-06-06 21:52:39 +02:00
|
|
|
g_deviceWindowPtr = (0 != desc.dwBackBufferCount) ? DDraw::DirectDraw::getDeviceWindowPtr(dd.get()) : nullptr;
|
2022-04-08 16:13:31 +02:00
|
|
|
g_deviceWindow = g_deviceWindowPtr ? *g_deviceWindowPtr : nullptr;
|
2022-06-06 21:52:39 +02:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
2022-04-08 16:13:31 +02:00
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
onRestore();
|
2022-04-08 16:13:31 +02:00
|
|
|
updateDevicePresentationWindowPos();
|
2018-10-03 20:49:50 +02:00
|
|
|
|
|
|
|
return DD_OK;
|
2016-08-27 22:39:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw>);
|
|
|
|
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw2>);
|
|
|
|
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw4>);
|
|
|
|
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw7>);
|
2015-12-25 01:57:44 +01:00
|
|
|
|
2022-06-07 15:46:38 +02:00
|
|
|
void RealPrimarySurface::destroyDefaultPrimary()
|
|
|
|
{
|
|
|
|
g_defaultPrimary.release();
|
|
|
|
g_defaultPrimaryDD.release();
|
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
HRESULT RealPrimarySurface::flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags)
|
2016-08-27 22:39:28 +02:00
|
|
|
{
|
2020-07-13 23:44:05 +02:00
|
|
|
const DWORD flipInterval = getFlipInterval(flags);
|
2022-04-15 23:49:46 +02:00
|
|
|
if (0 == flipInterval ||
|
|
|
|
Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcLastUpdate) < DELAYED_FLIP_MODE_TIMEOUT_MS)
|
2020-07-13 23:44:05 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
PrimarySurface::waitForIdle();
|
|
|
|
Compat::ScopedCriticalSection lock(g_presentCs);
|
|
|
|
g_isDelayedFlipPending = true;
|
|
|
|
g_isUpdatePending = false;
|
|
|
|
g_isUpdateReady = false;
|
|
|
|
g_lastUpdateThreadId = GetCurrentThreadId();
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
2020-07-13 23:44:05 +02:00
|
|
|
else
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
updateNow(PrimarySurface::getPrimary());
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
2020-07-13 23:44:05 +02:00
|
|
|
g_flipEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + flipInterval;
|
2018-10-03 20:49:50 +02:00
|
|
|
|
|
|
|
if (0 != flipInterval)
|
|
|
|
{
|
|
|
|
g_lastFlipSurface = Surface::getSurface(
|
|
|
|
surfaceTargetOverride ? *surfaceTargetOverride : *PrimarySurface::getLastSurface());
|
|
|
|
}
|
2020-07-13 23:44:05 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
g_lastFlipSurface = nullptr;
|
|
|
|
}
|
2022-04-15 23:49:46 +02:00
|
|
|
|
|
|
|
g_qpcDelayedFlipEnd = Time::queryPerformanceCounter();
|
2018-10-03 20:49:50 +02:00
|
|
|
return DD_OK;
|
2016-04-17 22:56:25 +02:00
|
|
|
}
|
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
int RealPrimarySurface::flush()
|
2020-04-23 20:22:00 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
auto vsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter();
|
|
|
|
if (static_cast<int>(vsyncCount - g_presentEndVsyncCount) < 0)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
Compat::ScopedCriticalSection lock(g_presentCs);
|
|
|
|
if (!g_isUpdateReady)
|
|
|
|
{
|
|
|
|
if (g_isUpdatePending)
|
|
|
|
{
|
|
|
|
auto msSinceUpdateStart = Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcUpdateStart);
|
|
|
|
if (msSinceUpdateStart < 10)
|
|
|
|
{
|
|
|
|
return 10 - static_cast<int>(msSinceUpdateStart);
|
|
|
|
}
|
|
|
|
g_isUpdateReady = true;
|
|
|
|
}
|
|
|
|
else if (g_isDelayedFlipPending)
|
|
|
|
{
|
|
|
|
auto msSinceDelayedFlipEnd = Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcDelayedFlipEnd);
|
|
|
|
if (msSinceDelayedFlipEnd < 3)
|
|
|
|
{
|
|
|
|
return 3 - static_cast<int>(msSinceDelayedFlipEnd);
|
|
|
|
}
|
|
|
|
g_isDelayedFlipPending = false;
|
|
|
|
g_isUpdateReady = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!g_isUpdateReady)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto src(g_isDelayedFlipPending ? g_lastFlipSurface->getDDS() : DDraw::PrimarySurface::getPrimary());
|
|
|
|
RECT emptyRect = {};
|
|
|
|
HRESULT result = src ? src->BltFast(src, 0, 0, src, &emptyRect, DDBLTFAST_WAIT) : DD_OK;
|
|
|
|
if (DDERR_SURFACEBUSY == result || DDERR_LOCKEDSURFACES == result)
|
2020-04-23 20:22:00 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
return 1;
|
2020-04-23 20:22:00 +02:00
|
|
|
}
|
2022-04-15 23:49:46 +02:00
|
|
|
|
|
|
|
updateNow(src);
|
|
|
|
return 0;
|
2020-04-23 20:22:00 +02:00
|
|
|
}
|
|
|
|
|
2022-04-08 16:13:31 +02:00
|
|
|
HWND RealPrimarySurface::getDevicePresentationWindow()
|
|
|
|
{
|
|
|
|
return g_devicePresentationWindow;
|
|
|
|
}
|
|
|
|
|
2017-05-27 23:53:25 +02:00
|
|
|
HRESULT RealPrimarySurface::getGammaRamp(DDGAMMARAMP* rampData)
|
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
DDraw::ScopedThreadLock lock;
|
2017-05-27 23:53:25 +02:00
|
|
|
auto gammaControl(CompatPtr<IDirectDrawGammaControl>::from(g_frontBuffer.get()));
|
|
|
|
if (!gammaControl)
|
|
|
|
{
|
|
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gammaControl->GetGammaRamp(gammaControl, 0, rampData);
|
|
|
|
}
|
|
|
|
|
2021-06-12 20:49:36 +02:00
|
|
|
RECT RealPrimarySurface::getMonitorRect()
|
|
|
|
{
|
|
|
|
return g_monitorRect;
|
|
|
|
}
|
|
|
|
|
2022-06-06 21:52:39 +02:00
|
|
|
HWND RealPrimarySurface::getPresentationWindow()
|
|
|
|
{
|
|
|
|
return g_presentationWindow;
|
|
|
|
}
|
|
|
|
|
2016-08-27 22:39:28 +02:00
|
|
|
CompatWeakPtr<IDirectDrawSurface7> RealPrimarySurface::getSurface()
|
2015-12-25 01:57:44 +01:00
|
|
|
{
|
2016-08-27 22:39:28 +02:00
|
|
|
return g_frontBuffer;
|
2015-12-25 01:57:44 +01:00
|
|
|
}
|
|
|
|
|
2022-04-08 16:13:31 +02:00
|
|
|
HWND RealPrimarySurface::getTopmost()
|
|
|
|
{
|
|
|
|
if (g_isFullscreen && g_devicePresentationWindow)
|
|
|
|
{
|
|
|
|
return g_devicePresentationWindow;
|
|
|
|
}
|
2022-06-06 21:52:39 +02:00
|
|
|
if (g_presentationWindow && IsWindowVisible(g_presentationWindow))
|
|
|
|
{
|
|
|
|
return g_presentationWindow;
|
|
|
|
}
|
2022-04-08 16:13:31 +02:00
|
|
|
return HWND_TOPMOST;
|
|
|
|
}
|
|
|
|
|
2018-07-17 20:46:38 +02:00
|
|
|
void RealPrimarySurface::init()
|
|
|
|
{
|
2021-03-01 22:59:07 +01:00
|
|
|
Dll::createThread(&updateThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
|
2018-07-17 20:46:38 +02:00
|
|
|
}
|
|
|
|
|
2021-06-21 23:15:25 +02:00
|
|
|
bool RealPrimarySurface::isFullscreen()
|
2016-04-10 17:12:36 +02:00
|
|
|
{
|
2021-06-21 23:15:25 +02:00
|
|
|
return g_isFullscreen;
|
2016-04-10 17:12:36 +02:00
|
|
|
}
|
2016-08-27 22:39:28 +02:00
|
|
|
|
|
|
|
bool RealPrimarySurface::isLost()
|
2016-04-10 17:12:36 +02:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
DDraw::ScopedThreadLock lock;
|
2016-08-27 22:39:28 +02:00
|
|
|
return g_frontBuffer && DDERR_SURFACELOST == g_frontBuffer->IsLost(g_frontBuffer);
|
2016-04-10 17:12:36 +02:00
|
|
|
}
|
|
|
|
|
2016-08-27 22:39:28 +02:00
|
|
|
void RealPrimarySurface::release()
|
2016-04-19 23:57:35 +02:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
DDraw::ScopedThreadLock lock;
|
2016-08-27 22:39:28 +02:00
|
|
|
g_frontBuffer.release();
|
2016-04-19 23:57:35 +02:00
|
|
|
}
|
|
|
|
|
2016-08-27 22:39:28 +02:00
|
|
|
HRESULT RealPrimarySurface::restore()
|
2015-12-25 01:57:44 +01:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
DDraw::ScopedThreadLock lock;
|
|
|
|
HRESULT result = g_frontBuffer->Restore(g_frontBuffer);
|
|
|
|
if (SUCCEEDED(result))
|
|
|
|
{
|
|
|
|
onRestore();
|
|
|
|
}
|
|
|
|
return result;
|
2015-12-25 01:57:44 +01:00
|
|
|
}
|
|
|
|
|
2020-07-13 23:44:05 +02:00
|
|
|
void RealPrimarySurface::scheduleUpdate()
|
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
Compat::ScopedCriticalSection lock(g_presentCs);
|
2020-07-13 23:44:05 +02:00
|
|
|
g_qpcLastUpdate = Time::queryPerformanceCounter();
|
2022-04-15 23:49:46 +02:00
|
|
|
if (!g_isUpdatePending)
|
|
|
|
{
|
|
|
|
g_qpcUpdateStart = g_qpcLastUpdate;
|
|
|
|
g_isUpdatePending = true;
|
|
|
|
g_isDelayedFlipPending = false;
|
|
|
|
g_lastUpdateThreadId = GetCurrentThreadId();
|
|
|
|
}
|
|
|
|
g_isUpdateReady = false;
|
2020-07-13 23:44:05 +02:00
|
|
|
}
|
|
|
|
|
2017-05-27 23:53:25 +02:00
|
|
|
HRESULT RealPrimarySurface::setGammaRamp(DDGAMMARAMP* rampData)
|
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
DDraw::ScopedThreadLock lock;
|
2017-05-27 23:53:25 +02:00
|
|
|
auto gammaControl(CompatPtr<IDirectDrawGammaControl>::from(g_frontBuffer.get()));
|
|
|
|
if (!gammaControl)
|
|
|
|
{
|
|
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gammaControl->SetGammaRamp(gammaControl, 0, rampData);
|
|
|
|
}
|
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
void RealPrimarySurface::setUpdateReady()
|
2016-08-27 22:39:28 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
Compat::ScopedCriticalSection lock(g_presentCs);
|
|
|
|
if ((g_isUpdatePending || g_isDelayedFlipPending) && GetCurrentThreadId() == g_lastUpdateThreadId)
|
2017-07-16 20:35:31 +02:00
|
|
|
{
|
2022-04-15 23:49:46 +02:00
|
|
|
g_isUpdateReady = true;
|
|
|
|
g_isDelayedFlipPending = false;
|
2017-07-16 20:35:31 +02:00
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
2017-07-16 20:35:31 +02:00
|
|
|
|
2022-04-08 16:13:31 +02:00
|
|
|
void RealPrimarySurface::updateDevicePresentationWindowPos()
|
|
|
|
{
|
|
|
|
if (!g_devicePresentationWindow)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Gdi::GuiThread::execute([&]()
|
|
|
|
{
|
2022-06-06 21:52:39 +02:00
|
|
|
if (IsWindowVisible(g_deviceWindow) && !IsIconic(g_deviceWindow))
|
2022-04-08 16:13:31 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
bool RealPrimarySurface::waitForFlip(CompatWeakPtr<IDirectDrawSurface7> surface)
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
|
|
|
auto primary(DDraw::PrimarySurface::getPrimary());
|
2022-04-15 23:49:46 +02:00
|
|
|
if (!surface || !primary || !g_lastFlipSurface ||
|
|
|
|
surface != primary && surface != g_lastFlipSurface->getDDS())
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
|
|
|
return true;
|
2016-04-15 00:08:22 +02:00
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
|
2022-04-15 23:49:46 +02:00
|
|
|
auto vsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter();
|
|
|
|
while (static_cast<int>(vsyncCount - g_flipEndVsyncCount) < 0)
|
|
|
|
{
|
|
|
|
flush();
|
|
|
|
++vsyncCount;
|
|
|
|
D3dDdi::KernelModeThunks::waitForVsyncCounter(vsyncCount);
|
|
|
|
g_qpcDelayedFlipEnd = Time::queryPerformanceCounter();
|
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
return true;
|
2016-05-15 17:59:35 +02:00
|
|
|
}
|
2015-12-25 01:57:44 +01:00
|
|
|
}
|