mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-12 17:38:19 +00:00
117 lines
4.2 KiB
C++
117 lines
4.2 KiB
C++
#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<BYTE*>(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);
|
|
} |