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