You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.9 KiB
102 lines
2.9 KiB
|
|
// attempt to fix vsync with opengl on windows |
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=467617 |
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/d3dkmthk/nf-d3dkmthk-d3dkmtwaitforverticalblankevent |
|
// NOTE: requires installing windows driver kit addon for msvc |
|
// TODO: not working with hdc provided by SDL, try enumerating display devices as described here: |
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/d3dkmthk/nf-d3dkmthk-d3dkmtopenadapterfromhdc |
|
// NOTE: the above seems to make some difference in lowering cpu usage, but cpu stays at max frequency even when relatively idle. |
|
|
|
// TODO: if d3dkmt... doensn't work, try DWMFlush() https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmflush |
|
// glfw uses this https://github.com/glfw/glfw/blob/master/src/wgl_context.c |
|
// |
|
// if that doesn't work... https://docs.microsoft.com/en-us/windows/desktop/api/timeapi/nf-timeapi-timebeginperiod |
|
// to increase schedular granularity. can then use sleep(1) for 1ms resolution |
|
|
|
#pragma once |
|
|
|
#include <cstdint> |
|
|
|
#include "SDL_syswm.h" |
|
|
|
#if defined(_WIN32) |
|
#include "windows.h" |
|
#include "d3dkmthk.h" |
|
|
|
typedef uint32_t D3DKMT_HANDLE; |
|
typedef struct { |
|
D3DKMT_HANDLE hAdapter = NULL; |
|
UINT vidID = 0; |
|
} platform_win_device_handles; |
|
platform_win_device_handles g_platform_win_device_handles; |
|
|
|
#endif // _WIN32 |
|
|
|
|
|
inline bool |
|
platform_init(SDL_Window* window) |
|
{ |
|
#if defined(_WIN32) |
|
D3DKMT_HANDLE hAdapter = NULL; |
|
UINT vidID = 0; |
|
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData; |
|
DISPLAY_DEVICE dd; |
|
HDC hdc; |
|
|
|
memset(&dd, 0, sizeof(dd)); |
|
dd.cb = sizeof dd; |
|
|
|
for (int i = 0; EnumDisplayDevicesA(NULL, i, &dd, 0); ++i) { |
|
if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) |
|
break; |
|
} |
|
|
|
hdc = CreateDC(NULL, dd.DeviceName, NULL, NULL); |
|
if (hdc == NULL) |
|
return false; |
|
|
|
OpenAdapterData.hDc = hdc; |
|
if ((D3DKMTOpenAdapterFromHdc(&OpenAdapterData)) >= 0) { |
|
DeleteDC(hdc); |
|
g_platform_win_device_handles.hAdapter = OpenAdapterData.hAdapter; |
|
g_platform_win_device_handles.vidID = OpenAdapterData.VidPnSourceId; |
|
return true; |
|
} |
|
|
|
DeleteDC(hdc); |
|
return false; |
|
#endif // _WIN32 |
|
|
|
return true; |
|
} |
|
|
|
inline void |
|
platform_wait_for_vblank(bool wait=true) |
|
{ |
|
if (!wait) return; |
|
|
|
#if defined(_WIN32) |
|
_D3DKMT_WAITFORVERTICALBLANKEVENT waitForVBlankData; |
|
memset(&waitForVBlankData, 0, sizeof(waitForVBlankData)); |
|
waitForVBlankData.hAdapter = g_platform_win_device_handles.hAdapter; |
|
waitForVBlankData.VidPnSourceId = g_platform_win_device_handles.vidID; |
|
NTSTATUS ret = D3DKMTWaitForVerticalBlankEvent(&waitForVBlankData); |
|
|
|
switch (ret) { |
|
case 0x00000000: // STATUS_SUCCESS |
|
//OutputDebugString("Success\r\n"); |
|
break; |
|
//case STATUS_DEVICE_REMOVED: |
|
// OutputDebugString("STATUS_DEVICE_REMOVED\r\n"); |
|
// break; |
|
case STATUS_INVALID_PARAMETER: |
|
OutputDebugString("STATUS_INVALID_PARAMETER\r\n"); |
|
break; |
|
default: |
|
OutputDebugString("????"); |
|
} |
|
#endif // _WIN32 |
|
|
|
// TODO: implement/test for linux |
|
} |
|
|
|
|