From 5de175c1f3153ab3c6f1afd0f7178efa38d59e54 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Fri, 27 May 2022 02:07:20 +1000 Subject: [PATCH] [client] all: unify the LG splash screen into an overlay --- client/CMakeLists.txt | 1 + client/include/interface/overlay.h | 4 +- client/renderers/EGL/CMakeLists.txt | 5 - client/renderers/EGL/egl.c | 63 +--------- client/renderers/EGL/splash.c | 178 ---------------------------- client/renderers/EGL/splash.h | 30 ----- client/renderers/OpenGL/opengl.c | 154 ++---------------------- client/src/app.c | 1 + client/src/main.c | 8 +- client/src/overlay/splash.c | 171 ++++++++++++++++++++++++++ client/src/overlays.h | 2 + resources/CMakeLists.txt | 1 + resources/lg-logo.svg | 9 +- 13 files changed, 200 insertions(+), 427 deletions(-) delete mode 100644 client/renderers/EGL/splash.c delete mode 100644 client/renderers/EGL/splash.h create mode 100644 client/src/overlay/splash.c diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 72af8d81..2b25961c 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -139,6 +139,7 @@ set(SOURCES src/overlay_utils.c src/render_queue.c + src/overlay/splash.c src/overlay/alert.c src/overlay/fps.c src/overlay/graphs.c diff --git a/client/include/interface/overlay.h b/client/include/interface/overlay.h index 39cbb2b5..f9e80b46 100644 --- a/client/include/interface/overlay.h +++ b/client/include/interface/overlay.h @@ -25,6 +25,8 @@ #include "common/types.h" +#define TICK_RATE 25 + struct LG_OverlayOps { /* internal name of the overlay for debugging */ @@ -63,7 +65,7 @@ struct LG_OverlayOps int (*render)(void * udata, bool interactive, struct Rect * windowRects, int maxRects); - /* called 25 times a second by the application + /* called TICK_RATE times a second by the application * * Note: This may not run in the same context as `render`! * diff --git a/client/renderers/EGL/CMakeLists.txt b/client/renderers/EGL/CMakeLists.txt index 61161de9..1709794b 100644 --- a/client/renderers/EGL/CMakeLists.txt +++ b/client/renderers/EGL/CMakeLists.txt @@ -55,10 +55,6 @@ build_shaders( shader/cursor_mono.frag shader/damage.vert shader/damage.frag - shader/splash_bg.vert - shader/splash_bg.frag - shader/splash_logo.vert - shader/splash_logo.frag shader/basic.vert shader/ffx_cas.frag shader/ffx_fsr1_easu.frag @@ -87,7 +83,6 @@ add_library(renderer_EGL STATIC desktop_rects.c cursor.c draw.c - splash.c damage.c framebuffer.c postprocess.c diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index 44a4323a..4597ac55 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -45,11 +45,9 @@ #include "damage.h" #include "desktop.h" #include "cursor.h" -#include "splash.h" #include "postprocess.h" #include "util.h" -#define SPLASH_FADE_TIME 1000000 #define MAX_BUFFER_AGE 3 #define DESKTOP_DAMAGE_COUNT 4 #define MAX_ACCUMULATED_DAMAGE ((KVMFR_MAX_DAMAGE_RECTS + MAX_OVERLAY_RECTS + 2) * MAX_BUFFER_AGE) @@ -77,15 +75,11 @@ struct Inst EGL_Desktop * desktop; // the desktop EGL_Cursor * cursor; // the mouse cursor - EGL_Splash * splash; // the splash screen EGL_Damage * damage; // the damage display bool imgui; // if imgui was initialized LG_RendererFormat format; bool formatValid; - bool start; - uint64_t waitFadeTime; - bool waitDone; int width, height; float uiScale; @@ -284,7 +278,6 @@ static void egl_deinitialize(LG_Renderer * renderer) egl_desktopFree(&this->desktop); egl_cursorFree (&this->cursor); - egl_splashFree (&this->splash); egl_damageFree (&this->damage); LG_LOCK_FREE(this->lock); @@ -323,7 +316,6 @@ static void egl_onRestart(LG_Renderer * renderer) eglDestroyContext(this->display, this->frameContext); this->frameContext = NULL; - this->start = false; INTERLOCKED_SECTION(this->desktopDamageLock, { this->desktopDamage[this->desktopDamageIdx].count = -1; @@ -592,8 +584,6 @@ static bool egl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame, int d } ringbuffer_push(this->importTimings, &(float){ (nanotime() - start) * 1e-6f }); - this->start = true; - INTERLOCKED_SECTION(this->desktopDamageLock, { struct DesktopDamage * damage = this->desktopDamage + this->desktopDamageIdx; if (damage->count == -1 || damageRectsCount == 0 || @@ -928,12 +918,6 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA) return false; } - if (!egl_splashInit(&this->splash)) - { - DEBUG_ERROR("Failed to initialize the splash screen"); - return false; - } - if (!egl_damageInit(&this->damage)) { DEBUG_ERROR("Failed to initialize the damage display"); @@ -954,8 +938,8 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA) static bool egl_needsRender(LG_Renderer * renderer) { - struct Inst * this = UPCAST(struct Inst, renderer); - return !this->waitDone; + //struct Inst * this = UPCAST(struct Inst, renderer); + return false; } inline static EGLint egl_bufferAge(struct Inst * this) @@ -1012,7 +996,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, { struct Inst * this = UPCAST(struct Inst, renderer); EGLint bufferAge = egl_bufferAge(this); - bool renderAll = invalidateWindow || !this->start || this->hadOverlay || + bool renderAll = invalidateWindow || this->hadOverlay || bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE || this->showSpice; @@ -1089,7 +1073,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, } ++this->overlayHistoryIdx; - if (this->start && this->destRect.w > 0 && this->destRect.h > 0) + if (this->destRect.w > 0 && this->destRect.h > 0) { if (egl_desktopRender(this->desktop, this->destRect.w, this->destRect.h, @@ -1097,14 +1081,6 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, this->scaleX , this->scaleY , this->scaleType , rotate, renderAll ? NULL : accumulated)) { - if (!this->waitFadeTime) - { - if (!this->params.quickSplash) - this->waitFadeTime = microtime() + SPLASH_FADE_TIME; - else - this->waitDone = true; - } - if (!this->showSpice) cursorState = egl_cursorRender(this->cursor, (this->format.rotate + rotate) % LG_ROTATE_MAX, @@ -1116,35 +1092,6 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, renderLetterBox(this); - if (!this->waitDone) - { - float a = 1.0f; - if (!this->waitFadeTime) - a = 1.0f; - else - { - uint64_t t = microtime(); - if (t > this->waitFadeTime) - this->waitDone = true; - else - { - uint64_t delta = this->waitFadeTime - t; - a = 1.0f / SPLASH_FADE_TIME * delta; - } - } - - if (!this->waitDone) - { - egl_splashRender(this->splash, a, this->splashRatio); - hasOverlay = true; - } - } - else if (!this->start) - { - egl_splashRender(this->splash, 1.0f, this->splashRatio); - hasOverlay = true; - } - hasOverlay |= egl_damageRender(this->damage, rotate, newFrame ? desktopDamage : NULL); hasOverlay |= invalidateWindow; @@ -1271,8 +1218,6 @@ static void egl_spiceShow(LG_Renderer * renderer, bool show) struct Inst * this = UPCAST(struct Inst, renderer); this->showSpice = show; egl_desktopSpiceShow(this->desktop, show); - if (show) - this->start = true; } struct LG_RendererOps LGR_EGL = diff --git a/client/renderers/EGL/splash.c b/client/renderers/EGL/splash.c deleted file mode 100644 index f1c649e9..00000000 --- a/client/renderers/EGL/splash.c +++ /dev/null @@ -1,178 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2022 The Looking Glass Authors - * https://looking-glass.io - * - * 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 "splash.h" -#include "common/debug.h" - -#include "draw.h" -#include "texture.h" -#include "shader.h" -#include "model.h" - -#include -#include -#include -#include - -// these headers are auto generated by cmake -#include "splash_bg.vert.h" -#include "splash_bg.frag.h" -#include "splash_logo.vert.h" -#include "splash_logo.frag.h" - -struct EGL_Splash -{ - EGL_Shader * bgShader; - EGL_Model * bg; - - EGL_Shader * logoShader; - EGL_Model * logo; - - // uniforms - GLint uScale; -}; - -bool egl_splashInit(EGL_Splash ** splash) -{ - *splash = malloc(sizeof(**splash)); - if (!*splash) - { - DEBUG_ERROR("Failed to malloc EGL_Splash"); - return false; - } - - memset(*splash, 0, sizeof(**splash)); - - if (!egl_shaderInit(&(*splash)->bgShader)) - { - DEBUG_ERROR("Failed to initialize the splash bgShader"); - return false; - } - - if (!egl_shaderCompile((*splash)->bgShader, - b_shader_splash_bg_vert, b_shader_splash_bg_vert_size, - b_shader_splash_bg_frag, b_shader_splash_bg_frag_size)) - { - DEBUG_ERROR("Failed to compile the splash bgShader"); - return false; - } - - if (!egl_modelInit(&(*splash)->bg)) - { - DEBUG_ERROR("Failed to intiailize the splash bg model"); - return false; - } - - egl_modelSetDefault((*splash)->bg, false); - - if (!egl_shaderInit(&(*splash)->logoShader)) - { - DEBUG_ERROR("Failed to initialize the splash logoShader"); - return false; - } - - if (!egl_shaderCompile((*splash)->logoShader, - b_shader_splash_logo_vert, b_shader_splash_logo_vert_size, - b_shader_splash_logo_frag, b_shader_splash_logo_frag_size)) - { - DEBUG_ERROR("Failed to compile the splash logoShader"); - return false; - } - - (*splash)->uScale = egl_shaderGetUniform((*splash)->logoShader, "scale"); - - if (!egl_modelInit(&(*splash)->logo)) - { - DEBUG_ERROR("Failed to intiailize the splash model"); - return false; - } - - /* build the splash model */ - #define P(x) ((1.0f/800.0f)*(float)(x)) - egl_drawTorusArc((*splash)->logo, 30, P( 0 ), P(0), P(102), P(98), 0.0f, -M_PI); - egl_drawTorus ((*splash)->logo, 30, P(-100), P(8), P(8 ), P(4 )); - egl_drawTorus ((*splash)->logo, 30, P( 100), P(8), P(8 ), P(4 )); - - egl_drawTorus ((*splash)->logo, 60, P(0), P(0), P(83), P(79)); - egl_drawTorus ((*splash)->logo, 60, P(0), P(0), P(67), P(63)); - - static const GLfloat lines[][12] = - { - { - P( -2), P(-140), 0.0f, - P( -2), P(-100), 0.0f, - P( 2), P(-140), 0.0f, - P( 2), P(-100), 0.0f - }, - { - P(-26), P(-144), 0.0f, - P(-26), P(-140), 0.0f, - P( 26), P(-144), 0.0f, - P( 26), P(-140), 0.0f - }, - { - P(-40), P(-156), 0.0f, - P(-40), P(-152), 0.0f, - P( 40), P(-156), 0.0f, - P( 40), P(-152), 0.0f - } - }; - - egl_modelAddVerts((*splash)->logo, lines[0], NULL, 4); - egl_modelAddVerts((*splash)->logo, lines[1], NULL, 4); - egl_modelAddVerts((*splash)->logo, lines[2], NULL, 4); - - egl_drawTorusArc((*splash)->logo, 10, P(-26), P(-154), P(10), P(14), M_PI , -M_PI / 2.0); - egl_drawTorusArc((*splash)->logo, 10, P( 26), P(-154), P(10), P(14), M_PI / 2.0f, -M_PI / 2.0); - #undef P - - return true; -} - -void egl_splashFree(EGL_Splash ** splash) -{ - if (!*splash) - return; - - egl_modelFree(&(*splash)->bg ); - egl_modelFree(&(*splash)->logo); - - egl_shaderFree(&(*splash)->bgShader ); - egl_shaderFree(&(*splash)->logoShader); - - free(*splash); - *splash = NULL; -} - -void egl_splashRender(EGL_Splash * splash, float alpha, float scaleY) -{ - glEnable(GL_BLEND); - glBlendColor(0, 0, 0, alpha); - glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); - - egl_shaderUse(splash->bgShader); - egl_modelRender(splash->bg); - - egl_shaderUse(splash->logoShader); - glUniform1f(splash->uScale, scaleY); - egl_modelRender(splash->logo); - - glDisable(GL_BLEND); -} diff --git a/client/renderers/EGL/splash.h b/client/renderers/EGL/splash.h deleted file mode 100644 index 6c19b073..00000000 --- a/client/renderers/EGL/splash.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2022 The Looking Glass Authors - * https://looking-glass.io - * - * 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 - */ - -#pragma once - -#include - -typedef struct EGL_Splash EGL_Splash; - -bool egl_splashInit(EGL_Splash ** splash); -void egl_splashFree(EGL_Splash ** splash); - -void egl_splashRender(EGL_Splash * splash, float alpha, float scaleY); diff --git a/client/renderers/OpenGL/opengl.c b/client/renderers/OpenGL/opengl.c index b82bbfba..1f8c7a24 100644 --- a/client/renderers/OpenGL/opengl.c +++ b/client/renderers/OpenGL/opengl.c @@ -45,8 +45,6 @@ #define SPICE_TEXTURE 2 #define TEXTURE_COUNT 3 -#define FADE_TIME 1000000 - static struct Option opengl_options[] = { { @@ -147,11 +145,6 @@ struct Inst GLsync fences[BUFFER_COUNT]; GLuint textures[TEXTURE_COUNT]; - bool start; - bool waiting; - uint64_t waitFadeTime; - bool waitDone; - LG_Lock mouseLock; LG_RendererCursor mouseCursor; int mouseWidth; @@ -182,7 +175,6 @@ static enum ConfigStatus configure(struct Inst * this); static void updateMouseShape(struct Inst * this); static bool drawFrame(struct Inst * this); static void drawMouse(struct Inst * this); -static void renderWait(struct Inst * this); const char * opengl_getName(void) { @@ -222,10 +214,7 @@ bool opengl_create(LG_Renderer ** renderer, const LG_RendererParams params, bool opengl_initialize(LG_Renderer * renderer) { - struct Inst * this = UPCAST(struct Inst, renderer); - - this->waiting = true; - this->waitDone = false; +// struct Inst * this = UPCAST(struct Inst, renderer); return true; } @@ -268,10 +257,7 @@ void opengl_deinitialize(LG_Renderer * renderer) void opengl_onRestart(LG_Renderer * renderer) { - struct Inst * this = UPCAST(struct Inst, renderer); - - this->waiting = true; - this->start = false; +// struct Inst * this = UPCAST(struct Inst, renderer); } static void setupModelView(struct Inst * this) @@ -401,7 +387,6 @@ bool opengl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame, int dmaFd atomic_store_explicit(&this->frameUpdate, true, memory_order_release); LG_UNLOCK(this->frameLock); - this->start = true; return true; } @@ -490,8 +475,8 @@ bool opengl_renderStartup(LG_Renderer * renderer, bool useDMA) static bool opengl_needsRender(LG_Renderer * renderer) { - struct Inst * this = UPCAST(struct Inst, renderer); - return !this->waitDone; +// struct Inst * this = UPCAST(struct Inst, renderer); + return false; } bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate, const bool newFrame, @@ -501,18 +486,6 @@ bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate, const bool setupModelView(this); - if (this->start && this->waiting) - { - this->waiting = false; - if (!this->params.quickSplash) - this->waitFadeTime = microtime() + FADE_TIME; - else - { - glDisable(GL_MULTISAMPLE); - this->waitDone = true; - } - } - switch(configure(this)) { case CONFIG_STATUS_ERROR: @@ -528,21 +501,13 @@ bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate, const bool glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - if (this->waiting) - renderWait(this); + if (this->spiceShow) + glCallList(this->spiceList); else { - if (this->spiceShow) - glCallList(this->spiceList); - else - { - updateMouseShape(this); - glCallList(this->texList + this->texRIndex); - drawMouse(this); - } - - if (!this->waitDone) - renderWait(this); + updateMouseShape(this); + glCallList(this->texList + this->texRIndex); + drawMouse(this); } if (app_renderOverlay(NULL, 0) != 0) @@ -564,105 +529,6 @@ bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate, const bool return true; } -static void drawTorus(float x, float y, float inner, float outer, - unsigned int pts) -{ - glBegin(GL_QUAD_STRIP); - for (unsigned int i = 0; i <= pts; ++i) - { - float angle = (i / (float)pts) * M_PI * 2.0f; - glVertex2f(x + (inner * cos(angle)), y + (inner * sin(angle))); - glVertex2f(x + (outer * cos(angle)), y + (outer * sin(angle))); - } - glEnd(); -} - -static void drawTorusArc(float x, float y, float inner, float outer, - unsigned int pts, float s, float e) -{ - glBegin(GL_QUAD_STRIP); - for (unsigned int i = 0; i <= pts; ++i) - { - float angle = s + ((i / (float)pts) * e); - glVertex2f(x + (inner * cos(angle)), y + (inner * sin(angle))); - glVertex2f(x + (outer * cos(angle)), y + (outer * sin(angle))); - } - glEnd(); -} - -static void renderWait(struct Inst * this) -{ - float a; - if (this->waiting) - a = 1.0f; - else - { - if (this->waitDone) - return; - - uint64_t t = microtime(); - if (t > this->waitFadeTime) - { - glDisable(GL_MULTISAMPLE); - this->waitDone = true; - return; - } - - uint64_t delta = this->waitFadeTime - t; - a = 1.0f / FADE_TIME * delta; - } - - glEnable(GL_BLEND); - glPushMatrix(); - glLoadIdentity(); - glTranslatef(this->window.x / 2.0f, this->window.y / 2.0f, 0.0f); - - //draw the background gradient - glBegin(GL_TRIANGLE_FAN); - glColor4f(0.234375f, 0.015625f, 0.425781f, a); - glVertex2f(0, 0); - glColor4f(0, 0, 0, a); - for (unsigned int i = 0; i <= 100; ++i) - { - float angle = (i / (float)100) * M_PI * 2.0f; - glVertex2f(cos(angle) * this->window.x, sin(angle) * this->window.y); - } - glEnd(); - - // draw the logo - glColor4f(1.0f, 1.0f, 1.0f, a); - glScalef (2.0f, 2.0f, 1.0f); - - drawTorus ( 0, 0, 40, 42, 60); - drawTorus ( 0, 0, 32, 34, 60); - drawTorus (-50, -3, 2, 4, 30); - drawTorus ( 50, -3, 2, 4, 30); - drawTorusArc( 0, 0, 51, 49, 60, 0.0f, M_PI); - - glBegin(GL_QUADS); - glVertex2f(-1 , 50); - glVertex2f(-1 , 76); - glVertex2f( 1 , 76); - glVertex2f( 1 , 50); - glVertex2f(-14, 76); - glVertex2f(-14, 78); - glVertex2f( 14, 78); - glVertex2f( 14, 76); - glVertex2f(-21, 83); - glVertex2f(-21, 85); - glVertex2f( 21, 85); - glVertex2f( 21, 83); - glEnd(); - - drawTorusArc(-14, 83, 5, 7, 10, M_PI , M_PI / 2.0f); - drawTorusArc( 14, 83, 5, 7, 10, M_PI * 1.5f, M_PI / 2.0f); - - //FIXME: draw the diagonal marks on the circle - - glPopMatrix(); - glDisable(GL_BLEND); -} - static void * opengl_createTexture(LG_Renderer * renderer, int width, int height, uint8_t * data) { @@ -811,8 +677,6 @@ static void opengl_spiceShow(LG_Renderer * renderer, bool show) { struct Inst * this = UPCAST(struct Inst, renderer); this->spiceShow = show; - if (show) - this->start = true; } const LG_RendererOps LGR_OpenGL = diff --git a/client/src/app.c b/client/src/app.c index da23f64f..9679d18d 100644 --- a/client/src/app.c +++ b/client/src/app.c @@ -1066,6 +1066,7 @@ void app_useSpiceDisplay(bool enable) { purespice_connectChannel(PS_CHANNEL_DISPLAY); renderQueue_spiceShow(true); + overlaySplash_show(false); } else { diff --git a/client/src/main.c b/client/src/main.c index b9aded73..4ccf2520 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -192,7 +192,7 @@ static int renderThread(void * unused) } LGTimer * tickTimer; - if (!lgCreateTimer(40, tickTimerFn, NULL, &tickTimer)) + if (!lgCreateTimer(1000 / TICK_RATE, tickTimerFn, NULL, &tickTimer)) { lgTimerDestroy(fpsTimer); DEBUG_ERROR("Failed to create the tick timer"); @@ -779,6 +779,8 @@ int main_frameThread(void * unused) break; } + overlaySplash_show(false); + if (frame->flags & FRAME_FLAG_REQUEST_ACTIVATION) g_state.ds->requestActivation(); @@ -821,7 +823,10 @@ int main_frameThread(void * unused) RENDERER(onRestart); if (g_state.state != APP_STATE_SHUTDOWN) + { + overlaySplash_show(true); app_useSpiceDisplay(true); + } if (g_state.useDMA) { @@ -1719,6 +1724,7 @@ int main(int argc, char * argv[]) gl_dynProcsInit(); g_state.overlays = ll_new(); + app_registerOverlay(&LGOverlaySplash, NULL); app_registerOverlay(&LGOverlayConfig, NULL); app_registerOverlay(&LGOverlayAlert , NULL); app_registerOverlay(&LGOverlayFPS , NULL); diff --git a/client/src/overlay/splash.c b/client/src/overlay/splash.c new file mode 100644 index 00000000..79d1119e --- /dev/null +++ b/client/src/overlay/splash.c @@ -0,0 +1,171 @@ +/** + * Looking Glass + * Copyright © 2017-2022 The Looking Glass Authors + * https://looking-glass.io + * + * 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 "interface/overlay.h" +#include "cimgui.h" + +#include "../overlays.h" +#include "../main.h" +#include "overlay_utils.h" + +#include "resources/lg-logo.svg.h" + +#include +#include + +static bool l_show; +static bool l_fadeDone; +static float l_alpha; +static OverlayImage l_logo; + +static bool splash_init(void ** udata, const void * params) +{ + l_show = true; + l_fadeDone = false; + l_alpha = 1.0f; + + overlayLoadSVG(b_lg_logo_svg, b_lg_logo_svg_size, &l_logo, 200, 200); + + return true; +} + +static void splash_free(void * udata) +{ + overlayFreeImage(&l_logo); +} + +static void drawRadialGradient(ImDrawList * list, int x, int y, int w, int h, + int steps, ImU32 innerColor, ImU32 outerColor) +{ + const ImVec2 uv = list->_Data->TexUvWhitePixel; + + ImDrawList_PrimReserve(list, steps * 3, steps + 2); + for(int i = 0; i < steps; ++i) + { + ImDrawList_PrimWriteIdx(list, list->_VtxCurrentIdx); + ImDrawList_PrimWriteIdx(list, list->_VtxCurrentIdx + i + 1); + ImDrawList_PrimWriteIdx(list, list->_VtxCurrentIdx + i + 2); + } + + ImDrawList_PrimWriteVtx(list, + (ImVec2){x, y}, + uv, + innerColor); + + for (unsigned int i = 0; i < steps + 1; ++i) + { + float angle = (i / (float)steps) * M_PI * 2.0f; + ImDrawList_PrimWriteVtx(list, + (ImVec2){ + x + cos(angle) * w, + y + sin(angle) * h + }, + uv, + outerColor); + } +} + +static int splash_render(void * udata, bool interactive, struct Rect * windowRects, + int maxRects) +{ + if (!l_show && l_fadeDone) + return 0; + + const float alpha = l_fadeDone ? 1.0f : l_alpha; + ImVec2 * screen = overlayGetScreenSize(); + ImDrawList * list = igGetBackgroundDrawList_Nil(); + + struct Rect rect = { + .x = 0, + .y = 0, + .w = screen->x, + .h = screen->y + }; + + struct Rect logoRect = { + .x = screen->x / 2 - l_logo.width / 2, + .y = screen->y / 2 - l_logo.height / 2, + .w = l_logo.width, + .h = l_logo.height + }; + + const ImU32 innerColor = igColorConvertFloat4ToU32((ImVec4){ + 0.234375f, 0.015625f, 0.425781f, alpha}); + const ImU32 outerColor = igColorConvertFloat4ToU32((ImVec4){ + 0.0f, 0.0f, 0.0f, alpha}); + const ImU32 imageColor = igColorConvertFloat4ToU32((ImVec4){ + 1.0f, 1.0f, 1.0f, alpha}); + + drawRadialGradient(list, + screen->x / 2, screen->y / 2, + screen->x , screen->y , + 12, + innerColor, + outerColor); + + ImDrawList_AddImage( + list, + l_logo.tex, + (ImVec2){ + logoRect.x, + logoRect.y + }, + (ImVec2){ + logoRect.x + logoRect.w, + logoRect.y + logoRect.h + }, + (ImVec2){ 0, 0 }, + (ImVec2){ 1, 1 }, + imageColor); + + *windowRects = rect; + return 1; +} + +static bool splash_tick(void * udata, unsigned long long tickCount) +{ + if (!l_show && l_alpha > 0.0f) + { + l_alpha -= 1.0f / TICK_RATE; + if (l_alpha <= 0.0f) + l_fadeDone = true; + return true; + } + + return false; +} + +struct LG_OverlayOps LGOverlaySplash = +{ + .name = "splash", + .init = splash_init, + .free = splash_free, + .render = splash_render, + .tick = splash_tick, +}; + +void overlaySplash_show(bool show) +{ + if (l_show == show) + return; + + l_show = show; + app_invalidateOverlay(true); +} diff --git a/client/src/overlays.h b/client/src/overlays.h index bc9b1fd1..4d4a93b0 100644 --- a/client/src/overlays.h +++ b/client/src/overlays.h @@ -33,6 +33,7 @@ struct Overlay struct Rect lastRects[MAX_OVERLAY_RECTS]; }; +extern struct LG_OverlayOps LGOverlaySplash; extern struct LG_OverlayOps LGOverlayAlert; extern struct LG_OverlayOps LGOverlayFPS; extern struct LG_OverlayOps LGOverlayGraphs; @@ -64,6 +65,7 @@ typedef enum LG_UserStatus } LGUserStatus; +void overlaySplash_show(bool show); void overlayStatus_set(LGUserStatus, bool value); #endif diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 12c053e9..f10c6a99 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -15,6 +15,7 @@ function(build_resources) endfunction() build_resources( + lg-logo.svg status/spice.svg status/recording.svg ) diff --git a/resources/lg-logo.svg b/resources/lg-logo.svg index d766682e..dd5daa2b 100644 --- a/resources/lg-logo.svg +++ b/resources/lg-logo.svg @@ -4,15 +4,8 @@ - - - - +