mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[idd] implement cursor shape & position transmission
This commit is contained in:
parent
c11748a76f
commit
bbd0c7a99b
@ -374,6 +374,9 @@ void CIndirectDeviceContext::LGMPTimer()
|
||||
if (wrapper)
|
||||
wrapper->context->ResendLastFrame();
|
||||
}
|
||||
|
||||
if (lgmpHostQueueNewSubs(m_pointerQueue))
|
||||
ResendCursor();
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FORMAT format, void* data)
|
||||
@ -444,4 +447,100 @@ void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FO
|
||||
lgmpHostQueuePost(m_frameQueue, 0, m_frameMemory[m_frameIndex]);
|
||||
memcpy(fb->data, data, (size_t)height * (size_t)pitch);
|
||||
fb->wp = height * pitch;
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info, const BYTE * data)
|
||||
{
|
||||
PLGMPMemory mem;
|
||||
if (info.CursorShapeInfo.CursorType == IDDCX_CURSOR_SHAPE_TYPE_UNINITIALIZED)
|
||||
{
|
||||
mem = m_pointerMemory[m_pointerMemoryIndex];
|
||||
if (++m_pointerMemoryIndex == LGMP_Q_POINTER_LEN)
|
||||
m_pointerMemoryIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mem = m_pointerShapeMemory[m_pointerShapeIndex];
|
||||
if (++m_pointerShapeIndex == POINTER_SHAPE_BUFFERS)
|
||||
m_pointerShapeIndex = 0;
|
||||
}
|
||||
|
||||
KVMFRCursor * cursor = (KVMFRCursor *)lgmpHostMemPtr(mem);
|
||||
|
||||
m_cursorVisible = info.IsCursorVisible;
|
||||
m_cursorX = info.X;
|
||||
m_cursorY = info.Y;
|
||||
|
||||
cursor->x = (int16_t)info.X;
|
||||
cursor->y = (int16_t)info.Y;
|
||||
|
||||
uint32_t flags = CURSOR_FLAG_POSITION |
|
||||
(info.IsCursorVisible ? CURSOR_FLAG_VISIBLE : 0);
|
||||
|
||||
if (info.CursorShapeInfo.CursorType != IDDCX_CURSOR_SHAPE_TYPE_UNINITIALIZED)
|
||||
{
|
||||
memcpy(cursor + 1, data,
|
||||
(size_t)(info.CursorShapeInfo.Height * info.CursorShapeInfo.Pitch));
|
||||
|
||||
cursor->hx = (int8_t )info.CursorShapeInfo.XHot;
|
||||
cursor->hy = (int8_t )info.CursorShapeInfo.YHot;
|
||||
cursor->width = (uint32_t)info.CursorShapeInfo.Width;
|
||||
cursor->height = (uint32_t)info.CursorShapeInfo.Height;
|
||||
cursor->pitch = (uint32_t)info.CursorShapeInfo.Pitch;
|
||||
|
||||
switch (info.CursorShapeInfo.CursorType)
|
||||
{
|
||||
case IDDCX_CURSOR_SHAPE_TYPE_ALPHA:
|
||||
cursor->type = CURSOR_TYPE_COLOR;
|
||||
break;
|
||||
|
||||
case IDDCX_CURSOR_SHAPE_TYPE_MASKED_COLOR:
|
||||
cursor->type = CURSOR_TYPE_MASKED_COLOR;
|
||||
break;
|
||||
}
|
||||
|
||||
flags |= CURSOR_FLAG_SHAPE;
|
||||
m_pointerShape = mem;
|
||||
}
|
||||
|
||||
LGMP_STATUS status;
|
||||
while ((status = lgmpHostQueuePost(m_pointerQueue, flags, mem)) != LGMP_OK)
|
||||
{
|
||||
if (status == LGMP_ERR_QUEUE_FULL)
|
||||
{
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBGPRINT("lgmpHostQueuePost Failed (Pointer): %s", lgmpStatusString(status));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::ResendCursor()
|
||||
{
|
||||
PLGMPMemory mem = m_pointerShape;
|
||||
if (!mem)
|
||||
return;
|
||||
|
||||
KVMFRCursor* cursor = (KVMFRCursor*)lgmpHostMemPtr(mem);
|
||||
cursor->x = (int16_t)m_cursorX;
|
||||
cursor->y = (int16_t)m_cursorY;
|
||||
|
||||
const uint32_t flags =
|
||||
CURSOR_FLAG_POSITION | CURSOR_FLAG_SHAPE |
|
||||
(m_cursorVisible ? CURSOR_FLAG_VISIBLE : 0);
|
||||
|
||||
LGMP_STATUS status;
|
||||
while ((status = lgmpHostQueuePost(m_pointerQueue, flags, mem)) != LGMP_OK)
|
||||
{
|
||||
if (status == LGMP_ERR_QUEUE_FULL)
|
||||
{
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBGPRINT("lgmpHostQueuePost Failed (Pointer): %s", lgmpStatusString(status));
|
||||
break;
|
||||
}
|
||||
}
|
@ -21,14 +21,20 @@ private:
|
||||
IDDCX_ADAPTER m_adapter = nullptr;
|
||||
IDDCX_MONITOR m_monitor = nullptr;
|
||||
|
||||
CIVSHMEM m_ivshmem;
|
||||
CIVSHMEM m_ivshmem;
|
||||
|
||||
PLGMPHost m_lgmp = nullptr;
|
||||
PLGMPHostQueue m_frameQueue = nullptr;
|
||||
PLGMPHost m_lgmp = nullptr;
|
||||
WDFTIMER m_lgmpTimer = nullptr;
|
||||
PLGMPHostQueue m_frameQueue = nullptr;
|
||||
|
||||
PLGMPHostQueue m_pointerQueue = nullptr;
|
||||
PLGMPMemory m_pointerMemory [LGMP_Q_POINTER_LEN ] = {};
|
||||
PLGMPMemory m_pointerShapeMemory[POINTER_SHAPE_BUFFERS] = {};
|
||||
PLGMPMemory m_pointerShape = nullptr;
|
||||
int m_pointerMemoryIndex = 0;
|
||||
int m_pointerShapeIndex = 0;
|
||||
bool m_cursorVisible = false;
|
||||
int m_cursorX = 0, m_cursorY = 0;
|
||||
|
||||
size_t m_maxFrameSize = 0;
|
||||
int m_frameIndex = 0;
|
||||
@ -42,10 +48,8 @@ private:
|
||||
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
bool SetupLGMP();
|
||||
|
||||
void LGMPTimer();
|
||||
|
||||
WDFTIMER m_lgmpTimer = nullptr;
|
||||
void ResendCursor();
|
||||
|
||||
public:
|
||||
CIndirectDeviceContext(_In_ WDFDEVICE wdfDevice) :
|
||||
@ -58,6 +62,7 @@ public:
|
||||
void FinishInit(UINT connectorIndex);
|
||||
|
||||
void SendFrame(int width, int height, int pitch, DXGI_FORMAT format, void* data);
|
||||
void SendCursor(const IDARG_OUT_QUERY_HWCURSOR & info, const BYTE * data);
|
||||
};
|
||||
|
||||
struct CIndirectDeviceContextWrapper
|
||||
|
@ -1,20 +1,27 @@
|
||||
#include "CIndirectMonitorContext.h"
|
||||
#include "Direct3DDevice.h"
|
||||
#include "Debug.h"
|
||||
|
||||
CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device) :
|
||||
m_monitor(monitor),
|
||||
m_devContext(device)
|
||||
{
|
||||
m_terminateEvent .Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||
m_cursorDataEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||
m_thread.Attach(CreateThread(nullptr, 0, _CursorThread, this, 0, nullptr));
|
||||
m_shapeBuffer = new BYTE[512 * 512 * 4];
|
||||
}
|
||||
|
||||
CIndirectMonitorContext::~CIndirectMonitorContext()
|
||||
{
|
||||
m_thread.reset();
|
||||
m_swapChain.reset();
|
||||
SetEvent(m_terminateEvent.Get());
|
||||
delete[] m_shapeBuffer;
|
||||
}
|
||||
|
||||
void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent)
|
||||
{
|
||||
m_thread.reset();
|
||||
m_swapChain.reset();
|
||||
auto device = std::make_shared<Direct3DDevice>(renderAdapter);
|
||||
if (FAILED(device->Init()))
|
||||
{
|
||||
@ -22,10 +29,67 @@ void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID re
|
||||
return;
|
||||
}
|
||||
|
||||
m_thread.reset(new CSwapChainProcessor(m_devContext, swapChain, device, newFrameEvent));
|
||||
m_swapChain.reset(new CSwapChainProcessor(m_devContext, swapChain, device, newFrameEvent));
|
||||
|
||||
IDARG_IN_SETUP_HWCURSOR c = {};
|
||||
c.CursorInfo.Size = sizeof(c.CursorInfo);
|
||||
c.CursorInfo.AlphaCursorSupport = TRUE;
|
||||
c.CursorInfo.ColorXorCursorSupport = IDDCX_XOR_CURSOR_SUPPORT_FULL;
|
||||
c.CursorInfo.MaxX = 512;
|
||||
c.CursorInfo.MaxY = 512;
|
||||
c.hNewCursorDataAvailable = m_cursorDataEvent.Get();
|
||||
NTSTATUS status = IddCxMonitorSetupHardwareCursor(m_monitor, &c);
|
||||
if (!NT_SUCCESS(status))
|
||||
DBGPRINT("IddCxMonitorSetupHardwareCursor Failed: %08x", status);
|
||||
}
|
||||
|
||||
void CIndirectMonitorContext::UnassignSwapChain()
|
||||
{
|
||||
m_thread.reset();
|
||||
m_swapChain.reset();
|
||||
}
|
||||
|
||||
DWORD CALLBACK CIndirectMonitorContext::_CursorThread(LPVOID arg)
|
||||
{
|
||||
reinterpret_cast<CIndirectMonitorContext*>(arg)->CursorThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CIndirectMonitorContext::CursorThread()
|
||||
{
|
||||
HRESULT hr = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
HANDLE waitHandles[] =
|
||||
{
|
||||
m_cursorDataEvent.Get(),
|
||||
m_terminateEvent.Get()
|
||||
};
|
||||
DWORD waitResult = WaitForMultipleObjects(ARRAYSIZE(waitHandles), waitHandles, FALSE, 100);
|
||||
if (waitResult == WAIT_TIMEOUT)
|
||||
continue;
|
||||
else if (waitResult == WAIT_OBJECT_0 + 1)
|
||||
break;
|
||||
else if (waitResult != WAIT_OBJECT_0)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(waitResult);
|
||||
DBGPRINT("WaitForMultipleObjects: %08", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
IDARG_IN_QUERY_HWCURSOR in = {};
|
||||
in.LastShapeId = m_lastShapeId;
|
||||
in.pShapeBuffer = m_shapeBuffer;
|
||||
in.ShapeBufferSizeInBytes = 512 * 512 * 4;
|
||||
|
||||
IDARG_OUT_QUERY_HWCURSOR out = {};
|
||||
NTSTATUS status = IddCxMonitorQueryHardwareCursor(m_monitor, &in, &out);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DBGPRINT("IddCxMonitorQueryHardwareCursor failed: %08x", status);
|
||||
return;
|
||||
}
|
||||
|
||||
m_devContext->SendCursor(out, m_shapeBuffer);
|
||||
}
|
||||
}
|
@ -8,12 +8,24 @@
|
||||
#include "CIndirectDeviceContext.h"
|
||||
#include "CSwapChainProcessor.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
class CIndirectMonitorContext
|
||||
{
|
||||
protected:
|
||||
private:
|
||||
IDDCX_MONITOR m_monitor;
|
||||
CIndirectDeviceContext * m_devContext;
|
||||
std::unique_ptr<CSwapChainProcessor> m_thread;
|
||||
std::unique_ptr<CSwapChainProcessor> m_swapChain;
|
||||
|
||||
Wrappers::Event m_terminateEvent;
|
||||
Wrappers::Event m_cursorDataEvent;
|
||||
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread;
|
||||
BYTE * m_shapeBuffer;
|
||||
|
||||
DWORD m_lastShapeId = 0;
|
||||
|
||||
static DWORD CALLBACK _CursorThread(LPVOID arg);
|
||||
void CursorThread();
|
||||
|
||||
public:
|
||||
CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device);
|
||||
@ -25,8 +37,8 @@ public:
|
||||
|
||||
inline void ResendLastFrame()
|
||||
{
|
||||
if (m_thread)
|
||||
m_thread->ResendLastFrame();
|
||||
if (m_swapChain)
|
||||
m_swapChain->ResendLastFrame();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user