diff --git a/client/renderers/EGL/cursor.c b/client/renderers/EGL/cursor.c index eb715cef..38f80a6a 100644 --- a/client/renderers/EGL/cursor.c +++ b/client/renderers/EGL/cursor.c @@ -80,11 +80,11 @@ struct EGL_Cursor struct EGL_Model * model; }; -static bool egl_cursor_tex_init(struct CursorTex * t, +static bool cursorTexInit(EGL * egl, struct CursorTex * t, const char * vertex_code , size_t vertex_size, const char * fragment_code, size_t fragment_size) { - if (!egl_textureInit(&t->texture, NULL, EGL_TEXTYPE_BUFFER, false)) + if (!egl_textureInit(egl, &t->texture, NULL, EGL_TEXTYPE_BUFFER, false)) { DEBUG_ERROR("Failed to initialize the cursor texture"); return false; @@ -110,8 +110,8 @@ static bool egl_cursor_tex_init(struct CursorTex * t, return true; } -static inline void egl_cursor_tex_uniforms(EGL_Cursor * cursor, struct CursorTex * t, - bool mono, float x, float y, float w, float h) +static inline void setCursorTexUniforms(EGL_Cursor * cursor, + struct CursorTex * t, bool mono, float x, float y, float w, float h) { if (mono) { @@ -127,13 +127,13 @@ static inline void egl_cursor_tex_uniforms(EGL_Cursor * cursor, struct CursorTex } } -static void egl_cursor_tex_free(struct CursorTex * t) +static void cursorTexFree(struct CursorTex * t) { egl_textureFree(&t->texture); egl_shaderFree (&t->shader ); }; -bool egl_cursorInit(EGL_Cursor ** cursor) +bool egl_cursorInit(EGL * egl, EGL_Cursor ** cursor) { *cursor = (EGL_Cursor *)malloc(sizeof(EGL_Cursor)); if (!*cursor) @@ -145,12 +145,12 @@ bool egl_cursorInit(EGL_Cursor ** cursor) memset(*cursor, 0, sizeof(EGL_Cursor)); LG_LOCK_INIT((*cursor)->lock); - if (!egl_cursor_tex_init(&(*cursor)->norm, + if (!cursorTexInit(egl, &(*cursor)->norm, b_shader_cursor_vert , b_shader_cursor_vert_size, b_shader_cursor_rgb_frag, b_shader_cursor_rgb_frag_size)) return false; - if (!egl_cursor_tex_init(&(*cursor)->mono, + if (!cursorTexInit(egl, &(*cursor)->mono, b_shader_cursor_vert , b_shader_cursor_vert_size, b_shader_cursor_mono_frag, b_shader_cursor_mono_frag_size)) return false; @@ -161,7 +161,7 @@ bool egl_cursorInit(EGL_Cursor ** cursor) return false; } - egl_modelSetDefault((*cursor)->model); + egl_modelSetDefault((*cursor)->model, true); (*cursor)->cbMode = option_get_int("egl", "cbMode"); @@ -182,8 +182,8 @@ void egl_cursorFree(EGL_Cursor ** cursor) if ((*cursor)->data) free((*cursor)->data); - egl_cursor_tex_free(&(*cursor)->norm); - egl_cursor_tex_free(&(*cursor)->mono); + cursorTexFree(&(*cursor)->norm); + cursorTexFree(&(*cursor)->mono); egl_modelFree(&(*cursor)->model); free(*cursor); @@ -342,13 +342,13 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor, case LG_CURSOR_MONOCHROME: { egl_shaderUse(cursor->norm.shader); - egl_cursor_tex_uniforms(cursor, &cursor->norm, true, pos.x, pos.y, size.w, size.h); + setCursorTexUniforms(cursor, &cursor->norm, true, pos.x, pos.y, size.w, size.h); glBlendFunc(GL_ZERO, GL_SRC_COLOR); egl_modelSetTexture(cursor->model, cursor->norm.texture); egl_modelRender(cursor->model); egl_shaderUse(cursor->mono.shader); - egl_cursor_tex_uniforms(cursor, &cursor->mono, true, pos.x, pos.y, size.w, size.h); + setCursorTexUniforms(cursor, &cursor->mono, true, pos.x, pos.y, size.w, size.h); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); egl_modelSetTexture(cursor->model, cursor->mono.texture); egl_modelRender(cursor->model); @@ -358,7 +358,7 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor, case LG_CURSOR_COLOR: { egl_shaderUse(cursor->norm.shader); - egl_cursor_tex_uniforms(cursor, &cursor->norm, false, pos.x, pos.y, size.w, size.h); + setCursorTexUniforms(cursor, &cursor->norm, false, pos.x, pos.y, size.w, size.h); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); egl_modelRender(cursor->model); break; @@ -367,7 +367,7 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor, case LG_CURSOR_MASKED_COLOR: { egl_shaderUse(cursor->mono.shader); - egl_cursor_tex_uniforms(cursor, &cursor->mono, false, pos.x, pos.y, size.w, size.h); + setCursorTexUniforms(cursor, &cursor->mono, false, pos.x, pos.y, size.w, size.h); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); egl_modelRender(cursor->model); break; diff --git a/client/renderers/EGL/cursor.h b/client/renderers/EGL/cursor.h index c76ddb9c..c8e6e5be 100644 --- a/client/renderers/EGL/cursor.h +++ b/client/renderers/EGL/cursor.h @@ -22,6 +22,7 @@ #include +#include "egl.h" #include "interface/renderer.h" typedef struct EGL_Cursor EGL_Cursor; @@ -31,7 +32,7 @@ struct CursorState { struct Rect rect; }; -bool egl_cursorInit(EGL_Cursor ** cursor); +bool egl_cursorInit(EGL * egl, EGL_Cursor ** cursor); void egl_cursorFree(EGL_Cursor ** cursor); bool egl_cursorSetShape( diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index 42ad6da5..b922c2f9 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -22,6 +22,7 @@ #include "common/debug.h" #include "common/option.h" #include "common/locking.h" +#include "common/array.h" #include "app.h" #include "texture.h" @@ -33,6 +34,8 @@ #include // these headers are auto generated by cmake +#include "null.vert.h" +#include "null.frag.h" #include "desktop.vert.h" #include "desktop_rgb.frag.h" #include "desktop_rgb.def.h" @@ -41,28 +44,26 @@ struct DesktopShader { EGL_Shader * shader; GLint uTransform; - GLint uUVScale; GLint uDesktopSize; GLint uScaleAlgo; - GLint uNV, uNVGain; + GLint uNVGain; GLint uCBMode; }; struct EGL_Desktop { + EGL * egl; EGLDisplay * display; EGL_Texture * texture; - struct DesktopShader * shader; // the active shader + struct DesktopShader shader; EGL_DesktopRects * mesh; + CountedBuffer * matrix; // internals int width, height; LG_RendererRotate rotate; - // shader instances - struct DesktopShader shader_generic; - // scale algorithm int scaleAlgo; @@ -80,7 +81,7 @@ struct EGL_Desktop // forwards void egl_desktop_toggle_nv(int key, void * opaque); -static bool egl_init_desktop_shader( +static bool egl_initDesktopShader( struct DesktopShader * shader, const char * vertex_code , size_t vertex_size, const char * fragment_code, size_t fragment_size @@ -96,40 +97,37 @@ static bool egl_init_desktop_shader( return false; } - egl_shaderAssocTextures(shader->shader, 1); - shader->uTransform = egl_shaderGetUniform(shader->shader, "transform"); - shader->uUVScale = egl_shaderGetUniform(shader->shader, "uvScale" ); shader->uDesktopSize = egl_shaderGetUniform(shader->shader, "size" ); shader->uScaleAlgo = egl_shaderGetUniform(shader->shader, "scaleAlgo"); - shader->uNV = egl_shaderGetUniform(shader->shader, "nv" ); shader->uNVGain = egl_shaderGetUniform(shader->shader, "nvGain" ); shader->uCBMode = egl_shaderGetUniform(shader->shader, "cbMode" ); return true; } -bool egl_desktopInit(EGL_Desktop ** desktop, EGLDisplay * display, bool useDMA, int maxRects) +bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop, EGLDisplay * display, + bool useDMA, int maxRects) { - *desktop = (EGL_Desktop *)malloc(sizeof(EGL_Desktop)); + *desktop = (EGL_Desktop *)calloc(1, sizeof(EGL_Desktop)); if (!*desktop) { DEBUG_ERROR("Failed to malloc EGL_Desktop"); return false; } - memset(*desktop, 0, sizeof(EGL_Desktop)); + (*desktop)->egl = egl; (*desktop)->display = display; - if (!egl_textureInit(&(*desktop)->texture, display, + if (!egl_textureInit(egl, &(*desktop)->texture, display, useDMA ? EGL_TEXTYPE_DMABUF : EGL_TEXTYPE_FRAMEBUFFER, true)) { DEBUG_ERROR("Failed to initialize the desktop texture"); return false; } - if (!egl_init_desktop_shader( - &(*desktop)->shader_generic, + if (!egl_initDesktopShader( + &(*desktop)->shader, b_shader_desktop_vert , b_shader_desktop_vert_size, b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size)) { @@ -143,6 +141,13 @@ bool egl_desktopInit(EGL_Desktop ** desktop, EGLDisplay * display, bool useDMA, return false; } + (*desktop)->matrix = countedBufferNew(6 * sizeof(GLfloat)); + if (!(*desktop)->matrix) + { + DEBUG_ERROR("Failed to allocate the desktop matrix buffer"); + return false; + } + app_registerKeybind(KEY_N, egl_desktop_toggle_nv, *desktop, "Toggle night vision mode"); (*desktop)->nvMax = option_get_int("egl", "nvGainMax"); @@ -181,9 +186,10 @@ void egl_desktopFree(EGL_Desktop ** desktop) if (!*desktop) return; - egl_textureFree (&(*desktop)->texture ); - egl_shaderFree (&(*desktop)->shader_generic.shader); - egl_desktopRectsFree(&(*desktop)->mesh ); + egl_textureFree (&(*desktop)->texture ); + egl_shaderFree (&(*desktop)->shader.shader); + egl_desktopRectsFree(&(*desktop)->mesh ); + countedBufferRelease(&(*desktop)->matrix ); free(*desktop); *desktop = NULL; @@ -237,22 +243,18 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format) { case FRAME_TYPE_BGRA: pixFmt = EGL_PF_BGRA; - desktop->shader = &desktop->shader_generic; break; case FRAME_TYPE_RGBA: pixFmt = EGL_PF_RGBA; - desktop->shader = &desktop->shader_generic; break; case FRAME_TYPE_RGBA10: pixFmt = EGL_PF_RGBA10; - desktop->shader = &desktop->shader_generic; break; case FRAME_TYPE_RGBA16F: pixFmt = EGL_PF_RGBA16F; - desktop->shader = &desktop->shader_generic; break; default: @@ -290,7 +292,8 @@ bool egl_desktop_update(EGL_Desktop * desktop, const FrameBuffer * frame, int dm desktop->useDMA = false; egl_textureFree(&desktop->texture); - if (!egl_textureInit(&desktop->texture, desktop->display, EGL_TEXTYPE_FRAMEBUFFER, true)) + if (!egl_textureInit(desktop->egl, &desktop->texture, desktop->display, + EGL_TEXTYPE_FRAMEBUFFER, true)) { DEBUG_ERROR("Failed to initialize the desktop texture"); return false; @@ -307,9 +310,6 @@ bool egl_desktopRender(EGL_Desktop * desktop, const float x, const float y, const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType, LG_RendererRotate rotate, const struct DamageRects * rects) { - if (!desktop->shader) - return false; - enum EGL_TexStatus status; if ((status = egl_textureProcess(desktop->texture)) != EGL_TEX_STATUS_OK) { @@ -339,28 +339,45 @@ bool egl_desktopRender(EGL_Desktop * desktop, const float x, const float y, scaleAlgo = desktop->scaleAlgo; } - float matrix[6]; - egl_desktopRectsMatrix(matrix, desktop->width, desktop->height, x, y, scaleX, scaleY, rotate); + egl_desktopRectsMatrix((float *)desktop->matrix->data, + desktop->width, desktop->height, x, y, scaleX, scaleY, rotate); egl_desktopRectsUpdate(desktop->mesh, rects, desktop->width, desktop->height); - const struct DesktopShader * shader = desktop->shader; - egl_shaderUse(shader->shader); - glUniform1i(shader->uScaleAlgo , scaleAlgo); - glUniform2f(shader->uDesktopSize, desktop->width, desktop->height); - glUniform2f(shader->uUVScale , 1.0f / desktop->width, 1.0f / desktop->height); - glUniformMatrix3x2fv(shader->uTransform, 1, GL_FALSE, matrix); - - if (desktop->nvGain) - { - glUniform1i(shader->uNV, 1); - glUniform1f(shader->uNVGain, (float)desktop->nvGain); - } - else - glUniform1i(shader->uNV, 0); - - glUniform1i(shader->uCBMode, desktop->cbMode); - egl_textureBind(desktop->texture); + + const struct DesktopShader * shader = &desktop->shader; + EGL_Uniform uniforms[] = + { + { + .type = EGL_UNIFORM_TYPE_1I, + .location = shader->uScaleAlgo, + .i = { scaleAlgo }, + }, + { + .type = EGL_UNIFORM_TYPE_2F, + .location = shader->uDesktopSize, + .f = { desktop->width, desktop->height }, + }, + { + .type = EGL_UNIFORM_TYPE_M3x2FV, + .location = shader->uTransform, + .m.transpose = GL_FALSE, + .m.v = desktop->matrix + }, + { + .type = EGL_UNIFORM_TYPE_1F, + .location = shader->uNVGain, + .f = { (float)desktop->nvGain } + }, + { + .type = EGL_UNIFORM_TYPE_1I, + .location = shader->uCBMode, + .f = { desktop->cbMode } + } + }; + + egl_shaderSetUniforms(shader->shader, uniforms, ARRAY_LENGTH(uniforms)); + egl_shaderUse(shader->shader); egl_desktopRectsRender(desktop->mesh); glBindTexture(GL_TEXTURE_2D, 0); return true; diff --git a/client/renderers/EGL/desktop.h b/client/renderers/EGL/desktop.h index ed6e4d6d..484afd67 100644 --- a/client/renderers/EGL/desktop.h +++ b/client/renderers/EGL/desktop.h @@ -22,7 +22,7 @@ #include -#include "interface/renderer.h" +#include "egl.h" #include "desktop_rects.h" typedef struct EGL_Desktop EGL_Desktop; @@ -37,7 +37,8 @@ enum EGL_DesktopScaleType struct Option; bool egl_desktopScaleValidate(struct Option * opt, const char ** error); -bool egl_desktopInit(EGL_Desktop ** desktop, EGLDisplay * display, bool useDMA, int maxRects); +bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop, EGLDisplay * display, + bool useDMA, int maxRects); void egl_desktopFree(EGL_Desktop ** desktop); void egl_desktopConfigUI(EGL_Desktop * desktop); diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index 785fe91a..8c3a29d2 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -400,6 +400,11 @@ static void egl_update_scale_type(struct Inst * this) this->scaleType = EGL_DESKTOP_UPSCALE; } +void egl_resetViewport(EGL * this) +{ + glViewport(0, 0, this->width, this->height); +} + static void egl_onResize(LG_Renderer * renderer, const int width, const int height, const double scale, const LG_RendererRect destRect, LG_RendererRotate rotate) { @@ -782,13 +787,13 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA) eglSwapInterval(this->display, this->opt.vsync ? 1 : 0); - if (!egl_desktopInit(&this->desktop, this->display, useDMA, MAX_ACCUMULATED_DAMAGE)) + if (!egl_desktopInit(this, &this->desktop, this->display, useDMA, MAX_ACCUMULATED_DAMAGE)) { DEBUG_ERROR("Failed to initialize the desktop"); return false; } - if (!egl_cursorInit(&this->cursor)) + if (!egl_cursorInit(this, &this->cursor)) { DEBUG_ERROR("Failed to initialize the cursor"); return false; diff --git a/client/renderers/EGL/egl.h b/client/renderers/EGL/egl.h new file mode 100644 index 00000000..9f0c9051 --- /dev/null +++ b/client/renderers/EGL/egl.h @@ -0,0 +1,24 @@ +/** + * Looking Glass + * Copyright © 2017-2021 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 + +typedef struct Inst EGL; +void egl_resetViewport(EGL * egl); diff --git a/client/renderers/EGL/model.c b/client/renderers/EGL/model.c index 952b9b62..11b0a6b4 100644 --- a/client/renderers/EGL/model.c +++ b/client/renderers/EGL/model.c @@ -93,7 +93,7 @@ void egl_modelFree(EGL_Model ** model) *model = NULL; } -void egl_modelSetDefault(EGL_Model * model) +void egl_modelSetDefault(EGL_Model * model, bool flipped) { static const GLfloat square[] = { @@ -103,7 +103,15 @@ void egl_modelSetDefault(EGL_Model * model) 1.0f, 1.0f, 0.0f }; - static const GLfloat uvs[] = + static const GLfloat uvsNormal[] = + { + 0.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f + }; + + static const GLfloat uvsFlipped[] = { 0.0f, 1.0f, 1.0f, 1.0f, @@ -111,7 +119,7 @@ void egl_modelSetDefault(EGL_Model * model) 1.0f, 0.0f }; - egl_modelAddVerts(model, square, uvs, 4); + egl_modelAddVerts(model, square, flipped ? uvsFlipped : uvsNormal, 4); } void egl_modelAddVerts(EGL_Model * model, const GLfloat * verticies, const GLfloat * uvs, const size_t count) diff --git a/client/renderers/EGL/model.h b/client/renderers/EGL/model.h index 02577843..6a114884 100644 --- a/client/renderers/EGL/model.h +++ b/client/renderers/EGL/model.h @@ -27,11 +27,12 @@ #include typedef struct EGL_Model EGL_Model; +typedef struct EGL_Texture EGL_Texture; bool egl_modelInit(EGL_Model ** model); void egl_modelFree(EGL_Model ** model); -void egl_modelSetDefault (EGL_Model * model); +void egl_modelSetDefault (EGL_Model * model, bool flipped); void egl_modelAddVerts(EGL_Model * model, const GLfloat * verticies, const GLfloat * uvs, const size_t count); void egl_modelSetShader (EGL_Model * model, EGL_Shader * shader); void egl_modelSetTexture (EGL_Model * model, EGL_Texture * texture); diff --git a/client/renderers/EGL/shader.c b/client/renderers/EGL/shader.c index f1242e24..8acc4c30 100644 --- a/client/renderers/EGL/shader.c +++ b/client/renderers/EGL/shader.c @@ -30,31 +30,38 @@ struct EGL_Shader { bool hasShader; GLuint shader; + + EGL_Uniform * uniforms; + int uniformCount; + int uniformUsed; }; bool egl_shaderInit(EGL_Shader ** this) { - *this = (EGL_Shader *)malloc(sizeof(EGL_Shader)); + *this = (EGL_Shader *)calloc(1, sizeof(EGL_Shader)); if (!*this) { DEBUG_ERROR("Failed to malloc EGL_Shader"); return false; } - memset(*this, 0, sizeof(EGL_Shader)); return true; } -void egl_shaderFree(EGL_Shader ** this) +void egl_shaderFree(EGL_Shader ** shader) { - if (!*this) + EGL_Shader * this = *shader; + if (!this) return; - if ((*this)->hasShader) - glDeleteProgram((*this)->shader); + if (this->hasShader) + glDeleteProgram(this->shader); - free(*this); - *this = NULL; + egl_shaderFreeUniforms(this); + free(this->uniforms); + + free(this); + *shader = NULL; } bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fragment_file) @@ -187,12 +194,277 @@ bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, return true; } +void egl_shaderSetUniforms(EGL_Shader * this, EGL_Uniform * uniforms, int count) +{ + egl_shaderFreeUniforms(this); + if (count > this->uniformCount) + { + free(this->uniforms); + this->uniforms = malloc(sizeof(*this->uniforms) * count); + this->uniformCount = count; + } + + this->uniformUsed = count; + memcpy(this->uniforms, uniforms, sizeof(*this->uniforms) * count); + + for(int i = 0; i < this->uniformUsed; ++i) + { + switch(this->uniforms[i].type) + { + case EGL_UNIFORM_TYPE_1FV: + case EGL_UNIFORM_TYPE_2FV: + case EGL_UNIFORM_TYPE_3FV: + case EGL_UNIFORM_TYPE_4FV: + case EGL_UNIFORM_TYPE_1IV: + case EGL_UNIFORM_TYPE_2IV: + case EGL_UNIFORM_TYPE_3IV: + case EGL_UNIFORM_TYPE_4IV: + case EGL_UNIFORM_TYPE_1UIV: + case EGL_UNIFORM_TYPE_2UIV: + case EGL_UNIFORM_TYPE_3UIV: + case EGL_UNIFORM_TYPE_4UIV: + countedBufferAddRef(this->uniforms[i].v); + break; + + case EGL_UNIFORM_TYPE_M2FV: + case EGL_UNIFORM_TYPE_M3FV: + case EGL_UNIFORM_TYPE_M4FV: + case EGL_UNIFORM_TYPE_M2x3FV: + case EGL_UNIFORM_TYPE_M3x2FV: + case EGL_UNIFORM_TYPE_M2x4FV: + case EGL_UNIFORM_TYPE_M4x2FV: + case EGL_UNIFORM_TYPE_M3x4FV: + case EGL_UNIFORM_TYPE_M4x3FV: + countedBufferAddRef(this->uniforms[i].m.v); + break; + + default: + break; + } + } +}; + +void egl_shaderFreeUniforms(EGL_Shader * this) +{ + for(int i = 0; i < this->uniformUsed; ++i) + { + switch(this->uniforms[i].type) + { + case EGL_UNIFORM_TYPE_1FV: + case EGL_UNIFORM_TYPE_2FV: + case EGL_UNIFORM_TYPE_3FV: + case EGL_UNIFORM_TYPE_4FV: + case EGL_UNIFORM_TYPE_1IV: + case EGL_UNIFORM_TYPE_2IV: + case EGL_UNIFORM_TYPE_3IV: + case EGL_UNIFORM_TYPE_4IV: + case EGL_UNIFORM_TYPE_1UIV: + case EGL_UNIFORM_TYPE_2UIV: + case EGL_UNIFORM_TYPE_3UIV: + case EGL_UNIFORM_TYPE_4UIV: + countedBufferRelease(&this->uniforms[i].v); + break; + + case EGL_UNIFORM_TYPE_M2FV: + case EGL_UNIFORM_TYPE_M3FV: + case EGL_UNIFORM_TYPE_M4FV: + case EGL_UNIFORM_TYPE_M2x3FV: + case EGL_UNIFORM_TYPE_M3x2FV: + case EGL_UNIFORM_TYPE_M2x4FV: + case EGL_UNIFORM_TYPE_M4x2FV: + case EGL_UNIFORM_TYPE_M3x4FV: + case EGL_UNIFORM_TYPE_M4x3FV: + countedBufferRelease(&this->uniforms[i].m.v); + break; + + default: + break; + } + } + this->uniformUsed = 0; +} + void egl_shaderUse(EGL_Shader * this) { if (this->hasShader) glUseProgram(this->shader); else DEBUG_ERROR("Shader program has not been compiled"); + + for(int i = 0; i < this->uniformUsed; ++i) + { + EGL_Uniform * uniform = &this->uniforms[i]; + switch(uniform->type) + { + case EGL_UNIFORM_TYPE_1F: + glUniform1f(uniform->location, uniform->f[0]); + break; + + case EGL_UNIFORM_TYPE_2F: + glUniform2f(uniform->location, uniform->f[0], uniform->f[1]); + break; + + case EGL_UNIFORM_TYPE_3F: + glUniform3f(uniform->location, uniform->f[0], uniform->f[1], + uniform->f[2]); + break; + + case EGL_UNIFORM_TYPE_4F: + glUniform4f(uniform->location, uniform->f[0], uniform->f[1], + uniform->f[2], uniform->f[3]); + break; + + case EGL_UNIFORM_TYPE_1I: + glUniform1i(uniform->location, uniform->i[0]); + break; + + case EGL_UNIFORM_TYPE_2I: + glUniform2i(uniform->location, uniform->i[0], uniform->i[1]); + break; + + case EGL_UNIFORM_TYPE_3I: + glUniform3i(uniform->location, uniform->i[0], uniform->i[1], + uniform->i[2]); + break; + + case EGL_UNIFORM_TYPE_4I: + glUniform4i(uniform->location, uniform->i[0], uniform->i[1], + uniform->i[2], uniform->i[3]); + break; + + case EGL_UNIFORM_TYPE_1UI: + glUniform1ui(uniform->location, uniform->ui[0]); + break; + + case EGL_UNIFORM_TYPE_2UI: + glUniform2ui(uniform->location, uniform->ui[0], uniform->ui[1]); + break; + + case EGL_UNIFORM_TYPE_3UI: + glUniform3ui(uniform->location, uniform->ui[0], uniform->ui[1], + uniform->ui[2]); + break; + + case EGL_UNIFORM_TYPE_4UI: + glUniform4ui(uniform->location, uniform->ui[0], uniform->ui[1], + uniform->ui[2], uniform->ui[3]); + break; + + case EGL_UNIFORM_TYPE_1FV: + glUniform1fv(uniform->location, uniform->v->size / sizeof(GLfloat), + (const GLfloat *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_2FV: + glUniform2fv(uniform->location, uniform->v->size / sizeof(GLfloat) / 2, + (const GLfloat *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_3FV: + glUniform3fv(uniform->location, uniform->v->size / sizeof(GLfloat) / 3, + (const GLfloat *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_4FV: + glUniform4fv(uniform->location, uniform->v->size / sizeof(GLfloat) / 4, + (const GLfloat *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_1IV: + glUniform1iv(uniform->location, uniform->v->size / sizeof(GLint), + (const GLint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_2IV: + glUniform2iv(uniform->location, uniform->v->size / sizeof(GLint) / 2, + (const GLint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_3IV: + glUniform3iv(uniform->location, uniform->v->size / sizeof(GLint) / 3, + (const GLint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_4IV: + glUniform4iv(uniform->location, uniform->v->size / sizeof(GLint) / 4, + (const GLint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_1UIV: + glUniform1uiv(uniform->location, uniform->v->size / sizeof(GLuint), + (const GLuint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_2UIV: + glUniform2uiv(uniform->location, uniform->v->size / sizeof(GLuint) / 2, + (const GLuint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_3UIV: + glUniform3uiv(uniform->location, uniform->v->size / sizeof(GLuint) / 3, + (const GLuint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_4UIV: + glUniform4uiv(uniform->location, uniform->v->size / sizeof(GLuint) / 4, + (const GLuint *)uniform->v->data); + break; + + case EGL_UNIFORM_TYPE_M2FV: + glUniformMatrix2fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 2, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M3FV: + glUniformMatrix3fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 3, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M4FV: + glUniformMatrix4fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 4, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M2x3FV: + glUniformMatrix2x3fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 6, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M3x2FV: + glUniformMatrix3x2fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 6, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M2x4FV: + glUniformMatrix2x4fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 8, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M4x2FV: + glUniformMatrix4x2fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 8, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M3x4FV: + glUniformMatrix3x4fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 12, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + + case EGL_UNIFORM_TYPE_M4x3FV: + glUniformMatrix4x3fv(uniform->location, + uniform->v->size / sizeof(GLfloat) / 12, + uniform->m.transpose, (const GLfloat *)uniform->m.v->data); + break; + } + } } void egl_shaderAssocTextures(EGL_Shader * this, const int count) diff --git a/client/renderers/EGL/shader.h b/client/renderers/EGL/shader.h index f0b90334..53adb54d 100644 --- a/client/renderers/EGL/shader.h +++ b/client/renderers/EGL/shader.h @@ -25,8 +25,74 @@ #include +#include "common/countedbuffer.h" + typedef struct EGL_Shader EGL_Shader; +enum EGL_UniformType +{ + EGL_UNIFORM_TYPE_1F, + EGL_UNIFORM_TYPE_2F, + EGL_UNIFORM_TYPE_3F, + EGL_UNIFORM_TYPE_4F, + EGL_UNIFORM_TYPE_1I, + EGL_UNIFORM_TYPE_2I, + EGL_UNIFORM_TYPE_3I, + EGL_UNIFORM_TYPE_4I, + EGL_UNIFORM_TYPE_1UI, + EGL_UNIFORM_TYPE_2UI, + EGL_UNIFORM_TYPE_3UI, + EGL_UNIFORM_TYPE_4UI, + + // vectors + EGL_UNIFORM_TYPE_1FV, + EGL_UNIFORM_TYPE_2FV, + EGL_UNIFORM_TYPE_3FV, + EGL_UNIFORM_TYPE_4FV, + EGL_UNIFORM_TYPE_1IV, + EGL_UNIFORM_TYPE_2IV, + EGL_UNIFORM_TYPE_3IV, + EGL_UNIFORM_TYPE_4IV, + EGL_UNIFORM_TYPE_1UIV, + EGL_UNIFORM_TYPE_2UIV, + EGL_UNIFORM_TYPE_3UIV, + EGL_UNIFORM_TYPE_4UIV, + + // matrices + EGL_UNIFORM_TYPE_M2FV, + EGL_UNIFORM_TYPE_M3FV, + EGL_UNIFORM_TYPE_M4FV, + EGL_UNIFORM_TYPE_M2x3FV, + EGL_UNIFORM_TYPE_M3x2FV, + EGL_UNIFORM_TYPE_M2x4FV, + EGL_UNIFORM_TYPE_M4x2FV, + EGL_UNIFORM_TYPE_M3x4FV, + EGL_UNIFORM_TYPE_M4x3FV +}; + +typedef struct EGL_Uniform +{ + enum EGL_UniformType type; + GLint location; + + union + { + GLfloat f [4]; + GLint i [4]; + GLuint ui[4]; + + CountedBuffer * v; + + struct + { + CountedBuffer * v; + GLboolean transpose; + } + m; + }; +} +EGL_Uniform; + bool egl_shaderInit(EGL_Shader ** shader); void egl_shaderFree(EGL_Shader ** shader); @@ -36,6 +102,10 @@ bool egl_shaderLoad(EGL_Shader * model, const char * vertex_file, bool egl_shaderCompile(EGL_Shader * model, const char * vertex_code, size_t vertex_size, const char * fragment_code, size_t fragment_size); +void egl_shaderSetUniforms(EGL_Shader * shader, EGL_Uniform * uniforms, + int count); +void egl_shaderFreeUniforms(EGL_Shader * shader); + void egl_shaderUse(EGL_Shader * shader); void egl_shaderAssocTextures(EGL_Shader * shader, const int count); diff --git a/client/renderers/EGL/shader/desktop.vert b/client/renderers/EGL/shader/desktop.vert index 10f13171..e570fd2d 100644 --- a/client/renderers/EGL/shader/desktop.vert +++ b/client/renderers/EGL/shader/desktop.vert @@ -3,11 +3,15 @@ layout(location = 0) in vec2 vertex; out highp vec2 uv; -uniform highp vec2 uvScale; +uniform highp vec2 size; uniform mat3x2 transform; void main() { + highp vec2 uvScale; + gl_Position = vec4(transform * vec3(vertex, 1.0), 0.0, 1.0); + uvScale.x = 1.0 / size.x; + uvScale.y = 1.0 / size.y; uv = vertex * uvScale; } diff --git a/client/renderers/EGL/shader/desktop_rgb.frag b/client/renderers/EGL/shader/desktop_rgb.frag index c0e7be29..5b722253 100644 --- a/client/renderers/EGL/shader/desktop_rgb.frag +++ b/client/renderers/EGL/shader/desktop_rgb.frag @@ -13,7 +13,6 @@ uniform sampler2D sampler1; uniform int scaleAlgo; uniform highp vec2 size; -uniform int nv; uniform highp float nvGain; uniform int cbMode; @@ -67,7 +66,7 @@ void main() color.b += (error.r * 0.7) + (error.b * 1.0); } - if (nv == 1) + if (nvGain > 0.0) { highp float lumi = 1.0 - (0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b); color *= 1.0 + lumi; diff --git a/client/renderers/EGL/splash.c b/client/renderers/EGL/splash.c index 43a762e3..7428ef2e 100644 --- a/client/renderers/EGL/splash.c +++ b/client/renderers/EGL/splash.c @@ -80,7 +80,7 @@ bool egl_splashInit(EGL_Splash ** splash) return false; } - egl_modelSetDefault((*splash)->bg); + egl_modelSetDefault((*splash)->bg, false); if (!egl_shaderInit(&(*splash)->logoShader)) { diff --git a/client/renderers/EGL/texture.c b/client/renderers/EGL/texture.c index 2d709135..7b95574e 100644 --- a/client/renderers/EGL/texture.c +++ b/client/renderers/EGL/texture.c @@ -25,6 +25,7 @@ #include #include "shader.h" #include "common/framebuffer.h" +#include "common/debug.h" #include #include @@ -36,8 +37,16 @@ extern const EGL_TextureOps EGL_TextureBufferStream; extern const EGL_TextureOps EGL_TextureFrameBuffer; extern const EGL_TextureOps EGL_TextureDMABUF; -bool egl_textureInit(EGL_Texture ** texture, EGLDisplay * display, - EGL_TexType type, bool streaming) +typedef struct RenderStep +{ + GLuint fb; + GLuint tex; + EGL_Shader * shader; +} +RenderStep; + +bool egl_textureInit(EGL * egl, EGL_Texture ** texture_, + EGLDisplay * display, EGL_TexType type, bool streaming) { const EGL_TextureOps * ops; @@ -61,21 +70,71 @@ bool egl_textureInit(EGL_Texture ** texture, EGLDisplay * display, return false; } - *texture = NULL; - if (!ops->init(texture, display)) + *texture_ = NULL; + if (!ops->init(texture_, display)) return false; - memcpy(&(*texture)->ops, ops, sizeof(*ops)); + EGL_Texture * this = *texture_; + memcpy(&this->ops, ops, sizeof(*ops)); + this->egl = egl; + + glGenSamplers(1, &this->sampler); + glSamplerParameteri(this->sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glSamplerParameteri(this->sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE); + glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE); + + this->textures = ringbuffer_new(8, sizeof(GLuint)); + return true; } void egl_textureFree(EGL_Texture ** tex) { - (*tex)->ops.free(*tex); + EGL_Texture * this = *tex; + + if (this->render) + { + RenderStep * step; + while(ll_shift(this->render, (void **)&step)) + { + if (step->fb) + glDeleteFramebuffers(1, &step->fb); + + glDeleteTextures(1, &step->tex); + free(step); + } + ll_free(this->render); + egl_modelFree(&this->model); + } + + glDeleteSamplers(1, &this->sampler); + ringbuffer_free(&this->textures); + + this->ops.free(this); *tex = NULL; } -bool egl_textureSetup(EGL_Texture * texture, enum EGL_PixelFormat pixFmt, +bool setupRenderStep(EGL_Texture * this, RenderStep * step) +{ + glBindTexture(GL_TEXTURE_2D, step->tex); + glTexImage2D(GL_TEXTURE_2D, + 0, + this->format.intFormat, + this->format.width, + this->format.height, + 0, + this->format.format, + this->format.dataType, + NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, 0); + + return true; +} + +bool egl_textureSetup(EGL_Texture * this, enum EGL_PixelFormat pixFmt, size_t width, size_t height, size_t stride) { const struct EGL_TexSetup setup = @@ -85,21 +144,43 @@ bool egl_textureSetup(EGL_Texture * texture, enum EGL_PixelFormat pixFmt, .height = height, .stride = stride }; - texture->size = height * stride; - return texture->ops.setup(texture, &setup); + this->size = height * stride; + + if (!egl_texUtilGetFormat(&setup, &this->format)) + return false; + + this->formatValid = true; + + /* reconfigure any intermediate render steps */ + if (this->render) + { + RenderStep * step; + for(ll_reset(this->render); ll_walk(this->render, (void **)&step); ) + if (!setupRenderStep(this, step)) + return false; + } + + return this->ops.setup(this, &setup); } -bool egl_textureUpdate(EGL_Texture * texture, const uint8_t * buffer) +bool egl_textureUpdate(EGL_Texture * this, const uint8_t * buffer) { const struct EGL_TexUpdate update = { .type = EGL_TEXTYPE_BUFFER, .buffer = buffer }; - return texture->ops.update(texture, &update); + + if (this->ops.update(this, &update)) + { + atomic_store(&this->updated, true); + return true; + } + + return false; } -bool egl_textureUpdateFromFrame(EGL_Texture * texture, +bool egl_textureUpdateFromFrame(EGL_Texture * this, const FrameBuffer * frame, const FrameDamageRect * damageRects, int damageRectsCount) { @@ -110,10 +191,17 @@ bool egl_textureUpdateFromFrame(EGL_Texture * texture, .rects = damageRects, .rectCount = damageRectsCount, }; - return texture->ops.update(texture, &update); + + if (this->ops.update(this, &update)) + { + atomic_store(&this->updated, true); + return true; + } + + return false; } -bool egl_textureUpdateFromDMA(EGL_Texture * texture, +bool egl_textureUpdateFromDMA(EGL_Texture * this, const FrameBuffer * frame, const int dmaFd) { const struct EGL_TexUpdate update = @@ -123,17 +211,135 @@ bool egl_textureUpdateFromDMA(EGL_Texture * texture, }; /* wait for completion */ - framebuffer_wait(frame, texture->size); + framebuffer_wait(frame, this->size); - return texture->ops.update(texture, &update); + if (this->ops.update(this, &update)) + { + atomic_store(&this->updated, true); + return true; + } + + return false; } -enum EGL_TexStatus egl_textureProcess(EGL_Texture * texture) +enum EGL_TexStatus egl_textureProcess(EGL_Texture * this) { - return texture->ops.process(texture); + EGL_TexStatus status; + if ((status = this->ops.process(this)) == EGL_TEX_STATUS_OK) + { + if (atomic_exchange(&this->updated, false)) + this->postProcessed = false; + } + return status; } -enum EGL_TexStatus egl_textureBind(EGL_Texture * texture) +static bool rbBindTexture(int index, void * value, void * udata) { - return texture->ops.bind(texture); + GLuint * tex = (GLuint *)value; + EGL_Texture * this = (EGL_Texture *)udata; + + glActiveTexture(GL_TEXTURE0 + index); + glBindTexture(GL_TEXTURE_2D, *tex); + glBindSampler(0, this->sampler); + return true; +} + +enum EGL_TexStatus egl_textureBind(EGL_Texture * this) +{ + GLuint tex; + EGL_TexStatus status; + + if (!this->render) + { + if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK) + return status; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex); + glBindSampler(0, this->sampler); + return EGL_TEX_STATUS_OK; + } + + RenderStep * step; + ringbuffer_reset(this->textures); + + /* if the postProcessing has not yet been done */ + if (!this->postProcessed) + { + if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK) + return status; + + ringbuffer_push(this->textures, &tex); + ringbuffer_forEach(this->textures, rbBindTexture, this, true); + + for(ll_reset(this->render); ll_walk(this->render, (void **)&step); ) + { + /* create the framebuffer here as it must be in the same gl context as + * it's usage */ + if (!step->fb) + { + glGenFramebuffers(1, &step->fb); + glBindFramebuffer(GL_FRAMEBUFFER, step->fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, step->tex, 0); + glDrawBuffers(1, &(GLenum){GL_COLOR_ATTACHMENT0}); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + DEBUG_ERROR("Failed to setup the shader framebuffer"); + return EGL_TEX_STATUS_ERROR; + } + } + else + glBindFramebuffer(GL_FRAMEBUFFER, step->fb); + + glViewport(0, 0, this->format.width, this->format.height); + egl_shaderUse(step->shader); + egl_modelRender(this->model); + + ringbuffer_push(this->textures, &step->tex); + ringbuffer_forEach(this->textures, rbBindTexture, this, true); + } + + /* restore the state and the viewport */ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glUseProgram(0); + egl_resetViewport(this->egl); + + this->postProcessed = true; + } + else + { + /* bind the last texture */ + ll_peek_tail(this->render, (void **)&step); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, step->tex); + glBindSampler(0, this->sampler); + } + + return EGL_TEX_STATUS_OK; +} + +enum EGL_TexStatus egl_textureAddShader(EGL_Texture * this, EGL_Shader * shader) +{ + if (!this->render) + { + this->render = ll_new(); + egl_modelInit(&this->model); + egl_modelSetDefault(this->model, false); + } + + RenderStep * step = calloc(1, sizeof(*step)); + glGenTextures(1, &step->tex); + step->shader = shader; + + if (this->formatValid) + if (!setupRenderStep(this, step)) + { + glDeleteTextures(1, &step->tex); + free(step); + return EGL_TEX_STATUS_ERROR; + } + + ll_push(this->render, step); + return EGL_TEX_STATUS_OK; } diff --git a/client/renderers/EGL/texture.h b/client/renderers/EGL/texture.h index 238e555c..cde00f7e 100644 --- a/client/renderers/EGL/texture.h +++ b/client/renderers/EGL/texture.h @@ -21,14 +21,22 @@ #pragma once #include +#include "egl.h" #include "shader.h" +#include "model.h" #include "common/framebuffer.h" +#include "common/ringbuffer.h" #include "util.h" +#include "ll.h" #include #include +#include "texture_util.h" + +typedef struct EGL_Model EGL_Model; + typedef enum EGL_TexType { EGL_TEXTYPE_BUFFER, @@ -113,20 +121,32 @@ typedef struct EGL_TextureOps /* called from a background job to prepare the texture for use before bind */ enum EGL_TexStatus (*process)(EGL_Texture * texture); - /* bind the texture for use */ - enum EGL_TexStatus (*bind)(EGL_Texture * texture); + /* get the texture for use */ + enum EGL_TexStatus (*get)(EGL_Texture * texture, GLuint * tex); } EGL_TextureOps; struct EGL_Texture { struct EGL_TextureOps ops; + EGL * egl; + GLuint sampler; + RingBuffer textures; + + EGL_TexFormat format; + bool formatValid; // needed for dmabuf size_t size; + + // for applying shaders + struct ll * render; + _Atomic(bool) updated; + bool postProcessed; + EGL_Model * model; }; -bool egl_textureInit(EGL_Texture ** texture, EGLDisplay * display, +bool egl_textureInit(EGL * egl, EGL_Texture ** texture, EGLDisplay * display, EGL_TexType type, bool streaming); void egl_textureFree(EGL_Texture ** tex); @@ -145,3 +165,5 @@ bool egl_textureUpdateFromDMA(EGL_Texture * texture, enum EGL_TexStatus egl_textureProcess(EGL_Texture * texture); enum EGL_TexStatus egl_textureBind(EGL_Texture * texture); + +enum EGL_TexStatus egl_textureAddShader(EGL_Texture * texture, EGL_Shader * shader); diff --git a/client/renderers/EGL/texture_buffer.c b/client/renderers/EGL/texture_buffer.c index cba87e17..eec31203 100644 --- a/client/renderers/EGL/texture_buffer.c +++ b/client/renderers/EGL/texture_buffer.c @@ -38,9 +38,6 @@ static void egl_texBuffer_cleanup(TextureBuffer * this) if (this->tex[0]) glDeleteTextures(this->texCount, this->tex); - if (this->sampler) - glDeleteSamplers(1, &this->sampler); - if (this->sync) { glDeleteSync(this->sync); @@ -88,27 +85,18 @@ bool egl_texBufferSetup(EGL_Texture * texture, const EGL_TexSetup * setup) egl_texBuffer_cleanup(this); - if (!egl_texUtilGetFormat(setup, &this->format)) - return false; - - glGenSamplers(1, &this->sampler); - glSamplerParameteri(this->sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glSamplerParameteri(this->sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE); - glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE); - glGenTextures(this->texCount, this->tex); for(int i = 0; i < this->texCount; ++i) { glBindTexture(GL_TEXTURE_2D, this->tex[i]); glTexImage2D(GL_TEXTURE_2D, 0, - this->format.intFormat, - this->format.width, - this->format.height, + texture->format.intFormat, + texture->format.width, + texture->format.height, 0, - this->format.format, - this->format.dataType, + texture->format.format, + texture->format.dataType, NULL); } @@ -118,19 +106,19 @@ bool egl_texBufferSetup(EGL_Texture * texture, const EGL_TexSetup * setup) return true; } -static bool egl_texBuffer_update(EGL_Texture * texture, const EGL_TexUpdate * update) +static bool egl_texBufferUpdate(EGL_Texture * texture, const EGL_TexUpdate * update) { TextureBuffer * this = UPCAST(TextureBuffer, texture); assert(update->type == EGL_TEXTYPE_BUFFER); glBindTexture(GL_TEXTURE_2D, this->tex[0]); - glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.pitch); + glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->format.pitch); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - this->format.width, - this->format.height, - this->format.format, - this->format.dataType, + texture->format.width, + texture->format.height, + texture->format.format, + texture->format.dataType, update->buffer); glBindTexture(GL_TEXTURE_2D, 0); @@ -142,15 +130,11 @@ EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture) return EGL_TEX_STATUS_OK; } -EGL_TexStatus egl_texBufferBind(EGL_Texture * texture) +EGL_TexStatus egl_texBufferGet(EGL_Texture * texture, GLuint * tex) { TextureBuffer * this = UPCAST(TextureBuffer, texture); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, this->tex[0]); - glBindSampler(0, this->sampler); - - return true; + *tex = this->tex[0]; + return EGL_TEX_STATUS_OK; } // streaming functions @@ -173,7 +157,7 @@ bool egl_texBufferStreamSetup(EGL_Texture * texture, const EGL_TexSetup * setup) return false; TextureBuffer * this = UPCAST(TextureBuffer, texture); - return egl_texUtilGenBuffers(&this->format, this->buf, this->texCount); + return egl_texUtilGenBuffers(&texture->format, this->buf, this->texCount); } static bool egl_texBufferStreamUpdate(EGL_Texture * texture, @@ -184,7 +168,7 @@ static bool egl_texBufferStreamUpdate(EGL_Texture * texture, LG_LOCK(this->copyLock); memcpy(this->buf[this->bufIndex].map, update->buffer, - this->format.bufferSize); + texture->format.bufferSize); this->buf[this->bufIndex].updated = true; LG_UNLOCK(this->copyLock); @@ -215,13 +199,13 @@ EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture) glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo); glBindTexture(GL_TEXTURE_2D, tex); - glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.pitch); + glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->format.pitch); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - this->format.width, - this->format.height, - this->format.format, - this->format.dataType, + texture->format.width, + texture->format.height, + texture->format.format, + texture->format.dataType, (const void *)0); glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); @@ -233,7 +217,7 @@ EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture) return EGL_TEX_STATUS_OK; } -EGL_TexStatus egl_texBufferStreamBind(EGL_Texture * texture) +EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex) { TextureBuffer * this = UPCAST(TextureBuffer, texture); @@ -262,10 +246,7 @@ EGL_TexStatus egl_texBufferStreamBind(EGL_Texture * texture) } } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, this->tex[this->rIndex]); - glBindSampler(0, this->sampler); - + *tex = this->tex[this->rIndex]; return EGL_TEX_STATUS_OK; } @@ -274,9 +255,9 @@ const EGL_TextureOps EGL_TextureBuffer = .init = egl_texBufferInit, .free = egl_texBufferFree, .setup = egl_texBufferSetup, - .update = egl_texBuffer_update, + .update = egl_texBufferUpdate, .process = egl_texBufferProcess, - .bind = egl_texBufferBind + .get = egl_texBufferGet }; const EGL_TextureOps EGL_TextureBufferStream = @@ -286,5 +267,5 @@ const EGL_TextureOps EGL_TextureBufferStream = .setup = egl_texBufferStreamSetup, .update = egl_texBufferStreamUpdate, .process = egl_texBufferStreamProcess, - .bind = egl_texBufferStreamBind + .get = egl_texBufferStreamGet }; diff --git a/client/renderers/EGL/texture_buffer.h b/client/renderers/EGL/texture_buffer.h index c5c03d2d..f3a7d37d 100644 --- a/client/renderers/EGL/texture_buffer.h +++ b/client/renderers/EGL/texture_buffer.h @@ -31,7 +31,6 @@ typedef struct TextureBuffer EGL_Texture base; bool free; - EGL_TexFormat format; int texCount; GLuint tex[EGL_TEX_BUFFER_MAX]; GLuint sampler; @@ -48,10 +47,10 @@ bool egl_texBufferInit(EGL_Texture ** texture_, EGLDisplay * display); void egl_texBufferFree(EGL_Texture * texture_); bool egl_texBufferSetup(EGL_Texture * texture_, const EGL_TexSetup * setup); EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture_); -EGL_TexStatus egl_texBufferBind(EGL_Texture * texture_); +EGL_TexStatus egl_texBufferGet(EGL_Texture * texture_, GLuint * tex); bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGLDisplay * display); bool egl_texBufferStreamSetup(EGL_Texture * texture_, const EGL_TexSetup * setup); EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture_); -EGL_TexStatus egl_texBufferStreamBind(EGL_Texture * texture_); +EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture_, GLuint * tex); diff --git a/client/renderers/EGL/texture_dmabuf.c b/client/renderers/EGL/texture_dmabuf.c index f752e36b..63fcfffd 100644 --- a/client/renderers/EGL/texture_dmabuf.c +++ b/client/renderers/EGL/texture_dmabuf.c @@ -99,12 +99,12 @@ static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup glBindTexture(GL_TEXTURE_2D, parent->tex[0]); glTexImage2D(GL_TEXTURE_2D, 0, - parent->format.intFormat, - parent->format.width, - parent->format.height, + texture->format.intFormat, + texture->format.width, + texture->format.height, 0, - parent->format.format, - parent->format.dataType, + texture->format.format, + texture->format.dataType, NULL); return true; @@ -130,12 +130,12 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture, { EGLAttrib const attribs[] = { - EGL_WIDTH , parent->format.width, - EGL_HEIGHT , parent->format.height, - EGL_LINUX_DRM_FOURCC_EXT , parent->format.fourcc, + EGL_WIDTH , texture->format.width, + EGL_HEIGHT , texture->format.height, + EGL_LINUX_DRM_FOURCC_EXT , texture->format.fourcc, EGL_DMA_BUF_PLANE0_FD_EXT , update->dmaFD, EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, - EGL_DMA_BUF_PLANE0_PITCH_EXT , parent->format.stride, + EGL_DMA_BUF_PLANE0_PITCH_EXT , texture->format.stride, EGL_NONE , EGL_NONE }; @@ -182,14 +182,11 @@ static EGL_TexStatus egl_texDMABUFProcess(EGL_Texture * texture) return EGL_TEX_STATUS_OK; } -static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture) +static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex) { TextureBuffer * parent = UPCAST(TextureBuffer, texture); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, parent->tex[0]); - glBindSampler(0, parent->sampler); - + *tex = parent->tex[0]; return EGL_TEX_STATUS_OK; } @@ -200,5 +197,5 @@ EGL_TextureOps EGL_TextureDMABUF = .setup = egl_texDMABUFSetup, .update = egl_texDMABUFUpdate, .process = egl_texDMABUFProcess, - .bind = egl_texDMABUFBind + .get = egl_texDMABUFGet }; diff --git a/client/renderers/EGL/texture_framebuffer.c b/client/renderers/EGL/texture_framebuffer.c index 420a5194..54ef8323 100644 --- a/client/renderers/EGL/texture_framebuffer.c +++ b/client/renderers/EGL/texture_framebuffer.c @@ -85,11 +85,11 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update) framebuffer_read( update->frame, parent->buf[parent->bufIndex].map, - parent->format.stride, - parent->format.height, - parent->format.width, - parent->format.bpp, - parent->format.stride + texture->format.stride, + texture->format.height, + texture->format.width, + texture->format.bpp, + texture->format.stride ); else { @@ -100,10 +100,10 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update) damage->rects, damage->count, parent->buf[parent->bufIndex].map, - parent->format.stride, - parent->format.height, + texture->format.stride, + texture->format.height, update->frame, - parent->format.stride + texture->format.stride ); } @@ -132,10 +132,10 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update) EGL_TextureOps EGL_TextureFrameBuffer = { - .init = egl_texFBInit, - .free = egl_texFBFree, - .setup = egl_texBufferStreamSetup, - .update = egl_texFBUpdate, - .process = egl_texBufferStreamProcess, - .bind = egl_texBufferStreamBind + .init = egl_texFBInit, + .free = egl_texFBFree, + .setup = egl_texBufferStreamSetup, + .update = egl_texFBUpdate, + .process = egl_texBufferStreamProcess, + .get = egl_texBufferStreamGet }; diff --git a/client/renderers/EGL/texture_util.c b/client/renderers/EGL/texture_util.c index c0e02f6b..405b41b3 100644 --- a/client/renderers/EGL/texture_util.c +++ b/client/renderers/EGL/texture_util.c @@ -18,6 +18,7 @@ * Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "texture.h" #include "texture_util.h" #include diff --git a/client/renderers/EGL/texture_util.h b/client/renderers/EGL/texture_util.h index 31378fcc..abde0284 100644 --- a/client/renderers/EGL/texture_util.h +++ b/client/renderers/EGL/texture_util.h @@ -22,6 +22,8 @@ #include "texture.h" +typedef struct EGL_TexSetup EGL_TexSetup; + typedef struct EGL_TexFormat { size_t bpp;