diff --git a/idd/LGCommon/PipeMsg.h b/idd/LGCommon/PipeMsg.h index 043aa2ad..f650fe93 100644 --- a/idd/LGCommon/PipeMsg.h +++ b/idd/LGCommon/PipeMsg.h @@ -28,7 +28,8 @@ struct LGPipeMsg unsigned size; enum { - SETCURSORPOS + SETCURSORPOS, + SETDISPLAYMODE } type; union @@ -39,5 +40,12 @@ struct LGPipeMsg uint32_t y; } curorPos; + + struct + { + uint32_t width; + uint32_t height; + } + displayMode; }; }; \ No newline at end of file diff --git a/idd/LGIdd/CIndirectDeviceContext.cpp b/idd/LGIdd/CIndirectDeviceContext.cpp index 90b574cf..5a8a4e32 100644 --- a/idd/LGIdd/CIndirectDeviceContext.cpp +++ b/idd/LGIdd/CIndirectDeviceContext.cpp @@ -42,11 +42,58 @@ static const struct LGMPQueueConfig POINTER_QUEUE_CONFIG = 1000 //subTimeout }; +const DWORD DefaultDisplayModes[][3] = +{ + {7680, 4800, 120}, {7680, 4320, 120}, {6016, 3384, 120}, {5760, 3600, 120}, + {5760, 3240, 120}, {5120, 2800, 120}, {4096, 2560, 120}, {4096, 2304, 120}, + {3840, 2400, 120}, {3840, 2160, 120}, {3200, 2400, 120}, {3200, 1800, 120}, + {3008, 1692, 120}, {2880, 1800, 120}, {2880, 1620, 120}, {2560, 1600, 120}, + {2560, 1440, 120}, {1920, 1440, 120}, {1920, 1200, 120}, {1920, 1080, 120}, + {1600, 1200, 120}, {1600, 1024, 120}, {1600, 1050, 120}, {1600, 900 , 120}, + {1440, 900 , 120}, {1400, 1050, 120}, {1366, 768 , 120}, {1360, 768 , 120}, + {1280, 1024, 120}, {1280, 960 , 120}, {1280, 800 , 120}, {1280, 768 , 120}, + {1280, 720 , 120}, {1280, 600 , 120}, {1152, 864 , 120}, {1024, 768 , 120}, + {800 , 600 , 120}, {640 , 480 , 120} +}; + +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 +}; + +const DWORD DefaultPreferredDisplayMode = 19; + +void CIndirectDeviceContext::PopulateDefaultModes(bool setDefaultMode) +{ + m_displayModes.reserve(m_displayModes.size() + + ARRAYSIZE(DefaultDisplayModes)); + + for (int i = 0; i < ARRAYSIZE(DefaultDisplayModes); ++i) + { + DisplayMode m; + m.width = DefaultDisplayModes[i][0]; + m.height = DefaultDisplayModes[i][1]; + m.refresh = DefaultDisplayModes[i][2]; + m.preferred = setDefaultMode && (i == DefaultPreferredDisplayMode); + m_displayModes.push_back(m); + } +} + void CIndirectDeviceContext::InitAdapter() { if (!m_ivshmem.Init() || !m_ivshmem.Open()) return; + m_displayModes.clear(); + PopulateDefaultModes(true); + IDDCX_ADAPTER_CAPS caps = {}; caps.Size = sizeof(caps); @@ -114,30 +161,10 @@ void CIndirectDeviceContext::InitAdapter() } factory->Release(); - // setup some default display modes - DisplayMode m; - m.refresh = 120; - - m.width = 800 ; m.height = 600 ; m.preferred = false; m_displayModes.push_back(m); - m.width = 1024; m.height = 768 ; m.preferred = false; m_displayModes.push_back(m); - m.width = 1920; m.height = 1200; m.preferred = true ; m_displayModes.push_back(m); - 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; @@ -210,7 +237,16 @@ void CIndirectDeviceContext::ReplugMonitor() } } -void CIndirectDeviceContext::UnassignSwapChain() +void CIndirectDeviceContext::OnAssignSwapChain() +{ + if (m_setCustomMode) + { + m_setCustomMode = false; + g_pipe.SetDisplayMode(m_customMode.width, m_customMode.height); + } +} + +void CIndirectDeviceContext::OnUnassignedSwapChain() { if (m_replugMonitor) { @@ -300,6 +336,89 @@ NTSTATUS CIndirectDeviceContext::MonitorQueryTargetModes( return STATUS_SUCCESS; } +void CIndirectDeviceContext::SetResolution(int width, int height) +{ + m_displayModes.clear(); + m_customMode.width = width; + m_customMode.height = height; + m_customMode.refresh = 120; + m_customMode.preferred = true; + m_displayModes.push_back(m_customMode); + PopulateDefaultModes(false); + + m_setCustomMode = true; + +#if 1 + ReplugMonitor(); +#else + + if (IDD_IS_FUNCTION_AVAILABLE(IddCxMonitorUpdateModes2)) + { + IDDCX_TARGET_MODE2* modes = (IDDCX_TARGET_MODE2*)_malloca( + m_displayModes.size() * sizeof(IDDCX_TARGET_MODE2)); + + if (!modes) + { + DEBUG_ERROR("Failed to allocate memory for the mode list"); + return; + } + + ZeroMemory(modes, m_displayModes.size() * sizeof(IDDCX_TARGET_MODE2)); + + IDARG_IN_UPDATEMODES2 um = {}; + um.Reason = IDDCX_UPDATE_REASON_OTHER; + um.TargetModeCount = (UINT)m_displayModes.size(); + um.pTargetModes = modes; + auto* mode = modes; + for (auto it = m_displayModes.cbegin(); it != m_displayModes.cend(); ++it, ++mode) + { + mode->Size = sizeof(IDDCX_TARGET_MODE2); + mode->RequiredBandwidth = (UINT64)(it->width * it->height * it->refresh * 32); + mode->BitsPerComponent.Rgb = IDDCX_BITS_PER_COMPONENT_8; + + FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, it->width, it->height, it->refresh, true); + } + + NTSTATUS status = IddCxMonitorUpdateModes2(m_monitor, &um); + if (!NT_SUCCESS(status)) + DEBUG_ERROR("IddCxMonitorUpdateModes2 Failed (0x%08x)", status); + + _freea(modes); + } + else + { + IDDCX_TARGET_MODE* modes = (IDDCX_TARGET_MODE*)_malloca( + m_displayModes.size() * sizeof(IDDCX_TARGET_MODE)); + + if (!modes) + { + DEBUG_ERROR("Failed to allocate memory for the mode list"); + return; + } + + IDARG_IN_UPDATEMODES um = {}; + um.Reason = IDDCX_UPDATE_REASON_OTHER; + um.TargetModeCount = (UINT)m_displayModes.size(); + um.pTargetModes = modes; + + auto* mode = modes; + for (auto it = m_displayModes.cbegin(); it != m_displayModes.cend(); ++it, ++mode) + { + mode->Size = sizeof(IDDCX_TARGET_MODE); + mode->RequiredBandwidth = (UINT64)(it->width * it->height * it->refresh * 32); + + FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, it->width, it->height, it->refresh, true); + } + + NTSTATUS status = IddCxMonitorUpdateModes(m_monitor, &um); + if (!NT_SUCCESS(status)) + DEBUG_ERROR("IddCxMonitorUpdateModes Failed (0x%08x)", status); + + _freea(modes); + } +#endif +} + bool CIndirectDeviceContext::SetupLGMP(size_t alignSize) { // this may get called multiple times as we need to delay calling it until @@ -522,14 +641,7 @@ void CIndirectDeviceContext::LGMPTimer() case KVMFR_MESSAGE_WINDOWSIZE: { KVMFRWindowSize* ws = (KVMFRWindowSize*)msg; - m_displayModes.clear(); - DisplayMode m; - m.width = ws->w; - m.height = ws->h; - m.refresh = 120; - m.preferred = true; - m_displayModes.push_back(m); - ReplugMonitor(); + SetResolution(ws->w, ws->h); } } diff --git a/idd/LGIdd/CIndirectDeviceContext.h b/idd/LGIdd/CIndirectDeviceContext.h index de14bdf8..16638513 100644 --- a/idd/LGIdd/CIndirectDeviceContext.h +++ b/idd/LGIdd/CIndirectDeviceContext.h @@ -83,6 +83,8 @@ private: bool preferred; }; std::vector m_displayModes; + DisplayMode m_customMode = {}; + bool m_setCustomMode = false; public: CIndirectDeviceContext(_In_ WDFDEVICE wdfDevice) : @@ -92,10 +94,13 @@ public: bool SetupLGMP(size_t alignSize); + void PopulateDefaultModes(bool setDefaultMode); void InitAdapter(); void FinishInit(UINT connectorIndex); void ReplugMonitor(); - void UnassignSwapChain(); + + void OnAssignSwapChain(); + void OnUnassignedSwapChain(); NTSTATUS ParseMonitorDescription( const IDARG_IN_PARSEMONITORDESCRIPTION* inArgs, IDARG_OUT_PARSEMONITORDESCRIPTION* outArgs); @@ -104,6 +109,8 @@ public: NTSTATUS MonitorQueryTargetModes( const IDARG_IN_QUERYTARGETMODES* inArgs, IDARG_OUT_QUERYTARGETMODES* outArgs); + void SetResolution(int width, int height); + size_t GetAlignSize() { return m_alignSize; } size_t GetMaxFrameSize() { return m_maxFrameSize; } diff --git a/idd/LGIdd/CIndirectMonitorContext.cpp b/idd/LGIdd/CIndirectMonitorContext.cpp index b264ce73..68e48541 100644 --- a/idd/LGIdd/CIndirectMonitorContext.cpp +++ b/idd/LGIdd/CIndirectMonitorContext.cpp @@ -40,7 +40,8 @@ CIndirectMonitorContext::~CIndirectMonitorContext() void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent) { reInit: - m_swapChain.reset(); + UnassignSwapChain(); + m_dx11Device = std::make_shared(renderAdapter); if (FAILED(m_dx11Device->Init())) { diff --git a/idd/LGIdd/CPipeServer.cpp b/idd/LGIdd/CPipeServer.cpp index 05d62022..4f5b072f 100644 --- a/idd/LGIdd/CPipeServer.cpp +++ b/idd/LGIdd/CPipeServer.cpp @@ -160,4 +160,17 @@ void CPipeServer::SetCursorPos(uint32_t x, uint32_t y) msg.curorPos.x = x; msg.curorPos.y = y; WriteMsg(msg); +} + +void CPipeServer::SetDisplayMode(uint32_t width, uint32_t height) +{ + if (!m_connected) + return; + + LGPipeMsg msg; + msg.size = sizeof(msg); + msg.type = LGPipeMsg::SETDISPLAYMODE; + msg.displayMode.width = width; + msg.displayMode.height = height; + WriteMsg(msg); } \ No newline at end of file diff --git a/idd/LGIdd/CPipeServer.h b/idd/LGIdd/CPipeServer.h index 67a18d1a..6b8b87b9 100644 --- a/idd/LGIdd/CPipeServer.h +++ b/idd/LGIdd/CPipeServer.h @@ -54,6 +54,7 @@ class CPipeServer void DeInit(); void SetCursorPos(uint32_t x, uint32_t y); + void SetDisplayMode(uint32_t width, uint32_t height); }; extern CPipeServer g_pipe; \ No newline at end of file diff --git a/idd/LGIdd/Device.cpp b/idd/LGIdd/Device.cpp index c56b80b4..50808bfc 100644 --- a/idd/LGIdd/Device.cpp +++ b/idd/LGIdd/Device.cpp @@ -108,6 +108,7 @@ NTSTATUS LGIddMonitorAssignSwapChain(IDDCX_MONITOR monitor, const IDARG_IN_SETSW auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor); wrapper->context->AssignSwapChain( inArgs->hSwapChain, inArgs->RenderAdapterLuid, inArgs->hNextSurfaceAvailable); + wrapper->context->GetDeviceContext()->OnAssignSwapChain(); return STATUS_SUCCESS; } @@ -115,7 +116,7 @@ NTSTATUS LGIddMonitorUnassignSwapChain(IDDCX_MONITOR monitor) { auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor); wrapper->context->UnassignSwapChain(); - wrapper->context->GetDeviceContext()->UnassignSwapChain(); + wrapper->context->GetDeviceContext()->OnUnassignedSwapChain(); return STATUS_SUCCESS; } diff --git a/idd/LGIdd/Device.h b/idd/LGIdd/Device.h index 04ee464e..8f15783c 100644 --- a/idd/LGIdd/Device.h +++ b/idd/LGIdd/Device.h @@ -24,33 +24,6 @@ #include -#if 1 -const DWORD DisplayModes[][3] = -{ - {7680, 4800, 120}, {7680, 4320, 120}, {6016, 3384, 120}, {5760, 3600, 120}, - {5760, 3240, 120}, {5120, 2800, 120}, {4096, 2560, 120}, {4096, 2304, 120}, - {3840, 2400, 120}, {3840, 2160, 120}, {3200, 2400, 120}, {3200, 1800, 120}, - {3008, 1692, 120}, {2880, 1800, 120}, {2880, 1620, 120}, {2560, 1600, 120}, - {2560, 1440, 120}, {1920, 1440, 120}, {1920, 1200, 120}, {1920, 1080, 120}, - {1600, 1200, 120}, {1600, 1024, 120}, {1600, 1050, 120}, {1600, 900 , 120}, - {1440, 900 , 120}, {1400, 1050, 120}, {1366, 768 , 120}, {1360, 768 , 120}, - {1280, 1024, 120}, {1280, 960 , 120}, {1280, 800 , 120}, {1280, 768 , 120}, - {1280, 720 , 120}, {1280, 600 , 120}, {1152, 864 , 120}, {1024, 768 , 120}, - {800 , 600 , 120}, {640 , 480 , 120} -}; - -const DWORD PreferredDisplayMode = 19; -#else -const DWORD DisplayModes[][3] = -{ - { 2560, 1440, 144 }, - { 1920, 1080, 60 }, - { 1024, 768, 60 }, -}; - -const DWORD PreferredDisplayMode = 0; -#endif - typedef struct _DEVICE_CONTEXT { ULONG PrivateDeviceData; // just a placeholder diff --git a/idd/LGIddHelper/CPipeClient.cpp b/idd/LGIddHelper/CPipeClient.cpp index 84a1427f..58d8ec53 100644 --- a/idd/LGIddHelper/CPipeClient.cpp +++ b/idd/LGIddHelper/CPipeClient.cpp @@ -211,6 +211,10 @@ void CPipeClient::Thread() HandleSetCursorPos(msg); break; + case LGPipeMsg::SETDISPLAYMODE: + HandleSetDisplayMode(msg); + break; + default: DEBUG_ERROR("Unknown message type %d", msg.type); break; @@ -228,4 +232,17 @@ void CPipeClient::HandleSetCursorPos(const LGPipeMsg& msg) { SetActiveDesktop(); SetCursorPos(msg.curorPos.x, msg.curorPos.y); +} + +void CPipeClient::HandleSetDisplayMode(const LGPipeMsg& msg) +{ + DEVMODE dm = {}; + dm.dmSize = sizeof(dm); + dm.dmPelsWidth = msg.displayMode.width; + dm.dmPelsHeight = msg.displayMode.height; + dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + + LONG result = ChangeDisplaySettingsEx(NULL, &dm, NULL, CDS_UPDATEREGISTRY, NULL); + if (result != DISP_CHANGE_SUCCESSFUL) + DEBUG_ERROR("ChangeDisplaySettingsEx Failed (0x%08x)", result); } \ No newline at end of file diff --git a/idd/LGIddHelper/CPipeClient.h b/idd/LGIddHelper/CPipeClient.h index 8dbe9959..53140304 100644 --- a/idd/LGIddHelper/CPipeClient.h +++ b/idd/LGIddHelper/CPipeClient.h @@ -46,6 +46,7 @@ private: void SetActiveDesktop(); void HandleSetCursorPos(const LGPipeMsg& msg); + void HandleSetDisplayMode(const LGPipeMsg& msg); public: ~CPipeClient() { DeInit(); }