1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Updated presentation logic

This commit is contained in:
narzoul 2022-04-15 23:49:46 +02:00
parent 55eab96f78
commit 80863f77a7
22 changed files with 315 additions and 162 deletions

View File

@ -5,11 +5,26 @@
namespace Time namespace Time
{ {
long long g_qpcFrequency = 0; long long g_qpcFrequency = 0;
HANDLE g_waitableTimer = nullptr;
void init() void init()
{ {
LARGE_INTEGER qpc; LARGE_INTEGER qpc;
QueryPerformanceFrequency(&qpc); QueryPerformanceFrequency(&qpc);
g_qpcFrequency = qpc.QuadPart; g_qpcFrequency = qpc.QuadPart;
g_waitableTimer = CreateWaitableTimer(nullptr, FALSE, nullptr);
}
void waitForNextTick()
{
LARGE_INTEGER due = {};
due.QuadPart = -1;
if (!g_waitableTimer ||
!SetWaitableTimer(g_waitableTimer, &due, 0, nullptr, nullptr, FALSE) ||
WAIT_OBJECT_0 != WaitForSingleObject(g_waitableTimer, INFINITE))
{
Sleep(1);
}
} }
} }

View File

@ -25,10 +25,5 @@ namespace Time
return qpc.QuadPart; return qpc.QuadPart;
} }
inline ULONG64 queryThreadCycleTime() void waitForNextTick();
{
ULONG64 cycleTime = 0;
QueryThreadCycleTime(GetCurrentThread(), &cycleTime);
return cycleTime;
}
} }

View File

@ -21,9 +21,6 @@
namespace Config namespace Config
{ {
const unsigned delayedFlipModeTimeout = 200;
const unsigned maxPaletteUpdatesPerMs = 5;
extern Settings::AlternatePixelCenter alternatePixelCenter; extern Settings::AlternatePixelCenter alternatePixelCenter;
extern Settings::Antialiasing antialiasing; extern Settings::Antialiasing antialiasing;
extern Settings::ConfigHotKey configHotKey; extern Settings::ConfigHotKey configHotKey;

View File

@ -27,6 +27,7 @@ namespace D3dDdi
: m_origVtable(CompatVtable<D3DDDI_DEVICEFUNCS>::s_origVtable) : m_origVtable(CompatVtable<D3DDDI_DEVICEFUNCS>::s_origVtable)
, m_adapter(adapter) , m_adapter(adapter)
, m_device(device) , m_device(device)
, m_eventQuery(nullptr)
, m_renderTarget(nullptr) , m_renderTarget(nullptr)
, m_renderTargetSubResourceIndex(0) , m_renderTargetSubResourceIndex(0)
, m_sharedPrimary(nullptr) , m_sharedPrimary(nullptr)
@ -34,6 +35,10 @@ namespace D3dDdi
, m_state(*this) , m_state(*this)
, m_shaderBlitter(*this) , m_shaderBlitter(*this)
{ {
D3DDDIARG_CREATEQUERY createQuery = {};
createQuery.QueryType = D3DDDIQUERYTYPE_EVENT;
m_origVtable.pfnCreateQuery(m_device, &createQuery);
m_eventQuery = createQuery.hQuery;
} }
void Device::add(Adapter& adapter, HANDLE device) void Device::add(Adapter& adapter, HANDLE device)
@ -388,6 +393,33 @@ namespace D3dDdi
m_state.updateConfig(); m_state.updateConfig();
} }
void Device::waitForIdle()
{
D3dDdi::ScopedCriticalSection lock;
flushPrimitives();
D3DDDIARG_ISSUEQUERY issueQuery = {};
issueQuery.hQuery = m_eventQuery;
issueQuery.Flags.End = 1;
m_origVtable.pfnIssueQuery(m_device, &issueQuery);
if (m_origVtable.pfnFlush1)
{
m_origVtable.pfnFlush1(m_device, 0);
}
else
{
m_origVtable.pfnFlush(m_device);
}
BOOL result = FALSE;
D3DDDIARG_GETQUERYDATA getQueryData = {};
getQueryData.hQuery = m_eventQuery;
getQueryData.pData = &result;
while (S_FALSE == m_origVtable.pfnGetQueryData(m_device, &getQueryData))
{
}
}
std::map<HANDLE, Device> Device::s_devices; std::map<HANDLE, Device> Device::s_devices;
bool Device::s_isFlushEnabled = true; bool Device::s_isFlushEnabled = true;
} }

View File

@ -58,6 +58,7 @@ namespace D3dDdi
void prepareForGpuWrite(); void prepareForGpuWrite();
void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data); void setRenderTarget(const D3DDDIARG_SETRENDERTARGET& data);
void updateConfig(); void updateConfig();
void waitForIdle();
static void add(Adapter& adapter, HANDLE device); static void add(Adapter& adapter, HANDLE device);
static Device& get(HANDLE device) { return s_devices.find(device)->second; } static Device& get(HANDLE device) { return s_devices.find(device)->second; }
@ -75,6 +76,7 @@ namespace D3dDdi
D3DDDI_DEVICEFUNCS m_origVtable; D3DDDI_DEVICEFUNCS m_origVtable;
Adapter& m_adapter; Adapter& m_adapter;
HANDLE m_device; HANDLE m_device;
HANDLE m_eventQuery;
std::map<HANDLE, std::unique_ptr<Resource>> m_resources; std::map<HANDLE, std::unique_ptr<Resource>> m_resources;
Resource* m_renderTarget; Resource* m_renderTarget;
UINT m_renderTargetSubResourceIndex; UINT m_renderTargetSubResourceIndex;

