#include "CIndirectDeviceContext.h" #include "CIndirectMonitorContext.h" void CIndirectDeviceContext::InitAdapter() { IDDCX_ADAPTER_CAPS caps = {}; caps.Size = sizeof(caps); caps.MaxMonitorsSupported = 1; caps.EndPointDiagnostics.Size = sizeof(caps.EndPointDiagnostics); caps.EndPointDiagnostics.GammaSupport = IDDCX_FEATURE_IMPLEMENTATION_NONE; caps.EndPointDiagnostics.TransmissionType = IDDCX_TRANSMISSION_TYPE_OTHER; caps.EndPointDiagnostics.pEndPointFriendlyName = L"Looking Glass IDD Device"; caps.EndPointDiagnostics.pEndPointManufacturerName = L"Looking Glass"; caps.EndPointDiagnostics.pEndPointModelName = L"Looking Glass"; IDDCX_ENDPOINT_VERSION ver = {}; ver.Size = sizeof(ver); ver.MajorVer = 1; caps.EndPointDiagnostics.pFirmwareVersion = &ver; caps.EndPointDiagnostics.pHardwareVersion = &ver; WDF_OBJECT_ATTRIBUTES attr; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, CIndirectDeviceContextWrapper); IDARG_IN_ADAPTER_INIT init = {}; init.WdfDevice = m_wdfDevice; init.pCaps = ∩︀ init.ObjectAttributes = &attr; IDARG_OUT_ADAPTER_INIT initOut; NTSTATUS status = IddCxAdapterInitAsync(&init, &initOut); if (!NT_SUCCESS(status)) return; m_adapter = initOut.AdapterObject; // try to co-exist with the virtual video device by telling IddCx which adapter we prefer to render on IDXGIFactory * factory = NULL; IDXGIAdapter * dxgiAdapter; CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)&factory); for (UINT i = 0; factory->EnumAdapters(i, &dxgiAdapter) != DXGI_ERROR_NOT_FOUND; ++i) { DXGI_ADAPTER_DESC adapterDesc; dxgiAdapter->GetDesc(&adapterDesc); dxgiAdapter->Release(); if ((adapterDesc.VendorId == 0x1414 && adapterDesc.DeviceId == 0x008c) || // Microsoft Basic Render Driver (adapterDesc.VendorId == 0x1b36 && adapterDesc.DeviceId == 0x000d) || // QXL (adapterDesc.VendorId == 0x1234 && adapterDesc.DeviceId == 0x1111)) // QEMU Standard VGA continue; IDARG_IN_ADAPTERSETRENDERADAPTER args = {}; args.PreferredRenderAdapter = adapterDesc.AdapterLuid; IddCxAdapterSetRenderAdapter(m_adapter, &args); break; } factory->Release(); auto * wrapper = WdfObjectGet_CIndirectDeviceContextWrapper(m_adapter); wrapper->context = this; } static const BYTE EDID[] = { 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x30,0xE8,0x34,0x12,0xC9,0x07,0xCC,0x00, 0x01,0x21,0x01,0x04,0xA5,0x3C,0x22,0x78,0xFB,0x6C,0xE5,0xA5,0x55,0x50,0xA0,0x23, 0x0B,0x50,0x54,0x00,0x02,0x00,0xD1,0xC0,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x58,0xE3,0x00,0xA0,0xA0,0xA0,0x29,0x50,0x30,0x20, 0x35,0x00,0x55,0x50,0x21,0x00,0x00,0x1A,0x00,0x00,0x00,0xFF,0x00,0x4C,0x6F,0x6F, 0x6B,0x69,0x6E,0x67,0x47,0x6C,0x61,0x73,0x73,0x0A,0x00,0x00,0x00,0xFC,0x00,0x4C, 0x6F,0x6F,0x6B,0x69,0x6E,0x67,0x20,0x47,0x6C,0x61,0x73,0x73,0x00,0x00,0x00,0xFD, 0x00,0x28,0x9B,0xFA,0xFA,0x40,0x01,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x4A }; void CIndirectDeviceContext::FinishInit(UINT connectorIndex) { WDF_OBJECT_ATTRIBUTES attr; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, CIndirectMonitorContextWrapper); IDDCX_MONITOR_INFO info = {}; info.Size = sizeof(info); info.MonitorType = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI; info.ConnectorIndex = connectorIndex; info.MonitorDescription.Size = sizeof(info.MonitorDescription); info.MonitorDescription.Type = IDDCX_MONITOR_DESCRIPTION_TYPE_EDID; if (connectorIndex >= 1) { info.MonitorDescription.DataSize = 0; info.MonitorDescription.pData = nullptr; } else { info.MonitorDescription.DataSize = sizeof(EDID); info.MonitorDescription.pData = const_cast(EDID); } CoCreateGuid(&info.MonitorContainerId); IDARG_IN_MONITORCREATE create = {}; create.ObjectAttributes = &attr; create.pMonitorInfo = &info; IDARG_OUT_MONITORCREATE createOut; NTSTATUS status = IddCxMonitorCreate(m_adapter, &create, &createOut); if (!NT_SUCCESS(status)) return; auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(createOut.MonitorObject); wrapper->context = new CIndirectMonitorContext(createOut.MonitorObject); IDARG_OUT_MONITORARRIVAL out; status = IddCxMonitorArrival(createOut.MonitorObject, &out); }