/* 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 #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; _Atomic(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); atomic_init(&(*help)->bmp, NULL); 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) { LG_FontBitmap * bmp = NULL; if (help_text) { bmp = help->font->render(help->fontObj, 0xffffff00, help_text); if (!bmp) DEBUG_ERROR("Failed to render help text"); } else help->shouldRender = false; bmp = atomic_exchange(&help->bmp, bmp); if (bmp) { help->font->release(help->fontObj, bmp); } } void egl_help_render(EGL_Help * help, const float scaleX, const float scaleY) { LG_FontBitmap * bmp = atomic_exchange(&help->bmp, NULL); if (bmp) { if (help->iwidth != bmp->width || help->iheight != bmp->height) { help->iwidth = bmp->width; help->iheight = bmp->height; help->width = (float)bmp->width; help->height = (float)bmp->height; egl_texture_setup( help->texture, EGL_PF_BGRA, bmp->width , bmp->height, bmp->width * bmp->bpp, false, false ); } egl_texture_update ( help->texture, bmp->pixels ); help->shouldRender = true; help->font->release(help->fontObj, bmp); } if (!help->shouldRender) return; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_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); // 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); }