mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-04-24 23:56:26 +00:00
[idd] driver: improve display mode support and resolution switch
This commit is contained in:
parent
6396ff1e9c
commit
7afb9b93eb
@ -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;
|
||||
};
|
||||
};
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,8 @@ private:
|
||||
bool preferred;
|
||||
};
|
||||
std::vector<DisplayMode> 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; }
|
||||
|
||||
|
@ -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<CD3D11Device>(renderAdapter);
|
||||
if (FAILED(m_dx11Device->Init()))
|
||||
{
|
||||
|
@ -161,3 +161,16 @@ void CPipeServer::SetCursorPos(uint32_t x, uint32_t y)
|
||||
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);
|
||||
}
|
@ -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;
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -24,33 +24,6 @@
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#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
|
||||
|
@ -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;
|
||||
@ -229,3 +233,16 @@ 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);
|
||||
}
|
@ -46,6 +46,7 @@ private:
|
||||
void SetActiveDesktop();
|
||||
|
||||
void HandleSetCursorPos(const LGPipeMsg& msg);
|
||||
void HandleSetDisplayMode(const LGPipeMsg& msg);
|
||||
|
||||
public:
|
||||
~CPipeClient() { DeInit(); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user