mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Updated presentation logic
This commit is contained in:
parent
55eab96f78
commit
80863f77a7
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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; }
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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))
|
||||||
{
|
{
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user