mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-23 14:03:40 +00:00
[host] better sync, helps enormously with 4K!!!
This commit is contained in:
parent
73a2597c8a
commit
471303a179
@ -348,12 +348,15 @@ size_t DXGI::GetMaxFrameSize()
|
|||||||
return (m_width * m_height * 4);
|
return (m_width * m_height * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout)
|
GrabStatus Capture::DXGI::Capture()
|
||||||
{
|
{
|
||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
|
|
||||||
timeout = false;
|
m_cursor.updated = false;
|
||||||
|
m_cursor.hasPos = false;
|
||||||
|
m_cursor.hasShape = false;
|
||||||
|
|
||||||
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
||||||
IDXGIResourcePtr res;
|
IDXGIResourcePtr res;
|
||||||
|
|
||||||
@ -368,10 +371,7 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
|
|||||||
|
|
||||||
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
||||||
if (status == DXGI_ERROR_WAIT_TIMEOUT)
|
if (status == DXGI_ERROR_WAIT_TIMEOUT)
|
||||||
{
|
return GRAB_STATUS_TIMEOUT;
|
||||||
timeout = true;
|
|
||||||
return GRAB_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
break;
|
break;
|
||||||
@ -385,27 +385,27 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
|
|||||||
m_lastMousePos.x != frameInfo.PointerPosition.Position.x ||
|
m_lastMousePos.x != frameInfo.PointerPosition.Position.x ||
|
||||||
m_lastMousePos.y != frameInfo.PointerPosition.Position.y
|
m_lastMousePos.y != frameInfo.PointerPosition.Position.y
|
||||||
) {
|
) {
|
||||||
cursor.updated = true;
|
m_cursor.updated = true;
|
||||||
cursor.hasPos = true;
|
m_cursor.hasPos = true;
|
||||||
cursor.x = frameInfo.PointerPosition.Position.x;
|
m_cursor.x = frameInfo.PointerPosition.Position.x;
|
||||||
cursor.y = frameInfo.PointerPosition.Position.y;
|
m_cursor.y = frameInfo.PointerPosition.Position.y;
|
||||||
m_lastMousePos.x = frameInfo.PointerPosition.Position.x;
|
m_lastMousePos.x = frameInfo.PointerPosition.Position.x;
|
||||||
m_lastMousePos.y = frameInfo.PointerPosition.Position.y;
|
m_lastMousePos.y = frameInfo.PointerPosition.Position.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
||||||
{
|
{
|
||||||
cursor.updated = true;
|
m_cursor.updated = true;
|
||||||
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.visible = m_lastMouseVis == TRUE;
|
m_cursor.visible = m_lastMouseVis == TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the pointer shape has changed
|
// if the pointer shape has changed
|
||||||
if (frameInfo.PointerShapeBufferSize > 0)
|
if (frameInfo.PointerShapeBufferSize > 0)
|
||||||
{
|
{
|
||||||
cursor.updated = true;
|
m_cursor.updated = true;
|
||||||
if (m_pointerBufSize < frameInfo.PointerShapeBufferSize)
|
if (m_pointerBufSize < frameInfo.PointerShapeBufferSize)
|
||||||
{
|
{
|
||||||
if (m_pointer)
|
if (m_pointer)
|
||||||
@ -424,20 +424,20 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
|
|||||||
|
|
||||||
switch (shapeInfo.Type)
|
switch (shapeInfo.Type)
|
||||||
{
|
{
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR : cursor.type = CURSOR_TYPE_COLOR; break;
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR : m_cursor.type = CURSOR_TYPE_COLOR; break;
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: cursor.type = CURSOR_TYPE_MASKED_COLOR; break;
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: m_cursor.type = CURSOR_TYPE_MASKED_COLOR; break;
|
||||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : cursor.type = CURSOR_TYPE_MONOCHROME; break;
|
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : m_cursor.type = CURSOR_TYPE_MONOCHROME; break;
|
||||||
default:
|
default:
|
||||||
DEBUG_ERROR("Invalid cursor type");
|
DEBUG_ERROR("Invalid cursor type");
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.hasShape = true;
|
m_cursor.hasShape = true;
|
||||||
cursor.shape = m_pointer;
|
m_cursor.shape = m_pointer;
|
||||||
cursor.w = shapeInfo.Width;
|
m_cursor.w = shapeInfo.Width;
|
||||||
cursor.h = shapeInfo.Height;
|
m_cursor.h = shapeInfo.Height;
|
||||||
cursor.pitch = shapeInfo.Pitch;
|
m_cursor.pitch = shapeInfo.Pitch;
|
||||||
cursor.dataSize = m_pointerSize;
|
m_cursor.dataSize = m_pointerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we also have frame data, break out to process it
|
// if we also have frame data, break out to process it
|
||||||
@ -447,7 +447,7 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
|
|||||||
res = NULL;
|
res = NULL;
|
||||||
|
|
||||||
// if the cursor has been updated
|
// if the cursor has been updated
|
||||||
if (cursor.updated)
|
if (m_cursor.updated)
|
||||||
return GRAB_STATUS_CURSOR;
|
return GRAB_STATUS_CURSOR;
|
||||||
|
|
||||||
// otherwise just try again
|
// otherwise just try again
|
||||||
@ -477,9 +477,9 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
|
|||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.QueryInterface(IID_PPV_ARGS(&texture));
|
res.QueryInterface(IID_PPV_ARGS(&m_ftexture));
|
||||||
|
|
||||||
if (!texture)
|
if (!m_ftexture)
|
||||||
{
|
{
|
||||||
ReleaseFrame();
|
ReleaseFrame();
|
||||||
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
||||||
@ -495,6 +495,8 @@ GrabStatus Capture::DXGI::ReleaseFrame()
|
|||||||
return GRAB_STATUS_OK;
|
return GRAB_STATUS_OK;
|
||||||
|
|
||||||
m_releaseFrame = false;
|
m_releaseFrame = false;
|
||||||
|
m_ftexture = NULL;
|
||||||
|
|
||||||
switch (m_dup->ReleaseFrame())
|
switch (m_dup->ReleaseFrame())
|
||||||
{
|
{
|
||||||
case S_OK:
|
case S_OK:
|
||||||
@ -512,21 +514,17 @@ GrabStatus Capture::DXGI::ReleaseFrame()
|
|||||||
return GRAB_STATUS_OK;
|
return GRAB_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cursor)
|
GrabStatus Capture::DXGI::DiscardFrame()
|
||||||
|
{
|
||||||
|
return ReleaseFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame)
|
||||||
{
|
{
|
||||||
GrabStatus result;
|
GrabStatus result;
|
||||||
ID3D11Texture2DPtr texture;
|
|
||||||
bool timeout;
|
|
||||||
D3D11_MAPPED_SUBRESOURCE mapping;
|
D3D11_MAPPED_SUBRESOURCE mapping;
|
||||||
|
|
||||||
result = GrabFrameTexture(frame, cursor, texture, timeout);
|
m_deviceContext->CopyResource(m_texture[0], m_ftexture);
|
||||||
if (timeout)
|
|
||||||
return GRAB_STATUS_TIMEOUT;
|
|
||||||
|
|
||||||
if (result != GRAB_STATUS_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
m_deviceContext->CopyResource(m_texture[0], texture);
|
|
||||||
|
|
||||||
result = ReleaseFrame();
|
result = ReleaseFrame();
|
||||||
if (result != GRAB_STATUS_OK)
|
if (result != GRAB_STATUS_OK)
|
||||||
@ -556,21 +554,12 @@ GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cu
|
|||||||
return GRAB_STATUS_OK;
|
return GRAB_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus Capture::DXGI::GrabFrameYUV420(struct FrameInfo & frame, struct CursorInfo & cursor)
|
GrabStatus Capture::DXGI::GrabFrameYUV420(struct FrameInfo & frame)
|
||||||
{
|
{
|
||||||
GrabStatus result;
|
GrabStatus result;
|
||||||
ID3D11Texture2DPtr texture;
|
|
||||||
bool timeout;
|
|
||||||
|
|
||||||
result = GrabFrameTexture(frame, cursor, texture, timeout);
|
|
||||||
if (timeout)
|
|
||||||
return GRAB_STATUS_TIMEOUT;
|
|
||||||
|
|
||||||
if (result != GRAB_STATUS_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
TextureList planes;
|
TextureList planes;
|
||||||
if (!m_textureConverter->Convert(texture, planes))
|
if (!m_textureConverter->Convert(m_ftexture, planes))
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
|
|
||||||
for(int i = 0; i < 3; ++i)
|
for(int i = 0; i < 3; ++i)
|
||||||
@ -624,7 +613,7 @@ GrabStatus Capture::DXGI::GrabFrameYUV420(struct FrameInfo & frame, struct Curso
|
|||||||
return GRAB_STATUS_OK;
|
return GRAB_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorInfo & cursor)
|
GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame)
|
||||||
{
|
{
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
#if 0
|
#if 0
|
||||||
@ -673,16 +662,27 @@ GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorI
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus DXGI::GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor)
|
GrabStatus DXGI::GetFrame(struct FrameInfo & frame)
|
||||||
{
|
{
|
||||||
|
if (!m_ftexture)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("A frame has not been captured");
|
||||||
|
return GRAB_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
frame.width = m_width;
|
frame.width = m_width;
|
||||||
frame.height = m_height;
|
frame.height = m_height;
|
||||||
|
|
||||||
switch (m_frameType)
|
switch (m_frameType)
|
||||||
{
|
{
|
||||||
case FRAME_TYPE_YUV420: return GrabFrameYUV420(frame, cursor);
|
case FRAME_TYPE_YUV420: return GrabFrameYUV420(frame);
|
||||||
case FRAME_TYPE_H264 : return GrabFrameH264 (frame, cursor);
|
case FRAME_TYPE_H264 : return GrabFrameH264 (frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GrabFrameRaw(frame, cursor);
|
return GrabFrameRaw(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CursorInfo & DXGI::GetCursor()
|
||||||
|
{
|
||||||
|
return m_cursor;
|
||||||
}
|
}
|
@ -56,18 +56,23 @@ namespace Capture
|
|||||||
|
|
||||||
enum FrameType GetFrameType();
|
enum FrameType GetFrameType();
|
||||||
size_t GetMaxFrameSize();
|
size_t GetMaxFrameSize();
|
||||||
enum GrabStatus GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor);
|
GrabStatus Capture();
|
||||||
|
GrabStatus GetFrame (struct FrameInfo & frame );
|
||||||
|
const CursorInfo & GetCursor();
|
||||||
|
GrabStatus DiscardFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool InitRawCapture();
|
bool InitRawCapture();
|
||||||
bool InitYUV420Capture();
|
bool InitYUV420Capture();
|
||||||
bool InitH264Capture();
|
bool InitH264Capture();
|
||||||
|
|
||||||
GrabStatus GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout);
|
struct CursorInfo m_cursor;
|
||||||
|
ID3D11Texture2DPtr m_ftexture;
|
||||||
|
|
||||||
GrabStatus ReleaseFrame();
|
GrabStatus ReleaseFrame();
|
||||||
GrabStatus GrabFrameRaw (struct FrameInfo & frame, struct CursorInfo & cursor);
|
GrabStatus GrabFrameRaw (struct FrameInfo & frame);
|
||||||
GrabStatus GrabFrameYUV420 (struct FrameInfo & frame, struct CursorInfo & cursor);
|
GrabStatus GrabFrameYUV420 (struct FrameInfo & frame);
|
||||||
GrabStatus GrabFrameH264 (struct FrameInfo & frame, struct CursorInfo & cursor);
|
GrabStatus GrabFrameH264 (struct FrameInfo & frame);
|
||||||
|
|
||||||
CaptureOptions * m_options;
|
CaptureOptions * m_options;
|
||||||
|
|
||||||
|
@ -71,5 +71,8 @@ public:
|
|||||||
virtual bool ReInitialize() = 0;
|
virtual bool ReInitialize() = 0;
|
||||||
virtual enum FrameType GetFrameType() = 0;
|
virtual enum FrameType GetFrameType() = 0;
|
||||||
virtual size_t GetMaxFrameSize() = 0;
|
virtual size_t GetMaxFrameSize() = 0;
|
||||||
virtual enum GrabStatus GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor) = 0;
|
virtual enum GrabStatus Capture() = 0;
|
||||||
|
virtual enum GrabStatus GetFrame(struct FrameInfo & frame) = 0;
|
||||||
|
virtual const CursorInfo & GetCursor() = 0;
|
||||||
|
virtual enum GrabStatus DiscardFrame() = 0;
|
||||||
};
|
};
|
||||||
|
@ -98,8 +98,8 @@ bool Service::Initialize(ICapture * captureDevice)
|
|||||||
m_shmHeader->version = KVMFR_HEADER_VERSION;
|
m_shmHeader->version = KVMFR_HEADER_VERSION;
|
||||||
|
|
||||||
// zero and tell the client we have restarted
|
// zero and tell the client we have restarted
|
||||||
ZeroMemory(&m_shmHeader->frame , sizeof(KVMFRFrame ));
|
ZeroMemory(&(m_shmHeader->frame ), sizeof(KVMFRFrame ));
|
||||||
ZeroMemory(&m_shmHeader->cursor, sizeof(KVMFRCursor));
|
ZeroMemory(&(m_shmHeader->cursor), sizeof(KVMFRCursor));
|
||||||
m_shmHeader->flags &= ~KVMFR_HEADER_FLAG_RESTART;
|
m_shmHeader->flags &= ~KVMFR_HEADER_FLAG_RESTART;
|
||||||
|
|
||||||
m_haveFrame = false;
|
m_haveFrame = false;
|
||||||
@ -171,12 +171,8 @@ bool Service::Process()
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
volatile uint8_t *flags = &m_shmHeader->flags;
|
volatile uint8_t *flags = &(m_shmHeader->flags);
|
||||||
int tryCount = 0;
|
|
||||||
|
|
||||||
// wait for the host to notify that is it is ready to proceed
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
// check if the client has flagged a restart
|
// check if the client has flagged a restart
|
||||||
if (*flags & KVMFR_HEADER_FLAG_RESTART)
|
if (*flags & KVMFR_HEADER_FLAG_RESTART)
|
||||||
{
|
{
|
||||||
@ -194,31 +190,9 @@ bool Service::Process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
INTERLOCKED_AND8((volatile char *)flags, ~(KVMFR_HEADER_FLAG_RESTART));
|
INTERLOCKED_AND8((volatile char *)flags, ~(KVMFR_HEADER_FLAG_RESTART));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the client has flagged it's ready for a frame
|
GrabStatus result;
|
||||||
if (!(m_shmHeader->frame.flags & KVMFR_FRAME_FLAG_UPDATE))
|
|
||||||
break;
|
|
||||||
|
|
||||||
// save CPU if the client has stopped polling for updates
|
|
||||||
if (++tryCount > m_tryTarget * 400)
|
|
||||||
{
|
|
||||||
m_tryTarget = 250;
|
|
||||||
Sleep(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int diff = (tryCount - m_lastTryCount) / 200;
|
|
||||||
m_lastTryCount = tryCount;
|
|
||||||
m_tryTarget += diff;
|
|
||||||
if (m_tryTarget < 250)
|
|
||||||
m_tryTarget = 250;
|
|
||||||
|
|
||||||
struct FrameInfo frame = {0};
|
|
||||||
struct CursorInfo cursor = {0};
|
|
||||||
frame.buffer = m_frame[m_frameIndex];
|
|
||||||
frame.bufferSize = m_frameSize;
|
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
bool cursorOnly = false;
|
bool cursorOnly = false;
|
||||||
@ -226,7 +200,7 @@ bool Service::Process()
|
|||||||
for(int i = 0; i < 2; ++i)
|
for(int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
// capture a frame of data
|
// capture a frame of data
|
||||||
switch (m_capture->GrabFrame(frame, cursor))
|
switch (m_capture->Capture())
|
||||||
{
|
{
|
||||||
case GRAB_STATUS_OK:
|
case GRAB_STATUS_OK:
|
||||||
ok = true;
|
ok = true;
|
||||||
@ -298,6 +272,8 @@ bool Service::Process()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CursorInfo & cursor = m_capture->GetCursor();
|
||||||
|
|
||||||
if (cursor.updated)
|
if (cursor.updated)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&m_cursorCS);
|
EnterCriticalSection(&m_cursorCS);
|
||||||
@ -326,24 +302,48 @@ bool Service::Process()
|
|||||||
|
|
||||||
if (!cursorOnly)
|
if (!cursorOnly)
|
||||||
{
|
{
|
||||||
KVMFRFrame * fi = &m_shmHeader->frame;
|
volatile KVMFRFrame * fi = &(m_shmHeader->frame);
|
||||||
|
|
||||||
// only update the header if the frame is new
|
// only update the header if the frame is new
|
||||||
if (!repeat)
|
if (!repeat)
|
||||||
{
|
{
|
||||||
|
FrameInfo frame = { 0 };
|
||||||
|
frame.buffer = m_frame[m_frameIndex];
|
||||||
|
frame.bufferSize = m_frameSize;
|
||||||
|
|
||||||
|
result = m_capture->GetFrame(frame);
|
||||||
|
if (result != GRAB_STATUS_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* don't touch the frame inforamtion until the client is done with it */
|
||||||
|
while (fi->flags & KVMFR_FRAME_FLAG_UPDATE)
|
||||||
|
{
|
||||||
|
if (*flags & KVMFR_HEADER_FLAG_RESTART)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fi->type = m_capture->GetFrameType();
|
fi->type = m_capture->GetFrameType();
|
||||||
fi->width = frame.width;
|
fi->width = frame.width;
|
||||||
fi->height = frame.height;
|
fi->height = frame.height;
|
||||||
fi->stride = frame.stride;
|
fi->stride = frame.stride;
|
||||||
fi->pitch = frame.pitch;
|
fi->pitch = frame.pitch;
|
||||||
fi->dataPos = m_dataOffset[m_frameIndex];
|
fi->dataPos = m_dataOffset[m_frameIndex];
|
||||||
}
|
|
||||||
|
|
||||||
if (++m_frameIndex == MAX_FRAMES)
|
if (++m_frameIndex == MAX_FRAMES)
|
||||||
m_frameIndex = 0;
|
m_frameIndex = 0;
|
||||||
|
|
||||||
// remember that we have a valid frame
|
// remember that we have a valid frame
|
||||||
m_haveFrame = true;
|
m_haveFrame = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* don't touch the frame inforamtion until the client is done with it */
|
||||||
|
while (fi->flags & KVMFR_FRAME_FLAG_UPDATE)
|
||||||
|
{
|
||||||
|
if (*flags & KVMFR_HEADER_FLAG_RESTART)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// signal a frame update
|
// signal a frame update
|
||||||
fi->flags |= KVMFR_FRAME_FLAG_UPDATE;
|
fi->flags |= KVMFR_FRAME_FLAG_UPDATE;
|
||||||
@ -361,7 +361,7 @@ DWORD Service::CursorThread()
|
|||||||
if (WaitForSingleObject(m_cursorEvent, 1000) != WAIT_OBJECT_0)
|
if (WaitForSingleObject(m_cursorEvent, 1000) != WAIT_OBJECT_0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
KVMFRCursor * cursor = &m_shmHeader->cursor;
|
volatile KVMFRCursor * cursor = &(m_shmHeader->cursor);
|
||||||
// wait until the client is ready
|
// wait until the client is ready
|
||||||
while (cursor->flags != 0)
|
while (cursor->flags != 0)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user