[client] seperate frame setup and data events

This commit is contained in:
Geoffrey McRae 2020-10-12 19:43:29 +11:00
parent 7a49f75d95
commit 58ba76a27f
9 changed files with 171 additions and 136 deletions

View File

@ -86,34 +86,36 @@ typedef const char * (* LG_RendererGetName)();
// called pre-creation to allow the renderer to register any options it might have // called pre-creation to allow the renderer to register any options it might have
typedef void (* LG_RendererSetup)(); typedef void (* LG_RendererSetup)();
typedef bool (* LG_RendererCreate )(void ** opaque, const LG_RendererParams params); typedef bool (* LG_RendererCreate )(void ** opaque, const LG_RendererParams params);
typedef bool (* LG_RendererInitialize )(void * opaque, Uint32 * sdlFlags); typedef bool (* LG_RendererInitialize )(void * opaque, Uint32 * sdlFlags);
typedef void (* LG_RendererDeInitialize)(void * opaque); typedef void (* LG_RendererDeInitialize )(void * opaque);
typedef void (* LG_RendererOnRestart )(void * opaque); typedef void (* LG_RendererOnRestart )(void * opaque);
typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height, const LG_RendererRect destRect); 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_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_RendererOnMouseEvent )(void * opaque, const bool visible , const int x, const int y);
typedef bool (* LG_RendererOnFrameEvent)(void * opaque, const LG_RendererFormat format, const FrameBuffer * frame); typedef bool (* LG_RendererOnFrameFormat)(void * opaque, const LG_RendererFormat format);
typedef void (* LG_RendererOnAlert )(void * opaque, const LG_MsgAlert alert, const char * message, bool ** closeFlag); typedef bool (* LG_RendererOnFrame )(void * opaque, const FrameBuffer * frame);
typedef bool (* LG_RendererRender )(void * opaque, SDL_Window *window); typedef void (* LG_RendererOnAlert )(void * opaque, const LG_MsgAlert alert, const char * message, bool ** closeFlag);
typedef void (* LG_RendererUpdateFPS )(void * opaque, const float avgUPS, const float avgFPS); typedef bool (* LG_RendererRender )(void * opaque, SDL_Window *window);
typedef void (* LG_RendererUpdateFPS )(void * opaque, const float avgUPS, const float avgFPS);
typedef struct LG_Renderer typedef struct LG_Renderer
{ {
LG_RendererGetName get_name; LG_RendererGetName get_name;
LG_RendererSetup setup; LG_RendererSetup setup;
LG_RendererCreate create; LG_RendererCreate create;
LG_RendererInitialize initialize; LG_RendererInitialize initialize;
LG_RendererDeInitialize deinitialize; LG_RendererDeInitialize deinitialize;
LG_RendererOnRestart on_restart; LG_RendererOnRestart on_restart;
LG_RendererOnResize on_resize; LG_RendererOnResize on_resize;
LG_RendererOnMouseShape on_mouse_shape; LG_RendererOnMouseShape on_mouse_shape;
LG_RendererOnMouseEvent on_mouse_event; LG_RendererOnMouseEvent on_mouse_event;
LG_RendererOnFrameEvent on_frame_event; LG_RendererOnFrameFormat on_frame_format;
LG_RendererOnAlert on_alert; LG_RendererOnFrame on_frame;
LG_RendererRender render_startup; LG_RendererOnAlert on_alert;
LG_RendererRender render; LG_RendererRender render_startup;
LG_RendererUpdateFPS update_fps; LG_RendererRender render;
LG_RendererUpdateFPS update_fps;
} }
LG_Renderer; LG_Renderer;

View File