View File

@ -2,7 +2,6 @@
#include <string> #include <string>
#include <Windows.h> #include <Windows.h>
#include <VersionHelpers.h>
#include <Common/Log.h> #include <Common/Log.h>
#include <Common/Hook.h> #include <Common/Hook.h>
@ -107,6 +106,21 @@ namespace
return LOG_RESULT(result); return LOG_RESULT(result);
} }
NTSTATUS APIENTRY createDevice(D3DKMT_CREATEDEVICE* pData)
{
LOG_FUNC("D3DKMTCreateDevice", pData);
NTSTATUS result = D3DKMTCreateDevice(pData);
if (SUCCEEDED(result))
{
D3DKMT_SETQUEUEDLIMIT limit = {};
limit.hDevice = pData->hDevice;
limit.Type = D3DKMT_SET_QUEUEDLIMIT_PRESENT;
limit.QueuedPresentLimit = 1;
D3DKMTSetQueuedLimit(&limit);
}
return LOG_RESULT(result);
}
HDC WINAPI ddrawCreateDcA(LPCSTR pwszDriver, LPCSTR pwszDevice, LPCSTR pszPort, const DEVMODEA* pdm) HDC WINAPI ddrawCreateDcA(LPCSTR pwszDriver, LPCSTR pwszDevice, LPCSTR pszPort, const DEVMODEA* pdm)
{ {
LOG_FUNC("ddrawCreateDCA", pwszDriver, pwszDevice, pszPort, pdm); LOG_FUNC("ddrawCreateDCA", pwszDriver, pwszDevice, pszPort, pdm);
@ -152,7 +166,7 @@ namespace
{ {
D3DKMT_GETSCANLINE data = {}; D3DKMT_GETSCANLINE data = {};
getVidPnSource(data.hAdapter, data.VidPnSourceId); getVidPnSource(data.hAdapter, data.VidPnSourceId);
if (!data.hAdapter || FAILED(D3DKMTGetScanLine(&data)) || data.InVerticalBlank) if (!data.hAdapter || FAILED(D3DKMTGetScanLine(&data)))
{ {
return -1; return -1;
} }
@ -189,19 +203,6 @@ namespace
return LOG_RESULT(result); return LOG_RESULT(result);
} }
void pollForVerticalBlank()
{
int scanLine = getScanLine();
int prevScanLine = scanLine;
auto qpcStart = Time::queryPerformanceCounter();
while (scanLine >= prevScanLine && Time::queryPerformanceCounter() - qpcStart < Time::g_qpcFrequency / 60)
{
Sleep(1);
prevScanLine = scanLine;
scanLine = getScanLine();
}
}
NTSTATUS APIENTRY present(D3DKMT_PRESENT* pData) NTSTATUS APIENTRY present(D3DKMT_PRESENT* pData)
{ {
LOG_FUNC("D3DKMTPresent", pData); LOG_FUNC("D3DKMTPresent", pData);
@ -252,6 +253,7 @@ namespace
{ {
LOG_FUNC("D3DKMTSetGammaRamp", pData); LOG_FUNC("D3DKMTSetGammaRamp", pData);
UINT vsyncCounter = D3dDdi::KernelModeThunks::getVsyncCounter(); UINT vsyncCounter = D3dDdi::KernelModeThunks::getVsyncCounter();
DDraw::RealPrimarySurface::setUpdateReady();
DDraw::RealPrimarySurface::flush(); DDraw::RealPrimarySurface::flush();
HRESULT result = D3DKMTSetGammaRamp(pData); HRESULT result = D3DKMTSetGammaRamp(pData);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
@ -324,30 +326,24 @@ namespace
void waitForVerticalBlank() void waitForVerticalBlank()
{ {
if (IsWindows8OrGreater()) auto qpcStart = Time::queryPerformanceCounter();
int scanLine = getScanLine();
int prevScanLine = 0;
while (scanLine >= prevScanLine)
{ {
D3DKMT_WAITFORVERTICALBLANKEVENT data = {}; Time::waitForNextTick();
prevScanLine = scanLine;
{ scanLine = getScanLine();
Compat::ScopedSrwLockShared lock(g_adapterInfoSrwLock);
data.hAdapter = g_lastOpenAdapterInfo.adapter;
data.VidPnSourceId = g_lastOpenAdapterInfo.vidPnSourceId;
}
if (!data.hAdapter)
{
updateGdiAdapterInfo();
data.hAdapter = g_gdiAdapterInfo.adapter;
data.VidPnSourceId = g_gdiAdapterInfo.vidPnSourceId;
}
if (data.hAdapter && SUCCEEDED(D3DKMTWaitForVerticalBlankEvent(&data)))
{
return;
}
} }
pollForVerticalBlank(); if (scanLine < 0)
{
auto msElapsed = static_cast<DWORD>(Time::qpcToMs(Time::queryPerformanceCounter() - qpcStart));
if (msElapsed < 16)
{
Sleep(16 - msElapsed);
}
}
} }
} }
@ -412,6 +408,7 @@ namespace D3dDdi
Compat::hookIatFunction(Dll::g_origDDrawModule, "CreateDCA", ddrawCreateDcA); Compat::hookIatFunction(Dll::g_origDDrawModule, "CreateDCA", ddrawCreateDcA);
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCloseAdapter", closeAdapter); Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCloseAdapter", closeAdapter);
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCreateDCFromMemory", createDcFromMemory); Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCreateDCFromMemory", createDcFromMemory);
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCreateDevice", createDevice);
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTOpenAdapterFromHdc", openAdapterFromHdc); Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTOpenAdapterFromHdc", openAdapterFromHdc);
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTPresent", present); Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTPresent", present);
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTQueryAdapterInfo", queryAdapterInfo); Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTQueryAdapterInfo", queryAdapterInfo);

