2021-05-15 16:06:26 +02:00
|
|
|
#include <atomic>
|
2018-12-09 14:23:36 +01:00
|
|
|
#include <string>
|
2016-11-29 00:00:49 +01:00
|
|
|
|
2021-11-21 16:32:55 +01:00
|
|
|
#include <Windows.h>
|
|
|
|
#include <VersionHelpers.h>
|
|
|
|
|
2020-04-23 20:22:00 +02:00
|
|
|
#include <Common/Log.h>
|
|
|
|
#include <Common/Hook.h>
|
2020-07-13 23:44:05 +02:00
|
|
|
#include <Common/ScopedSrwLock.h>
|
2020-04-23 20:22:00 +02:00
|
|
|
#include <Common/Time.h>
|
2022-03-27 11:39:27 +02:00
|
|
|
#include <Config/Config.h>
|
2020-04-23 20:22:00 +02:00
|
|
|
#include <D3dDdi/Device.h>
|
|
|
|
#include <D3dDdi/KernelModeThunks.h>
|
|
|
|
#include <D3dDdi/Log/KernelModeThunksLog.h>
|
|
|
|
#include <D3dDdi/Resource.h>
|
|
|
|
#include <D3dDdi/ScopedCriticalSection.h>
|
|
|
|
#include <DDraw/RealPrimarySurface.h>
|
|
|
|
#include <DDraw/ScopedThreadLock.h>
|
|
|
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
|
|
|
#include <Gdi/Palette.h>
|
|
|
|
#include <Win32/DisplayMode.h>
|
2016-11-29 00:00:49 +01:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2019-04-23 12:44:13 +02:00
|
|
|
D3DDDIFORMAT g_dcFormatOverride = D3DDDIFMT_UNKNOWN;
|
2021-06-15 23:14:33 +02:00
|
|
|
PALETTEENTRY* g_dcPaletteOverride = nullptr;
|
2021-06-05 17:29:51 +02:00
|
|
|
D3dDdi::KernelModeThunks::AdapterInfo g_gdiAdapterInfo = {};
|
|
|
|
D3dDdi::KernelModeThunks::AdapterInfo g_lastOpenAdapterInfo = {};
|
2021-11-21 16:32:55 +01:00
|
|
|
Compat::SrwLock g_adapterInfoSrwLock;
|
2021-06-12 20:49:36 +02:00
|
|
|
std::string g_lastDDrawDeviceName;
|
2016-11-29 00:00:49 +01:00
|
|
|
|
2021-11-21 16:32:55 +01:00
|
|
|
long long g_qpcLastVsync = 0;
|
2020-07-13 23:44:05 +02:00
|
|
|
UINT g_vsyncCounter = 0;
|
|
|
|
CONDITION_VARIABLE g_vsyncCounterCv = CONDITION_VARIABLE_INIT;
|
|
|
|
Compat::SrwLock g_vsyncCounterSrwLock;
|
2017-05-17 20:41:05 +02:00
|
|
|
|
2021-11-21 16:32:55 +01:00
|
|
|
void getVidPnSource(D3DKMT_HANDLE& adapter, UINT& vidPnSourceId);
|
|
|
|
void updateGdiAdapterInfo();
|
2020-07-13 23:44:05 +02:00
|
|
|
void waitForVerticalBlank();
|
2020-04-23 20:22:00 +02:00
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
NTSTATUS APIENTRY closeAdapter(const D3DKMT_CLOSEADAPTER* pData)
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2021-11-21 16:32:55 +01:00
|
|
|
Compat::ScopedSrwLockExclusive lock(g_adapterInfoSrwLock);
|
2018-10-03 20:49:50 +02:00
|
|
|
if (pData && pData->hAdapter == g_lastOpenAdapterInfo.adapter)
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
g_lastOpenAdapterInfo = {};
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
2019-08-28 21:04:28 +02:00
|
|
|
return D3DKMTCloseAdapter(pData);
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
|
|
|
|
2018-03-11 18:42:06 +01:00
|
|
|
NTSTATUS APIENTRY createDcFromMemory(D3DKMT_CREATEDCFROMMEMORY* pData)
|
|
|
|
{
|
2018-11-03 01:36:38 +01:00
|
|
|
LOG_FUNC("D3DKMTCreateDCFromMemory", pData);
|
2019-04-23 12:44:13 +02:00
|
|
|
|
|
|
|
auto origFormat = pData->Format;
|
|
|
|
if (D3DDDIFMT_UNKNOWN != g_dcFormatOverride)
|
|
|
|
{
|
|
|
|
pData->Format = g_dcFormatOverride;
|
|
|
|
}
|
|
|
|
|
2019-08-02 22:16:44 +02:00
|
|
|
std::vector<PALETTEENTRY> palette;
|
|
|
|
auto origColorTable = pData->pColorTable;
|
|
|
|
|
|
|
|
if (D3DDDIFMT_P8 == pData->Format)
|
2018-03-11 18:42:06 +01:00
|
|
|
{
|
2019-08-02 22:16:44 +02:00
|
|
|
if (g_dcPaletteOverride)
|
|
|
|
{
|
2021-06-15 23:14:33 +02:00
|
|
|
pData->pColorTable = g_dcPaletteOverride;
|
2019-08-02 22:16:44 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DDraw::ScopedThreadLock ddLock;
|
|
|
|
D3dDdi::ScopedCriticalSection driverLock;
|
2019-08-19 22:42:48 +02:00
|
|
|
auto primaryResource = D3dDdi::Device::findResource(DDraw::PrimarySurface::getFrontResource());
|
2019-08-02 22:16:44 +02:00
|
|
|
if (primaryResource && pData->pMemory == primaryResource->getLockPtr(0) &&
|
|
|
|
(DDraw::PrimarySurface::getOrigCaps() & DDSCAPS_COMPLEX))
|
|
|
|
{
|
|
|
|
pData->pColorTable = Gdi::Palette::getDefaultPalette();
|
|
|
|
}
|
|
|
|
else if (pData->pColorTable)
|
|
|
|
{
|
|
|
|
palette.assign(pData->pColorTable, pData->pColorTable + 256);
|
|
|
|
auto sysPal = Gdi::Palette::getSystemPalette();
|
|
|
|
for (UINT i = 0; i < 256; ++i)
|
|
|
|
{
|
|
|
|
if (palette[i].peFlags & PC_EXPLICIT)
|
|
|
|
{
|
|
|
|
palette[i] = sysPal[palette[i].peRed];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pData->pColorTable = palette.data();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
palette = Gdi::Palette::getHardwarePalette();
|
|
|
|
pData->pColorTable = palette.data();
|
|
|
|
}
|
|
|
|
}
|
2018-03-11 18:42:06 +01:00
|
|
|
}
|
2019-04-23 12:44:13 +02:00
|
|
|
|
2019-08-28 21:04:28 +02:00
|
|
|
auto result = D3DKMTCreateDCFromMemory(pData);
|
2019-04-23 12:44:13 +02:00
|
|
|
pData->Format = origFormat;
|
2019-08-02 22:16:44 +02:00
|
|
|
pData->pColorTable = origColorTable;
|
2018-11-03 01:36:38 +01:00
|
|
|
return LOG_RESULT(result);
|
2018-03-11 18:42:06 +01:00
|
|
|
}
|
|
|
|
|
2018-12-09 14:23:36 +01:00
|
|
|
HDC WINAPI ddrawCreateDcA(LPCSTR pwszDriver, LPCSTR pwszDevice, LPCSTR pszPort, const DEVMODEA* pdm)
|
|
|
|
{
|
|
|
|
LOG_FUNC("ddrawCreateDCA", pwszDriver, pwszDevice, pszPort, pdm);
|
2021-06-05 17:29:51 +02:00
|
|
|
if (pwszDevice)
|
|
|
|
{
|
2021-06-12 20:49:36 +02:00
|
|
|
g_lastDDrawDeviceName = pwszDevice;
|
2021-06-05 17:29:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MONITORINFOEXA mi = {};
|
|
|
|
mi.cbSize = sizeof(mi);
|
|
|
|
CALL_ORIG_FUNC(GetMonitorInfoA)(MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY), &mi);
|
2021-06-12 20:49:36 +02:00
|
|
|
g_lastDDrawDeviceName = mi.szDevice;
|
2021-06-05 17:29:51 +02:00
|
|
|
}
|
2019-08-28 21:04:28 +02:00
|
|
|
return LOG_RESULT(CreateDCA(pwszDriver, pwszDevice, pszPort, pdm));
|
2018-12-09 14:23:36 +01:00
|
|
|
}
|
|
|
|
|
2021-06-12 20:49:36 +02:00
|
|
|
BOOL CALLBACK findMonitorInfo(HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT /*lprcMonitor*/, LPARAM dwData)
|
2018-12-09 14:23:36 +01:00
|
|
|
{
|
2021-06-12 20:49:36 +02:00
|
|
|
MONITORINFOEXW mi = {};
|
2018-12-09 14:23:36 +01:00
|
|
|
mi.cbSize = sizeof(mi);
|
2021-06-12 20:49:36 +02:00
|
|
|
CALL_ORIG_FUNC(GetMonitorInfoW)(hMonitor, &mi);
|
|
|
|
if (0 == wcscmp(reinterpret_cast<MONITORINFOEXW*>(dwData)->szDevice, mi.szDevice))
|
2018-12-09 14:23:36 +01:00
|
|
|
{
|
2021-06-12 20:49:36 +02:00
|
|
|
*reinterpret_cast<MONITORINFOEXW*>(dwData) = mi;
|
2018-12-09 14:23:36 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-06-12 20:49:36 +02:00
|
|
|
D3dDdi::KernelModeThunks::AdapterInfo getAdapterInfo(const std::string& deviceName, const D3DKMT_OPENADAPTERFROMHDC& data)
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2021-06-05 17:29:51 +02:00
|
|
|
D3dDdi::KernelModeThunks::AdapterInfo adapterInfo = {};
|
2018-10-03 20:49:50 +02:00
|
|
|
adapterInfo.adapter = data.hAdapter;
|
|
|
|
adapterInfo.vidPnSourceId = data.VidPnSourceId;
|
2021-06-05 17:29:51 +02:00
|
|
|
adapterInfo.luid = data.AdapterLuid;
|
2021-06-12 20:49:36 +02:00
|
|
|
wcscpy_s(adapterInfo.monitorInfo.szDevice, std::wstring(deviceName.begin(), deviceName.end()).c_str());
|
|
|
|
EnumDisplayMonitors(nullptr, nullptr, findMonitorInfo, reinterpret_cast<LPARAM>(&adapterInfo.monitorInfo));
|
2018-10-03 20:49:50 +02:00
|
|
|
return adapterInfo;
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 16:32:55 +01:00
|
|
|
int getScanLine()
|
|
|
|
{
|
|
|
|
D3DKMT_GETSCANLINE data = {};
|
|
|
|
getVidPnSource(data.hAdapter, data.VidPnSourceId);
|
|
|
|
if (!data.hAdapter || FAILED(D3DKMTGetScanLine(&data)) || data.InVerticalBlank)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return data.ScanLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
void getVidPnSource(D3DKMT_HANDLE& adapter, UINT& vidPnSourceId)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Compat::ScopedSrwLockShared lock(g_adapterInfoSrwLock);
|
|
|
|
if (g_lastOpenAdapterInfo.adapter)
|
|
|
|
{
|
|
|
|
adapter = g_lastOpenAdapterInfo.adapter;
|
|
|
|
vidPnSourceId = g_lastOpenAdapterInfo.vidPnSourceId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Compat::ScopedSrwLockExclusive lock(g_adapterInfoSrwLock);
|
|
|
|
updateGdiAdapterInfo();
|
|
|
|
adapter = g_gdiAdapterInfo.adapter;
|
|
|
|
vidPnSourceId = g_gdiAdapterInfo.vidPnSourceId;
|
|
|
|
}
|
|
|
|
|
2018-07-17 20:46:38 +02:00
|
|
|
NTSTATUS APIENTRY openAdapterFromHdc(D3DKMT_OPENADAPTERFROMHDC* pData)
|
|
|
|
{
|
2018-11-03 01:36:38 +01:00
|
|
|
LOG_FUNC("D3DKMTOpenAdapterFromHdc", pData);
|
2019-08-28 21:04:28 +02:00
|
|
|
NTSTATUS result = D3DKMTOpenAdapterFromHdc(pData);
|
2018-10-03 20:49:50 +02:00
|
|
|
if (SUCCEEDED(result))
|
2018-07-17 20:46:38 +02:00
|
|
|
{
|
2021-11-21 16:32:55 +01:00
|
|
|
Compat::ScopedSrwLockExclusive lock(g_adapterInfoSrwLock);
|
2021-06-12 20:49:36 +02:00
|
|
|
g_lastOpenAdapterInfo = getAdapterInfo(g_lastDDrawDeviceName, *pData);
|
2018-07-17 20:46:38 +02:00
|
|
|
}
|
2018-11-03 01:36:38 +01:00
|
|
|
return LOG_RESULT(result);
|
2018-07-17 20:46:38 +02:00
|
|
|
}
|
|
|
|
|
2021-11-21 16:32:55 +01:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-29 00:00:49 +01:00
|
|
|
NTSTATUS APIENTRY queryAdapterInfo(const D3DKMT_QUERYADAPTERINFO* pData)
|
|
|
|
{
|
2018-11-03 01:36:38 +01:00
|
|
|
LOG_FUNC("D3DKMTQueryAdapterInfo", pData);
|
2019-08-28 21:04:28 +02:00
|
|
|
NTSTATUS result = D3DKMTQueryAdapterInfo(pData);
|
2019-07-29 23:13:52 +02:00
|
|
|
if (SUCCEEDED(result))
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2019-07-29 23:13:52 +02:00
|
|
|
switch (pData->Type)
|
|
|
|
{
|
2022-03-27 11:39:27 +02:00
|
|
|
case KMTQAITYPE_UMDRIVERNAME:
|
|
|
|
if (Config::forceD3D9On12.get() &&
|
|
|
|
KMTUMDVERSION_DX9 == static_cast<D3DKMT_UMDFILENAMEINFO*>(pData->pPrivateDriverData)->Version)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2019-07-29 23:13:52 +02:00
|
|
|
case KMTQAITYPE_GETSEGMENTSIZE:
|
|
|
|
{
|
|
|
|
auto info = static_cast<D3DKMT_SEGMENTSIZEINFO*>(pData->pPrivateDriverData);
|
2021-10-31 00:08:09 +02:00
|
|
|
info->DedicatedVideoMemorySize += info->DedicatedSystemMemorySize;
|
|
|
|
info->DedicatedSystemMemorySize = 0;
|
|
|
|
|
2019-07-29 23:13:52 +02:00
|
|
|
const ULONGLONG maxMem = 0x3FFF0000;
|
2021-10-31 00:08:09 +02:00
|
|
|
if (info->DedicatedVideoMemorySize < maxMem)
|
2019-07-29 23:13:52 +02:00
|
|
|
{
|
2021-10-31 00:08:09 +02:00
|
|
|
auto addedMem = min(maxMem - info->DedicatedVideoMemorySize, info->SharedSystemMemorySize);
|
|
|
|
info->DedicatedVideoMemorySize += addedMem;
|
|
|
|
info->SharedSystemMemorySize -= addedMem;
|
2019-07-29 23:13:52 +02:00
|
|
|
}
|
2021-10-31 00:08:09 +02:00
|
|
|
|
|
|
|
info->DedicatedVideoMemorySize = min(info->DedicatedVideoMemorySize, maxMem);
|
|
|
|
info->SharedSystemMemorySize = min(info->SharedSystemMemorySize, maxMem);
|
2022-03-27 11:39:27 +02:00
|
|
|
break;
|
2019-07-29 23:13:52 +02:00
|
|
|
}
|
|
|
|
}
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
2018-11-03 01:36:38 +01:00
|
|
|
return LOG_RESULT(result);
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
|
|
|
|
2020-04-23 20:22:00 +02:00
|
|
|
NTSTATUS APIENTRY setGammaRamp(const D3DKMT_SETGAMMARAMP* pData)
|
|
|
|
{
|
|
|
|
LOG_FUNC("D3DKMTSetGammaRamp", pData);
|
2020-07-13 23:44:05 +02:00
|
|
|
UINT vsyncCounter = D3dDdi::KernelModeThunks::getVsyncCounter();
|
2020-04-23 20:22:00 +02:00
|
|
|
DDraw::RealPrimarySurface::flush();
|
|
|
|
HRESULT result = D3DKMTSetGammaRamp(pData);
|
2020-07-13 23:44:05 +02:00
|
|
|
if (SUCCEEDED(result))
|
|
|
|
{
|
|
|
|
D3dDdi::KernelModeThunks::waitForVsyncCounter(vsyncCounter + 1);
|
|
|
|
}
|
2020-04-23 20:22:00 +02:00
|
|
|
return LOG_RESULT(result);
|
|
|
|
}
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
void updateGdiAdapterInfo()
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
static auto lastDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness() - 1;
|
|
|
|
const auto currentDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness();
|
|
|
|
if (currentDisplaySettingsUniqueness != lastDisplaySettingsUniqueness)
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
if (g_gdiAdapterInfo.adapter)
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2018-10-03 20:49:50 +02:00
|
|
|
D3DKMT_CLOSEADAPTER data = {};
|
|
|
|
data.hAdapter = g_gdiAdapterInfo.adapter;
|
2019-08-28 21:04:28 +02:00
|
|
|
D3DKMTCloseAdapter(&data);
|
2018-10-03 20:49:50 +02:00
|
|
|
g_gdiAdapterInfo = {};
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
|
|
|
|
2018-12-30 13:07:55 +01:00
|
|
|
MONITORINFOEX mi = {};
|
|
|
|
mi.cbSize = sizeof(mi);
|
|
|
|
GetMonitorInfo(MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY), &mi);
|
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
D3DKMT_OPENADAPTERFROMHDC data = {};
|
2018-12-30 13:07:55 +01:00
|
|
|
data.hDc = CreateDC(mi.szDevice, mi.szDevice, nullptr, nullptr);
|
2019-08-28 21:04:28 +02:00
|
|
|
if (SUCCEEDED(D3DKMTOpenAdapterFromHdc(&data)))
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2021-06-12 20:49:36 +02:00
|
|
|
g_gdiAdapterInfo = getAdapterInfo(mi.szDevice, data);
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
2018-12-30 13:07:55 +01:00
|
|
|
DeleteDC(data.hDc);
|
2016-11-29 00:00:49 +01:00
|
|
|
|
2018-10-03 20:49:50 +02:00
|
|
|
lastDisplaySettingsUniqueness = currentDisplaySettingsUniqueness;
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-23 20:22:00 +02:00
|
|
|
|
2021-02-28 22:34:47 +01:00
|
|
|
unsigned WINAPI vsyncThreadProc(LPVOID /*lpParameter*/)
|
2020-04-23 20:22:00 +02:00
|
|
|
{
|
2021-03-01 22:59:07 +01:00
|
|
|
while (true)
|
2020-07-13 23:44:05 +02:00
|
|
|
{
|
|
|
|
waitForVerticalBlank();
|
|
|
|
|
|
|
|
{
|
|
|
|
Compat::ScopedSrwLockExclusive lock(g_vsyncCounterSrwLock);
|
2021-11-21 16:32:55 +01:00
|
|
|
g_qpcLastVsync = Time::queryPerformanceCounter();
|
2020-07-13 23:44:05 +02:00
|
|
|
++g_vsyncCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
WakeAllConditionVariable(&g_vsyncCounterCv);
|
|
|
|
}
|
2020-04-23 20:22:00 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2016-11-29 00:00:49 +01:00
|
|
|
|
2020-07-13 23:44:05 +02:00
|
|
|
void waitForVerticalBlank()
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2021-11-21 16:32:55 +01:00
|
|
|
if (IsWindows8OrGreater())
|
2018-07-17 20:46:38 +02:00
|
|
|
{
|
2021-11-21 16:32:55 +01:00
|
|
|
D3DKMT_WAITFORVERTICALBLANKEVENT data = {};
|
2018-07-17 20:46:38 +02:00
|
|
|
|
2021-11-21 16:32:55 +01:00
|
|
|
{
|
|
|
|
Compat::ScopedSrwLockShared lock(g_adapterInfoSrwLock);
|
|
|
|
data.hAdapter = g_lastOpenAdapterInfo.adapter;
|
|
|
|
data.VidPnSourceId = g_lastOpenAdapterInfo.vidPnSourceId;
|
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
|
2021-11-21 16:32:55 +01:00
|
|
|
if (!data.hAdapter)
|
|
|
|
{
|
|
|
|
updateGdiAdapterInfo();
|
|
|
|
data.hAdapter = g_gdiAdapterInfo.adapter;
|
|
|
|
data.VidPnSourceId = g_gdiAdapterInfo.vidPnSourceId;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data.hAdapter && SUCCEEDED(D3DKMTWaitForVerticalBlankEvent(&data)))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
2021-11-21 16:32:55 +01:00
|
|
|
|
|
|
|
pollForVerticalBlank();
|
2020-07-13 23:44:05 +02:00
|
|
|
}
|
|
|
|
}
|
2018-10-03 20:49:50 +02:00
|
|
|
|
2020-07-13 23:44:05 +02:00
|
|
|
namespace D3dDdi
|
|
|
|
{
|
|
|
|
namespace KernelModeThunks
|
|
|
|
{
|
2021-06-05 17:29:51 +02:00
|
|
|
AdapterInfo getAdapterInfo(CompatRef<IDirectDraw7> dd)
|
|
|
|
{
|
|
|
|
DDraw::ScopedThreadLock lock;
|
|
|
|
DDDEVICEIDENTIFIER2 di = {};
|
|
|
|
dd.get().lpVtbl->GetDeviceIdentifier(&dd, &di, 0);
|
|
|
|
return getLastOpenAdapterInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
AdapterInfo getLastOpenAdapterInfo()
|
|
|
|
{
|
2021-11-21 16:32:55 +01:00
|
|
|
Compat::ScopedSrwLockShared srwLock(g_adapterInfoSrwLock);
|
2021-06-05 17:29:51 +02:00
|
|
|
return g_lastOpenAdapterInfo;
|
|
|
|
}
|
|
|
|
|
2021-05-15 16:06:26 +02:00
|
|
|
long long getQpcLastVsync()
|
|
|
|
{
|
2021-11-21 16:32:55 +01:00
|
|
|
Compat::ScopedSrwLockShared lock(g_vsyncCounterSrwLock);
|
2021-05-15 16:06:26 +02:00
|
|
|
return g_qpcLastVsync;
|
|
|
|
}
|
|
|
|
|
2020-07-13 23:44:05 +02:00
|
|
|
UINT getVsyncCounter()
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2020-07-13 23:44:05 +02:00
|
|
|
Compat::ScopedSrwLockShared lock(g_vsyncCounterSrwLock);
|
|
|
|
return g_vsyncCounter;
|
2017-05-17 20:41:05 +02:00
|
|
|
}
|
|
|
|
|
2021-03-14 18:48:26 +01:00
|
|
|
void installHooks()
|
2016-11-29 00:00:49 +01:00
|
|
|
{
|
2021-03-14 18:48:26 +01:00
|
|
|
Compat::hookIatFunction(Dll::g_origDDrawModule, "CreateDCA", ddrawCreateDcA);
|
|
|
|
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCloseAdapter", closeAdapter);
|
|
|
|
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTCreateDCFromMemory", createDcFromMemory);
|
|
|
|
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTOpenAdapterFromHdc", openAdapterFromHdc);
|
|
|
|
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTQueryAdapterInfo", queryAdapterInfo);
|
|
|
|
Compat::hookIatFunction(Dll::g_origDDrawModule, "D3DKMTSetGammaRamp", setGammaRamp);
|
2016-12-13 22:27:01 +01:00
|
|
|
|
2021-03-01 22:59:07 +01:00
|
|
|
Dll::createThread(&vsyncThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
|
2017-05-17 20:41:05 +02:00
|
|
|
}
|
|
|
|
|
2019-04-23 12:44:13 +02:00
|
|
|
void setDcFormatOverride(UINT format)
|
|
|
|
{
|
|
|
|
g_dcFormatOverride = static_cast<D3DDDIFORMAT>(format);
|
|
|
|
}
|
|
|
|
|
2021-06-15 23:14:33 +02:00
|
|
|
void setDcPaletteOverride(PALETTEENTRY* palette)
|
2019-08-02 22:16:44 +02:00
|
|
|
{
|
2021-06-15 23:14:33 +02:00
|
|
|
g_dcPaletteOverride = palette;
|
2019-08-02 22:16:44 +02:00
|
|
|
}
|
|
|
|
|
2020-07-13 23:44:05 +02:00
|
|
|
bool waitForVsyncCounter(UINT counter)
|
|
|
|
{
|
|
|
|
bool waited = false;
|
|
|
|
Compat::ScopedSrwLockShared lock(g_vsyncCounterSrwLock);
|
|
|
|
while (static_cast<INT>(g_vsyncCounter - counter) < 0)
|
2018-10-03 20:49:50 +02:00
|
|
|
{
|
2020-07-13 23:44:05 +02:00
|
|
|
SleepConditionVariableSRW(&g_vsyncCounterCv, &g_vsyncCounterSrwLock, INFINITE,
|
|
|
|
CONDITION_VARIABLE_LOCKMODE_SHARED);
|
|
|
|
waited = true;
|
2018-10-03 20:49:50 +02:00
|
|
|
}
|
2020-07-13 23:44:05 +02:00
|
|
|
return waited;
|
2016-12-13 22:27:01 +01:00
|
|
|
}
|
2016-11-29 00:00:49 +01:00
|
|
|
}
|
|
|
|
}
|