A small OpenGL 3+ renderer and game engine
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

// 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
}