View File

@ -832,6 +832,16 @@ namespace D3dDdi
auto rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex; auto rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex;
auto rtRect = rtSurface.resource ? data.SrcRect : data.DstRect; auto rtRect = rtSurface.resource ? data.SrcRect : data.DstRect;
if (D3DDDIPOOL_SYSTEMMEM == srcResource->m_fixedData.Pool)
{
srcResource = repo.getTempTexture(srcWidth, srcHeight, getPixelFormat(srcResource->m_fixedData.Format)).resource;
if (!srcResource)
{
return E_OUTOFMEMORY;
}
copySubResourceRegion(*srcResource, 0, data.SrcRect, data.hSrcResource, data.SrcSubResourceIndex, data.SrcRect);
}
if (D3DDDIFMT_P8 == srcResource->m_origData.Format) if (D3DDDIFMT_P8 == srcResource->m_origData.Format)
{ {
auto entries(Gdi::Palette::getHardwarePalette()); auto entries(Gdi::Palette::getHardwarePalette());

View File

@ -27,6 +27,7 @@ namespace D3dDdi
operator HANDLE() const { return m_handle; } operator HANDLE() const { return m_handle; }
const Resource* getCustomResource() { return m_msaaSurface.resource ? m_msaaSurface.resource : m_msaaResolvedSurface.resource; } const Resource* getCustomResource() { return m_msaaSurface.resource ? m_msaaSurface.resource : m_msaaResolvedSurface.resource; }
Device& getDevice() const { return m_device; }
const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; } const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; }
const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; } const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; }
bool isClampable() const { return m_isClampable; } bool isClampable() const { return m_isClampable; }

View File

@ -73,6 +73,7 @@ namespace
template <typename TDirectDraw> template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE WaitForVerticalBlank(TDirectDraw* This, DWORD dwFlags, HANDLE hEvent) HRESULT STDMETHODCALLTYPE WaitForVerticalBlank(TDirectDraw* This, DWORD dwFlags, HANDLE hEvent)
{ {
DDraw::RealPrimarySurface::setUpdateReady();
DDraw::RealPrimarySurface::flush(); DDraw::RealPrimarySurface::flush();
return getOrigVtable(This).WaitForVerticalBlank(This, dwFlags, hEvent); return getOrigVtable(This).WaitForVerticalBlank(This, dwFlags, hEvent);
} }

View File

