mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-11-17 23:42:20 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c5b2b5c1c | ||
|
|
758b7af754 | ||
|
|
b89a8fee04 | ||
|
|
2bb8b0227c | ||
|
|
ae4156d041 | ||
|
|
fe337cf510 | ||
|
|
7bfed41523 | ||
|
|
9bb66b7bd6 | ||
|
|
f7420317f1 | ||
|
|
c1379a45d2 | ||
|
|
9c03327701 | ||
|
|
0d8b2449cf | ||
|
|
d1bd5b3115 | ||
|
|
e03621a622 |
@@ -30,6 +30,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
@@ -544,4 +545,4 @@ bool ivshmem_kick_irq(uint16_t clientID, uint16_t vector)
|
||||
|
||||
DEBUG_ERROR("failed to send kick");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef struct LG_RendererParams
|
||||
TTF_Font * font;
|
||||
bool showFPS;
|
||||
bool resample;
|
||||
bool vsync;
|
||||
}
|
||||
LG_RendererParams;
|
||||
|
||||
@@ -97,4 +98,4 @@ typedef struct LG_Renderer
|
||||
LG_RendererOnFrameEvent on_frame_event;
|
||||
LG_RendererRender render;
|
||||
}
|
||||
LG_Renderer;
|
||||
LG_Renderer;
|
||||
119
client/main.c
119
client/main.c
@@ -50,6 +50,7 @@ struct AppState
|
||||
SDL_Point srcSize;
|
||||
LG_RendererRect dstRect;
|
||||
SDL_Point cursor;
|
||||
bool cursorVisible;
|
||||
bool haveCursorPos;
|
||||
float scaleX, scaleY;
|
||||
|
||||
@@ -63,6 +64,7 @@ struct AppState
|
||||
|
||||
struct AppParams
|
||||
{
|
||||
bool vsync;
|
||||
bool autoResize;
|
||||
bool allowResize;
|
||||
bool keepAspect;
|
||||
@@ -84,6 +86,7 @@ struct AppParams
|
||||
struct AppState state;
|
||||
struct AppParams params =
|
||||
{
|
||||
.vsync = true,
|
||||
.autoResize = false,
|
||||
.allowResize = true,
|
||||
.keepAspect = true,
|
||||
@@ -136,8 +139,11 @@ inline void updatePositionInfo()
|
||||
state.dstRect.h = h;
|
||||
}
|
||||
|
||||
state.scaleX = (float)state.srcSize.y / (float)state.dstRect.h;
|
||||
state.scaleY = (float)state.srcSize.x / (float)state.dstRect.w;
|
||||
if (state.started)
|
||||
{
|
||||
state.scaleX = (float)state.srcSize.y / (float)state.dstRect.h;
|
||||
state.scaleY = (float)state.srcSize.x / (float)state.dstRect.w;
|
||||
}
|
||||
|
||||
if (state.lgr)
|
||||
state.lgr->on_resize(state.lgrData, w, h, state.dstRect);
|
||||
@@ -147,6 +153,12 @@ int renderThread(void * unused)
|
||||
{
|
||||
bool error = false;
|
||||
struct KVMFRHeader header;
|
||||
|
||||
LG_RendererCursor cursorType = LG_CURSOR_COLOR;
|
||||
struct KVMFRCursor cursor = {};
|
||||
size_t cursorDataSize = 0;
|
||||
uint8_t * cursorData = NULL;
|
||||
|
||||
volatile uint32_t * updateCount = &state.shm->updateCount;
|
||||
|
||||
memset(&header, 0, sizeof(struct KVMFRHeader));
|
||||
@@ -254,7 +266,35 @@ int renderThread(void * unused)
|
||||
state.srcSize.y = header.frame.height;
|
||||
if (params.autoResize)
|
||||
SDL_SetWindowSize(state.window, header.frame.width, header.frame.height);
|
||||
|
||||
state.started = true;
|
||||
updatePositionInfo();
|
||||
|
||||
// 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))
|
||||
{
|
||||
DEBUG_ERROR("Failed to update mouse shape");
|
||||
break;
|
||||
}
|
||||
|
||||
free(cursorData);
|
||||
cursorData = NULL;
|
||||
cursorDataSize = 0;
|
||||
}
|
||||
|
||||
// if we have a cursor position, send it now
|
||||
if (state.haveCursorPos)
|
||||
{
|
||||
state.lgr->on_mouse_event(
|
||||
state.lgrData,
|
||||
state.cursorVisible,
|
||||
state.cursor.x,
|
||||
state.cursor.y
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t * data = (const uint8_t *)state.shm + header.frame.dataPos;
|
||||
@@ -272,24 +312,29 @@ int renderThread(void * unused)
|
||||
{
|
||||
state.cursor.x = header.cursor.x;
|
||||
state.cursor.y = header.cursor.y;
|
||||
state.cursorVisible = header.cursor.flags & KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
state.haveCursorPos = true;
|
||||
}
|
||||
|
||||
if (header.cursor.flags & KVMFR_CURSOR_FLAG_SHAPE)
|
||||
{
|
||||
LG_RendererCursor c = LG_CURSOR_COLOR;
|
||||
switch(header.cursor.type)
|
||||
{
|
||||
case CURSOR_TYPE_COLOR : c = LG_CURSOR_COLOR ; break;
|
||||
case CURSOR_TYPE_MONOCHROME : c = LG_CURSOR_MONOCHROME ; break;
|
||||
case CURSOR_TYPE_MASKED_COLOR: c = LG_CURSOR_MASKED_COLOR; break;
|
||||
default:
|
||||
DEBUG_ERROR("Invalid cursor type");
|
||||
break;
|
||||
}
|
||||
|
||||
if (state.lgr)
|
||||
{
|
||||
bool bad = false;
|
||||
switch(header.cursor.type)
|
||||
{
|
||||
case CURSOR_TYPE_COLOR : cursorType = LG_CURSOR_COLOR ; break;
|
||||
case CURSOR_TYPE_MONOCHROME : cursorType = LG_CURSOR_MONOCHROME ; break;
|
||||
case CURSOR_TYPE_MASKED_COLOR: cursorType = LG_CURSOR_MASKED_COLOR; break;
|
||||
default:
|
||||
DEBUG_ERROR("Invalid cursor type");
|
||||
bad = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bad)
|
||||
break;
|
||||
|
||||
// check the data position is sane
|
||||
const uint64_t dataSize = header.cursor.h * header.cursor.pitch;
|
||||
if (header.cursor.dataPos + dataSize > state.shmSize)
|
||||
@@ -299,14 +344,22 @@ int renderThread(void * unused)
|
||||
}
|
||||
|
||||
const uint8_t * data = (const uint8_t *)state.shm + header.cursor.dataPos;
|
||||
if (!state.lgr->on_mouse_shape(
|
||||
state.lgrData,
|
||||
c,
|
||||
header.cursor.w,
|
||||
header.cursor.h,
|
||||
header.cursor.pitch,
|
||||
data
|
||||
))
|
||||
if (!state.started)
|
||||
{
|
||||
// save off the cursor data so we can tell the renderer when it's ready
|
||||
if (cursorDataSize < dataSize)
|
||||
{
|
||||
if (cursorData) free(cursorData);
|
||||
cursorData = (uint8_t *)malloc(dataSize);
|
||||
cursorDataSize = dataSize;
|
||||
}
|
||||
memcpy(&cursor, &header.cursor, sizeof(struct KVMFRCursor));
|
||||
memcpy(cursorData, data, dataSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!state.lgr->on_mouse_shape(state.lgrData, cursorType, header.cursor.w,
|
||||
header.cursor.h, header.cursor.pitch, data))
|
||||
{
|
||||
DEBUG_ERROR("Failed to update mouse shape");
|
||||
break;
|
||||
@@ -314,21 +367,24 @@ int renderThread(void * unused)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.lgr)
|
||||
if (state.lgr && state.started)
|
||||
{
|
||||
state.lgr->on_mouse_event(
|
||||
state.lgrData,
|
||||
(header.cursor.flags & KVMFR_CURSOR_FLAG_VISIBLE) != 0,
|
||||
state.cursorVisible,
|
||||
state.cursor.x,
|
||||
state.cursor.y
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.lgr)
|
||||
if (state.started && state.lgr)
|
||||
state.lgr->render(state.lgrData);
|
||||
}
|
||||
|
||||
if (cursorData)
|
||||
free(cursorData);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -631,6 +687,7 @@ int run()
|
||||
lgrParams.font = state.font;
|
||||
lgrParams.resample = params.useMipmap;
|
||||
lgrParams.showFPS = params.showFPS;
|
||||
lgrParams.vsync = params.vsync;
|
||||
Uint32 sdlFlags;
|
||||
|
||||
// probe for a a suitable renderer
|
||||
@@ -676,6 +733,11 @@ int run()
|
||||
)
|
||||
);
|
||||
|
||||
if (params.fullscreen)
|
||||
{
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||
}
|
||||
|
||||
// set the compositor hint to bypass for low latency
|
||||
SDL_SysWMinfo wminfo;
|
||||
SDL_VERSION(&wminfo.version);
|
||||
@@ -841,13 +903,14 @@ void doHelp(char * app)
|
||||
" -M Don't hide the host cursor\n"
|
||||
"\n"
|
||||
" -m Disable mipmapping\n"
|
||||
" -v Disable VSync\n"
|
||||
" -v Disable VSYNC\n"
|
||||
" -k Enable FPS display\n"
|
||||
"\n"
|
||||
" -a Auto resize the window to the guest\n"
|
||||
" -n Don't allow the window to be manually resized\n"
|
||||
" -r Don't maintain the aspect ratio\n"
|
||||
" -d Borderless mode\n"
|
||||
" -F Borderless fullscreen mode\n"
|
||||
" -x XPOS Initial window X position [current: %s]\n"
|
||||
" -y YPOS Initial window Y position [current: %s]\n"
|
||||
" -w WIDTH Initial window width [current: %u]\n"
|
||||
@@ -894,7 +957,7 @@ void doLicense()
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int c;
|
||||
while((c = getopt(argc, argv, "hf:sc:p:jMmkanrdFx:y:w:b:l")) != -1)
|
||||
while((c = getopt(argc, argv, "hf:sc:p:jMmvkanrdFx:y:w:b:l")) != -1)
|
||||
switch(c)
|
||||
{
|
||||
case '?':
|
||||
@@ -931,6 +994,10 @@ int main(int argc, char * argv[])
|
||||
params.useMipmap = false;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
params.vsync = false;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
params.showFPS = true;
|
||||
break;
|
||||
|
||||
@@ -47,6 +47,7 @@ struct LGR_OpenGL
|
||||
{
|
||||
LG_RendererParams params;
|
||||
bool configured;
|
||||
SDL_Window * sdlWindow;
|
||||
SDL_GLContext glContext;
|
||||
bool doneInfo;
|
||||
|
||||
@@ -81,6 +82,7 @@ struct LGR_OpenGL
|
||||
SDL_Rect fpsRect;
|
||||
|
||||
bool mouseUpdate;
|
||||
bool newShape;
|
||||
uint64_t lastMouseDraw;
|
||||
LG_RendererCursor mouseType;
|
||||
bool mouseVisible;
|
||||
@@ -131,7 +133,7 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, Uint3
|
||||
}
|
||||
|
||||
*sdlFlags = SDL_WINDOW_OPENGL;
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -147,6 +149,7 @@ bool lgr_opengl_configure(void * opaque, SDL_Window *window, const LG_RendererFo
|
||||
return false;
|
||||
}
|
||||
|
||||
this->sdlWindow = window;
|
||||
this->glContext = SDL_GL_CreateContext(window);
|
||||
if (!this->glContext)
|
||||
{
|
||||
@@ -168,7 +171,7 @@ bool lgr_opengl_configure(void * opaque, SDL_Window *window, const LG_RendererFo
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
SDL_GL_SetSwapInterval(this->params.vsync ? 1 : 0);
|
||||
|
||||
// check if the GPU supports GL_ARB_buffer_storage first
|
||||
// there is no advantage to this renderer if it is not present.
|
||||
@@ -491,6 +494,7 @@ bool lgr_opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, co
|
||||
}
|
||||
|
||||
this->mouseUpdate = true;
|
||||
this->newShape = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -700,15 +704,27 @@ bool lgr_opengl_render(void * opaque)
|
||||
if (!this->mouseUpdate)
|
||||
return true;
|
||||
|
||||
// don't update the mouse too fast
|
||||
const uint64_t delta = nanotime() - this->lastMouseDraw;
|
||||
if (delta < 1e7)
|
||||
return true;
|
||||
}
|
||||
if (!this->newShape)
|
||||
{
|
||||
// don't update the mouse too fast
|
||||
const uint64_t delta = nanotime() - this->lastMouseDraw;
|
||||
if (delta < 5e6)
|
||||
return true;
|
||||
}
|
||||
this->newShape = false;
|
||||
|
||||
// wait for vsync
|
||||
unsigned int count;
|
||||
glXWaitVideoSyncSGI(1, 0, &count);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
glCallList(this->texList + this->texIndex);
|
||||
lgr_opengl_draw_mouse(this);
|
||||
if (this->fpsTexture)
|
||||
glCallList(this->fpsList);
|
||||
glDrawBuffer(GL_BACK);
|
||||
glFlush();
|
||||
|
||||
this->mouseUpdate = false;
|
||||
this->lastMouseDraw = nanotime();
|
||||
return true;
|
||||
}
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
@@ -718,7 +734,15 @@ bool lgr_opengl_render(void * opaque)
|
||||
lgr_opengl_draw_mouse(this);
|
||||
if (this->fpsTexture)
|
||||
glCallList(this->fpsList);
|
||||
glFlush();
|
||||
|
||||
unsigned int before, after;
|
||||
glXGetVideoSyncSGI(&before);
|
||||
SDL_GL_SwapWindow(this->sdlWindow);
|
||||
|
||||
// wait for the swap to happen to ensure we dont buffer frames
|
||||
glXGetVideoSyncSGI(&after);
|
||||
if (before == after)
|
||||
glXWaitVideoSyncSGI(1, 0, &before);
|
||||
|
||||
++this->frameCount;
|
||||
const uint64_t t = nanotime();
|
||||
|
||||
@@ -31,6 +31,7 @@ DXGI::DXGI() :
|
||||
m_deviceContext(),
|
||||
m_dup(),
|
||||
m_texture(),
|
||||
m_surface(),
|
||||
m_pointer(NULL)
|
||||
{
|
||||
}
|
||||
@@ -190,6 +191,15 @@ void DXGI::DeInitialize()
|
||||
m_pointerBufSize = 0;
|
||||
}
|
||||
|
||||
if (m_surfaceMapped)
|
||||
{
|
||||
m_surface->Unmap();
|
||||
m_surfaceMapped = false;
|
||||
}
|
||||
|
||||
if (m_surface)
|
||||
m_surface.Release();
|
||||
|
||||
if (m_texture)
|
||||
m_texture.Release();
|
||||
|
||||
@@ -241,7 +251,22 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
status = m_dup->AcquireNextFrame(INFINITE, &frameInfo, &res);
|
||||
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
||||
if (status == DXGI_ERROR_WAIT_TIMEOUT)
|
||||
{
|
||||
if (!m_surfaceMapped)
|
||||
break;
|
||||
|
||||
// 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.stride = m_rect.Pitch / 4;
|
||||
|
||||
unsigned int size = m_height * m_rect.Pitch;
|
||||
memcpySSE(frame.buffer, m_rect.pBits, size < frame.bufferSize ? size : frame.bufferSize);
|
||||
return GRAB_STATUS_OK;
|
||||
}
|
||||
|
||||
if (!SUCCEEDED(status))
|
||||
break;
|
||||
|
||||
@@ -371,8 +396,7 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
src->GetDesc(&desc);
|
||||
src->GetDesc(&m_desc);
|
||||
|
||||
m_deviceContext->CopyResource(m_texture, src);
|
||||
|
||||
@@ -380,38 +404,42 @@ GrabStatus DXGI::GrabFrame(FrameInfo & frame)
|
||||
res.Release();
|
||||
src.Release();
|
||||
|
||||
IDXGISurface1Ptr surface(m_texture);
|
||||
if (!surface)
|
||||
if (m_surfaceMapped)
|
||||
{
|
||||
status = m_surface->Unmap();
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_ERROR("Failed to unmap surface: %08x", (int)status);
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
m_surfaceMapped = false;
|
||||
m_surface.Release();
|
||||
}
|
||||
|
||||
m_surface = m_texture;
|
||||
if (!m_surface)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get IDXGISurface1");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
DXGI_MAPPED_RECT rect;
|
||||
status = surface->Map(&rect, DXGI_MAP_READ);
|
||||
status = m_surface->Map(&m_rect, DXGI_MAP_READ);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_ERROR("Failed to map surface: %08x", (int)status);
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
m_surfaceMapped = true;
|
||||
|
||||
m_width = desc.Width;
|
||||
m_height = desc.Height;
|
||||
m_width = m_desc.Width;
|
||||
m_height = m_desc.Height;
|
||||
|
||||
frame.width = desc.Width;
|
||||
frame.height = desc.Height;
|
||||
frame.stride = rect.Pitch / 4;
|
||||
frame.width = m_desc.Width;
|
||||
frame.height = m_desc.Height;
|
||||
frame.stride = m_rect.Pitch / 4;
|
||||
|
||||
unsigned int size = m_height * rect.Pitch;
|
||||
memcpySSE(frame.buffer, rect.pBits, size < frame.bufferSize ? size : frame.bufferSize);
|
||||
|
||||
status = surface->Unmap();
|
||||
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_ERROR("Failed to unmap surface: %08x", (int)status);
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
unsigned int size = m_height * m_rect.Pitch;
|
||||
memcpySSE(frame.buffer, m_rect.pBits, size < frame.bufferSize ? size : frame.bufferSize);
|
||||
|
||||
return GRAB_STATUS_OK;
|
||||
}
|
||||
@@ -80,6 +80,10 @@ namespace Capture
|
||||
IDXGIOutput1Ptr m_output;
|
||||
IDXGIOutputDuplicationPtr m_dup;
|
||||
ID3D11Texture2DPtr m_texture;
|
||||
IDXGISurface1Ptr m_surface;
|
||||
D3D11_TEXTURE2D_DESC m_desc;
|
||||
DXGI_MAPPED_RECT m_rect;
|
||||
bool m_surfaceMapped;
|
||||
BYTE * m_pointer;
|
||||
UINT m_pointerBufSize;
|
||||
UINT m_pointerSize;
|
||||
|
||||
@@ -61,11 +61,10 @@ bool NvFBC::Initialize(CaptureOptions * options)
|
||||
if (_strcmpi(*it, "nowait") == 0) { m_optNoWait = true ; continue; }
|
||||
}
|
||||
|
||||
std::string nvfbc = Util::GetSystemRoot() + "\\" + NVFBC_LIBRARY_NAME;
|
||||
m_hDLL = LoadLibraryA(nvfbc.c_str());
|
||||
m_hDLL = LoadLibraryA(NVFBC_LIBRARY_NAME);
|
||||
if (!m_hDLL)
|
||||
{
|
||||
DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", GetLastError(), nvfbc.c_str());
|
||||
DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", GetLastError(), NVFBC_LIBRARY_NAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -76,7 +75,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.c_str());
|
||||
DEBUG_ERROR("Unable to locate required entry points in %s", NVFBC_LIBRARY_NAME);
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ Service::Service() :
|
||||
m_memory(NULL),
|
||||
m_timer(NULL),
|
||||
m_capture(NULL),
|
||||
m_header(NULL),
|
||||
m_shmHeader(NULL),
|
||||
m_frameIndex(0),
|
||||
m_cursorDataSize(0),
|
||||
m_cursorData(NULL),
|
||||
@@ -92,15 +92,15 @@ bool Service::Initialize(ICapture * captureDevice)
|
||||
}
|
||||
|
||||
// update everything except for the hostID
|
||||
memcpy(m_header->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC));
|
||||
m_header->version = KVMFR_HEADER_VERSION;
|
||||
m_header->guestID = m_ivshmem->GetPeerID();
|
||||
m_header->updateCount = 0;
|
||||
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_header->flags, KVMFR_HEADER_FLAG_RESTART);
|
||||
ZeroMemory(&m_header->frame , sizeof(KVMFRFrame ));
|
||||
ZeroMemory(&m_header->cursor, sizeof(KVMFRCursor));
|
||||
INTERLOCKED_AND8((char *)&m_shmHeader->flags, KVMFR_HEADER_FLAG_RESTART);
|
||||
ZeroMemory(&m_shmHeader->frame , sizeof(KVMFRFrame ));
|
||||
ZeroMemory(&m_shmHeader->cursor, sizeof(KVMFRCursor));
|
||||
|
||||
m_initialized = true;
|
||||
return true;
|
||||
@@ -108,7 +108,7 @@ bool Service::Initialize(ICapture * captureDevice)
|
||||
|
||||
bool Service::InitPointers()
|
||||
{
|
||||
m_header = reinterpret_cast<KVMFRHeader *>(m_memory);
|
||||
m_shmHeader = reinterpret_cast<KVMFRHeader *>(m_memory);
|
||||
m_frame[0] = (uint8_t *)(((uintptr_t)m_memory + sizeof(KVMFRHeader *) + 0x7F) & ~0x7F);
|
||||
m_frameSize = ((m_ivshmem->GetSize() - (m_frame[0] - m_memory)) & ~0x7F) >> 1;
|
||||
m_frame[1] = m_frame[0] + m_frameSize;
|
||||
@@ -142,7 +142,7 @@ void Service::DeInitialize()
|
||||
m_cursorData = NULL;
|
||||
}
|
||||
|
||||
m_header = NULL;
|
||||
m_shmHeader = NULL;
|
||||
m_frame[0] = NULL;
|
||||
m_frame[1] = NULL;
|
||||
m_dataOffset[0] = 0;
|
||||
@@ -171,7 +171,7 @@ bool Service::Process()
|
||||
frame.buffer = m_frame[m_frameIndex];
|
||||
frame.bufferSize = m_frameSize;
|
||||
|
||||
volatile uint8_t *flags = &m_header->flags;
|
||||
volatile uint8_t *flags = &m_shmHeader->flags;
|
||||
|
||||
// wait for the host to notify that is it is ready to proceed
|
||||
while (true)
|
||||
@@ -181,7 +181,7 @@ bool Service::Process()
|
||||
// check if the client has flagged a restart
|
||||
if (f & KVMFR_HEADER_FLAG_RESTART)
|
||||
{
|
||||
m_header->updateCount = 0;
|
||||
m_shmHeader->updateCount = 0;
|
||||
INTERLOCKED_AND8((volatile char *)flags, ~(KVMFR_HEADER_FLAG_RESTART));
|
||||
restart = true;
|
||||
break;
|
||||
@@ -252,17 +252,17 @@ bool Service::Process()
|
||||
}
|
||||
|
||||
uint8_t updateFlags = 0;
|
||||
m_header->cursor.flags = 0;
|
||||
m_header.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_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];
|
||||
if (++m_frameIndex == 2)
|
||||
m_frameIndex = 0;
|
||||
}
|
||||
@@ -280,11 +280,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_header.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_header.cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
m_header.cursor.x = m_cursor.x;
|
||||
m_header.cursor.y = m_cursor.y;
|
||||
}
|
||||
|
||||
if (frame.cursor.hasShape || m_shapePending || (m_cursor.hasShape && restart))
|
||||
@@ -323,15 +323,15 @@ bool Service::Process()
|
||||
{
|
||||
// give the host the new cursor shape
|
||||
updateFlags |= KVMFR_HEADER_FLAG_CURSOR;
|
||||
m_header->cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
|
||||
m_header.cursor.flags |= KVMFR_CURSOR_FLAG_SHAPE;
|
||||
if (m_cursor.visible)
|
||||
m_header->cursor.flags |= KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
m_header.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];
|
||||
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];
|
||||
memcpy(m_frame[m_frameIndex], m_cursorData, m_cursor.dataSize);
|
||||
m_shapePending = false;
|
||||
|
||||
@@ -344,8 +344,16 @@ bool Service::Process()
|
||||
INTERLOCKED_AND8((volatile char *)flags, KVMFR_HEADER_FLAG_RESTART);
|
||||
INTERLOCKED_OR8 ((volatile char *)flags, updateFlags);
|
||||
|
||||
// increment the update count to resume the host
|
||||
++m_header->updateCount;
|
||||
// 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
|
||||
);
|
||||
|
||||
// increment the update count so the guest stops waiting
|
||||
++m_shmHeader->updateCount;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -54,7 +54,8 @@ private:
|
||||
HANDLE m_timer;
|
||||
ICapture * m_capture;
|
||||
|
||||
KVMFRHeader * m_header;
|
||||
KVMFRHeader m_header;
|
||||
KVMFRHeader * m_shmHeader;
|
||||
uint8_t * m_frame[2];
|
||||
size_t m_frameSize;
|
||||
uint64_t m_dataOffset[2];
|
||||
|
||||
35
host/Util.h
35
host/Util.h
@@ -23,45 +23,10 @@ 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