mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-11-17 15:38:45 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3784e9c06f | ||
|
|
24709ef186 | ||
|
|
db59e67ddb | ||
|
|
1815387bbb | ||
|
|
6595374a2c | ||
|
|
9d8f3a79b0 | ||
|
|
bf85358715 | ||
|
|
b77a34b8b6 | ||
|
|
287b983d27 |
@@ -155,7 +155,7 @@ int renderThread(void * unused)
|
||||
struct KVMFRHeader header;
|
||||
|
||||
LG_RendererCursor cursorType = LG_CURSOR_COLOR;
|
||||
struct KVMFRCursor cursor = {};
|
||||
struct KVMFRFrame cursor = {};
|
||||
size_t cursorDataSize = 0;
|
||||
uint8_t * cursorData = NULL;
|
||||
|
||||
@@ -203,12 +203,14 @@ int renderThread(void * unused)
|
||||
{
|
||||
// sainty check of the frame format
|
||||
if (
|
||||
header.frame.type >= FRAME_TYPE_MAX ||
|
||||
header.frame.width == 0 ||
|
||||
header.frame.height == 0 ||
|
||||
header.frame.stride == 0 ||
|
||||
header.frame.dataPos == 0 ||
|
||||
header.frame.dataPos > state.shmSize
|
||||
header.detail.frame.type >= FRAME_TYPE_MAX ||
|
||||
header.detail.frame.width == 0 ||
|
||||
header.detail.frame.height == 0 ||
|
||||
header.detail.frame.stride == 0 ||
|
||||
header.detail.frame.pitch == 0 ||
|
||||
header.detail.frame.dataPos == 0 ||
|
||||
header.detail.frame.dataPos > state.shmSize ||
|
||||
header.detail.frame.pitch < header.detail.frame.width
|
||||
){
|
||||
usleep(1000);
|
||||
continue;
|
||||
@@ -216,19 +218,18 @@ int renderThread(void * unused)
|
||||
|
||||
// setup the renderer format with the frame format details
|
||||
LG_RendererFormat lgrFormat;
|
||||
lgrFormat.width = header.frame.width;
|
||||
lgrFormat.height = header.frame.height;
|
||||
lgrFormat.stride = header.frame.stride;
|
||||
lgrFormat.width = header.detail.frame.width;
|
||||
lgrFormat.height = header.detail.frame.height;
|
||||
lgrFormat.stride = header.detail.frame.stride;
|
||||
lgrFormat.pitch = header.detail.frame.pitch;
|
||||
|
||||
switch(header.frame.type)
|
||||
switch(header.detail.frame.type)
|
||||
{
|
||||
case FRAME_TYPE_ARGB:
|
||||
lgrFormat.pitch = header.frame.stride * 4;
|
||||
lgrFormat.bpp = 32;
|
||||
break;
|
||||
|
||||
case FRAME_TYPE_RGB:
|
||||
lgrFormat.pitch = header.frame.stride * 3;
|
||||
lgrFormat.bpp = 24;
|
||||
break;
|
||||
|
||||
@@ -243,7 +244,7 @@ int renderThread(void * unused)
|
||||
|
||||
// check the header's dataPos is sane
|
||||
const size_t dataSize = lgrFormat.height * lgrFormat.pitch;
|
||||
if (header.frame.dataPos + dataSize > state.shmSize)
|
||||
if (header.detail.frame.dataPos + dataSize > state.shmSize)
|
||||
{
|
||||
DEBUG_ERROR("The guest sent an invalid dataPos");
|
||||
break;
|
||||
@@ -262,10 +263,10 @@ int renderThread(void * unused)
|
||||
break;
|
||||
}
|
||||
|
||||
state.srcSize.x = header.frame.width;
|
||||
state.srcSize.y = header.frame.height;
|
||||
state.srcSize.x = header.detail.frame.width;
|
||||
state.srcSize.y = header.detail.frame.height;
|
||||
if (params.autoResize)
|
||||
SDL_SetWindowSize(state.window, header.frame.width, header.frame.height);
|
||||
SDL_SetWindowSize(state.window, header.detail.frame.width, header.detail.frame.height);
|
||||
|
||||
state.started = true;
|
||||
updatePositionInfo();
|
||||
@@ -273,8 +274,14 @@ int renderThread(void * unused)
|
||||
// if we have saved shape info, send it now
|
||||
if (cursorData)
|
||||
{
|
||||
if (!state.lgr->on_mouse_shape(state.lgrData, cursorType, cursor.w,
|
||||
cursor.h, cursor.pitch, cursorData))
|
||||
if (!state.lgr->on_mouse_shape(
|
||||
state.lgrData,
|
||||
cursorType,
|
||||
cursor.width,
|
||||
cursor.height,
|
||||
cursor.pitch,
|
||||
cursorData
|
||||
))
|
||||
{
|
||||
DEBUG_ERROR("Failed to update mouse shape");
|
||||
break;
|
||||
@@ -288,7 +295,8 @@ int renderThread(void * unused)
|
||||
// if we have a cursor position, send it now
|
||||
if (state.haveCursorPos)
|
||||
{
|
||||
state.lgr->on_mouse_event(
|
||||
state.lgr->on_mouse_event
|
||||
(
|
||||
state.lgrData,
|
||||
state.cursorVisible,
|
||||
state.cursor.x,
|
||||
@@ -297,7 +305,7 @@ int renderThread(void * unused)
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t * data = (const uint8_t *)state.shm + header.frame.dataPos;
|
||||
const uint8_t * data = (const uint8_t *)state.shm + header.detail.frame.dataPos;
|
||||
if (!state.lgr->on_frame_event(state.lgrData, data))
|
||||
{
|
||||
DEBUG_ERROR("Failed to render the frame");
|
||||
@@ -308,20 +316,20 @@ int renderThread(void * unused)
|
||||
// if we have cursor data
|
||||
if (header.flags & KVMFR_HEADER_FLAG_CURSOR)
|
||||
{
|
||||
if (header.cursor.flags & KVMFR_CURSOR_FLAG_POS)
|
||||
if (header.detail.cursor.flags & KVMFR_CURSOR_FLAG_POS)
|
||||
{
|
||||
state.cursor.x = header.cursor.x;
|
||||
state.cursor.y = header.cursor.y;
|
||||
state.cursorVisible = header.cursor.flags & KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
state.cursor.x = header.detail.cursor.x;
|
||||
state.cursor.y = header.detail.cursor.y;
|
||||
state.cursorVisible = header.detail.cursor.flags & KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
state.haveCursorPos = true;
|
||||
}
|
||||
|
||||
if (header.cursor.flags & KVMFR_CURSOR_FLAG_SHAPE)
|
||||
if (header.detail.cursor.flags & KVMFR_CURSOR_FLAG_SHAPE)
|
||||
{
|
||||
if (state.lgr)
|
||||
{
|
||||
bool bad = false;
|
||||
switch(header.cursor.type)
|
||||
switch(header.detail.cursor.type)
|
||||
{
|
||||
case CURSOR_TYPE_COLOR : cursorType = LG_CURSOR_COLOR ; break;
|
||||
case CURSOR_TYPE_MONOCHROME : cursorType = LG_CURSOR_MONOCHROME ; break;
|
||||
@@ -336,14 +344,14 @@ int renderThread(void * unused)
|
||||
break;
|
||||
|
||||
// check the data position is sane
|
||||
const uint64_t dataSize = header.cursor.h * header.cursor.pitch;
|
||||
if (header.cursor.dataPos + dataSize > state.shmSize)
|
||||
const uint64_t dataSize = header.detail.frame.height * header.detail.frame.pitch;
|
||||
if (header.detail.frame.dataPos + dataSize > state.shmSize)
|
||||
{
|
||||
DEBUG_ERROR("The guest sent an invalid mouse dataPos");
|
||||
break;
|
||||
}
|
||||
|
||||
const uint8_t * data = (const uint8_t *)state.shm + header.cursor.dataPos;
|
||||
const uint8_t * data = (const uint8_t *)state.shm + header.detail.frame.dataPos;
|
||||
if (!state.started)
|
||||
{
|
||||
// save off the cursor data so we can tell the renderer when it's ready
|
||||
@@ -353,13 +361,19 @@ int renderThread(void * unused)
|
||||
cursorData = (uint8_t *)malloc(dataSize);
|
||||
cursorDataSize = dataSize;
|
||||
}
|
||||
memcpy(&cursor, &header.cursor, sizeof(struct KVMFRCursor));
|
||||
memcpy(&cursor, &header.detail.frame, sizeof(struct KVMFRFrame));
|
||||
memcpy(cursorData, data, dataSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!state.lgr->on_mouse_shape(state.lgrData, cursorType, header.cursor.w,
|
||||
header.cursor.h, header.cursor.pitch, data))
|
||||
if (!state.lgr->on_mouse_shape(
|
||||
state.lgrData,
|
||||
cursorType,
|
||||
header.detail.frame.width,
|
||||
header.detail.frame.height,
|
||||
header.detail.frame.pitch,
|
||||
data)
|
||||
)
|
||||
{
|
||||
DEBUG_ERROR("Failed to update mouse shape");
|
||||
break;
|
||||
@@ -805,8 +819,7 @@ int run()
|
||||
DEBUG_ERROR("Failed to map memory");
|
||||
break;
|
||||
}
|
||||
state.shmSize = ivshmem_get_map_size();
|
||||
state.shm->hostID = ivshmem_get_id();
|
||||
state.shmSize = ivshmem_get_map_size();
|
||||
|
||||
if (params.useSpice)
|
||||
{
|
||||
|
||||
@@ -69,7 +69,6 @@ struct LGR_OpenGL
|
||||
int fpsList;
|
||||
int mouseList;
|
||||
LG_RendererRect destRect;
|
||||
bool mipmap;
|
||||
|
||||
bool hasTextures;
|
||||
GLuint textures[TEXTURE_COUNT];
|
||||
@@ -365,7 +364,7 @@ void lgr_opengl_on_resize(void * opaque, const int width, const int height, cons
|
||||
if (!this || !this->configured)
|
||||
return;
|
||||
|
||||
this->window.x = width;
|
||||
this->window.x = width;
|
||||
this->window.y = height;
|
||||
memcpy(&this->destRect, &destRect, sizeof(LG_RendererRect));
|
||||
|
||||
@@ -634,15 +633,17 @@ bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data)
|
||||
(this->format.width > this->destRect.w) ||
|
||||
(this->format.height > this->destRect.h));
|
||||
|
||||
if (this->mipmap != mipmap)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
|
||||
this->mipmap = mipmap;
|
||||
}
|
||||
|
||||
if (mipmap)
|
||||
{
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <stdint.h>
|
||||
|
||||
#define KVMFR_HEADER_MAGIC "[[KVMFR]]"
|
||||
#define KVMFR_HEADER_VERSION 3
|
||||
#define KVMFR_HEADER_VERSION 4
|
||||
|
||||
typedef enum FrameType
|
||||
{
|
||||
@@ -49,9 +49,6 @@ 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 pitch; // shape row length in bytes
|
||||
uint64_t dataPos; // offset to the cursor data
|
||||
}
|
||||
KVMFRCursor;
|
||||
|
||||
@@ -60,7 +57,8 @@ 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
|
||||
uint32_t stride; // the row stride (zero if cursor data)
|
||||
uint32_t pitch; // the row pitch (stride in bytes)
|
||||
uint64_t dataPos; // offset to the frame
|
||||
}
|
||||
KVMFRFrame;
|
||||
@@ -70,16 +68,19 @@ KVMFRFrame;
|
||||
#define KVMFR_HEADER_FLAG_RESTART 4 // restart signal from client
|
||||
#define KVMFR_HEADER_FLAG_READY 8 // ready signal from client
|
||||
|
||||
typedef struct KVMFRDetail
|
||||
{
|
||||
KVMFRFrame frame; // the frame information
|
||||
KVMFRCursor cursor; // the cursor information
|
||||
}
|
||||
KVMFRDetail;
|
||||
|
||||
typedef struct KVMFRHeader
|
||||
{
|
||||
char magic[sizeof(KVMFR_HEADER_MAGIC)];
|
||||
uint32_t version; // version of this structure
|
||||
uint16_t hostID; // the host ivshmem client id
|
||||
uint16_t guestID; // the guest ivshmem client id
|
||||
uint32_t updateCount; // updated each change
|
||||
uint8_t flags; // KVMFR_HEADER_FLAGS
|
||||
|
||||
KVMFRFrame frame; // the frame information
|
||||
KVMFRCursor cursor; // the cursor information
|
||||
KVMFRDetail detail; // details
|
||||
}
|
||||
KVMFRHeader;
|
||||
KVMFRHeader;
|
||||
|
||||
@@ -260,6 +260,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
||||
// send the last frame again if we timeout to prevent the client stalling on restart
|
||||
frame.width = m_desc.Width;
|
||||
frame.height = m_desc.Height;
|
||||
frame.pitch = m_rect.Pitch;
|
||||
frame.stride = m_rect.Pitch / 4;
|
||||
|
||||
unsigned int size = m_height * m_rect.Pitch;
|
||||
@@ -346,32 +347,34 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
||||
if (SUCCEEDED(status))
|
||||
break;
|
||||
|
||||
HDESK desktop = NULL;
|
||||
switch (status)
|
||||
{
|
||||
case DXGI_ERROR_ACCESS_LOST: // desktop switch, mode change or switch DWM on or off
|
||||
return GRAB_STATUS_REINIT;
|
||||
// desktop switch, mode change, switch DWM on or off or Secure Desktop
|
||||
case DXGI_ERROR_ACCESS_LOST:
|
||||
// see if we can open the desktop, if so request a reinit
|
||||
// if not the secure desktop is active so just wait for it
|
||||
// instead of aborting out
|
||||
desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
|
||||
if (desktop)
|
||||
{
|
||||
// open suceeded, not on the secure desktop, return to reinit
|
||||
CloseDesktop(desktop);
|
||||
return GRAB_STATUS_REINIT;
|
||||
}
|
||||
// fall through
|
||||
|
||||
case WAIT_ABANDONED: // this can happen also during desktop switches, not documented by MS though
|
||||
{
|
||||
// see if we can open the desktop, if not the secure desktop
|
||||
// is active so just wait for it instead of aborting out
|
||||
HDESK desktop = NULL;
|
||||
while(!desktop)
|
||||
// this can happen during desktop switches also, not documented by MS though
|
||||
case WAIT_ABANDONED:
|
||||
do
|
||||
{
|
||||
desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
|
||||
if (desktop)
|
||||
break;
|
||||
Sleep(100);
|
||||
}
|
||||
} while (!desktop);
|
||||
CloseDesktop(desktop);
|
||||
|
||||
if (!ReInitialize())
|
||||
{
|
||||
DEBUG_ERROR("Failed to ReInitialize after lost access to desktop");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return GRAB_STATUS_REINIT;
|
||||
|
||||
default:
|
||||
// unknown failure
|
||||
@@ -436,6 +439,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
||||
|
||||
frame.width = m_desc.Width;
|
||||
frame.height = m_desc.Height;
|
||||
frame.pitch = m_rect.Pitch;
|
||||
frame.stride = m_rect.Pitch / 4;
|
||||
|
||||
unsigned int size = m_height * m_rect.Pitch;
|
||||
|
||||
@@ -61,10 +61,11 @@ bool NvFBC::Initialize(CaptureOptions * options)
|
||||
if (_strcmpi(*it, "nowait") == 0) { m_optNoWait = true ; continue; }
|
||||
}
|
||||
|
||||
m_hDLL = LoadLibraryA(NVFBC_LIBRARY_NAME);
|
||||
std::string nvfbc = Util::GetSystemRoot() + "\\" + NVFBC_LIBRARY_NAME;
|
||||
m_hDLL = LoadLibraryA(nvfbc.c_str());
|
||||
if (!m_hDLL)
|
||||
{
|
||||
DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", GetLastError(), NVFBC_LIBRARY_NAME);
|
||||
DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", GetLastError(), nvfbc.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -75,7 +76,7 @@ bool NvFBC::Initialize(CaptureOptions * options)
|
||||
|
||||
if (!m_fnCreateEx || !m_fnSetGlobalFlags || !m_fnGetStatusEx || !m_fnEnable)
|
||||
{
|
||||
DEBUG_ERROR("Unable to locate required entry points in %s", NVFBC_LIBRARY_NAME);
|
||||
DEBUG_ERROR("Unable to locate required entry points in %s", nvfbc.c_str());
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
@@ -288,6 +289,7 @@ enum GrabStatus NvFBC::GrabFrame(struct FrameInfo & frame)
|
||||
}
|
||||
|
||||
frame.stride = frame.width;
|
||||
frame.pitch = dataWidth;
|
||||
uint8_t *src = (uint8_t *)m_frameBuffer + dataOffset;
|
||||
uint8_t *dst = (uint8_t *)frame.buffer;
|
||||
for(unsigned int y = 0; y < frame.height; ++y, dst += dataWidth, src += m_grabInfo.dwBufferWidth * 4)
|
||||
|
||||
@@ -42,6 +42,7 @@ struct FrameInfo
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int stride;
|
||||
unsigned int pitch;
|
||||
void * buffer;
|
||||
size_t bufferSize;
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ Service::Service() :
|
||||
m_cursorData(NULL),
|
||||
m_shapePending(false)
|
||||
{
|
||||
m_consoleSessionID = WTSGetActiveConsoleSessionId();
|
||||
m_ivshmem = IVSHMEM::Get();
|
||||
}
|
||||
|
||||
@@ -94,13 +95,11 @@ bool Service::Initialize(ICapture * captureDevice)
|
||||
// update everything except for the hostID
|
||||
memcpy(m_shmHeader->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC));
|
||||
m_shmHeader->version = KVMFR_HEADER_VERSION;
|
||||
m_shmHeader->guestID = m_ivshmem->GetPeerID();
|
||||
m_shmHeader->updateCount = 0;
|
||||
|
||||
// clear but retain the restart flag if it was set by the client
|
||||
INTERLOCKED_AND8((char *)&m_shmHeader->flags, KVMFR_HEADER_FLAG_RESTART);
|
||||
ZeroMemory(&m_shmHeader->frame , sizeof(KVMFRFrame ));
|
||||
ZeroMemory(&m_shmHeader->cursor, sizeof(KVMFRCursor));
|
||||
ZeroMemory(&m_shmHeader->detail, sizeof(KVMFRDetail));
|
||||
|
||||
m_initialized = true;
|
||||
return true;
|
||||
@@ -233,6 +232,13 @@ bool Service::Process()
|
||||
|
||||
case GRAB_STATUS_REINIT:
|
||||
DEBUG_INFO("ReInitialize Requested");
|
||||
if(WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
||||
{
|
||||
DEBUG_INFO("User switch detected, waiting to regain control");
|
||||
while (WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
if (!m_capture->ReInitialize() || !InitPointers())
|
||||
{
|
||||
DEBUG_ERROR("ReInitialize Failed");
|
||||
@@ -252,17 +258,18 @@ bool Service::Process()
|
||||
}
|
||||
|
||||
uint8_t updateFlags = 0;
|
||||
m_header.cursor.flags = 0;
|
||||
m_detail.cursor.flags = 0;
|
||||
|
||||
if (!cursorOnly)
|
||||
{
|
||||
// signal a frame update
|
||||
updateFlags |= KVMFR_HEADER_FLAG_FRAME;
|
||||
m_header.frame.type = m_capture->GetFrameType();
|
||||
m_header.frame.width = frame.width;
|
||||
m_header.frame.height = frame.height;
|
||||
m_header.frame.stride = frame.stride;
|
||||
m_header.frame.dataPos = m_dataOffset[m_frameIndex];
|
||||
m_detail.frame.type = m_capture->GetFrameType();
|
||||
m_detail.frame.width = frame.width;
|
||||
m_detail.frame.height = frame.height;
|
||||
m_detail.frame.stride = frame.stride;
|
||||
m_detail.frame.pitch = frame.pitch;
|
||||
m_detail.frame.dataPos = m_dataOffset[m_frameIndex];
|
||||
if (++m_frameIndex == 2)
|
||||
m_frameIndex = 0;
|
||||
}
|
||||
@@ -280,11 +287,11 @@ bool Service::Process()
|
||||
|
||||
// tell the host where the cursor is
|
||||
updateFlags |= KVMFR_HEADER_FLAG_CURSOR;
|
||||
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_POS;
|
||||
m_detail.cursor.flags |= KVMFR_CURSOR_FLAG_POS;
|
||||
if (m_cursor.visible)
|
||||
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
m_header.cursor.x = m_cursor.x;
|
||||
m_header.cursor.y = m_cursor.y;
|
||||
m_detail.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
m_detail.cursor.x = m_cursor.x;
|
||||
m_detail.cursor.y = m_cursor.y;
|
||||
}
|
||||
|
||||
if (frame.cursor.hasShape || m_shapePending || (m_cursor.hasShape && restart))
|
||||
@@ -323,15 +330,17 @@ bool Service::Process()
|
||||
{
|
||||
// give the host the new cursor shape
|
||||
updateFlags |= KVMFR_HEADER_FLAG_CURSOR;
|
||||
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
|
||||
m_detail.cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
|
||||
if (m_cursor.visible)
|
||||
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
m_detail.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
|
||||
m_header.cursor.type = m_cursor.type;
|
||||
m_header.cursor.w = m_cursor.w;
|
||||
m_header.cursor.h = m_cursor.h;
|
||||
m_header.cursor.pitch = m_cursor.pitch;
|
||||
m_header.cursor.dataPos = m_dataOffset[m_frameIndex];
|
||||
// shapes are sent as frame data
|
||||
m_detail.cursor.type = m_cursor.type;
|
||||
m_detail.frame.width = m_cursor.w;
|
||||
m_detail.frame.height = m_cursor.h;
|
||||
m_detail.frame.stride = 0;
|
||||
m_detail.frame.pitch = m_cursor.pitch;
|
||||
m_detail.frame.dataPos = m_dataOffset[m_frameIndex];
|
||||
memcpy(m_frame[m_frameIndex], m_cursorData, m_cursor.dataSize);
|
||||
m_shapePending = false;
|
||||
|
||||
@@ -344,13 +353,8 @@ bool Service::Process()
|
||||
INTERLOCKED_AND8((volatile char *)flags, KVMFR_HEADER_FLAG_RESTART);
|
||||
INTERLOCKED_OR8 ((volatile char *)flags, updateFlags);
|
||||
|
||||
// update the shared header but don't touch the setup fields
|
||||
const size_t offset = (uintptr_t)&m_header.frame - (uintptr_t)&m_header;
|
||||
memcpy(
|
||||
(uint8_t *)m_shmHeader + offset,
|
||||
(uint8_t *)&m_header + offset,
|
||||
sizeof(KVMFRHeader) - offset
|
||||
);
|
||||
// update the shared details only
|
||||
memcpy(&m_shmHeader->detail, &m_detail, sizeof(KVMFRDetail));
|
||||
|
||||
// increment the update count so the guest stops waiting
|
||||
++m_shmHeader->updateCount;
|
||||
|
||||
@@ -49,12 +49,13 @@ private:
|
||||
~Service();
|
||||
|
||||
bool m_initialized;
|
||||
DWORD m_consoleSessionID;
|
||||
uint8_t * m_memory;
|
||||
IVSHMEM * m_ivshmem;
|
||||
HANDLE m_timer;
|
||||
ICapture * m_capture;
|
||||
|
||||
KVMFRHeader m_header;
|
||||
KVMFRDetail m_detail;
|
||||
KVMFRHeader * m_shmHeader;
|
||||
uint8_t * m_frame[2];
|
||||
size_t m_frameSize;
|
||||
|
||||
35
host/Util.h
35
host/Util.h
@@ -23,10 +23,45 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <inttypes.h>
|
||||
#include <tmmintrin.h>
|
||||
|
||||
#include "common\debug.h"
|
||||
|
||||
|
||||
class Util
|
||||
{
|
||||
public:
|
||||
static std::string GetSystemRoot()
|
||||
{
|
||||
std::string defaultPath;
|
||||
|
||||
size_t pathSize;
|
||||
char *libPath;
|
||||
|
||||
if (_dupenv_s(&libPath, &pathSize, "SystemRoot") != 0)
|
||||
{
|
||||
DEBUG_ERROR("Unable to get the SystemRoot environment variable");
|
||||
return defaultPath;
|
||||
}
|
||||
|
||||
if (!pathSize)
|
||||
{
|
||||
DEBUG_ERROR("The SystemRoot environment variable is not set");
|
||||
return defaultPath;
|
||||
}
|
||||
#ifdef _WIN64
|
||||
defaultPath = std::string(libPath) + "\\System32";
|
||||
#else
|
||||
if (IsWow64())
|
||||
{
|
||||
defaultPath = std::string(libPath) + "\\Syswow64";
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultPath = std::string(libPath) + "\\System32";
|
||||
}
|
||||
#endif
|
||||
return defaultPath;
|
||||
}
|
||||
|
||||
static inline void BGRAtoRGB(uint8_t * orig, size_t imagesize, uint8_t * dest)
|
||||
{
|
||||
assert((uintptr_t)orig % 16 == 0);
|
||||
|
||||
Reference in New Issue
Block a user