@ -49,7 +49,8 @@ namespace DDraw
updatesInLastMs.pop_front(); updatesInLastMs.pop_front();
} }
if (updatesInLastMs.size() >= Config::maxPaletteUpdatesPerMs) const unsigned maxPaletteUpdatesPerMs = 5;
if (updatesInLastMs.size() >= maxPaletteUpdatesPerMs)
{ {
Sleep(1); Sleep(1);
updatesInLastMs.clear(); updatesInLastMs.clear();

View File

@ -1,10 +1,10 @@
#include <atomic>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <Common/Comparison.h> #include <Common/Comparison.h>
#include <Common/CompatPtr.h> #include <Common/CompatPtr.h>
#include <Common/Hook.h> #include <Common/Hook.h>
#include <Common/ScopedCriticalSection.h>
#include <Common/Time.h> #include <Common/Time.h>
#include <Config/Config.h> #include <Config/Config.h>
#include <D3dDdi/Device.h> #include <D3dDdi/Device.h>
@ -29,6 +29,8 @@
namespace namespace
{ {
const unsigned DELAYED_FLIP_MODE_TIMEOUT_MS = 200;
void onRelease(); void onRelease();
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer; CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
@ -40,11 +42,18 @@ namespace
bool g_isFullscreen = false; bool g_isFullscreen = false;
DDraw::Surface* g_lastFlipSurface = nullptr; DDraw::Surface* g_lastFlipSurface = nullptr;
Compat::CriticalSection g_presentCs;
bool g_isDelayedFlipPending = false;
bool g_isUpdatePending = false; bool g_isUpdatePending = false;
bool g_waitingForPrimaryUnlock = false; bool g_isUpdateReady = false;
std::atomic<long long> g_qpcLastUpdate = 0; DWORD g_lastUpdateThreadId = 0;
long long g_qpcLastUpdate = 0;
long long g_qpcUpdateStart = 0;
long long g_qpcDelayedFlipEnd = 0;
UINT g_flipEndVsyncCount = 0; UINT g_flipEndVsyncCount = 0;
UINT g_presentEndVsyncCount = 0; UINT g_presentEndVsyncCount = 0;
HWND g_devicePresentationWindow = nullptr; HWND g_devicePresentationWindow = nullptr;
HWND g_deviceWindow = nullptr; HWND g_deviceWindow = nullptr;
HWND* g_deviceWindowPtr = nullptr; HWND* g_deviceWindowPtr = nullptr;
@ -112,24 +121,14 @@ namespace
return 1; return 1;
} }
bool isFlipPending()
{
return static_cast<INT>(D3dDdi::KernelModeThunks::getVsyncCounter() - g_flipEndVsyncCount) < 0;
}
bool isPresentPending()
{
return static_cast<INT>(D3dDdi::KernelModeThunks::getVsyncCounter() - g_presentEndVsyncCount) < 0;
}
void onRelease() void onRelease()
{ {
LOG_FUNC("RealPrimarySurface::onRelease"); LOG_FUNC("RealPrimarySurface::onRelease");
g_frontBuffer = nullptr; g_frontBuffer = nullptr;
g_lastFlipSurface = nullptr;
g_clipper.release(); g_clipper.release();
g_isFullscreen = false; g_isFullscreen = false;
g_waitingForPrimaryUnlock = false;
g_surfaceDesc = {}; g_surfaceDesc = {};
DDraw::RealPrimarySurface::updateDevicePresentationWindowPos(); DDraw::RealPrimarySurface::updateDevicePresentationWindowPos();
@ -152,16 +151,20 @@ namespace
const bool isFlippable = 0 != (desc.ddsCaps.dwCaps & DDSCAPS_FLIP); const bool isFlippable = 0 != (desc.ddsCaps.dwCaps & DDSCAPS_FLIP);
g_surfaceDesc = desc; g_surfaceDesc = desc;
g_isFullscreen = isFlippable; g_isFullscreen = isFlippable;
g_isUpdatePending = true;
g_qpcLastUpdate = Time::queryPerformanceCounter() - Time::msToQpc(Config::delayedFlipModeTimeout);
if (isFlippable) if (isFlippable)
{ {
g_frontBuffer->Flip(g_frontBuffer, getLastSurface(), DDFLIP_WAIT); g_frontBuffer->Flip(g_frontBuffer, getLastSurface(), DDFLIP_WAIT);
g_flipEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + 1; D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1);
g_presentEndVsyncCount = g_flipEndVsyncCount;
D3dDdi::KernelModeThunks::waitForVsyncCounter(g_flipEndVsyncCount);
} }
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;
} }
void presentToPrimaryChain(CompatWeakPtr<IDirectDrawSurface7> src) void presentToPrimaryChain(CompatWeakPtr<IDirectDrawSurface7> src)
@ -202,11 +205,15 @@ namespace
D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr); D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr);
} }
void updateNow(CompatWeakPtr<IDirectDrawSurface7> src, UINT flipInterval) void updateNow(CompatWeakPtr<IDirectDrawSurface7> src)
{ {
{
Compat::ScopedCriticalSection lock(g_presentCs);
g_isUpdatePending = false;
g_isUpdateReady = false;
}
presentToPrimaryChain(src); presentToPrimaryChain(src);
g_isUpdatePending = false;
g_waitingForPrimaryUnlock = false;
if (g_isFullscreen && g_devicePresentationWindow) if (g_isFullscreen && g_devicePresentationWindow)
{ {
@ -214,60 +221,26 @@ namespace
g_frontBuffer->Flip(g_frontBuffer, getBackBuffer(), DDFLIP_WAIT); g_frontBuffer->Flip(g_frontBuffer, getBackBuffer(), DDFLIP_WAIT);
*g_deviceWindowPtr = g_deviceWindow; *g_deviceWindowPtr = g_deviceWindow;
} }
g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + max(flipInterval, 1); g_presentEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + 1;
}
void updateNowIfNotBusy()
{
auto primary(DDraw::PrimarySurface::getPrimary());
RECT emptyRect = {};
HRESULT result = primary ? primary->BltFast(primary, 0, 0, primary, &emptyRect, DDBLTFAST_WAIT) : DD_OK;
g_waitingForPrimaryUnlock = DDERR_SURFACEBUSY == result || DDERR_LOCKEDSURFACES == result;
if (!g_waitingForPrimaryUnlock)
{
const auto msSinceLastUpdate = Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcLastUpdate);
updateNow(primary, msSinceLastUpdate > Config::delayedFlipModeTimeout ? 0 : 1);
}
} }
unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/) unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/)
{ {
bool skipWaitForVsync = false; int msUntilUpdateReady = 0;
while (true) while (true)
{ {
if (!skipWaitForVsync) if (msUntilUpdateReady > 0)
{
Sleep(1);
}
else
{ {
D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1); D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1);
} }
skipWaitForVsync = false;
Sleep(1);
DDraw::ScopedThreadLock lock; DDraw::ScopedThreadLock lock;
Gdi::Caret::blink(); msUntilUpdateReady = DDraw::RealPrimarySurface::flush();
if (Gdi::Cursor::update())
{
g_isUpdatePending = true;
}
if (g_isUpdatePending && !isPresentPending())
{
auto qpcNow = Time::queryPerformanceCounter();
auto qpcLastVsync = D3dDdi::KernelModeThunks::getQpcLastVsync();
if (Time::qpcToMs(qpcNow - qpcLastVsync) < 1 ||
Time::qpcToMs(qpcNow - g_qpcLastUpdate) < 1 && Time::qpcToMs(qpcNow - qpcLastVsync) <= 3)
{
skipWaitForVsync = true;
}
else
{
updateNowIfNotBusy();
}
}
} }
return 0;
} }
} }
@ -325,27 +298,19 @@ namespace DDraw
HRESULT RealPrimarySurface::flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags) HRESULT RealPrimarySurface::flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags)
{ {
const DWORD flipInterval = getFlipInterval(flags); const DWORD flipInterval = getFlipInterval(flags);
if (0 == flipInterval) if (0 == flipInterval ||
Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcLastUpdate) < DELAYED_FLIP_MODE_TIMEOUT_MS)
{ {
g_isUpdatePending = true; PrimarySurface::waitForIdle();
return DD_OK; Compat::ScopedCriticalSection lock(g_presentCs);
} g_isDelayedFlipPending = true;
g_isUpdatePending = false;
const auto msSinceLastUpdate = Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcLastUpdate); g_isUpdateReady = false;
const bool isFlipDelayed = msSinceLastUpdate >= 0 && msSinceLastUpdate <= Config::delayedFlipModeTimeout; g_lastUpdateThreadId = GetCurrentThreadId();
if (isFlipDelayed)
{
if (!isPresentPending())
{
CompatPtr<IDirectDrawSurface7> prevPrimarySurface(
surfaceTargetOverride ? surfaceTargetOverride : PrimarySurface::getLastSurface());
updateNow(prevPrimarySurface, 0);
}
g_isUpdatePending = true;
} }
else else
{ {
updateNow(PrimarySurface::getPrimary(), flipInterval); updateNow(PrimarySurface::getPrimary());
} }
g_flipEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + flipInterval; g_flipEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + flipInterval;
@ -358,16 +323,60 @@ namespace DDraw
{ {
g_lastFlipSurface = nullptr; g_lastFlipSurface = nullptr;
} }
g_qpcDelayedFlipEnd = Time::queryPerformanceCounter();
return DD_OK; return DD_OK;
} }
void RealPrimarySurface::flush() int RealPrimarySurface::flush()
{ {
DDraw::ScopedThreadLock lock; auto vsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter();
if (g_isUpdatePending && !isPresentPending()) if (static_cast<int>(vsyncCount - g_presentEndVsyncCount) < 0)
{ {
updateNowIfNotBusy(); 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)
{
return 1;
}
updateNow(src);
return 0;
} }
HWND RealPrimarySurface::getDevicePresentationWindow() HWND RealPrimarySurface::getDevicePresentationWindow()
@ -441,8 +450,16 @@ namespace DDraw
void RealPrimarySurface::scheduleUpdate() void RealPrimarySurface::scheduleUpdate()
{ {
Compat::ScopedCriticalSection lock(g_presentCs);
g_qpcLastUpdate = Time::queryPerformanceCounter(); g_qpcLastUpdate = Time::queryPerformanceCounter();
g_isUpdatePending = true; if (!g_isUpdatePending)
{
g_qpcUpdateStart = g_qpcLastUpdate;
g_isUpdatePending = true;
g_isDelayedFlipPending = false;
g_lastUpdateThreadId = GetCurrentThreadId();
}
g_isUpdateReady = false;
} }
HRESULT RealPrimarySurface::setGammaRamp(DDGAMMARAMP* rampData) HRESULT RealPrimarySurface::setGammaRamp(DDGAMMARAMP* rampData)
@ -457,14 +474,13 @@ namespace DDraw
return gammaControl->SetGammaRamp(gammaControl, 0, rampData); return gammaControl->SetGammaRamp(gammaControl, 0, rampData);
} }
void RealPrimarySurface::update() void RealPrimarySurface::setUpdateReady()
{ {
DDraw::ScopedThreadLock lock; Compat::ScopedCriticalSection lock(g_presentCs);
g_qpcLastUpdate = Time::queryPerformanceCounter(); if ((g_isUpdatePending || g_isDelayedFlipPending) && GetCurrentThreadId() == g_lastUpdateThreadId)
g_isUpdatePending = true;
if (g_waitingForPrimaryUnlock)
{ {
updateNowIfNotBusy(); g_isUpdateReady = true;
g_isDelayedFlipPending = false;
} }
} }
@ -490,17 +506,23 @@ namespace DDraw
}); });
} }
bool RealPrimarySurface::waitForFlip(Surface* surface) bool RealPrimarySurface::waitForFlip(CompatWeakPtr<IDirectDrawSurface7> surface)
{ {
auto primary(DDraw::PrimarySurface::getPrimary()); auto primary(DDraw::PrimarySurface::getPrimary());
if (!surface || !primary || if (!surface || !primary || !g_lastFlipSurface ||
surface != g_lastFlipSurface && surface != primary && surface != g_lastFlipSurface->getDDS())
surface != Surface::getSurface(*DDraw::PrimarySurface::getPrimary()))
{ {
return true; return true;
} }
D3dDdi::KernelModeThunks::waitForVsyncCounter(g_flipEndVsyncCount); auto vsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter();
while (static_cast<int>(vsyncCount - g_flipEndVsyncCount) < 0)
{
flush();
++vsyncCount;
D3dDdi::KernelModeThunks::waitForVsyncCounter(vsyncCount);
g_qpcDelayedFlipEnd = Time::queryPerformanceCounter();
}
return true; return true;
} }
} }

