mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 13:37:22 +00:00
[host] updated to use new protocol design
This commit is contained in:
parent
0c90032db1
commit
818164da7f
@ -21,7 +21,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define KVMFR_HEADER_MAGIC "[[KVMFR]]"
|
#define KVMFR_HEADER_MAGIC "[[KVMFR]]"
|
||||||
#define KVMFR_HEADER_VERSION 1
|
#define KVMFR_HEADER_VERSION 2
|
||||||
|
#define KVMFR_CURSOR_BUFFER (32*32*4)
|
||||||
|
|
||||||
typedef enum FrameType
|
typedef enum FrameType
|
||||||
{
|
{
|
||||||
@ -29,20 +30,54 @@ typedef enum FrameType
|
|||||||
FRAME_TYPE_ARGB , // ABGR interleaved: A,R,G,B 32bpp
|
FRAME_TYPE_ARGB , // ABGR interleaved: A,R,G,B 32bpp
|
||||||
FRAME_TYPE_RGB , // RGB interleaved : R,G,B 24bpp
|
FRAME_TYPE_RGB , // RGB interleaved : R,G,B 24bpp
|
||||||
FRAME_TYPE_MAX , // sentinel value
|
FRAME_TYPE_MAX , // sentinel value
|
||||||
} FrameType;
|
}
|
||||||
|
FrameType;
|
||||||
|
|
||||||
struct KVMFRHeader
|
typedef enum CursorType
|
||||||
|
{
|
||||||
|
CURSOR_TYPE_COLOR ,
|
||||||
|
CURSOR_TYPE_MONOCHROME ,
|
||||||
|
CURSOR_TYPE_MASKED_COLOR
|
||||||
|
}
|
||||||
|
CursorType;
|
||||||
|
|
||||||
|
#define KVMFR_CURSOR_FLAG_VISIBLE 1 // cursor is visible
|
||||||
|
#define KVMFR_CURSOR_FLAG_SHAPE 2 // shape updated
|
||||||
|
#define KVMFR_CURSOR_FLAG_POS 4 // position updated
|
||||||
|
|
||||||
|
typedef struct KVMFRCursor
|
||||||
|
{
|
||||||
|
uint8_t flags; // KVMFR_CURSOR_FLAGS
|
||||||
|
int16_t x, y; // cursor x & y position
|
||||||
|
CursorType type; // shape buffer data type
|
||||||
|
uint8_t w, h; // shape width and height
|
||||||
|
uint8_t shape[KVMFR_CURSOR_BUFFER];
|
||||||
|
}
|
||||||
|
KVMFRCursor;
|
||||||
|
|
||||||
|
typedef struct KVMFRFrame
|
||||||
|
{
|
||||||
|
FrameType type; // the frame data type
|
||||||
|
uint32_t width; // the width
|
||||||
|
uint32_t height; // the height
|
||||||
|
uint32_t stride; // the row stride
|
||||||
|
uint64_t dataPos; // offset to the frame
|
||||||
|
}
|
||||||
|
KVMFRFrame;
|
||||||
|
|
||||||
|
#define KVMFR_HEADER_FLAG_FRAME 1 // frame update available
|
||||||
|
#define KVMFR_HEADER_FLAG_CURSOR 2 // cursor update available
|
||||||
|
|
||||||
|
typedef struct KVMFRHeader
|
||||||
{
|
{
|
||||||
char magic[sizeof(KVMFR_HEADER_MAGIC)];
|
char magic[sizeof(KVMFR_HEADER_MAGIC)];
|
||||||
uint32_t version; // version of this structure
|
uint32_t version; // version of this structure
|
||||||
uint16_t hostID; // the host ivshmem client id
|
uint16_t hostID; // the host ivshmem client id
|
||||||
uint16_t guestID; // the guest ivshmem client id
|
uint16_t guestID; // the guest ivshmem client id
|
||||||
FrameType frameType; // the frame type
|
int32_t updateCount; // updated each change
|
||||||
uint32_t width; // the width
|
uint8_t flags; // KVMFR_HEADER_FLAGS
|
||||||
uint32_t height; // the height
|
|
||||||
uint32_t stride; // the row stride
|
KVMFRFrame frame; // the frame information
|
||||||
int32_t mouseX; // the initial mouse X position
|
KVMFRCursor cursor; // the cursor information
|
||||||
int32_t mouseY; // the initial mouse Y position
|
}
|
||||||
uint64_t dataLen; // total lengh of the data after this header
|
KVMFRHeader;
|
||||||
uint64_t dataPos; // offset to the frame
|
|
||||||
};
|
|
||||||
|
@ -20,7 +20,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "DXGI.h"
|
#include "DXGI.h"
|
||||||
using namespace Capture;
|
using namespace Capture;
|
||||||
|
|
||||||
#include "Util.h"
|
|
||||||
#include "common\debug.h"
|
#include "common\debug.h"
|
||||||
#include "common\memcpySSE.h"
|
#include "common\memcpySSE.h"
|
||||||
|
|
||||||
@ -237,9 +236,73 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
CComPtr<IDXGIResource> res;
|
CComPtr<IDXGIResource> res;
|
||||||
|
|
||||||
HRESULT status;
|
HRESULT status;
|
||||||
|
bool cursorUpdate = false;
|
||||||
for(int i = 0; i < 2; ++i)
|
for(int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
{
|
{
|
||||||
status = m_dup->AcquireNextFrame(INFINITE, &frameInfo, &res);
|
status = m_dup->AcquireNextFrame(INFINITE, &frameInfo, &res);
|
||||||
|
if (!SUCCEEDED(status))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// if we have a mouse update
|
||||||
|
if (frameInfo.LastMouseUpdateTime.QuadPart)
|
||||||
|
{
|
||||||
|
cursorUpdate = true;
|
||||||
|
frame.cursor.hasPos = true;
|
||||||
|
frame.cursor.visible = frameInfo.PointerPosition.Visible;
|
||||||
|
frame.cursor.x = frameInfo.PointerPosition.Position.x;
|
||||||
|
frame.cursor.y = frameInfo.PointerPosition.Position.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the pointer shape has changed
|
||||||
|
if (frameInfo.PointerShapeBufferSize > 0)
|
||||||
|
{
|
||||||
|
cursorUpdate = true;
|
||||||
|
if (m_pointerBufSize < frameInfo.PointerShapeBufferSize)
|
||||||
|
{
|
||||||
|
if (m_pointer)
|
||||||
|
delete[] m_pointer;
|
||||||
|
m_pointer = new BYTE[frameInfo.PointerShapeBufferSize];
|
||||||
|
m_pointerBufSize = frameInfo.PointerShapeBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo;
|
||||||
|
status = m_dup->GetFramePointerShape(m_pointerBufSize, m_pointer, &m_pointerSize, &shapeInfo);
|
||||||
|
if (!SUCCEEDED(status))
|
||||||
|
{
|
||||||
|
m_dup->ReleaseFrame();
|
||||||
|
DEBUG_ERROR("Failed to get the new pointer shape: %08x", status);
|
||||||
|
return GRAB_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (shapeInfo.Type)
|
||||||
|
{
|
||||||
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR : frame.cursor.type = CURSOR_TYPE_COLOR; break;
|
||||||
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: frame.cursor.type = CURSOR_TYPE_MASKED_COLOR; break;
|
||||||
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : frame.cursor.type = CURSOR_TYPE_MONOCHROME; break;
|
||||||
|
default:
|
||||||
|
DEBUG_ERROR("Invalid cursor type");
|
||||||
|
return GRAB_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.cursor.hasShape = true;
|
||||||
|
frame.cursor.shape = m_pointer;
|
||||||
|
frame.cursor.w = shapeInfo.Width;
|
||||||
|
frame.cursor.h = shapeInfo.Height;
|
||||||
|
frame.cursor.dataSize = m_pointerSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameInfo.AccumulatedFrames == 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_dup->ReleaseFrame();
|
||||||
|
res.Release();
|
||||||
|
|
||||||
|
if (cursorUpdate)
|
||||||
|
return GRAB_STATUS_CURSOR;
|
||||||
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(status))
|
if (SUCCEEDED(status))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -298,26 +361,6 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
|
|
||||||
m_deviceContext->CopyResource(m_texture, src);
|
m_deviceContext->CopyResource(m_texture, src);
|
||||||
|
|
||||||
// if the pointer shape has changed
|
|
||||||
if (frameInfo.PointerShapeBufferSize > 0)
|
|
||||||
{
|
|
||||||
if (m_pointerBufSize < frameInfo.PointerShapeBufferSize)
|
|
||||||
{
|
|
||||||
if (m_pointer)
|
|
||||||
delete[] m_pointer;
|
|
||||||
m_pointer = new BYTE[frameInfo.PointerShapeBufferSize];
|
|
||||||
m_pointerBufSize = frameInfo.PointerShapeBufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = m_dup->GetFramePointerShape(m_pointerBufSize, m_pointer, &m_pointerSize, &m_shapeInfo);
|
|
||||||
if (!SUCCEEDED(status))
|
|
||||||
{
|
|
||||||
m_dup->ReleaseFrame();
|
|
||||||
DEBUG_ERROR("Failed to get the new pointer shape: %08x", status);
|
|
||||||
return GRAB_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dup->ReleaseFrame();
|
m_dup->ReleaseFrame();
|
||||||
res.Release();
|
res.Release();
|
||||||
src.Release();
|
src.Release();
|
||||||
@ -344,53 +387,10 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
|||||||
frame.width = desc.Width;
|
frame.width = desc.Width;
|
||||||
frame.height = desc.Height;
|
frame.height = desc.Height;
|
||||||
frame.stride = desc.Width;
|
frame.stride = desc.Width;
|
||||||
frame.outSize = min(frame.bufferSize, m_height * pitch);
|
|
||||||
|
|
||||||
// if we have a mouse update
|
memcpySSE(frame.buffer, rect.pBits, min(frame.bufferSize, m_height * pitch));
|
||||||
if (frameInfo.LastMouseUpdateTime.QuadPart)
|
|
||||||
{
|
|
||||||
m_pointerVisible = frameInfo.PointerPosition.Visible;
|
|
||||||
m_pointerPos = frameInfo.PointerPosition.Position;
|
|
||||||
|
|
||||||
frame.hasMousePos = true;
|
|
||||||
frame.mouseX = m_pointerPos.x;
|
|
||||||
frame.mouseY = m_pointerPos.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpySSE(frame.buffer, rect.pBits, frame.outSize);
|
|
||||||
status = surface->Unmap();
|
status = surface->Unmap();
|
||||||
|
|
||||||
// if the pointer is to be drawn
|
|
||||||
if (m_pointerVisible)
|
|
||||||
{
|
|
||||||
enum CursorType type;
|
|
||||||
switch (m_shapeInfo.Type)
|
|
||||||
{
|
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR : type = CURSOR_TYPE_COLOR ; break;
|
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: type = CURSOR_TYPE_MASKED_COLOR; break;
|
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : type = CURSOR_TYPE_MONOCHROME ; break;
|
|
||||||
default:
|
|
||||||
DEBUG_ERROR("Invalid cursor type");
|
|
||||||
return GRAB_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
POINT cursorPos;
|
|
||||||
POINT cursorRect;
|
|
||||||
cursorPos.x = m_pointerPos.x;
|
|
||||||
cursorPos.y = m_pointerPos.y;
|
|
||||||
cursorRect.x = m_shapeInfo.Width;
|
|
||||||
cursorRect.y = m_shapeInfo.Height;
|
|
||||||
|
|
||||||
Util::DrawCursor(
|
|
||||||
type,
|
|
||||||
m_pointer,
|
|
||||||
cursorRect,
|
|
||||||
m_shapeInfo.Pitch,
|
|
||||||
cursorPos,
|
|
||||||
frame
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to unmap surface: %08x", status);
|
DEBUG_ERROR("Failed to unmap surface: %08x", status);
|
||||||
|
@ -72,8 +72,5 @@ namespace Capture
|
|||||||
BYTE * m_pointer;
|
BYTE * m_pointer;
|
||||||
UINT m_pointerBufSize;
|
UINT m_pointerBufSize;
|
||||||
UINT m_pointerSize;
|
UINT m_pointerSize;
|
||||||
DXGI_OUTDUPL_POINTER_SHAPE_INFO m_shapeInfo;
|
|
||||||
BOOL m_pointerVisible;
|
|
||||||
POINT m_pointerPos;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
@ -287,8 +287,6 @@ enum GrabStatus NvFBC::GrabFrame(struct FrameInfo & frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
frame.stride = frame.width;
|
frame.stride = frame.width;
|
||||||
frame.outSize = frame.width * frame.height * 4;
|
|
||||||
|
|
||||||
uint8_t *src = (uint8_t *)m_frameBuffer + dataOffset;
|
uint8_t *src = (uint8_t *)m_frameBuffer + dataOffset;
|
||||||
uint8_t *dst = (uint8_t *)frame.buffer;
|
uint8_t *dst = (uint8_t *)frame.buffer;
|
||||||
for(unsigned int y = 0; y < frame.height; ++y, dst += dataWidth, src += m_grabInfo.dwBufferWidth * 4)
|
for(unsigned int y = 0; y < frame.height; ++y, dst += dataWidth, src += m_grabInfo.dwBufferWidth * 4)
|
||||||
|
@ -22,6 +22,19 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "common/KVMFR.h"
|
#include "common/KVMFR.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct CursorInfo
|
||||||
|
{
|
||||||
|
bool visible;
|
||||||
|
bool hasShape;
|
||||||
|
bool hasPos;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
enum CursorType type;
|
||||||
|
unsigned int w, h;
|
||||||
|
void * shape;
|
||||||
|
unsigned int dataSize;
|
||||||
|
};
|
||||||
|
|
||||||
struct FrameInfo
|
struct FrameInfo
|
||||||
{
|
{
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
@ -29,16 +42,15 @@ struct FrameInfo
|
|||||||
unsigned int stride;
|
unsigned int stride;
|
||||||
void * buffer;
|
void * buffer;
|
||||||
size_t bufferSize;
|
size_t bufferSize;
|
||||||
size_t outSize;
|
|
||||||
|
|
||||||
bool hasMousePos;
|
struct CursorInfo cursor;
|
||||||
int mouseX, mouseY;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GrabStatus
|
enum GrabStatus
|
||||||
{
|
{
|
||||||
GRAB_STATUS_OK,
|
GRAB_STATUS_OK,
|
||||||
GRAB_STATUS_REINIT,
|
GRAB_STATUS_REINIT,
|
||||||
|
GRAB_STATUS_CURSOR,
|
||||||
GRAB_STATUS_ERROR
|
GRAB_STATUS_ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ bool Service::Initialize(ICapture * captureDevice)
|
|||||||
m_header->version = KVMFR_HEADER_VERSION;
|
m_header->version = KVMFR_HEADER_VERSION;
|
||||||
m_header->guestID = m_ivshmem->GetPeerID();
|
m_header->guestID = m_ivshmem->GetPeerID();
|
||||||
m_header->hostID = hostID;
|
m_header->hostID = hostID;
|
||||||
m_header->frameType = m_capture->GetFrameType();
|
m_header->updateCount = 0;
|
||||||
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
return true;
|
return true;
|
||||||
@ -146,10 +146,10 @@ bool Service::Process()
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FrameInfo frame;
|
struct FrameInfo frame;
|
||||||
|
ZeroMemory(&frame, sizeof(FrameInfo));
|
||||||
frame.buffer = m_frame[m_frameIndex];
|
frame.buffer = m_frame[m_frameIndex];
|
||||||
frame.bufferSize = m_frameSize;
|
frame.bufferSize = m_frameSize;
|
||||||
frame.hasMousePos = false;
|
|
||||||
|
|
||||||
// wait for the host to notify that is it is ready to proceed
|
// wait for the host to notify that is it is ready to proceed
|
||||||
bool eventDone = false;
|
bool eventDone = false;
|
||||||
@ -180,6 +180,7 @@ bool Service::Process()
|
|||||||
ResetEvent(m_readyEvent);
|
ResetEvent(m_readyEvent);
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
bool cursorOnly = false;
|
||||||
for(int i = 0; i < 2; ++i)
|
for(int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
// capture a frame of data
|
// capture a frame of data
|
||||||
@ -189,8 +190,12 @@ bool Service::Process()
|
|||||||
ok = true;
|
ok = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GRAB_STATUS_CURSOR:
|
||||||
|
ok = true;
|
||||||
|
cursorOnly = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case GRAB_STATUS_ERROR:
|
case GRAB_STATUS_ERROR:
|
||||||
m_header->dataLen = 0;
|
|
||||||
DEBUG_ERROR("Capture failed");
|
DEBUG_ERROR("Capture failed");
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -214,30 +219,49 @@ bool Service::Process()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the frame details into the header
|
m_header->flags = 0;
|
||||||
// setup the header
|
m_header->cursor.flags = 0;
|
||||||
m_header->width = frame.width;
|
|
||||||
m_header->height = frame.height;
|
|
||||||
m_header->stride = frame.stride;
|
|
||||||
m_header->dataPos = m_dataOffset[m_frameIndex];
|
|
||||||
m_header->dataLen = frame.outSize;
|
|
||||||
|
|
||||||
// tell the host where the cursor is
|
if (!cursorOnly)
|
||||||
if (frame.hasMousePos)
|
|
||||||
{
|
{
|
||||||
m_header->mouseX = frame.mouseX;
|
// signal a frame update
|
||||||
m_header->mouseY = frame.mouseY;
|
m_header->flags |= KVMFR_HEADER_FLAG_FRAME;
|
||||||
}
|
m_header->frame.type = m_capture->GetFrameType();
|
||||||
else
|
m_header->frame.width = frame.width;
|
||||||
{
|
m_header->frame.height = frame.height;
|
||||||
POINT cursorPos;
|
m_header->frame.stride = frame.stride;
|
||||||
GetPhysicalCursorPos(&cursorPos);
|
m_header->frame.dataPos = m_dataOffset[m_frameIndex];
|
||||||
m_header->mouseX = cursorPos.x;
|
|
||||||
m_header->mouseY = cursorPos.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++m_frameIndex == 2)
|
if (++m_frameIndex == 2)
|
||||||
m_frameIndex = 0;
|
m_frameIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.cursor.hasPos)
|
||||||
|
{
|
||||||
|
// tell the host where the cursor is
|
||||||
|
m_header->flags |= KVMFR_HEADER_FLAG_CURSOR;
|
||||||
|
m_header->cursor.flags |= KVMFR_CURSOR_FLAG_POS;
|
||||||
|
m_header->cursor.x = frame.cursor.x;
|
||||||
|
m_header->cursor.y = frame.cursor.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.cursor.hasShape)
|
||||||
|
{
|
||||||
|
// give the host the new cursor shape
|
||||||
|
m_header->flags |= KVMFR_HEADER_FLAG_CURSOR;
|
||||||
|
m_header->cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
|
||||||
|
m_header->cursor.type = frame.cursor.type;
|
||||||
|
m_header->cursor.w = frame.cursor.w;
|
||||||
|
m_header->cursor.h = frame.cursor.h;
|
||||||
|
if (frame.cursor.dataSize > KVMFR_CURSOR_BUFFER)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Cursor shape size exceeds buffer size");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(m_header->cursor.shape, frame.cursor.shape, frame.cursor.dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment the update count to resume the host
|
||||||
|
++m_header->updateCount;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -25,14 +25,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "common\debug.h"
|
#include "common\debug.h"
|
||||||
|
|
||||||
enum CursorType
|
|
||||||
{
|
|
||||||
CURSOR_TYPE_COLOR,
|
|
||||||
CURSOR_TYPE_MONOCHROME,
|
|
||||||
CURSOR_TYPE_MASKED_COLOR,
|
|
||||||
CURSOR_TYPE_PACKED_MONOCHROME,
|
|
||||||
CURSOR_TYPE_PACKED_MASKED_COLOR
|
|
||||||
};
|
|
||||||
|
|
||||||
class Util
|
class Util
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user