[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.
This commit is contained in:
Quantum 2021-01-30 17:06:57 -05:00 committed by Geoffrey McRae
parent 17b0e2cb22
commit 5ac53362a3
7 changed files with 296 additions and 1 deletions

View File

@ -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

View File

@ -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;
}

207
client/renderers/EGL/help.c Normal file
View File

@ -0,0 +1,207 @@
/*
Looking Glass - KVM FrameRelay (KVMFR) Client
Copyright (C) 2021 Guanzhong Chen <quantum2048@gmail.com>
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 <stdlib.h>
#include <string.h>
// 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);
}

View File

@ -0,0 +1,32 @@
/*
Looking Glass - KVM FrameRelay (KVMFR) Client
Copyright (C) 2021 Guanzhong Chen <quantum2048@gmail.com>
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 <stdbool.h>
#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);

View File

@ -0,0 +1,11 @@
#version 300 es
in highp vec2 uv;
out highp vec4 color;
uniform sampler2D sampler1;
void main()
{
color = texture(sampler1, uv);
}

View File

@ -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;
}

View File

@ -0,0 +1,8 @@
#version 300 es
out highp vec4 color;
void main()
{
color = vec4(0.0, 0.0, 1.0, 1.0);
}