View File

@ -16,7 +16,7 @@ namespace DDraw
static HRESULT create(CompatRef<DirectDraw> dd); static HRESULT create(CompatRef<DirectDraw> dd);
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags); static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
static void flush(); static int flush();
static HWND getDevicePresentationWindow(); static HWND getDevicePresentationWindow();
static HRESULT getGammaRamp(DDGAMMARAMP* rampData); static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
static RECT getMonitorRect(); static RECT getMonitorRect();
@ -29,8 +29,8 @@ namespace DDraw
static HRESULT restore(); static HRESULT restore();
static void scheduleUpdate(); static void scheduleUpdate();
static HRESULT setGammaRamp(DDGAMMARAMP* rampData); static HRESULT setGammaRamp(DDGAMMARAMP* rampData);
static void update(); static void setUpdateReady();
static void updateDevicePresentationWindowPos(); static void updateDevicePresentationWindowPos();
static bool waitForFlip(Surface* surface); static bool waitForFlip(CompatWeakPtr<IDirectDrawSurface7> surface);
}; };
} }

View File

@ -14,6 +14,7 @@
namespace namespace
{ {
CompatWeakPtr<IDirectDrawSurface7> g_primarySurface; CompatWeakPtr<IDirectDrawSurface7> g_primarySurface;
D3dDdi::Device* g_device = nullptr;
HANDLE g_gdiResourceHandle = nullptr; HANDLE g_gdiResourceHandle = nullptr;
HANDLE g_frontResource = nullptr; HANDLE g_frontResource = nullptr;
DWORD g_origCaps = 0; DWORD g_origCaps = 0;
@ -28,6 +29,7 @@ namespace DDraw
{ {
LOG_FUNC("PrimarySurface::~PrimarySurface"); LOG_FUNC("PrimarySurface::~PrimarySurface");
g_device = nullptr;
g_gdiResourceHandle = nullptr; g_gdiResourceHandle = nullptr;
g_frontResource = nullptr; g_frontResource = nullptr;
g_primarySurface = nullptr; g_primarySurface = nullptr;
@ -91,6 +93,7 @@ namespace DDraw
ResizePalette(g_palette, 256); ResizePalette(g_palette, 256);
} }
g_device = D3dDdi::Device::findDeviceByResource(DirectDrawSurface::getDriverResourceHandle(*surface));
data->restore(); data->restore();
D3dDdi::Device::updateAllConfig(); D3dDdi::Device::updateAllConfig();
return DD_OK; return DD_OK;
@ -265,7 +268,15 @@ namespace DDraw
ReleaseDC(g_deviceWindow, dc); ReleaseDC(g_deviceWindow, dc);
} }
RealPrimarySurface::update(); RealPrimarySurface::scheduleUpdate();
}
void PrimarySurface::waitForIdle()
{
if (g_device)
{
g_device->waitForIdle();
}
} }
CompatWeakPtr<IDirectDrawPalette> PrimarySurface::s_palette; CompatWeakPtr<IDirectDrawPalette> PrimarySurface::s_palette;

