1 // D3DKMTWaitForVerticalBlankEvent (codename: SuperWaitVBlank) interface. - dink 2018
2 #include "burner.h"
3
4 typedef struct _D3DKMT_OPENADAPTERFROMHDC
5 {
6 HDC hDc;
7 UINT32 hAdapter;
8 LUID AdapterLuid;
9 UINT32 VidPnSourceId;
10 } D3DKMT_OPENADAPTERFROMHDC;
11
12 typedef struct _D3DKMT_CLOSEADAPTER {
13 UINT32 hAdapter;
14 } D3DKMT_CLOSEADAPTER;
15
16 typedef struct _D3DKMT_WAITFORVERTICALBLANKEVENT
17 {
18 UINT32 hAdapter;
19 UINT32 hDevice;
20 UINT32 VidPnSourceId;
21 } D3DKMT_WAITFORVERTICALBLANKEVENT;
22
23 #ifndef DISPLAY_DEVICE_ACTIVE
24 #define DISPLAY_DEVICE_ACTIVE 0x00000001
25 #endif
26
27 LONG (APIENTRY *D3DKMTWaitForVerticalBlankEvent) (D3DKMT_WAITFORVERTICALBLANKEVENT *lpParams);
28 LONG (APIENTRY *D3DKMTOpenAdapterFromHdc) (D3DKMT_OPENADAPTERFROMHDC *lpParams );
29 LONG (APIENTRY *D3DKMTCloseAdapter) (D3DKMT_CLOSEADAPTER *lpParams );
30
Empty_D3DKMTWaitForVerticalBlankEvent(D3DKMT_WAITFORVERTICALBLANKEVENT *)31 LONG APIENTRY Empty_D3DKMTWaitForVerticalBlankEvent (D3DKMT_WAITFORVERTICALBLANKEVENT *) { return 0; }
Empty_D3DKMTOpenAdapterFromHdc(D3DKMT_OPENADAPTERFROMHDC *)32 LONG APIENTRY Empty_D3DKMTOpenAdapterFromHdc (D3DKMT_OPENADAPTERFROMHDC *) { return 0; }
Empty_D3DKMTCloseAdapter(D3DKMT_CLOSEADAPTER *)33 LONG APIENTRY Empty_D3DKMTCloseAdapter (D3DKMT_CLOSEADAPTER * ) { return 0; }
34
35 static int SuperWaitVBlank_Initialised = 0;
36 static int SuperWaitVBlank_DLLsLoaded = 0;
37 static HINSTANCE hGdi32;
38 static D3DKMT_WAITFORVERTICALBLANKEVENT we = { 0, 0, 0 };
39
40 bool bVidDWMSync = true;
41
LoadGDIFunctions()42 void LoadGDIFunctions() {
43
44 hGdi32 = LoadLibrary(_T("gdi32.dll"));
45
46 if(!hGdi32) return;
47
48 D3DKMTWaitForVerticalBlankEvent = (LONG (WINAPI *)(D3DKMT_WAITFORVERTICALBLANKEVENT *)) GetProcAddress(hGdi32, "D3DKMTWaitForVerticalBlankEvent");
49 D3DKMTOpenAdapterFromHdc = (LONG (WINAPI *)(D3DKMT_OPENADAPTERFROMHDC *)) GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromHdc");
50 D3DKMTCloseAdapter = (LONG (WINAPI *)(D3DKMT_CLOSEADAPTER *)) GetProcAddress(hGdi32, "D3DKMTCloseAdapter");
51
52 if(!D3DKMTWaitForVerticalBlankEvent) bprintf(0, _T("Unable to acquire D3DKMTWaitForVerticalBlankEvent()!\n"));
53 if(!D3DKMTWaitForVerticalBlankEvent) D3DKMTWaitForVerticalBlankEvent = Empty_D3DKMTWaitForVerticalBlankEvent;
54
55 if(!D3DKMTOpenAdapterFromHdc) bprintf(0, _T("Unable to acquire D3DKMTOpenAdapterFromHdc()!\n"));
56 if(!D3DKMTOpenAdapterFromHdc) D3DKMTOpenAdapterFromHdc = Empty_D3DKMTOpenAdapterFromHdc;
57
58 if(!D3DKMTCloseAdapter) bprintf(0, _T("Unable to acquire D3DKMTCloseAdapter()!\n"));
59 if(!D3DKMTCloseAdapter) D3DKMTCloseAdapter = Empty_D3DKMTCloseAdapter;
60
61 FreeLibrary(hGdi32);
62
63 SuperWaitVBlank_DLLsLoaded = 1;
64 }
65
IsWindows7Plus()66 BOOL IsWindows7Plus() {
67
68 OSVERSIONINFO osvi;
69 memset(&osvi, 0, sizeof(OSVERSIONINFO));
70 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
71
72 GetVersionEx(&osvi);
73
74 return (osvi.dwMajorVersion >= 6); // win7+
75 }
76
77 // This will need re-init every vid init in the case of multiple monitors.
SuperWaitVBlankInit()78 void SuperWaitVBlankInit()
79 {
80 if(!IsWindows7Plus()) return;
81
82 if (!SuperWaitVBlank_DLLsLoaded) {
83 LoadGDIFunctions();
84 }
85
86 if (SuperWaitVBlank_Initialised) {
87 SuperWaitVBlankExit();
88 }
89
90 MONITORINFOEX mi;
91 memset(&mi, 0, sizeof(MONITORINFOEX));
92 mi.cbSize = sizeof(MONITORINFOEX);
93 HMONITOR hmon = MonitorFromWindow(hScrnWnd, MONITOR_DEFAULTTONEAREST); // get the monitor fba is running on
94 GetMonitorInfo(hmon, &mi);
95
96 HDC hDC = CreateDC(NULL, (LPWSTR)mi.szDevice, NULL, NULL);
97
98 if (hDC) {
99 D3DKMT_OPENADAPTERFROMHDC oa;
100 oa.hDc = hDC;
101 D3DKMTOpenAdapterFromHdc(&oa);
102 DeleteDC(hDC);
103 we.hAdapter = oa.hAdapter;
104 we.hDevice = 0;
105 we.VidPnSourceId = oa.VidPnSourceId;
106 bprintf(0, _T("SuperWaitVBlankInit() on %s\n"), mi.szDevice);
107
108 SuperWaitVBlank_Initialised = 1;
109 }
110 }
111
SuperWaitVBlankExit()112 void SuperWaitVBlankExit()
113 {
114 if (SuperWaitVBlank_Initialised) {
115 D3DKMT_CLOSEADAPTER ca = { we.hAdapter };
116 D3DKMTCloseAdapter(&ca);
117 memset(&we, 0, sizeof(we));
118
119 SuperWaitVBlank_Initialised = 0;
120 }
121 }
122
SuperWaitVBlank()123 int SuperWaitVBlank()
124 {
125 if (SuperWaitVBlank_Initialised) {
126 return D3DKMTWaitForVerticalBlankEvent(&we);
127 } else {
128 return 0xdead;
129 }
130 }
131