From 5ac53362a34c817335f534e84e8a2799cd8b8cc8 Mon Sep 17 00:00:00 2001 From: Quantum Date: Sat, 30 Jan 2021 17:06:57 -0500 Subject: [PATCH] [client] renderer/egl: implement support for rendering help text The help text is rendered in the bottom left corner on a semi-transparent background, very similar to how the FPS text is rendered. --- client/renderers/EGL/CMakeLists.txt | 4 + client/renderers/EGL/egl.c | 13 +- client/renderers/EGL/help.c | 207 +++++++++++++++++++++++ client/renderers/EGL/help.h | 32 ++++ client/renderers/EGL/shader/help.frag | 11 ++ client/renderers/EGL/shader/help.vert | 22 +++ client/renderers/EGL/shader/help_bg.frag | 8 + 7 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 client/renderers/EGL/help.c create mode 100644 client/renderers/EGL/help.h create mode 100644 client/renderers/EGL/shader/help.frag create mode 100644 client/renderers/EGL/shader/help.vert create mode 100644 client/renderers/EGL/shader/help_bg.frag diff --git a/client/renderers/EGL/CMakeLists.txt b/client/renderers/EGL/CMakeLists.txt index 3ecb4506..4ca516ff 100644 --- a/client/renderers/EGL/CMakeLists.txt +++ b/client/renderers/EGL/CMakeLists.txt @@ -22,6 +22,9 @@ make_object( shader/fps.vert shader/fps.frag shader/fps_bg.frag + shader/help.vert + shader/help.frag + shader/help_bg.frag shader/alert.vert shader/alert.frag shader/alert_bg.frag @@ -40,6 +43,7 @@ add_library(renderer_EGL STATIC desktop.c cursor.c fps.c + help.c draw.c splash.c alert.c diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index c4c9f081..ccd6f79b 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -45,6 +45,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "fps.h" #include "splash.h" #include "alert.h" +#include "help.h" #define SPLASH_FADE_TIME 1000000 #define ALERT_TIMEOUT 2000000 @@ -72,6 +73,7 @@ struct Inst EGL_FPS * fps; // the fps display EGL_Splash * splash; // the splash screen EGL_Alert * alert; // the alert display + EGL_Help * help; // the help display LG_RendererFormat format; bool formatValid; @@ -221,6 +223,7 @@ void egl_deinitialize(void * opaque) egl_fps_free (&this->fps ); egl_splash_free (&this->splash); egl_alert_free (&this->alert ); + egl_help_free (&this->help); LG_LOCK_FREE(this->lock); @@ -478,7 +481,8 @@ void egl_on_alert(void * opaque, const LG_MsgAlert alert, const char * message, void egl_on_help(void * opaque, const char * message) { - // TODO: Implement this. + struct Inst * this = (struct Inst *)opaque; + egl_help_set_text(this->help, message); } bool egl_render_startup(void * opaque) @@ -637,6 +641,12 @@ bool egl_render_startup(void * opaque) return false; } + if (!egl_help_init(&this->help, this->font, this->fontObj)) + { + DEBUG_ERROR("Failed to initialize the alert display"); + return false; + } + return true; } @@ -706,6 +716,7 @@ bool egl_render(void * opaque, LG_RendererRotate rotate) } egl_fps_render(this->fps, this->screenScaleX, this->screenScaleY); + egl_help_render(this->help, this->screenScaleX, this->screenScaleY); app_eglSwapBuffers(this->display, this->surface); return true; } diff --git a/client/renderers/EGL/help.c b/client/renderers/EGL/help.c new file mode 100644 index 00000000..f94dbb76 --- /dev/null +++ b/client/renderers/EGL/help.c @@ -0,0 +1,207 @@ +/* +Looking Glass - KVM FrameRelay (KVMFR) Client +Copyright (C) 2021 Guanzhong Chen +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 "help.h" +#include "common/debug.h" + +#include "texture.h" +#include "shader.h" +#include "model.h" + +#include +#include + +// these headers are auto generated by cmake +#include "help.vert.h" +#include "help.frag.h" +#include "help_bg.frag.h" + +struct EGL_Help +{ + const LG_Font * font; + LG_FontObj fontObj; + + EGL_Texture * texture; + EGL_Shader * shader; + EGL_Shader * shaderBG; + EGL_Model * model; + LG_FontBitmap * bmp; + + bool shouldRender; + int iwidth, iheight; + float width, height; + + // uniforms + GLint uScreen , uSize; + GLint uScreenBG, uSizeBG; +}; + +bool egl_help_init(EGL_Help ** help, const LG_Font * font, LG_FontObj fontObj) +{ + *help = (EGL_Help *)malloc(sizeof(EGL_Help)); + if (!*help) + { + DEBUG_ERROR("Failed to malloc EGL_Help"); + return false; + } + + memset(*help, 0, sizeof(EGL_Help)); + + (*help)->font = font; + (*help)->fontObj = fontObj; + + if (!egl_texture_init(&(*help)->texture, NULL)) + { + DEBUG_ERROR("Failed to initialize the help texture"); + return false; + } + + if (!egl_shader_init(&(*help)->shader)) + { + DEBUG_ERROR("Failed to initialize the help shader"); + return false; + } + + if (!egl_shader_init(&(*help)->shaderBG)) + { + DEBUG_ERROR("Failed to initialize the help bg shader"); + return false; + } + + + if (!egl_shader_compile((*help)->shader, + b_shader_help_vert, b_shader_help_vert_size, + b_shader_help_frag, b_shader_help_frag_size)) + { + DEBUG_ERROR("Failed to compile the help shader"); + return false; + } + + if (!egl_shader_compile((*help)->shaderBG, + b_shader_help_vert , b_shader_help_vert_size, + b_shader_help_bg_frag, b_shader_help_bg_frag_size)) + { + DEBUG_ERROR("Failed to compile the help shader"); + return false; + } + + + (*help)->uSize = egl_shader_get_uniform_location((*help)->shader , "size" ); + (*help)->uScreen = egl_shader_get_uniform_location((*help)->shader , "screen"); + (*help)->uSizeBG = egl_shader_get_uniform_location((*help)->shaderBG, "size" ); + (*help)->uScreenBG = egl_shader_get_uniform_location((*help)->shaderBG, "screen"); + + if (!egl_model_init(&(*help)->model)) + { + DEBUG_ERROR("Failed to initialize the fps model"); + return false; + } + + egl_model_set_default((*help)->model); + egl_model_set_texture((*help)->model, (*help)->texture); + + return true; +} + +void egl_help_free(EGL_Help ** help) +{ + if (!*help) + return; + + egl_texture_free(&(*help)->texture ); + egl_shader_free (&(*help)->shader ); + egl_shader_free (&(*help)->shaderBG); + egl_model_free (&(*help)->model ); + + free(*help); + *help = NULL; +} + +void egl_help_set_text(EGL_Help * help, const char * help_text) +{ + if (!help_text) + { + help->shouldRender = false; + return; + } + + help->bmp = help->font->render(help->fontObj, 0xffffff00, help_text); + if (!help->bmp) + { + DEBUG_ERROR("Failed to render help text"); + return; + } +} + +void egl_help_render(EGL_Help * help, const float scaleX, const float scaleY) +{ + if (help->bmp) + { + if (help->iwidth != help->bmp->width || help->iheight != help->bmp->height) + { + help->iwidth = help->bmp->width; + help->iheight = help->bmp->height; + help->width = (float)help->bmp->width; + help->height = (float)help->bmp->height; + + egl_texture_setup( + help->texture, + EGL_PF_BGRA, + help->bmp->width , + help->bmp->height, + help->bmp->width * help->bmp->bpp, + false, + false + ); + } + + egl_texture_update + ( + help->texture, + help->bmp->pixels + ); + + help->shouldRender = true; + help->font->release(help->fontObj, help->bmp); + help->bmp = NULL; + } + + if (!help->shouldRender) + return; + + glEnable(GL_BLEND); + glBlendColor(0, 0, 0, 0.5); + glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + + // render the background first + egl_shader_use(help->shaderBG); + glUniform2f(help->uScreenBG, scaleX , scaleY ); + glUniform2f(help->uSizeBG , help->width, help->height); + egl_model_render(help->model); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // render the texture over the background + egl_shader_use(help->shader); + glUniform2f(help->uScreen, scaleX , scaleY ); + glUniform2f(help->uSize , help->width, help->height); + egl_model_render(help->model); + + glDisable(GL_BLEND); +} diff --git a/client/renderers/EGL/help.h b/client/renderers/EGL/help.h new file mode 100644 index 00000000..b975c4e9 --- /dev/null +++ b/client/renderers/EGL/help.h @@ -0,0 +1,32 @@ +/* +Looking Glass - KVM FrameRelay (KVMFR) Client +Copyright (C) 2021 Guanzhong Chen +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 + +#include "interface/font.h" + +typedef struct EGL_Help EGL_Help; + +bool egl_help_init(EGL_Help ** help, const LG_Font * font, LG_FontObj fontObj); +void egl_help_free(EGL_Help ** help); + +void egl_help_set_text(EGL_Help * help, const char * help_text); +void egl_help_render(EGL_Help * help, const float scaleX, const float scaleY); diff --git a/client/renderers/EGL/shader/help.frag b/client/renderers/EGL/shader/help.frag new file mode 100644 index 00000000..a435c6d9 --- /dev/null +++ b/client/renderers/EGL/shader/help.frag @@ -0,0 +1,11 @@ +#version 300 es + +in highp vec2 uv; +out highp vec4 color; + +uniform sampler2D sampler1; + +void main() +{ + color = texture(sampler1, uv); +} diff --git a/client/renderers/EGL/shader/help.vert b/client/renderers/EGL/shader/help.vert new file mode 100644 index 00000000..24fe8a8f --- /dev/null +++ b/client/renderers/EGL/shader/help.vert @@ -0,0 +1,22 @@ +#version 300 es + +layout(location = 0) in vec3 vertexPosition_modelspace; +layout(location = 1) in vec2 vertexUV; + +uniform vec2 screen; +uniform vec2 size; + +out highp vec2 uv; + +void main() +{ + gl_Position.xyz = vertexPosition_modelspace; + gl_Position.w = 1.0; + gl_Position.xy *= screen.xy * size.xy; + gl_Position.x -= 1.0 - (screen.x * size.x); + gl_Position.y -= 1.0 - (screen.y * size.y); + gl_Position.x += screen.x * 10.0; + gl_Position.y += screen.y * 10.0; + + uv = vertexUV; +} diff --git a/client/renderers/EGL/shader/help_bg.frag b/client/renderers/EGL/shader/help_bg.frag new file mode 100644 index 00000000..3171af14 --- /dev/null +++ b/client/renderers/EGL/shader/help_bg.frag @@ -0,0 +1,8 @@ +#version 300 es + +out highp vec4 color; + +void main() +{ + color = vec4(0.0, 0.0, 1.0, 1.0); +}