Skip to content

Commit d12e66e

Browse files
authored
Merge pull request #1004 from Edreva/generic-slm-fixes
GenericSLM: Sync refresh waiter to connected SLM, not primary monitor
2 parents 29a37c5 + 34c042f commit d12e66e

3 files changed

Lines changed: 109 additions & 29 deletions

File tree

‎DeviceAdapters/GenericSLM/GenericSLM.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,10 @@ int GenericSLM::Initialize()
226226
(monitorName_.empty() ? "Test Mode" : monitorName_) +
227227
"]";
228228

229+
if (refreshWaiter_.SetMonitor(monitorName_) != 0)
230+
LogMessage("Could not attach vertical sync to " + monitorName_ +
231+
", reverting to primary display");
232+
229233
windowThread_ = new SLMWindowThread(monitorName_.empty(),
230234
windowTitle, x, y, w, h);
231235
windowThread_->Show();

‎DeviceAdapters/GenericSLM/RefreshWaiter.cpp‎

Lines changed: 99 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,47 +17,118 @@
1717
#include "RefreshWaiter.h"
1818

1919

20-
RefreshWaiter::RefreshWaiter()
20+
namespace {
21+
22+
struct FindGuidContext
23+
{
24+
const std::string* monitorName;
25+
GUID guid;
26+
bool found;
27+
};
28+
29+
// https://learn.microsoft.com/en-us/windows/win32/api/ddraw/nc-ddraw-lpddenumcallbackexa
30+
BOOL WINAPI FindGuidForMonitor(GUID* pGUID, LPSTR,
31+
LPSTR, LPVOID pContext, HMONITOR mointorHandle)
32+
{
33+
FindGuidContext* ctx = static_cast<FindGuidContext*>(pContext);
34+
if (pGUID == 0 || mointorHandle == 0)
35+
return TRUE;
36+
37+
MONITORINFOEXA info;
38+
info.cbSize = sizeof(info);
39+
if (GetMonitorInfoA(mointorHandle, &info) && *ctx->monitorName == info.szDevice)
40+
{
41+
ctx->guid = *pGUID;
42+
ctx->found = true;
43+
return FALSE;
44+
}
45+
return TRUE;
46+
}
47+
48+
}
49+
50+
51+
RefreshWaiter::RefreshWaiter() :
52+
hDDrawLib_(0),
53+
directDrawCreate_(0),
54+
directDrawEnumerateEx_(0),
55+
directDraw_(0)
2156
{
22-
hDDrawLib_ = LoadLibraryA("ddraw.dll");
23-
if (!hDDrawLib_)
24-
return;
25-
26-
directDrawCreate_ = (DirectDrawCreateFunc)GetProcAddress(hDDrawLib_,
27-
"DirectDrawCreate");
28-
if (!directDrawCreate_)
29-
return;
30-
31-
HRESULT hr = directDrawCreate_(0, &directDraw_, 0);
32-
if (hr != DD_OK)
33-
{
34-
directDraw_ = 0;
35-
return;
36-
}
57+
hDDrawLib_ = LoadLibraryA("ddraw.dll");
58+
if (!hDDrawLib_)
59+
return;
60+
61+
directDrawCreate_ = (DirectDrawCreateFunc)GetProcAddress(hDDrawLib_,
62+
"DirectDrawCreate");
63+
directDrawEnumerateEx_ = (DirectDrawEnumerateExFunc)GetProcAddress(hDDrawLib_,
64+
"DirectDrawEnumerateExA");
65+
if (!directDrawCreate_)
66+
return;
67+
68+
HRESULT hr = directDrawCreate_(0, &directDraw_, 0);
69+
if (hr != DD_OK)
70+
{
71+
directDraw_ = 0;
72+
return;
73+
}
3774
}
3875

3976

4077
RefreshWaiter::~RefreshWaiter()
4178
{
42-
if (directDraw_)
43-
directDraw_->Release();
79+
if (directDraw_)
80+
directDraw_->Release();
81+
82+
if (hDDrawLib_)
83+
FreeLibrary(hDDrawLib_);
84+
}
85+
86+
87+
int RefreshWaiter::SetMonitor(const std::string& monitorName)
88+
{
89+
if (!directDrawCreate_)
90+
return 1;
91+
92+
GUID* pGuid = 0;
93+
FindGuidContext ctx;
94+
ctx.monitorName = &monitorName;
95+
ctx.found = false;
96+
97+
if (!monitorName.empty())
98+
{
99+
if (!directDrawEnumerateEx_)
100+
return 1;
101+
102+
directDrawEnumerateEx_(FindGuidForMonitor, &ctx, DDENUM_ATTACHEDSECONDARYDEVICES);
103+
if (!ctx.found)
104+
return 1;
105+
106+
pGuid = &ctx.guid;
107+
}
108+
109+
IDirectDraw* newDirectDraw = 0;
110+
HRESULT hr = directDrawCreate_(pGuid, &newDirectDraw, 0);
111+
if (hr != DD_OK)
112+
return (int)hr;
44113

45-
if (hDDrawLib_)
46-
FreeLibrary(hDDrawLib_);
114+
if (directDraw_)
115+
directDraw_->Release();
116+
directDraw_ = newDirectDraw;
117+
return 0;
47118
}
48119

49120

50121
int RefreshWaiter::WaitForVerticalBlank()
51122
{
52-
if (!directDraw_)
53-
return 1;
123+
if (!directDraw_)
124+
return 1;
54125

55-
HRESULT result = directDraw_->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
126+
HRESULT result = directDraw_->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
56127

57-
if (result == DD_OK)
58-
{
59-
return 0;
60-
}
61-
return (int) result;
128+
if (result == DD_OK)
129+
{
130+
return 0;
131+
}
132+
return (int) result;
62133

63134
}

‎DeviceAdapters/GenericSLM/RefreshWaiter.h‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@
1919
#include <Windows.h>
2020
#include <ddraw.h>
2121

22+
#include <string>
23+
2224

2325
class RefreshWaiter
2426
{
2527
HMODULE hDDrawLib_;
2628
typedef HRESULT (WINAPI *DirectDrawCreateFunc)(GUID*, LPDIRECTDRAW*, IUnknown*);
29+
typedef HRESULT (WINAPI *DirectDrawEnumerateExFunc)(LPDDENUMCALLBACKEXA, LPVOID, DWORD);
2730
DirectDrawCreateFunc directDrawCreate_;
31+
DirectDrawEnumerateExFunc directDrawEnumerateEx_;
2832
IDirectDraw* directDraw_;
2933

3034
public:
3135
RefreshWaiter();
3236
~RefreshWaiter();
3337

38+
int SetMonitor(const std::string& monitorName);
3439
int WaitForVerticalBlank();
35-
};
40+
};

0 commit comments

Comments
 (0)