@ -175,60 +175,62 @@ void egl_desktop_free(EGL_Desktop ** desktop)
*desktop = NULL; *desktop = NULL;
} }
bool egl_desktop_update(EGL_Desktop * desktop, const bool sourceChanged, const LG_RendererFormat format, const FrameBuffer * frame) bool egl_desktop_setup(EGL_Desktop * desktop, const LG_RendererFormat format)
{ {
if (sourceChanged) enum EGL_PixelFormat pixFmt;
switch(format.type)
{ {
enum EGL_PixelFormat pixFmt; case FRAME_TYPE_BGRA:
switch(format.type) pixFmt = EGL_PF_BGRA;
{ desktop->shader = &desktop->shader_generic;
case FRAME_TYPE_BGRA: break;
pixFmt = EGL_PF_BGRA;
desktop->shader = &desktop->shader_generic;
break;
case FRAME_TYPE_RGBA: case FRAME_TYPE_RGBA:
pixFmt = EGL_PF_RGBA; pixFmt = EGL_PF_RGBA;
desktop->shader = &desktop->shader_generic; desktop->shader = &desktop->shader_generic;
break; break;
case FRAME_TYPE_RGBA10: case FRAME_TYPE_RGBA10:
pixFmt = EGL_PF_RGBA10; pixFmt = EGL_PF_RGBA10;
desktop->shader = &desktop->shader_generic; desktop->shader = &desktop->shader_generic;
break; break;
case FRAME_TYPE_RGBA16F: case FRAME_TYPE_RGBA16F:
pixFmt = EGL_PF_RGBA16F; pixFmt = EGL_PF_RGBA16F;
desktop->shader = &desktop->shader_generic; desktop->shader = &desktop->shader_generic;
break; break;
case FRAME_TYPE_YUV420: case FRAME_TYPE_YUV420:
pixFmt = EGL_PF_YUV420; pixFmt = EGL_PF_YUV420;
desktop->shader = &desktop->shader_yuv; desktop->shader = &desktop->shader_yuv;
break; break;
default: default:
DEBUG_ERROR("Unsupported frame format"); DEBUG_ERROR("Unsupported frame format");
return false;
}
desktop->width = format.width;
desktop->height = format.height;
if (!egl_texture_setup(
desktop->texture,
pixFmt,
format.width,
format.height,
format.pitch,
true // streaming texture
))
{
DEBUG_ERROR("Failed to setup the desktop texture");
return false; return false;
}
} }
desktop->width = format.width;
desktop->height = format.height;
if (!egl_texture_setup(
desktop->texture,
pixFmt,
format.width,
format.height,
format.pitch,
true // streaming texture
))
{
DEBUG_ERROR("Failed to setup the desktop texture");
return false;
}
return true;
}
bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame)
{
if (!egl_texture_update_from_frame(desktop->texture, frame)) if (!egl_texture_update_from_frame(desktop->texture, frame))
return false; return false;

View File

@ -28,5 +28,6 @@ typedef struct EGL_Desktop EGL_Desktop;
bool egl_desktop_init(void * egl, EGL_Desktop ** desktop); bool egl_desktop_init(void * egl, EGL_Desktop ** desktop);
void egl_desktop_free(EGL_Desktop ** desktop); void egl_desktop_free(EGL_Desktop ** desktop);
bool egl_desktop_update(EGL_Desktop * desktop, const bool sourceChanged, const LG_RendererFormat format, const FrameBuffer * frame); bool egl_desktop_setup (EGL_Desktop * desktop, const LG_RendererFormat format);
bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame);
bool egl_desktop_render(EGL_Desktop * desktop, const float x, const float y, const float scaleX, const float scaleY, const bool nearest); bool egl_desktop_render(EGL_Desktop * desktop, const float x, const float y, const float scaleX, const float scaleY, const bool nearest);

View File

