Evan's Blog
EvanZhu0721 / 公开仓库

SBMS

镜像已同步

SBMS complete the calculation rules for the default logical desktop topology relationship and the physical dimensions of the displays in the Windows multi-screen collaboration system.

上游 GitHub
READ-ONLY MIRROR

README、源码与 Release 已保存到本站;源码视图固定到 commit a37d6c4b。

main/ root / driver
a37d6c4b· 固定源码快照
driver/Driver.cpp17.8 KB
1#define NOMINMAX
2
3#include <windows.h>
4#include <wdf.h>
5#include <iddcx.h>
6#include <dxgi1_5.h>
7#include <d3d11.h>
8#include <new>
9
10EVT_WDF_DRIVER_DEVICE_ADD DeviceAdd;
11EVT_WDF_DEVICE_D0_ENTRY DeviceD0Entry;
12EVT_WDF_OBJECT_CONTEXT_CLEANUP MonitorCleanup;
13EVT_IDD_CX_ADAPTER_INIT_FINISHED AdapterInitFinished;
14EVT_IDD_CX_ADAPTER_COMMIT_MODES AdapterCommitModes;
15EVT_IDD_CX_PARSE_MONITOR_DESCRIPTION ParseMonitorDescription;
16EVT_IDD_CX_MONITOR_GET_DEFAULT_DESCRIPTION_MODES GetDefaultMonitorModes;
17EVT_IDD_CX_MONITOR_QUERY_TARGET_MODES QueryTargetModes;
18EVT_IDD_CX_MONITOR_ASSIGN_SWAPCHAIN AssignSwapChain;
19EVT_IDD_CX_MONITOR_UNASSIGN_SWAPCHAIN UnassignSwapChain;
20
21namespace
22{
23constexpr UINT kMaximumDimension = 16384;
24constexpr UINT kMaximumRefreshRate = 1000;
25constexpr UINT kMaximumMonitors = 16;
26constexpr wchar_t kSessionGate[] = L"Global\\SBMSSession-v7";
27constexpr UINT kGateMagic = 0x53424737;
28constexpr UINT kProtocolVersion = 7;
29
30struct GateHeader
31{
32 UINT magic;
33 UINT version;
34 UINT count;
35 UINT reserved;
36};
37
38struct GateEntry
39{
40 UINT connectorIndex;
41 UINT width;
42 UINT height;
43 UINT refreshNumerator;
44 UINT refreshDenominator;
45};
46
47struct GateConfig
48{
49 GateHeader header;
50 GateEntry entries[kMaximumMonitors];
51};
52
53static_assert(sizeof(GateHeader) == 16);
54static_assert(sizeof(GateEntry) == 20);
55static_assert(sizeof(GateConfig) == 336);
56
57struct ModeConfig
58{
59 UINT connectorIndex;
60 UINT width;
61 UINT height;
62 UINT refreshNumerator;
63 UINT refreshDenominator;
64};
65
66// One permanent monitor identity. Changing either value makes Windows treat the
67// virtual monitor as new hardware and loses its saved desktop placement.
68constexpr GUID kMonitorContainerId =
69 {0x67453031, 0x7ba9, 0x4d45, {0x8f, 0x0b, 0x72, 0x1d, 0xb4, 0x61, 0x62, 0x42}};
70
71GUID MonitorContainerId(UINT connectorIndex)
72{
73 GUID id = kMonitorContainerId;
74 id.Data1 ^= connectorIndex;
75 return id;
76}
77
78struct Drain
79{
80 IDDCX_SWAPCHAIN swapChain{};
81 ID3D11Device* d3dDevice{};
82 HANDLE frameAvailable{};
83 HANDLE stop{};
84 HANDLE thread{};
85 volatile LONG ownership{};
86};
87
88struct DeviceState
89{
90 WDFDEVICE device{};
91 IDDCX_ADAPTER adapter{};
92};
93
94struct MonitorState
95{
96 Drain* drain{};
97 ModeConfig mode{};
98};
99
100WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DeviceState, GetDeviceState);
101WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MonitorState, GetMonitorState);
102
103bool ValidateMode(
104 UINT connectorIndex,
105 UINT width,
106 UINT height,
107 UINT refreshNumerator,
108 UINT refreshDenominator,
109 ModeConfig& mode)
110{
111 if (connectorIndex >= kMaximumMonitors ||
112 width == 0 || height == 0 ||
113 width > kMaximumDimension || height > kMaximumDimension ||
114 refreshNumerator == 0 || refreshDenominator == 0)
115 {
116 return false;
117 }
118 const UINT64 maximumNumerator =
119 static_cast<UINT64>(refreshDenominator) * kMaximumRefreshRate;
120 if (refreshNumerator < refreshDenominator ||
121 refreshNumerator > maximumNumerator ||
122 static_cast<UINT64>(height) * refreshNumerator > MAXUINT32)
123 {
124 return false;
125 }
126
127 mode.connectorIndex = connectorIndex;
128 mode.width = width;
129 mode.height = height;
130 mode.refreshNumerator = refreshNumerator;
131 mode.refreshDenominator = refreshDenominator;
132 return true;
133}
134
135bool ReadSessionConfig(ModeConfig (&modes)[kMaximumMonitors], UINT& count)
136{
137 HANDLE gate = OpenFileMappingW(FILE_MAP_READ, FALSE, kSessionGate);
138 if (gate == nullptr)
139 {
140 return false;
141 }
142 const auto* config = static_cast<const GateConfig*>(
143 MapViewOfFile(gate, FILE_MAP_READ, 0, 0, sizeof(GateConfig)));
144 bool valid = false;
145 if (config != nullptr &&
146 config->header.magic == kGateMagic &&
147 config->header.version == kProtocolVersion &&
148 config->header.count > 0 &&
149 config->header.count <= kMaximumMonitors)
150 {
151 valid = true;
152 UINT connectorMask = 0;
153 for (UINT index = 0; index < config->header.count; ++index)
154 {
155 const GateEntry& entry = config->entries[index];
156 if (entry.connectorIndex >= kMaximumMonitors)
157 {
158 valid = false;
159 break;
160 }
161 const UINT connectorBit = 1u << entry.connectorIndex;
162 if ((connectorMask & connectorBit) != 0 ||
163 !ValidateMode(
164 entry.connectorIndex,
165 entry.width,
166 entry.height,
167 entry.refreshNumerator,
168 entry.refreshDenominator,
169 modes[index]))
170 {
171 valid = false;
172 break;
173 }
174 connectorMask |= connectorBit;
175 }
176 if (valid)
177 {
178 count = config->header.count;
179 }
180 }
181 if (config != nullptr) UnmapViewOfFile(config);
182 CloseHandle(gate);
183 return valid;
184}
185
186void FillSignal(
187 DISPLAYCONFIG_VIDEO_SIGNAL_INFO& signal,
188 const ModeConfig& config,
189 bool monitorMode)
190{
191 signal.activeSize.cx = config.width;
192 signal.activeSize.cy = config.height;
193 signal.totalSize.cx = config.width;
194 signal.totalSize.cy = config.height;
195 signal.vSyncFreq.Numerator = config.refreshNumerator;
196 signal.vSyncFreq.Denominator = config.refreshDenominator;
197 signal.hSyncFreq.Numerator = config.height * config.refreshNumerator;
198 signal.hSyncFreq.Denominator = config.refreshDenominator;
199 signal.pixelRate =
200 static_cast<UINT64>(config.width) *
201 config.height *
202 config.refreshNumerator /
203 config.refreshDenominator;
204 signal.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
205 signal.AdditionalSignalInfo.videoStandard = 255;
206 signal.AdditionalSignalInfo.vSyncFreqDivider = monitorMode ? 0 : 1;
207}
208
209IDDCX_MONITOR_MODE MonitorMode(
210 const ModeConfig& config,
211 IDDCX_MONITOR_MODE_ORIGIN origin)
212{
213 IDDCX_MONITOR_MODE mode{};
214 mode.Size = sizeof(mode);
215 mode.Origin = origin;
216 FillSignal(mode.MonitorVideoSignalInfo, config, true);
217 return mode;
218}
219
220IDDCX_TARGET_MODE TargetMode(const ModeConfig& config)
221{
222 IDDCX_TARGET_MODE mode{};
223 mode.Size = sizeof(mode);
224 FillSignal(mode.TargetVideoSignalInfo.targetVideoSignalInfo, config, false);
225 return mode;
226}
227
228void DestroyDrain(Drain* drain)
229{
230 if (drain->thread != nullptr) CloseHandle(drain->thread);
231 if (drain->stop != nullptr) CloseHandle(drain->stop);
232 if (drain->d3dDevice != nullptr) drain->d3dDevice->Release();
233 delete drain;
234}
235
236DWORD WINAPI DrainFrames(void* argument)
237{
238 auto* drain = static_cast<Drain*>(argument);
239
240 for (;;)
241 {
242 if (WaitForSingleObject(drain->stop, 0) == WAIT_OBJECT_0)
243 {
244 break;
245 }
246
247 IDARG_OUT_RELEASEANDACQUIREBUFFER buffer{};
248 const HRESULT result =
249 IddCxSwapChainReleaseAndAcquireBuffer(drain->swapChain, &buffer);
250
251 if (result == E_PENDING)
252 {
253 const HANDLE handles[] = {drain->frameAvailable, drain->stop};
254 const DWORD wait = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, INFINITE);
255 if (wait == WAIT_OBJECT_0)
256 {
257 continue;
258 }
259 break;
260 }
261
262 if (FAILED(result))
263 {
264 break;
265 }
266
267 if (buffer.MetaData.pSurface != nullptr)
268 {
269 buffer.MetaData.pSurface->Release();
270 }
271
272 if (FAILED(IddCxSwapChainFinishedProcessingFrame(drain->swapChain)))
273 {
274 break;
275 }
276 }
277
278 WdfObjectDelete(drain->swapChain);
279 drain->swapChain = nullptr;
280 if (InterlockedCompareExchange(&drain->ownership, 2, 0) == 1)
281 {
282 DestroyDrain(drain);
283 }
284 return 0;
285}
286
287void StopDrain(MonitorState* monitor)
288{
289 if (monitor == nullptr || monitor->drain == nullptr)
290 {
291 return;
292 }
293
294 Drain* drain = monitor->drain;
295 monitor->drain = nullptr;
296 SetEvent(drain->stop);
297 if (drain->thread != nullptr)
298 {
299 if (WaitForSingleObject(drain->thread, 5000) != WAIT_OBJECT_0)
300 {
301 // Either the worker observes state 1 and destroys itself, or it
302 // already published state 2 and cleanup remains here.
303 if (InterlockedCompareExchange(&drain->ownership, 1, 0) != 2)
304 {
305 return;
306 }
307 }
308 }
309 DestroyDrain(drain);
310}
311
312bool StartDrain(
313 MonitorState* monitor,
314 IDDCX_SWAPCHAIN swapChain,
315 LUID renderAdapter,
316 HANDLE frameAvailable)
317{
318 IDXGIFactory5* factory = nullptr;
319 IDXGIAdapter1* adapter = nullptr;
320 IDXGIDevice* dxgiDevice = nullptr;
321 ID3D11Device* d3dDevice = nullptr;
322
323 HRESULT result = CreateDXGIFactory2(0, IID_PPV_ARGS(&factory));
324 if (SUCCEEDED(result))
325 {
326 result = factory->EnumAdapterByLuid(renderAdapter, IID_PPV_ARGS(&adapter));
327 }
328 if (SUCCEEDED(result))
329 {
330 result = D3D11CreateDevice(
331 adapter,
332 D3D_DRIVER_TYPE_UNKNOWN,
333 nullptr,
334 D3D11_CREATE_DEVICE_BGRA_SUPPORT,
335 nullptr,
336 0,
337 D3D11_SDK_VERSION,
338 &d3dDevice,
339 nullptr,
340 nullptr);
341 }
342 if (SUCCEEDED(result))
343 {
344 result = d3dDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
345 }
346 if (SUCCEEDED(result))
347 {
348 IDARG_IN_SWAPCHAINSETDEVICE setDevice{};
349 setDevice.pDevice = dxgiDevice;
350 result = IddCxSwapChainSetDevice(swapChain, &setDevice);
351 }
352
353 if (dxgiDevice != nullptr) dxgiDevice->Release();
354 if (adapter != nullptr) adapter->Release();
355 if (factory != nullptr) factory->Release();
356
357 if (FAILED(result))
358 {
359 if (d3dDevice != nullptr) d3dDevice->Release();
360 return false;
361 }
362
363 auto* drain = new (std::nothrow) Drain{};
364 if (drain == nullptr)
365 {
366 d3dDevice->Release();
367 return false;
368 }
369
370 drain->swapChain = swapChain;
371 drain->d3dDevice = d3dDevice;
372 drain->frameAvailable = frameAvailable;
373 drain->stop = CreateEventW(nullptr, TRUE, FALSE, nullptr);
374 if (drain->stop != nullptr)
375 {
376 drain->thread = CreateThread(nullptr, 0, DrainFrames, drain, 0, nullptr);
377 }
378 if (drain->thread == nullptr)
379 {
380 if (drain->stop != nullptr) CloseHandle(drain->stop);
381 d3dDevice->Release();
382 delete drain;
383 return false;
384 }
385
386 monitor->drain = drain;
387 return true;
388}
389
390NTSTATUS ReportMonitor(DeviceState* state, const ModeConfig& mode)
391{
392 WDF_OBJECT_ATTRIBUTES attributes;
393 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, MonitorState);
394 attributes.EvtCleanupCallback = MonitorCleanup;
395
396 IDDCX_MONITOR_INFO info{};
397 info.Size = sizeof(info);
398 info.MonitorType = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER;
399 info.ConnectorIndex = mode.connectorIndex;
400 info.MonitorContainerId = MonitorContainerId(mode.connectorIndex);
401 info.MonitorDescription.Size = sizeof(info.MonitorDescription);
402 info.MonitorDescription.Type = IDDCX_MONITOR_DESCRIPTION_TYPE_EDID;
403 info.MonitorDescription.DataSize = 0;
404 info.MonitorDescription.pData = nullptr;
405
406 IDARG_IN_MONITORCREATE input{};
407 input.ObjectAttributes = &attributes;
408 input.pMonitorInfo = &info;
409 IDARG_OUT_MONITORCREATE output{};
410 const NTSTATUS createStatus =
411 IddCxMonitorCreate(state->adapter, &input, &output);
412 if (!NT_SUCCESS(createStatus))
413 {
414 return createStatus;
415 }
416
417 MonitorState* monitorState = GetMonitorState(output.MonitorObject);
418 monitorState->mode = mode;
419
420 IDARG_OUT_MONITORARRIVAL arrival{};
421 const NTSTATUS arrivalStatus =
422 IddCxMonitorArrival(output.MonitorObject, &arrival);
423 if (!NT_SUCCESS(arrivalStatus))
424 {
425 WdfObjectDelete(output.MonitorObject);
426 return arrivalStatus;
427 }
428
429 return STATUS_SUCCESS;
430}
431
432NTSTATUS ReportMonitors(DeviceState* state)
433{
434 ModeConfig modes[kMaximumMonitors]{};
435 UINT count = 0;
436 if (!ReadSessionConfig(modes, count))
437 {
438 return STATUS_INVALID_PARAMETER;
439 }
440
441 for (UINT index = 0; index < count; ++index)
442 {
443 const NTSTATUS status = ReportMonitor(state, modes[index]);
444 if (!NT_SUCCESS(status))
445 {
446 return status;
447 }
448 }
449 return STATUS_SUCCESS;
450}
451
452void InitAdapter(DeviceState* state)
453{
454 if (state->adapter != nullptr)
455 {
456 return;
457 }
458
459 IDDCX_ENDPOINT_VERSION version{};
460 version.Size = sizeof(version);
461 version.MajorVer = 1;
462
463 IDDCX_ADAPTER_CAPS caps{};
464 caps.Size = sizeof(caps);
465 caps.Flags = IDDCX_ADAPTER_FLAGS_USE_SMALLEST_MODE;
466 caps.MaxMonitorsSupported = kMaximumMonitors;
467 caps.EndPointDiagnostics.Size = sizeof(caps.EndPointDiagnostics);
468 caps.EndPointDiagnostics.GammaSupport = IDDCX_FEATURE_IMPLEMENTATION_NONE;
469 caps.EndPointDiagnostics.TransmissionType = IDDCX_TRANSMISSION_TYPE_WIRED_OTHER;
470 caps.EndPointDiagnostics.pEndPointFriendlyName = L"SBMS Display";
471 caps.EndPointDiagnostics.pEndPointManufacturerName = L"SBMS";
472 caps.EndPointDiagnostics.pEndPointModelName = L"SBMS IDD";
473 caps.EndPointDiagnostics.pFirmwareVersion = &version;
474 caps.EndPointDiagnostics.pHardwareVersion = &version;
475
476 WDF_OBJECT_ATTRIBUTES attributes;
477 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DeviceState);
478
479 IDARG_IN_ADAPTER_INIT input{};
480 input.WdfDevice = state->device;
481 input.pCaps = &caps;
482 input.ObjectAttributes = &attributes;
483 IDARG_OUT_ADAPTER_INIT output{};
484 if (NT_SUCCESS(IddCxAdapterInitAsync(&input, &output)))
485 {
486 state->adapter = output.AdapterObject;
487 DeviceState* adapterState = GetDeviceState(output.AdapterObject);
488 adapterState->device = state->device;
489 adapterState->adapter = output.AdapterObject;
490 }
491}
492}
493
494extern "C" DRIVER_INITIALIZE DriverEntry;
495
496extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, void*)
497{
498 return TRUE;
499}
500
501extern "C" NTSTATUS DriverEntry(
502 PDRIVER_OBJECT driverObject,
503 PUNICODE_STRING registryPath)
504{
505 WDF_DRIVER_CONFIG config;
506 WDF_DRIVER_CONFIG_INIT(&config, DeviceAdd);
507 WDF_OBJECT_ATTRIBUTES attributes;
508 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
509 return WdfDriverCreate(
510 driverObject, registryPath, &attributes, &config, WDF_NO_HANDLE);
511}
512
513NTSTATUS DeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT deviceInit)
514{
515 UNREFERENCED_PARAMETER(driver);
516
517 WDF_PNPPOWER_EVENT_CALLBACKS power;
518 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&power);
519 power.EvtDeviceD0Entry = DeviceD0Entry;
520 WdfDeviceInitSetPnpPowerEventCallbacks(deviceInit, &power);
521
522 IDD_CX_CLIENT_CONFIG idd;
523 IDD_CX_CLIENT_CONFIG_INIT(&idd);
524 idd.EvtIddCxAdapterInitFinished = AdapterInitFinished;
525 idd.EvtIddCxAdapterCommitModes = AdapterCommitModes;
526 idd.EvtIddCxParseMonitorDescription = ParseMonitorDescription;
527 idd.EvtIddCxMonitorGetDefaultDescriptionModes = GetDefaultMonitorModes;
528 idd.EvtIddCxMonitorQueryTargetModes = QueryTargetModes;
529 idd.EvtIddCxMonitorAssignSwapChain = AssignSwapChain;
530 idd.EvtIddCxMonitorUnassignSwapChain = UnassignSwapChain;
531
532 NTSTATUS status = IddCxDeviceInitConfig(deviceInit, &idd);
533 if (!NT_SUCCESS(status))
534 {
535 return status;
536 }
537
538 WDF_OBJECT_ATTRIBUTES attributes;
539 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DeviceState);
540 WDFDEVICE device = nullptr;
541 status = WdfDeviceCreate(&deviceInit, &attributes, &device);
542 if (!NT_SUCCESS(status))
543 {
544 return status;
545 }
546
547 DeviceState* state = GetDeviceState(device);
548 state->device = device;
549 status = IddCxDeviceInitialize(device);
550 return status;
551}
552
553NTSTATUS DeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previousState)
554{
555 UNREFERENCED_PARAMETER(previousState);
556 InitAdapter(GetDeviceState(device));
557 return STATUS_SUCCESS;
558}
559
560void MonitorCleanup(WDFOBJECT object)
561{
562 StopDrain(GetMonitorState(object));
563}
564
565NTSTATUS AdapterInitFinished(
566 IDDCX_ADAPTER adapter,
567 const IDARG_IN_ADAPTER_INIT_FINISHED* input)
568{
569 if (NT_SUCCESS(input->AdapterInitStatus))
570 {
571 return ReportMonitors(GetDeviceState(adapter));
572 }
573 return input->AdapterInitStatus;
574}
575
576NTSTATUS AdapterCommitModes(
577 IDDCX_ADAPTER adapter,
578 const IDARG_IN_COMMITMODES* input)
579{
580 UNREFERENCED_PARAMETER(adapter);
581 UNREFERENCED_PARAMETER(input);
582 return STATUS_SUCCESS;
583}
584
585NTSTATUS ParseMonitorDescription(
586 const IDARG_IN_PARSEMONITORDESCRIPTION* input,
587 IDARG_OUT_PARSEMONITORDESCRIPTION* output)
588{
589 UNREFERENCED_PARAMETER(input);
590 UNREFERENCED_PARAMETER(output);
591 return STATUS_INVALID_PARAMETER;
592}
593
594NTSTATUS GetDefaultMonitorModes(
595 IDDCX_MONITOR monitor,
596 const IDARG_IN_GETDEFAULTDESCRIPTIONMODES* input,
597 IDARG_OUT_GETDEFAULTDESCRIPTIONMODES* output)
598{
599 UNREFERENCED_PARAMETER(monitor);
600 output->DefaultMonitorModeBufferOutputCount = 1;
601 if (input->DefaultMonitorModeBufferInputCount == 0)
602 {
603 return STATUS_SUCCESS;
604 }
605 if (input->DefaultMonitorModeBufferInputCount < 1)
606 {
607 return STATUS_BUFFER_TOO_SMALL;
608 }
609
610 input->pDefaultMonitorModes[0] =
611 MonitorMode(GetMonitorState(monitor)->mode, IDDCX_MONITOR_MODE_ORIGIN_DRIVER);
612 output->PreferredMonitorModeIdx = 0;
613 return STATUS_SUCCESS;
614}
615
616NTSTATUS QueryTargetModes(
617 IDDCX_MONITOR monitor,
618 const IDARG_IN_QUERYTARGETMODES* input,
619 IDARG_OUT_QUERYTARGETMODES* output)
620{
621 UNREFERENCED_PARAMETER(monitor);
622 output->TargetModeBufferOutputCount = 1;
623 if (input->TargetModeBufferInputCount >= 1)
624 {
625 input->pTargetModes[0] = TargetMode(GetMonitorState(monitor)->mode);
626 }
627 return STATUS_SUCCESS;
628}
629
630NTSTATUS AssignSwapChain(
631 IDDCX_MONITOR monitor,
632 const IDARG_IN_SETSWAPCHAIN* input)
633{
634 MonitorState* state = GetMonitorState(monitor);
635 StopDrain(state);
636 if (!StartDrain(
637 state,
638 input->hSwapChain,
639 input->RenderAdapterLuid,
640 input->hNextSurfaceAvailable))
641 {
642 WdfObjectDelete(input->hSwapChain);
643 }
644 return STATUS_SUCCESS;
645}
646
647NTSTATUS UnassignSwapChain(IDDCX_MONITOR monitor)
648{
649 StopDrain(GetMonitorState(monitor));
650 return STATUS_SUCCESS;
651}
652