Skip to content

Commit

Permalink
[client/host] added new asyncronous memory copy
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gnif committed Oct 9, 2019
1 parent 6d2c464 commit bca54ab
Show file tree
Hide file tree
Showing 17 changed files with 336 additions and 255 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
fetch-4-ge93bd7a3bf+1
fetch-6-g59013b2e3f+1
5 changes: 3 additions & 2 deletions c-host/include/interface/capture.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA

#include <stdbool.h>
#include <stdint.h>
#include "common/framebuffer.h"

typedef enum CaptureResult
{
Expand Down Expand Up @@ -55,7 +56,6 @@ typedef struct CaptureFrame
unsigned int pitch;
unsigned int stride;
CaptureFormat format;
void * data;
}
CaptureFrame;

Expand Down Expand Up @@ -84,7 +84,8 @@ typedef struct CaptureInterface
unsigned int (*getMaxFrameSize)();

CaptureResult (*capture )();
CaptureResult (*getFrame )(CaptureFrame * frame );
CaptureResult (*waitFrame )(CaptureFrame * frame );
CaptureResult (*getFrame )(FrameBuffer frame );
CaptureResult (*getPointer)(CapturePointer * pointer);
}
CaptureInterface;
15 changes: 12 additions & 3 deletions c-host/platform/Windows/capture/DXGI/src/dxgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ static CaptureResult dxgi_capture()
return CAPTURE_RESULT_OK;
}

static CaptureResult dxgi_getFrame(CaptureFrame * frame)
static CaptureResult dxgi_waitFrame(CaptureFrame * frame)
{
assert(this);
assert(this->initialized);
Expand All @@ -778,7 +778,6 @@ static CaptureResult dxgi_getFrame(CaptureFrame * frame)
if (this->stop)
return CAPTURE_RESULT_REINIT;

// only reset the event if we used the texture
os_resetEvent(tex->mapped);

frame->width = this->width;
Expand All @@ -787,7 +786,16 @@ static CaptureResult dxgi_getFrame(CaptureFrame * frame)
frame->stride = this->stride;
frame->format = this->format;

memcpy(frame->data, tex->map.pData, this->pitch * this->height);
return CAPTURE_RESULT_OK;
}

static CaptureResult dxgi_getFrame(FrameBuffer frame)
{
assert(this);
assert(this->initialized);

Texture * tex = &this->texture[this->texRIndex];
framebuffer_write(frame, tex->map.pData, this->pitch * this->height);
os_signalEvent(tex->free);

if (++this->texRIndex == this->maxTextures)
Expand Down Expand Up @@ -867,6 +875,7 @@ struct CaptureInterface Capture_DXGI =
.free = dxgi_free,
.getMaxFrameSize = dxgi_getMaxFrameSize,
.capture = dxgi_capture,
.waitFrame = dxgi_waitFrame,
.getFrame = dxgi_getFrame,
.getPointer = dxgi_getPointer
};
15 changes: 13 additions & 2 deletions c-host/platform/Windows/capture/NVFBC/src/nvfbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "windows/debug.h"
#include "windows/mousehook.h"
#include "common/option.h"
#include "common/framebuffer.h"
#include <assert.h>
#include <stdlib.h>
#include <windows.h>
Expand Down Expand Up @@ -236,7 +237,7 @@ static CaptureResult nvfbc_capture()
return CAPTURE_RESULT_OK;
}

static CaptureResult nvfbc_getFrame(CaptureFrame * frame)
static CaptureResult nvfbc_waitFrame(CaptureFrame * frame)
{
if (!os_waitEvent(this->frameEvent, 1000))
return CAPTURE_RESULT_TIMEOUT;
Expand Down Expand Up @@ -266,7 +267,16 @@ static CaptureResult nvfbc_getFrame(CaptureFrame * frame)
#endif

frame->format = this->grabInfo.bIsHDR ? CAPTURE_FMT_RGBA10 : CAPTURE_FMT_BGRA;
memcpy(frame->data, this->frameBuffer, frame->pitch * frame->height);
return CAPTURE_RESULT_OK;
}