@ -308,20 +308,10 @@ bool egl_on_mouse_event(void * opaque, const bool visible, const int x, const in
return true; return true;
} }
bool egl_on_frame_event(void * opaque, const LG_RendererFormat format, const FrameBuffer * frame) bool egl_on_frame_format(void * opaque, const LG_RendererFormat format)
{ {
struct Inst * this = (struct Inst *)opaque; struct Inst * this = (struct Inst *)opaque;
const bool sourceChanged = ( memcpy(&this->format, &format, sizeof(LG_RendererFormat));
this->format.type != format.type ||
this->format.width != format.width ||
this->format.height != format.height ||
this->format.pitch != format.pitch
);
if (sourceChanged)
memcpy(&this->format, &format, sizeof(LG_RendererFormat));
this->useNearest = this->width < format.width || this->height < format.height;
/* this event runs in a second thread so we need to init it here */ /* this event runs in a second thread so we need to init it here */
if (!this->frameContext) if (!this->frameContext)
@ -344,7 +334,15 @@ bool egl_on_frame_event(void * opaque, const LG_RendererFormat format, const Fra
} }
} }
if (!egl_desktop_update(this->desktop, sourceChanged, format, frame)) this->useNearest = this->width < format.width || this->height < format.height;
return egl_desktop_setup(this->desktop, format);
}
bool egl_on_frame(void * opaque, const FrameBuffer * frame)
{
struct Inst * this = (struct Inst *)opaque;
if (!egl_desktop_update(this->desktop, frame))
{ {
DEBUG_INFO("Failed to to update the desktop"); DEBUG_INFO("Failed to to update the desktop");
return false; return false;
@ -614,18 +612,19 @@ void egl_update_fps(void * opaque, const float avgUPS, const float avgFPS)
struct LG_Renderer LGR_EGL = struct LG_Renderer LGR_EGL =
{ {
.get_name = egl_get_name, .get_name = egl_get_name,
.setup = egl_setup, .setup = egl_setup,
.create = egl_create, .create = egl_create,
.initialize = egl_initialize, .initialize = egl_initialize,
.deinitialize = egl_deinitialize, .deinitialize = egl_deinitialize,
.on_restart = egl_on_restart, .on_restart = egl_on_restart,
.on_resize = egl_on_resize, .on_resize = egl_on_resize,
.on_mouse_shape = egl_on_mouse_shape, .on_mouse_shape = egl_on_mouse_shape,
.on_mouse_event = egl_on_mouse_event, .on_mouse_event = egl_on_mouse_event,
.on_frame_event = egl_on_frame_event, .on_frame_format = egl_on_frame_format,
.on_alert = egl_on_alert, .on_frame = egl_on_frame,
.render_startup = egl_render_startup, .on_alert = egl_on_alert,
.render = egl_render, .render_startup = egl_render_startup,
.update_fps = egl_update_fps .render = egl_render,
.update_fps = egl_update_fps
}; };

View File

@ -375,36 +375,20 @@ bool opengl_on_mouse_event(void * opaque, const bool visible, const int x, const
return false; return false;
} }
bool opengl_on_frame_event(void * opaque, const LG_RendererFormat format, const FrameBuffer * frame) bool opengl_on_frame_format(void * opaque, const LG_RendererFormat format)
{ {
struct Inst * this = (struct Inst *)opaque; struct Inst * this = (struct Inst *)opaque;
if (!this)
{
DEBUG_ERROR("Invalid opaque pointer");
return false;
}
LG_LOCK(this->formatLock); LG_LOCK(this->formatLock);
if (this->reconfigure) memcpy(&this->format, &format, sizeof(LG_RendererFormat));
{ this->reconfigure = true;
LG_UNLOCK(this->formatLock);
return true;
}
if (!this->configured ||
this->format.type != format.type ||
this->format.width != format.width ||
this->format.height != format.height ||
this->format.stride != format.stride ||
this->format.bpp != format.bpp
)
{
memcpy(&this->format, &format, sizeof(LG_RendererFormat));
this->reconfigure = true;
LG_UNLOCK(this->formatLock);
return true;
}
LG_UNLOCK(this->formatLock); LG_UNLOCK(this->formatLock);
return true;
}
bool opengl_on_frame(void * opaque, const FrameBuffer * frame)
{
struct Inst * this = (struct Inst *)opaque;
LG_LOCK(this->syncLock); LG_LOCK(this->syncLock);
this->frame = frame; this->frame = frame;
@ -829,21 +813,22 @@ static void render_wait(struct Inst * this)
const LG_Renderer LGR_OpenGL = const LG_Renderer LGR_OpenGL =
{ {
.get_name = opengl_get_name, .get_name = opengl_get_name,
.setup = opengl_setup, .setup = opengl_setup,
.create = opengl_create, .create = opengl_create,
.initialize = opengl_initialize, .initialize = opengl_initialize,
.deinitialize = opengl_deinitialize, .deinitialize = opengl_deinitialize,
.on_restart = opengl_on_restart, .on_restart = opengl_on_restart,
.on_resize = opengl_on_resize, .on_resize = opengl_on_resize,
.on_mouse_shape = opengl_on_mouse_shape, .on_mouse_shape = opengl_on_mouse_shape,
.on_mouse_event = opengl_on_mouse_event, .on_mouse_event = opengl_on_mouse_event,
.on_frame_event = opengl_on_frame_event, .on_frame_format = opengl_on_frame_format,
.on_alert = opengl_on_alert, .on_frame = opengl_on_frame,
.render_startup = opengl_render_startup, .on_alert = opengl_on_alert,
.render = opengl_render, .render_startup = opengl_render_startup,
.update_fps = opengl_update_fps .render = opengl_render,
.update_fps = opengl_update_fps
}; };
static bool _check_gl_error(unsigned int line, const char * name) static bool _check_gl_error(unsigned int line, const char * name)

View File

@ -471,6 +471,18 @@ static int frameThread(void * unused)
formatValid = true; formatValid = true;
formatVer = frame->formatVer; formatVer = frame->formatVer;
DEBUG_INFO("Format: %s %ux%u %u %u",
FrameTypeStr[frame->type],
frame->width, frame->height,
frame->stride, frame->pitch);
if (!state.lgr->on_frame_format(state.lgrData, lgrFormat))
{
DEBUG_ERROR("renderer failed to configure format");
state.state = APP_STATE_SHUTDOWN;
break;
}
} }
if (lgrFormat.width != state.srcSize.x || lgrFormat.height != state.srcSize.y) if (lgrFormat.width != state.srcSize.x || lgrFormat.height != state.srcSize.y)
@ -485,9 +497,10 @@ static int frameThread(void * unused)
} }
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset); FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset);
if (!state.lgr->on_frame_event(state.lgrData, lgrFormat, fb)) if (!state.lgr->on_frame(state.lgrData, fb))
{ {
DEBUG_ERROR("renderer on frame event returned failure"); lgmpClientMessageDone(queue);
DEBUG_ERROR("renderer on frame returned failure");
state.state = APP_STATE_SHUTDOWN; state.state = APP_STATE_SHUTDOWN;
break; break;
} }

View File

@ -18,6 +18,7 @@ set(COMMON_SOURCES
src/stringlist.c src/stringlist.c
src/option.c src/option.c
src/framebuffer.c src/framebuffer.c
src/KVMFR.c
) )
add_library(lg_common STATIC ${COMMON_SOURCES}) add_library(lg_common STATIC ${COMMON_SOURCES})

View File

@ -35,6 +35,8 @@ typedef enum FrameType
} }
FrameType; FrameType;
extern const char * FrameTypeStr[FRAME_TYPE_MAX];
enum enum
{ {
CURSOR_FLAG_POSITION = 0x1, CURSOR_FLAG_POSITION = 0x1,

30
common/src/KVMFR.c Normal file
View File

@ -0,0 +1,30 @@
/*
KVMGFX Client - A KVM Client for VGA Passthrough
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
https://looking-glass.hostfission.com
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common/KVMFR.h"
const char * FrameTypeStr[FRAME_TYPE_MAX] =
{
"FRAME_TYPE_INVALID",
"FRAME_TYPE_BGRA",
"FRAME_TYPE_RGBA",
"FRAME_TYPE_RGBA10",
"FRAME_TYPE_RGBA16F",
"FRAME_TYPE_YUV420"
};