View File

@ -31,6 +31,7 @@ namespace DDraw
static bool isGdiSurface(TSurface* surface); static bool isGdiSurface(TSurface* surface);
static void updateFrontResource(); static void updateFrontResource();
static void waitForIdle();
virtual void restore(); virtual void restore();

View File

@ -91,11 +91,13 @@ namespace DDraw
return DDERR_SURFACELOST; return DDERR_SURFACELOST;
} }
RealPrimarySurface::flush();
HRESULT result = SurfaceImpl::Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); HRESULT result = SurfaceImpl::Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
bltToGdi(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); bltToGdi(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
RealPrimarySurface::update(); RealPrimarySurface::scheduleUpdate();
PrimarySurface::waitForIdle();
} }
return result; return result;
} }
@ -109,10 +111,12 @@ namespace DDraw
return DDERR_SURFACELOST; return DDERR_SURFACELOST;
} }
RealPrimarySurface::flush();
HRESULT result = SurfaceImpl::BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); HRESULT result = SurfaceImpl::BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
RealPrimarySurface::update(); RealPrimarySurface::scheduleUpdate();
PrimarySurface::waitForIdle();
} }
return result; return result;
} }
@ -120,7 +124,9 @@ namespace DDraw
template <typename TSurface> template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags) HRESULT PrimarySurfaceImpl<TSurface>::Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags)
{ {
DDraw::RealPrimarySurface::waitForFlip(m_data); RealPrimarySurface::setUpdateReady();
RealPrimarySurface::flush();
RealPrimarySurface::waitForFlip(m_data->getDDS());
auto surfaceTargetOverride(CompatPtr<TSurface>::from(lpDDSurfaceTargetOverride)); auto surfaceTargetOverride(CompatPtr<TSurface>::from(lpDDSurfaceTargetOverride));
const bool isFlipEmulated = 0 != (PrimarySurface::getOrigCaps() & DDSCAPS_SYSTEMMEMORY); const bool isFlipEmulated = 0 != (PrimarySurface::getOrigCaps() & DDSCAPS_SYSTEMMEMORY);
if (isFlipEmulated) if (isFlipEmulated)
@ -155,6 +161,13 @@ namespace DDraw
return result; return result;
} }
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::GetDC(TSurface* This, HDC* lphDC)
{
RealPrimarySurface::flush();
return SurfaceImpl::GetDC(This, lphDC);
}
template <typename TSurface> template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc) HRESULT PrimarySurfaceImpl<TSurface>::GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc)
{ {
@ -187,6 +200,7 @@ namespace DDraw
return DDERR_SURFACELOST; return DDERR_SURFACELOST;
} }
RealPrimarySurface::flush();
HRESULT result = SurfaceImpl::Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent); HRESULT result = SurfaceImpl::Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
@ -201,7 +215,7 @@ namespace DDraw
HRESULT result = SurfaceImpl::ReleaseDC(This, hDC); HRESULT result = SurfaceImpl::ReleaseDC(This, hDC);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
RealPrimarySurface::update(); RealPrimarySurface::scheduleUpdate();
} }
return result; return result;
} }
@ -244,7 +258,7 @@ namespace DDraw
HRESULT result = SurfaceImpl::Unlock(This, lpRect); HRESULT result = SurfaceImpl::Unlock(This, lpRect);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
RealPrimarySurface::update(); RealPrimarySurface::scheduleUpdate();
} }
return result; return result;
} }