static CaptureResult nvfbc_getFrame(FrameBuffer frame)
{
framebuffer_write(
frame,
this->frameBuffer,
this->grabInfo.dwHeight * this->grabInfo.dwBufferWidth * 4
);
return CAPTURE_RESULT_OK;
}

Expand Down Expand Up @@ -310,6 +320,7 @@ struct CaptureInterface Capture_NVFBC =
.free = nvfbc_free,
.getMaxFrameSize = nvfbc_getMaxFrameSize,
.capture = nvfbc_capture,
.waitFrame = nvfbc_waitFrame,
.getFrame = nvfbc_getFrame,
.getPointer = nvfbc_getPointer
};
12 changes: 6 additions & 6 deletions c-host/src/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct app

uint8_t * frames;
unsigned int frameSize;
uint8_t * frame[MAX_FRAMES];
FrameBuffer frame[MAX_FRAMES];
unsigned int frameOffset[MAX_FRAMES];

bool running;
Expand Down Expand Up @@ -168,9 +168,7 @@ static int frameThread(void * opaque)

while(app.running)
{
frame.data = app.frame[frameIndex];

switch(app.iface->getFrame(&frame))
switch(app.iface->waitFrame(&frame))
{
case CAPTURE_RESULT_OK:
break;
Expand Down Expand Up @@ -226,7 +224,9 @@ static int frameThread(void * opaque)
fi->dataPos = app.frameOffset[frameIndex];
frameValid = true;

framebuffer_prepare(app.frame[frameIndex]);
INTERLOCKED_OR8(&fi->flags, KVMFR_FRAME_FLAG_UPDATE);
app.iface->getFrame(app.frame[frameIndex]);

if (++frameIndex == MAX_FRAMES)
frameIndex = 0;
Expand Down Expand Up @@ -369,8 +369,8 @@ int app_main(int argc, char * argv[])

for (int i = 0; i < MAX_FRAMES; ++i)
{
app.frame [i] = app.frames + i * app.frameSize;
app.frameOffset[i] = app.frame[i] - shmemMap;
app.frame [i] = (FrameBuffer)(app.frames + i * app.frameSize);
app.frameOffset[i] = (uint8_t *)app.frame[i] - shmemMap;
DEBUG_INFO("Frame %d : 0x%" PRIXPTR " (0x%08x)", i, (uintptr_t)app.frame[i], app.frameOffset[i]);
}

Expand Down
3 changes: 2 additions & 1 deletion client/include/interface/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA

#include "app.h"
#include "common/KVMFR.h"
#include "common/framebuffer.h"

#define IS_LG_RENDERER_VALID(x) \
((x)->get_name && \
Expand Down Expand Up @@ -89,7 +90,7 @@ typedef void (* LG_RendererDeInitialize)(void * opaque);
typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height, const LG_RendererRect destRect);
typedef bool (* LG_RendererOnMouseShape)(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data);
typedef bool (* LG_RendererOnMouseEvent)(void * opaque, const bool visible , const int x, const int y);
typedef bool (* LG_RendererOnFrameEvent)(void * opaque, const LG_RendererFormat format, const uint8_t * data);
typedef bool (* LG_RendererOnFrameEvent)(void * opaque, const LG_RendererFormat format, const FrameBuffer frame);
typedef void (* LG_RendererOnAlert )(void * opaque, const LG_MsgAlert alert, const char * message, bool ** closeFlag);
typedef bool (* LG_RendererRender )(void * opaque, SDL_Window *window);
typedef void (* LG_RendererUpdateFPS )(void * opaque, const float avgUPS, const float avgFPS);
Expand Down
10 changes: 5 additions & 5 deletions client/renderers/EGL/desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 */
Expand All @@ -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)
Expand All @@ -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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion client/renderers/EGL/desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
4 changes: 2 additions & 2 deletions client/renderers/EGL/egl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
Expand All @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions client/renderers/EGL/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions client/renderers/EGL/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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);
Loading

0 comments on commit bca54ab

Please sign in to comment.