diff --git a/client/include/app.h b/client/include/app.h index 41837523..ed6a5de5 100644 --- a/client/include/app.h +++ b/client/include/app.h @@ -46,6 +46,7 @@ bool app_isFormatValid(void); void app_updateCursorPos(double x, double y); void app_updateWindowPos(int x, int y); void app_handleResizeEvent(int w, int h, double scale, const struct Border border); +void app_invalidateWindow(void); void app_handleMouseRelative(double normx, double normy, double rawx, double rawy); diff --git a/client/include/interface/renderer.h b/client/include/interface/renderer.h index 3a0e9eaf..6b84a869 100644 --- a/client/include/interface/renderer.h +++ b/client/include/interface/renderer.h @@ -112,7 +112,7 @@ typedef bool (* LG_RendererOnMouseEvent )(void * opaque, const bool visi typedef bool (* LG_RendererOnFrameFormat)(void * opaque, const LG_RendererFormat format, bool useDMA); typedef bool (* LG_RendererOnFrame )(void * opaque, const FrameBuffer * frame, int dmaFD, const FrameDamageRect * damage, int damageCount); typedef bool (* LG_RendererRenderStartup)(void * opaque); -typedef bool (* LG_RendererRender )(void * opaque, LG_RendererRotate rotate, const bool newFrame); +typedef bool (* LG_RendererRender )(void * opaque, LG_RendererRotate rotate, const bool newFrame, const bool invalidateWindow); typedef struct LG_Renderer { diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index b1007181..05d9cc21 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -791,7 +791,8 @@ bool egl_render_startup(void * opaque) return true; } -bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame) +bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame, + const bool invalidateWindow) { struct Inst * this = (struct Inst *)opaque; @@ -856,6 +857,7 @@ bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame) } hasOverlay |= egl_damage_render(this->damage, newFrame ? desktopDamage : NULL); + hasOverlay |= invalidateWindow; struct Rect damage[KVMFR_MAX_DAMAGE_RECTS + MAX_OVERLAY_RECTS + 2]; int damageIdx = app_renderOverlay(damage, MAX_OVERLAY_RECTS); diff --git a/client/renderers/OpenGL/opengl.c b/client/renderers/OpenGL/opengl.c index 1261cd6b..c5acbd61 100644 --- a/client/renderers/OpenGL/opengl.c +++ b/client/renderers/OpenGL/opengl.c @@ -456,7 +456,8 @@ bool opengl_render_startup(void * opaque) return true; } -bool opengl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame) +bool opengl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame, + const bool invalidateWindow) { struct Inst * this = (struct Inst *)opaque; if (!this) diff --git a/client/src/app.c b/client/src/app.c index 5a21b694..ff6a801d 100644 --- a/client/src/app.c +++ b/client/src/app.c @@ -418,6 +418,12 @@ void app_handleResizeEvent(int w, int h, double scale, const struct Border borde } } +void app_invalidateWindow(void) +{ + atomic_store(&g_state.invalidateWindow, true); + lgSignalEvent(g_state.frameEvent); +} + void app_handleCloseEvent(void) { if (!g_params.ignoreQuit || !g_cursor.inView) diff --git a/client/src/main.c b/client/src/main.c index 9e7989aa..ee22ffca 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -64,7 +64,6 @@ static int cursorThread(void * unused); static int renderThread(void * unused); static LGEvent *e_startup = NULL; -static LGEvent *e_frame = NULL; static LGThread *t_spice = NULL; static LGThread *t_render = NULL; static LGThread *t_cursor = NULL; @@ -170,7 +169,7 @@ static int renderThread(void * unused) { float ups = atomic_load_explicit(&g_state.ups, memory_order_relaxed); - if (!lgWaitEventAbs(e_frame, &time) || ups > g_params.fpsMin) + if (!lgWaitEventAbs(g_state.frameEvent, &time) || ups > g_params.fpsMin) { /* only update the time if we woke up early */ clock_gettime(CLOCK_MONOTONIC, &time); @@ -208,8 +207,11 @@ static int renderThread(void * unused) const bool newFrame = frameCount != lastFrameCount; lastFrameCount = frameCount; + const bool invalidate = atomic_exchange(&g_state.invalidateWindow, false); + LG_LOCK(g_state.lgrLock); - if (!g_state.lgr->render(g_state.lgrData, g_params.winRotate, newFrame)) + if (!g_state.lgr->render(g_state.lgrData, g_params.winRotate, newFrame, + invalidate)) { LG_UNLOCK(g_state.lgrLock); break; @@ -306,7 +308,7 @@ static int cursorThread(void * unused) ); if (!g_state.stopVideo) - lgSignalEvent(e_frame); + lgSignalEvent(g_state.frameEvent); } const struct timespec req = @@ -405,7 +407,7 @@ static int cursorThread(void * unused) ); if (g_params.mouseRedraw && g_cursor.guest.visible && !g_state.stopVideo) - lgSignalEvent(e_frame); + lgSignalEvent(g_state.frameEvent); } lgmpClientUnsubscribe(&queue); @@ -678,7 +680,7 @@ int main_frameThread(void * unused) g_state.lastFrameTimeValid = true; atomic_fetch_add_explicit(&g_state.frameCount, 1, memory_order_relaxed); - lgSignalEvent(e_frame); + lgSignalEvent(g_state.frameEvent); lgmpClientMessageDone(queue); } @@ -950,7 +952,7 @@ static int lg_run(void) } // setup the new frame event - if (!(e_frame = lgCreateEvent(true, 0))) + if (!(g_state.frameEvent = lgCreateEvent(true, 0))) { DEBUG_ERROR("failed to create the frame event"); return -1; @@ -1092,7 +1094,7 @@ restart: if (g_state.state == APP_STATE_RESTART) { lgSignalEvent(e_startup); - lgSignalEvent(e_frame); + lgSignalEvent(g_state.frameEvent); core_stopFrameThread(); @@ -1116,7 +1118,7 @@ static void lg_shutdown(void) if (t_render) { lgSignalEvent(e_startup); - lgSignalEvent(e_frame); + lgSignalEvent(g_state.frameEvent); lgJoinThread(t_render, NULL); } @@ -1129,10 +1131,10 @@ static void lg_shutdown(void) g_state.overlays = NULL; } - if (e_frame) + if (g_state.frameEvent) { - lgFreeEvent(e_frame); - e_frame = NULL; + lgFreeEvent(g_state.frameEvent); + g_state.frameEvent = NULL; } if (e_startup) diff --git a/client/src/main.h b/client/src/main.h index 6d0cf3bf..8f166152 100644 --- a/client/src/main.h +++ b/client/src/main.h @@ -30,6 +30,7 @@ #include "common/ivshmem.h" #include "common/locking.h" #include "common/ringbuffer.h" +#include "common/event.h" #include "spice/spice.h" #include @@ -103,6 +104,8 @@ struct AppState PLGMPClientQueue pointerQueue; LGThread * frameThread; + LGEvent * frameEvent; + atomic_bool invalidateWindow; bool formatValid; atomic_uint_least64_t frameTime; uint64_t lastFrameTime;