View File

@ -21,6 +21,7 @@ namespace DDraw
TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) override; TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) override;
virtual HRESULT Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags) override; virtual HRESULT Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags) override;
virtual HRESULT GetCaps(TSurface* This, TDdsCaps* lpDDSCaps) override; virtual HRESULT GetCaps(TSurface* This, TDdsCaps* lpDDSCaps) override;
virtual HRESULT GetDC(TSurface* This, HDC* lphDC);
virtual HRESULT GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc) override; virtual HRESULT GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc) override;
virtual HRESULT IsLost(TSurface* This) override; virtual HRESULT IsLost(TSurface* This) override;
virtual HRESULT Lock(TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc, virtual HRESULT Lock(TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc,

View File

@ -30,6 +30,8 @@ namespace DDraw
template <typename TSurface> template <typename TSurface>
static Surface* getSurface(TSurface& dds); static Surface* getSurface(TSurface& dds);
CompatWeakPtr<IDirectDrawSurface7> getDDS() const { return m_surface; };
template <typename TSurface> template <typename TSurface>
SurfaceImpl<TSurface>* getImpl() const; SurfaceImpl<TSurface>* getImpl() const;

View File

@ -109,7 +109,7 @@ namespace DDraw
TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
DWORD dwFlags, LPDDBLTFX lpDDBltFx) DWORD dwFlags, LPDDBLTFX lpDDBltFx)
{ {
RealPrimarySurface::waitForFlip(m_data); RealPrimarySurface::waitForFlip(m_data->getDDS());
DirectDrawClipper::update(); DirectDrawClipper::update();
return blt(This, lpDDSrcSurface, lpSrcRect, [=](TSurface* This, TSurface* lpDDSrcSurface, LPRECT lpSrcRect) return blt(This, lpDDSrcSurface, lpSrcRect, [=](TSurface* This, TSurface* lpDDSrcSurface, LPRECT lpSrcRect)
{ return getOrigVtable(This).Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); }); { return getOrigVtable(This).Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); });
@ -119,7 +119,7 @@ namespace DDraw
HRESULT SurfaceImpl<TSurface>::BltFast( HRESULT SurfaceImpl<TSurface>::BltFast(
TSurface* This, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) TSurface* This, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans)
{ {
RealPrimarySurface::waitForFlip(m_data); RealPrimarySurface::waitForFlip(m_data->getDDS());
return blt(This, lpDDSrcSurface, lpSrcRect, [=](TSurface* This, TSurface* lpDDSrcSurface, LPRECT lpSrcRect) return blt(This, lpDDSrcSurface, lpSrcRect, [=](TSurface* This, TSurface* lpDDSrcSurface, LPRECT lpSrcRect)
{ return getOrigVtable(This).BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); }); { return getOrigVtable(This).BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); });
} }
@ -144,7 +144,7 @@ namespace DDraw
template <typename TSurface> template <typename TSurface>
HRESULT SurfaceImpl<TSurface>::GetDC(TSurface* This, HDC* lphDC) HRESULT SurfaceImpl<TSurface>::GetDC(TSurface* This, HDC* lphDC)
{ {
RealPrimarySurface::waitForFlip(m_data); RealPrimarySurface::waitForFlip(m_data->getDDS());
HRESULT result = getOrigVtable(This).GetDC(This, lphDC); HRESULT result = getOrigVtable(This).GetDC(This, lphDC);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
@ -181,7 +181,7 @@ namespace DDraw
TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc, TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc,
DWORD dwFlags, HANDLE hEvent) DWORD dwFlags, HANDLE hEvent)
{ {
RealPrimarySurface::waitForFlip(m_data); RealPrimarySurface::waitForFlip(m_data->getDDS());
HRESULT result = getOrigVtable(This).Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent); HRESULT result = getOrigVtable(This).Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {

View File

@ -2,6 +2,7 @@
#include <Common/Hook.h> #include <Common/Hook.h>
#include <Common/Log.h> #include <Common/Log.h>
#include <DDraw/RealPrimarySurface.h>
#include <DDraw/Surfaces/PrimarySurface.h> #include <DDraw/Surfaces/PrimarySurface.h>
#include <Gdi/Cursor.h> #include <Gdi/Cursor.h>
#include <Win32/DisplayMode.h> #include <Win32/DisplayMode.h>
@ -222,7 +223,7 @@ namespace Gdi
} }
} }
bool update() void update()
{ {
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedCriticalSection lock(g_cs);
if (!IsRectEmpty(&g_monitorClipRect)) if (!IsRectEmpty(&g_monitorClipRect))
@ -238,11 +239,9 @@ namespace Gdi
(cursorInfo.hCursor != g_prevCursorInfo.hCursor || cursorInfo.ptScreenPos != g_prevCursorInfo.ptScreenPos)) (cursorInfo.hCursor != g_prevCursorInfo.hCursor || cursorInfo.ptScreenPos != g_prevCursorInfo.ptScreenPos))
{ {
g_prevCursorInfo = cursorInfo; g_prevCursorInfo = cursorInfo;
return true; DDraw::RealPrimarySurface::scheduleUpdate();
} }
} }
return false;
} }
} }
} }

