[client/host] added new asyncronous memory copy

This changes the method of the memory copy from the host application to
the guest. Instead of performing a full copy from the capture device
into shared memory, and then flagging the new frame, we instead set a
write pointer, flag the client that there is a new frame and then copy
in chunks of 1024 bytes until the entire frame is copied. The client
upon seeing the new frame flag begins to poll at high frequency the
write pointer and upon each update copies as much as it can into the
texture.

This should improve latency but also slightly increase CPU usage on the
client due to the high frequency polling.
This commit is contained in:
Geoffrey McRae
2019-10-01 23:17:20 +10:00
parent 6d2c464436
commit bca54ab1f6
17 changed files with 358 additions and 277 deletions

View File

@@ -60,7 +60,7 @@ struct EGL_Desktop
enum EGL_PixelFormat pixFmt;
unsigned int width, height;
unsigned int pitch;
const uint8_t * data;
FrameBuffer frame;
bool update;
// night vision
@@ -181,7 +181,7 @@ void egl_desktop_free(EGL_Desktop ** desktop)
*desktop = NULL;
}
bool egl_desktop_prepare_update(EGL_Desktop * desktop, const bool sourceChanged, const LG_RendererFormat format, const uint8_t * data)
bool egl_desktop_prepare_update(EGL_Desktop * desktop, const bool sourceChanged, const LG_RendererFormat format, const FrameBuffer frame)
{
if (sourceChanged)
{
@@ -217,7 +217,7 @@ bool egl_desktop_prepare_update(EGL_Desktop * desktop, const bool sourceChanged,
desktop->width = format.width;
desktop->height = format.height;
desktop->pitch = format.pitch;
desktop->data = data;
desktop->frame = frame;
desktop->update = true;
/* defer the actual update as the format has changed and we need to issue GL commands first */
@@ -226,7 +226,7 @@ bool egl_desktop_prepare_update(EGL_Desktop * desktop, const bool sourceChanged,
}
/* update the texture now */
return egl_texture_update(desktop->texture, data);
return egl_texture_update_from_frame(desktop->texture, frame);
}
void egl_desktop_perform_update(EGL_Desktop * desktop, const bool sourceChanged)
@@ -253,7 +253,7 @@ void egl_desktop_perform_update(EGL_Desktop * desktop, const bool sourceChanged)
if (desktop->update)
{
desktop->update = false;
egl_texture_update(desktop->texture, desktop->data);
egl_texture_update_from_frame(desktop->texture, desktop->frame);
}
}

View File

@@ -28,6 +28,6 @@ typedef struct EGL_Desktop EGL_Desktop;
bool egl_desktop_init(EGL_Desktop ** desktop);
void egl_desktop_free(EGL_Desktop ** desktop);
bool egl_desktop_prepare_update(EGL_Desktop * desktop, const bool sourceChanged, const LG_RendererFormat format, const uint8_t * data);
bool egl_desktop_prepare_update(EGL_Desktop * desktop, const bool sourceChanged, const LG_RendererFormat format, const FrameBuffer frame);
void egl_desktop_perform_update(EGL_Desktop * desktop, const bool sourceChanged);
bool egl_desktop_render(EGL_Desktop * desktop, const float x, const float y, const float scaleX, const float scaleY, const bool nearest);

View File

@@ -296,7 +296,7 @@ bool egl_on_mouse_event(void * opaque, const bool visible, const int x, const in
return true;
}
bool egl_on_frame_event(void * opaque, const LG_RendererFormat format, const uint8_t * data)
bool egl_on_frame_event(void * opaque, const LG_RendererFormat format, const FrameBuffer frame)
{
struct Inst * this = (struct Inst *)opaque;
this->sourceChanged = (
@@ -312,7 +312,7 @@ bool egl_on_frame_event(void * opaque, const LG_RendererFormat format, const uin
this->useNearest = this->width < format.width || this->height < format.height;
if (!egl_desktop_prepare_update(this->desktop, this->sourceChanged, format, data))
if (!egl_desktop_prepare_update(this->desktop, this->sourceChanged, format, frame))
{
DEBUG_INFO("Failed to prepare to update the desktop");
return false;

View File

@@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "texture.h"
#include "common/debug.h"
#include "common/locking.h"
#include "common/framebuffer.h"
#include "debug.h"
#include "utils.h"
@@ -278,6 +279,24 @@ bool egl_texture_update(EGL_Texture * texture, const uint8_t * buffer)
return true;
}
bool egl_texture_update_from_frame(EGL_Texture * texture, const FrameBuffer frame)
{
if (!texture->streaming)
return false;
if (texture->pboCount == 2)
return true;
framebuffer_read(frame, texture->pboMap[texture->pboWIndex], texture->pboBufferSize);
texture->pboSync[texture->pboWIndex] = 0;
if (++texture->pboWIndex == 2)
texture->pboWIndex = 0;
INTERLOCKED_INC(&texture->pboCount);
return true;
}
enum EGL_TexStatus egl_texture_process(EGL_Texture * texture)
{
if (!texture->streaming)

View File

@@ -21,6 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <stdbool.h>
#include "shader.h"
#include "common/framebuffer.h"
#include <GL/gl.h>
@@ -46,6 +47,7 @@ void egl_texture_free(EGL_Texture ** tex);
bool egl_texture_setup (EGL_Texture * texture, enum EGL_PixelFormat pixfmt, size_t width, size_t height, size_t stride, bool streaming);
bool egl_texture_update (EGL_Texture * texture, const uint8_t * buffer);
bool egl_texture_update_from_frame(EGL_Texture * texture, const FrameBuffer frame);
enum EGL_TexStatus egl_texture_process(EGL_Texture * texture);
enum EGL_TexStatus egl_texture_bind (EGL_Texture * texture);
int egl_texture_count (EGL_Texture * texture);