diff --git a/client/include/interface/renderer.h b/client/include/interface/renderer.h index 115d8c22..ee749f7d 100644 --- a/client/include/interface/renderer.h +++ b/client/include/interface/renderer.h @@ -94,6 +94,8 @@ typedef enum LG_RendererCursor } LG_RendererCursor; +typedef struct LG_Renderer LG_Renderer; + typedef struct LG_RendererOps { /* returns the friendly name of the renderer */ @@ -105,62 +107,69 @@ typedef struct LG_RendererOps /* creates an instance of the renderer * Context: lg_run */ - bool (*create)(void ** opaque, const LG_RendererParams params, + bool (*create)(LG_Renderer ** renderer, const LG_RendererParams params, bool * needsOpenGL); /* initializes the renderer for use * Context: lg_run */ - bool (*initialize)(void * opaque); + bool (*initialize)(LG_Renderer * renderer); /* deinitializes & frees the renderer * Context: lg_run & renderThread */ - void (*deinitialize)(void * opaque); + void (*deinitialize)(LG_Renderer * renderer); /* returns true if the specified feature is supported * Context: renderThread */ - bool (*supports)(void * opaque, LG_RendererSupport support); + bool (*supports)(LG_Renderer * renderer, LG_RendererSupport support); /* called when the renderer is to reset it's state * Context: lg_run & frameThread */ - void (*on_restart)(void * opaque); + void (*on_restart)(LG_Renderer * renderer); /* called when the viewport has been resized * Context: renderThrtead */ - void (*on_resize)(void * opaque, const int width, const int height, + void (*on_resize)(LG_Renderer * renderer, const int width, const int height, const double scale, const LG_RendererRect destRect, LG_RendererRotate rotate); /* called when the mouse shape has changed * Context: cursorThread */ - bool (*on_mouse_shape)(void * opaque, const LG_RendererCursor cursor, - const int width, const int height, const int pitch, - const uint8_t * data); + bool (*on_mouse_shape)(LG_Renderer * renderer, const LG_RendererCursor cursor, + const int width, const int height, const int pitch, const uint8_t * data); /* called when the mouse has moved or changed visibillity * Context: cursorThread */ - bool (*on_mouse_event)(void * opaque, const bool visible, - const int x, const int y); + bool (*on_mouse_event)(LG_Renderer * renderer, const bool visible, const int x, + const int y); /* called when the frame format has changed * Context: frameThread */ - bool (*on_frame_format)(void * opaque, const LG_RendererFormat format); + bool (*on_frame_format)(LG_Renderer * renderer, + const LG_RendererFormat format); /* called when there is a new frame * Context: frameThread */ - bool (*on_frame)(void * opaque, const FrameBuffer * frame, int dmaFD, + bool (*on_frame)(LG_Renderer * renderer, const FrameBuffer * frame, int dmaFD, const FrameDamageRect * damage, int damageCount); /* called when the rederer is to startup * Context: renderThread */ - bool (*render_startup)(void * opaque, bool useDMA); + bool (*render_startup)(LG_Renderer * renderer, bool useDMA); /* returns if the render method must be called even if nothing has changed. * Context: renderThread */ - bool (*needs_render)(void * opaque); + bool (*needs_render)(LG_Renderer * renderer); /* called to render the scene * Context: renderThread */ - bool (*render)(void * opaque, LG_RendererRotate rotate, const bool newFrame, - const bool invalidateWindow, void (*preSwap)(void * udata), void * udata); + bool (*render)(LG_Renderer * renderer, LG_RendererRotate rotate, + const bool newFrame, const bool invalidateWindow, + void (*preSwap)(void * udata), void * udata); } LG_RendererOps; + +typedef struct LG_Renderer +{ + LG_RendererOps ops; +} +LG_Renderer; diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index ec972441..1a5f66c2 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -63,6 +63,8 @@ struct Options struct Inst { + LG_Renderer base; + bool dmaSupport; LG_RendererParams params; struct Options opt; @@ -192,22 +194,23 @@ static void egl_setup(void) option_register(egl_options); } -static bool egl_create(void ** opaque, const LG_RendererParams params, bool * needsOpenGL) +static bool egl_create(LG_Renderer ** renderer, const LG_RendererParams params, + bool * needsOpenGL) { // check if EGL is even available if (!eglQueryString(EGL_NO_DISPLAY, EGL_VERSION)) return false; // create our local storage - *opaque = calloc(1, sizeof(struct Inst)); - if (!*opaque) + struct Inst * this = calloc(1, sizeof(*this)); + if (!this) { - DEBUG_INFO("Failed to allocate %lu bytes", sizeof(struct Inst)); + DEBUG_INFO("Failed to allocate %lu bytes", sizeof(*this)); return false; } + *renderer = &this->base; // safe off parameteres and init our default option values - struct Inst * this = (struct Inst *)*opaque; memcpy(&this->params, ¶ms, sizeof(LG_RendererParams)); this->opt.vsync = option_get_bool("egl", "vsync"); @@ -231,16 +234,16 @@ static bool egl_create(void ** opaque, const LG_RendererParams params, bool * ne return true; } -static bool egl_initialize(void * opaque) +static bool egl_initialize(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); DEBUG_INFO("Double buffering is %s", this->opt.doubleBuffer ? "on" : "off"); return true; } -static void egl_deinitialize(void * opaque) +static void egl_deinitialize(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); if (this->imgui) ImGui_ImplOpenGL3_Shutdown(); @@ -269,9 +272,9 @@ static void egl_deinitialize(void * opaque) free(this); } -static bool egl_supports(void * opaque, LG_RendererSupport flag) +static bool egl_supports(LG_Renderer * renderer, LG_RendererSupport flag) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); switch(flag) { @@ -283,9 +286,9 @@ static bool egl_supports(void * opaque, LG_RendererSupport flag) } } -static void egl_on_restart(void * opaque) +static void egl_on_restart(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); eglDestroyContext(this->display, this->frameContext); this->frameContext = NULL; @@ -397,10 +400,10 @@ static void egl_update_scale_type(struct Inst * this) this->scaleType = EGL_DESKTOP_UPSCALE; } -static void egl_on_resize(void * opaque, const int width, const int height, const double scale, +static void egl_on_resize(LG_Renderer * renderer, const int width, const int height, const double scale, const LG_RendererRect destRect, LG_RendererRotate rotate) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); this->width = width * scale; this->height = height * scale; @@ -444,11 +447,11 @@ static void egl_on_resize(void * opaque, const int width, const int height, cons egl_damage_resize(this->damage, this->translateX, this->translateY, this->scaleX, this->scaleY); } -static bool egl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, +static bool egl_on_mouse_shape(LG_Renderer * renderer, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); if (!egl_cursor_set_shape(this->cursor, cursor, width, height, pitch, data)) { @@ -463,9 +466,9 @@ static bool egl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, return true; } -static bool egl_on_mouse_event(void * opaque, const bool visible, const int x, const int y) +static bool egl_on_mouse_event(LG_Renderer * renderer, const bool visible, const int x, const int y) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); this->cursorVisible = visible; this->cursorX = x; this->cursorY = y; @@ -473,9 +476,9 @@ static bool egl_on_mouse_event(void * opaque, const bool visible, const int x, c return true; } -static bool egl_on_frame_format(void * opaque, const LG_RendererFormat format) +static bool egl_on_frame_format(LG_Renderer * renderer, const LG_RendererFormat format) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); memcpy(&this->format, &format, sizeof(LG_RendererFormat)); this->formatValid = true; @@ -506,10 +509,10 @@ static bool egl_on_frame_format(void * opaque, const LG_RendererFormat format) return egl_desktop_setup(this->desktop, format); } -static bool egl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd, +static bool egl_on_frame(LG_Renderer * renderer, const FrameBuffer * frame, int dmaFd, const FrameDamageRect * damageRects, int damageRectsCount) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); uint64_t start = nanotime(); if (!egl_desktop_update(this->desktop, frame, dmaFd, damageRects, damageRectsCount)) @@ -621,9 +624,9 @@ static void egl_config_ui(void * opaque) egl_desktop_config_ui(this->desktop); } -static bool egl_render_startup(void * opaque, bool useDMA) +static bool egl_render_startup(LG_Renderer * renderer, bool useDMA) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); this->nativeWind = app_getEGLNativeWindow(); if (!this->nativeWind) @@ -815,9 +818,9 @@ static bool egl_render_startup(void * opaque, bool useDMA) return true; } -static bool egl_needs_render(void * opaque) +static bool egl_needs_render(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); return !this->waitDone; } @@ -865,10 +868,11 @@ inline static void renderLetterBox(struct Inst * this) } } -static bool egl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame, - const bool invalidateWindow, void (*preSwap)(void * udata), void * udata) +static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, + const bool newFrame, const bool invalidateWindow, + void (*preSwap)(void * udata), void * udata) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); EGLint bufferAge = egl_buffer_age(this); bool renderAll = invalidateWindow || !this->start || this->hadOverlay || bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE; diff --git a/client/renderers/OpenGL/opengl.c b/client/renderers/OpenGL/opengl.c index efda228b..bf1d40fa 100644 --- a/client/renderers/OpenGL/opengl.c +++ b/client/renderers/OpenGL/opengl.c @@ -36,6 +36,7 @@ #include "common/framebuffer.h" #include "common/locking.h" #include "ll.h" +#include "util.h" #define BUFFER_COUNT 2 @@ -102,6 +103,8 @@ struct OpenGL_Options struct Inst { + LG_Renderer base; + LG_RendererParams params; struct OpenGL_Options opt; @@ -186,21 +189,19 @@ static void opengl_setup(void) option_register(opengl_options); } -bool opengl_create(void ** opaque, const LG_RendererParams params, +bool opengl_create(LG_Renderer ** renderer, const LG_RendererParams params, bool * needsOpenGL) { // create our local storage - *opaque = malloc(sizeof(struct Inst)); - if (!*opaque) + struct Inst * this = calloc(1, sizeof(*this)); + if (!this) { - DEBUG_INFO("Failed to allocate %lu bytes", sizeof(struct Inst)); + DEBUG_INFO("Failed to allocate %lu bytes", sizeof(*this)); return false; } - memset(*opaque, 0, sizeof(struct Inst)); + *renderer = &this->base; - struct Inst * this = (struct Inst *)*opaque; memcpy(&this->params, ¶ms, sizeof(LG_RendererParams)); - this->opt.mipmap = option_get_bool("opengl", "mipmap" ); this->opt.vsync = option_get_bool("opengl", "vsync" ); this->opt.preventBuffer = option_get_bool("opengl", "preventBuffer"); @@ -215,22 +216,18 @@ bool opengl_create(void ** opaque, const LG_RendererParams params, return true; } -bool opengl_initialize(void * opaque) +bool opengl_initialize(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; - if (!this) - return false; + struct Inst * this = UPCAST(struct Inst, renderer); this->waiting = true; this->waitDone = false; return true; } -void opengl_deinitialize(void * opaque) +void opengl_deinitialize(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; - if (!this) - return; + struct Inst * this = UPCAST(struct Inst, renderer); if (this->renderStarted) { @@ -264,16 +261,17 @@ void opengl_deinitialize(void * opaque) free(this); } -void opengl_on_restart(void * opaque) +void opengl_on_restart(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); + this->waiting = true; } -void opengl_on_resize(void * opaque, const int width, const int height, const double scale, +void opengl_on_resize(LG_Renderer * renderer, const int width, const int height, const double scale, const LG_RendererRect destRect, LG_RendererRotate rotate) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); this->window.x = width * scale; this->window.y = height * scale; @@ -312,12 +310,10 @@ void opengl_on_resize(void * opaque, const int width, const int height, const do ImGui_ImplOpenGL2_NewFrame(); } -bool opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, +bool opengl_on_mouse_shape(LG_Renderer * renderer, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data) { - struct Inst * this = (struct Inst *)opaque; - if (!this) - return false; + struct Inst * this = UPCAST(struct Inst, renderer); LG_LOCK(this->mouseLock); this->mouseCursor = cursor; @@ -341,11 +337,9 @@ bool opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, return true; } -bool opengl_on_mouse_event(void * opaque, const bool visible, const int x, const int y) +bool opengl_on_mouse_event(LG_Renderer * renderer, const bool visible, const int x, const int y) { - struct Inst * this = (struct Inst *)opaque; - if (!this) - return false; + struct Inst * this = UPCAST(struct Inst, renderer); if (this->mousePos.x == x && this->mousePos.y == y && this->mouseVisible == visible) return true; @@ -357,9 +351,9 @@ bool opengl_on_mouse_event(void * opaque, const bool visible, const int x, const return false; } -bool opengl_on_frame_format(void * opaque, const LG_RendererFormat format) +bool opengl_on_frame_format(LG_Renderer * renderer, const LG_RendererFormat format) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); LG_LOCK(this->formatLock); memcpy(&this->format, &format, sizeof(LG_RendererFormat)); @@ -368,10 +362,10 @@ bool opengl_on_frame_format(void * opaque, const LG_RendererFormat format) return true; } -bool opengl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd, +bool opengl_on_frame(LG_Renderer * renderer, const FrameBuffer * frame, int dmaFd, const FrameDamageRect * damage, int damageCount) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); LG_LOCK(this->frameLock); this->frame = frame; @@ -393,9 +387,9 @@ bool opengl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd, return true; } -bool opengl_render_startup(void * opaque, bool useDMA) +bool opengl_render_startup(LG_Renderer * renderer, bool useDMA) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); this->glContext = app_glCreateContext(); if (!this->glContext) @@ -456,18 +450,16 @@ bool opengl_render_startup(void * opaque, bool useDMA) return true; } -static bool opengl_needs_render(void * opaque) +static bool opengl_needs_render(LG_Renderer * renderer) { - struct Inst * this = (struct Inst *)opaque; + struct Inst * this = UPCAST(struct Inst, renderer); return !this->waitDone; } -bool opengl_render(void * opaque, LG_RendererRotate rotate, const bool newFrame, +bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate, const bool newFrame, const bool invalidateWindow, void (*preSwap)(void * udata), void * udata) { - struct Inst * this = (struct Inst *)opaque; - if (!this) - return false; + struct Inst * this = UPCAST(struct Inst, renderer); switch(configure(this)) { diff --git a/client/src/main.c b/client/src/main.c index 9baf86cb..70f832ef 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -147,7 +147,7 @@ static void preSwapCallback(void * udata) static int renderThread(void * unused) { - if (!g_state.lgr->render_startup(g_state.lgrData, g_state.useDMA)) + if (!RENDERER(render_startup, g_state.useDMA)) { g_state.state = APP_STATE_SHUTDOWN; @@ -156,8 +156,7 @@ static int renderThread(void * unused) return 1; } - if (g_state.lgr->supports && - !g_state.lgr->supports(g_state.lgrData, LG_SUPPORTS_DMABUF)) + if (g_state.lgr->ops.supports && !RENDERER(supports, LG_SUPPORTS_DMABUF)) g_state.useDMA = false; /* start up the fps timer */ @@ -191,7 +190,7 @@ static int renderThread(void * unused) && !forceRender && !pending && !app_overlayNeedsRender() - && !g_state.lgr->needs_render(g_state.lgrData)) + && !RENDERER(needs_render)) { if (g_state.ds->skipFrame) g_state.ds->skipFrame(); @@ -236,7 +235,7 @@ static int renderThread(void * unused) DEBUG_FATAL("Failed to build font atlas: %s (%s)", g_params.uiFont, g_state.fontName); if (g_state.lgr) - g_state.lgr->on_resize(g_state.lgrData, g_state.windowW, g_state.windowH, + RENDERER(on_resize, g_state.windowW, g_state.windowH, g_state.windowScale, g_state.dstRect, g_params.winRotate); atomic_compare_exchange_weak(&g_state.lgrResize, &resize, 0); } @@ -251,8 +250,8 @@ static int renderThread(void * unused) const uint64_t renderStart = nanotime(); LG_LOCK(g_state.lgrLock); - if (!g_state.lgr->render(g_state.lgrData, g_params.winRotate, newFrame, - invalidate, preSwapCallback, (void *)&renderStart)) + if (!RENDERER(render, g_params.winRotate, newFrame, invalidate, + preSwapCallback, (void *)&renderStart)) { LG_UNLOCK(g_state.lgrLock); break; @@ -295,7 +294,7 @@ static int renderThread(void * unused) core_stopFrameThread(); - g_state.lgr->deinitialize(g_state.lgrData); + RENDERER(deinitialize); g_state.lgr = NULL; LG_LOCK_FREE(g_state.lgrLock); @@ -338,9 +337,7 @@ static int cursorThread(void * unused) if (g_cursor.redraw && g_cursor.guest.valid) { g_cursor.redraw = false; - g_state.lgr->on_mouse_event - ( - g_state.lgrData, + RENDERER(on_mouse_event, g_cursor.guest.visible && (g_cursor.draw || !g_params.useSpiceInput), g_cursor.guest.x, g_cursor.guest.y @@ -403,8 +400,7 @@ static int cursorThread(void * unused) g_cursor.guest.hy = cursor->hy; const uint8_t * data = (const uint8_t *)(cursor + 1); - if (!g_state.lgr->on_mouse_shape( - g_state.lgrData, + if (!RENDERER(on_mouse_shape, cursorType, cursor->width, cursor->height, @@ -437,9 +433,7 @@ static int cursorThread(void * unused) g_cursor.redraw = false; - g_state.lgr->on_mouse_event - ( - g_state.lgrData, + RENDERER(on_mouse_event, g_cursor.guest.visible && (g_cursor.draw || !g_params.useSpiceInput), g_cursor.guest.x, g_cursor.guest.y @@ -616,7 +610,7 @@ int main_frameThread(void * unused) frame->rotation); LG_LOCK(g_state.lgrLock); - if (!g_state.lgr->on_frame_format(g_state.lgrData, lgrFormat)) + if (!RENDERER(on_frame_format, lgrFormat)) { DEBUG_ERROR("renderer failed to configure format"); g_state.state = APP_STATE_SHUTDOWN; @@ -683,8 +677,8 @@ int main_frameThread(void * unused) } FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset); - if (!g_state.lgr->on_frame(g_state.lgrData, fb, g_state.useDMA ? dma->fd : -1, - frame->damageRects, frame->damageRectsCount)) + if (!RENDERER(on_frame, fb, g_state.useDMA ? dma->fd : -1, + frame->damageRects, frame->damageRectsCount)) { lgmpClientMessageDone(queue); DEBUG_ERROR("renderer on frame returned failure"); @@ -723,7 +717,7 @@ int main_frameThread(void * unused) } lgmpClientUnsubscribe(&queue); - g_state.lgr->on_restart(g_state.lgrData); + RENDERER(on_restart); if (g_state.useDMA) { @@ -786,15 +780,22 @@ static bool tryRenderer(const int index, const LG_RendererParams lgrParams, } // create the renderer - g_state.lgrData = NULL; - *needsOpenGL = false; - if (!r->create(&g_state.lgrData, lgrParams, needsOpenGL)) + g_state.lgr = NULL; + *needsOpenGL = false; + if (!r->create(&g_state.lgr, lgrParams, needsOpenGL)) + { + g_state.lgr = NULL; return false; + } + + // init the ops member + memcpy(&g_state.lgr->ops, r, sizeof(*r)); // initialize the renderer - if (!r->initialize(g_state.lgrData)) + if (!r->initialize(g_state.lgr)) { - r->deinitialize(g_state.lgrData); + r->deinitialize(g_state.lgr); + g_state.lgr = NULL; return false; } @@ -924,7 +925,6 @@ static int lg_run(void) DEBUG_ERROR("Forced renderer failed to iniailize"); return -1; } - g_state.lgr = LG_Renderers[g_params.forceRendererIndex]; } else { @@ -932,10 +932,7 @@ static int lg_run(void) for(unsigned int i = 0; i < LG_RENDERER_COUNT; ++i) { if (tryRenderer(i, lgrParams, &needsOpenGL)) - { - g_state.lgr = LG_Renderers[i]; break; - } } } @@ -1176,7 +1173,7 @@ restart: lgInit(); - g_state.lgr->on_restart(g_state.lgrData); + RENDERER(on_restart); DEBUG_INFO("Waiting for the host to restart..."); goto restart; diff --git a/client/src/main.h b/client/src/main.h index 9982e6e4..1457a1d2 100644 --- a/client/src/main.h +++ b/client/src/main.h @@ -89,8 +89,7 @@ struct AppState bool posInfoValid; bool alignToGuest; - const LG_RendererOps * lgr; - void * lgrData; + LG_Renderer * lgr; atomic_int lgrResize; LG_Lock lgrLock; bool useDMA; @@ -284,3 +283,5 @@ extern struct CursorState g_cursor; extern struct AppParams g_params; int main_frameThread(void * unused); + +#define RENDERER(fn, ...) g_state.lgr->ops.fn(g_state.lgr, ##__VA_ARGS__)