View File

@ -12,6 +12,6 @@ namespace Gdi
HCURSOR setCursor(HCURSOR cursor); HCURSOR setCursor(HCURSOR cursor);
void setMonitorClipRect(const RECT& rect); void setMonitorClipRect(const RECT& rect);
void setEmulated(bool isEmulated); void setEmulated(bool isEmulated);
bool update(); void update();
} }
} }

View File

@ -4,6 +4,9 @@
#include <Common/Hook.h> #include <Common/Hook.h>
#include <D3dDdi/ScopedCriticalSection.h> #include <D3dDdi/ScopedCriticalSection.h>
#include <Dll/Dll.h> #include <Dll/Dll.h>
#include <DDraw/RealPrimarySurface.h>
#include <Gdi/Caret.h>
#include <Gdi/Cursor.h>
#include <Gdi/GuiThread.h> #include <Gdi/GuiThread.h>
#include <Gdi/Region.h> #include <Gdi/Region.h>
#include <Gdi/WinProc.h> #include <Gdi/WinProc.h>
@ -83,7 +86,7 @@ namespace
} }
MSG msg = {}; MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0)) while (CALL_ORIG_FUNC(GetMessageA)(&msg, nullptr, 0, 0))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
@ -91,6 +94,16 @@ namespace
return 0; return 0;
} }
unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/)
{
while (true)
{
Sleep(5);
Gdi::Caret::blink();
Gdi::Cursor::update();
}
}
} }
namespace Gdi namespace Gdi
@ -154,6 +167,7 @@ namespace Gdi
void start() void start()
{ {
Dll::createThread(messageWindowThreadProc, &g_threadId, THREAD_PRIORITY_TIME_CRITICAL, 0); Dll::createThread(messageWindowThreadProc, &g_threadId, THREAD_PRIORITY_TIME_CRITICAL, 0);
Dll::createThread(updateThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL, 0);
} }
} }
} }

View File

@ -147,6 +147,23 @@ namespace
return ddcWindowProc(hwnd, uMsg, wParam, lParam, CallWindowProcW, getWindowProc(hwnd).wndProcW); return ddcWindowProc(hwnd, uMsg, wParam, lParam, CallWindowProcW, getWindowProc(hwnd).wndProcW);
} }
BOOL WINAPI getMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
decltype(&GetMessageA) origGetMessage)
{
DDraw::RealPrimarySurface::setUpdateReady();
return origGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
}
BOOL WINAPI getMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
{
return getMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, CALL_ORIG_FUNC(GetMessageA));
}
BOOL WINAPI getMessageW(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
{
return getMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, CALL_ORIG_FUNC(GetMessageW));
}
LONG getWindowLong(HWND hWnd, int nIndex, LONG getWindowLong(HWND hWnd, int nIndex,
decltype(&GetWindowLongA) origGetWindowLong, WNDPROC(WindowProc::* wndProc)) decltype(&GetWindowLongA) origGetWindowLong, WNDPROC(WindowProc::* wndProc))
{ {
@ -290,6 +307,23 @@ namespace
} }
} }
BOOL peekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg,
decltype(&PeekMessageA) origPeekMessage)
{
DDraw::RealPrimarySurface::setUpdateReady();
return origPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
BOOL WINAPI peekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
{
return peekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, CALL_ORIG_FUNC(PeekMessageA));
}
BOOL WINAPI peekMessageW(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
{
return peekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, CALL_ORIG_FUNC(PeekMessageW));
}
BOOL WINAPI setLayeredWindowAttributes(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags) BOOL WINAPI setLayeredWindowAttributes(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags)
{ {
LOG_FUNC("SetLayeredWindowAttributes", hwnd, crKey, bAlpha, dwFlags); LOG_FUNC("SetLayeredWindowAttributes", hwnd, crKey, bAlpha, dwFlags);
@ -455,8 +489,12 @@ namespace Gdi
void installHooks() void installHooks()
{ {
HOOK_FUNCTION(user32, GetMessageA, getMessageA);
HOOK_FUNCTION(user32, GetMessageW, getMessageW);
HOOK_FUNCTION(user32, GetWindowLongA, getWindowLongA); HOOK_FUNCTION(user32, GetWindowLongA, getWindowLongA);
HOOK_FUNCTION(user32, GetWindowLongW, getWindowLongW); HOOK_FUNCTION(user32, GetWindowLongW, getWindowLongW);
HOOK_FUNCTION(user32, PeekMessageA, peekMessageA);
HOOK_FUNCTION(user32, PeekMessageW, peekMessageW);
HOOK_FUNCTION(user32, SetLayeredWindowAttributes, setLayeredWindowAttributes); HOOK_FUNCTION(user32, SetLayeredWindowAttributes, setLayeredWindowAttributes);
HOOK_FUNCTION(user32, SetWindowLongA, setWindowLongA); HOOK_FUNCTION(user32, SetWindowLongA, setWindowLongA);
HOOK_FUNCTION(user32, SetWindowLongW, setWindowLongW); HOOK_FUNCTION(user32, SetWindowLongW, setWindowLongW);