diff --git a/workspace/all/common/generic_video.c b/workspace/all/common/generic_video.c index 0d68a74ef..e2189ac27 100644 --- a/workspace/all/common/generic_video.c +++ b/workspace/all/common/generic_video.c @@ -31,48 +31,79 @@ #define NEXTUI_TSAN 1 #endif -static int finalScaleFilter=GL_LINEAR; static int reloadShaderTextures = 1; static int shaderResetRequested = 0; // shader stuff -typedef struct Shader { - int srcw; - int srch; - int texw; - int texh; - int filter; +typedef struct ShaderProgram { GLuint shader_p; - int scale; - int srctype; - int scaletype; char *filename; - GLuint texture; - int updated; + + // Cached from glGetUniformLocation() GLint u_FrameDirection; GLint u_FrameCount; GLint u_OutputSize; GLint u_TextureSize; GLint u_InputSize; - GLint OrigInputSize; - GLint texLocation; - GLint texelSizeLocation; + GLint u_OrigTextureSize; + GLint u_OrigInputSize; + GLint u_Texture; + GLint u_OrigTexture; + GLint u_texelSize; + ShaderParam *pragmas; // Dynamic array of parsed pragma parameters int num_pragmas; // Count of valid pragma parameters +} ShaderProgram; -} Shader; +ShaderProgram s_shader_default = {0}; +ShaderProgram s_shader_overlay = {0}; +ShaderProgram s_noshader = {0}; -GLuint g_shader_default = 0; -GLuint g_shader_overlay = 0; -GLuint g_noshader = 0; +typedef struct ShaderPass { + ShaderProgram * program; + int filter; + int alpha; + GLuint target_texture; + int target_updated; + int scale; + int srctype; + int scaletype; + int srcw; + int srch; + int texw; + int texh; +} ShaderPass; + +ShaderProgram shader_programs[MAXSHADERS]; +ShaderPass shaders[MAXSHADERS]; + +// memcpy these in initShaders() +const ShaderProgram blank_shader_program = { + .shader_p = 0, .filename = "stock.glsl" +}; +const ShaderPass blank_shader_pass = { .program = NULL, + .alpha = 0, .target_texture = 0, .target_updated = 1 +}; -Shader* shaders[MAXSHADERS] = { - &(Shader){ .shader_p = 0, .scale = 1, .filter = GL_LINEAR, .scaletype = 1, .srctype = 0, .filename ="stock.glsl", .texture = 0, .updated = 1 }, - &(Shader){ .shader_p = 0, .scale = 1, .filter = GL_LINEAR, .scaletype = 1, .srctype = 0, .filename ="stock.glsl", .texture = 0, .updated = 1 }, - &(Shader){ .shader_p = 0, .scale = 1, .filter = GL_LINEAR, .scaletype = 1, .srctype = 0, .filename ="stock.glsl", .texture = 0, .updated = 1 }, +ShaderPass s_pass_finalscale = { .program = &s_shader_default, + .filter = GL_NEAREST, + .alpha = 0, .target_texture = 0, .target_updated = 1 }; +ShaderPass s_pass_effect = { .program = &s_shader_overlay, + .alpha = 1, .target_texture = 0, .target_updated = 1 +}; + +ShaderPass s_pass_overlay = { .program = &s_shader_overlay, + .alpha = 1, .target_texture = 0, .target_updated = 1 +}; + +ShaderPass s_pass_notif = { .program = &s_shader_overlay, + .alpha = 1, .target_texture = 0, .target_updated = 1 +}; + + static int nrofshaders = 0; // choose between 1 and 3 pipelines, > pipelines = more cpu usage, but more shader options and shader upscaling stuff /////////////////////////////// @@ -269,9 +300,7 @@ char* load_shader_source(const char* filename) { return source; } -GLuint load_shader_from_file(GLenum type, const char* filename, const char* path) { - char filepath[256]; - snprintf(filepath, sizeof(filepath), "%s/%s", path, filename); +GLuint load_shader_from_file(GLenum type, const char* filepath) { char* source = load_shader_source(filepath); if (!source) return 0; @@ -431,29 +460,101 @@ GLuint load_shader_from_file(GLenum type, const char* filename, const char* path return shader; } +#define MAX_SHADER_PRAGMAS 32 +void loadShaderPragmas(ShaderProgram *shader, const char *shaderSource) { + shader->pragmas = calloc(MAX_SHADER_PRAGMAS, sizeof(ShaderParam)); + if (!shader->pragmas) { + fprintf(stderr, "Out of memory allocating pragmas for %s\n", shader->filename); + return; + } + shader->num_pragmas = extractPragmaParameters(shaderSource, shader->pragmas, MAX_SHADER_PRAGMAS); +} + +ShaderParam* PLAT_getShaderPragmas(int i) { + return shaders[i].program->pragmas; +} + +void init_shader_program(ShaderProgram * shader, const char * path, const char * filename) { + char filepath[512]; + snprintf(filepath, sizeof(filepath), "%s/%s", path, filename); + + const char *shaderSource = load_shader_source(filepath); + loadShaderPragmas(shader,shaderSource); + + GLuint vertex_shader1 = load_shader_from_file(GL_VERTEX_SHADER, filepath); + GLuint fragment_shader1 = load_shader_from_file(GL_FRAGMENT_SHADER, filepath); + + // Link the shader program + if (shader->shader_p != 0) { + LOG_info("Deleting previous shader %i\n",shader->shader_p); + glDeleteProgram(shader->shader_p); + } + shader->shader_p = link_program(vertex_shader1, fragment_shader1, filename); + + + if (shader->shader_p == 0) { + LOG_info("Shader linking failed for %s\n", filename); + } + + GLint success = 0; + glGetProgramiv(shader->shader_p, GL_LINK_STATUS, &success); + if (!success) { + char infoLog[512]; + glGetProgramInfoLog(shader->shader_p, 512, NULL, infoLog); + LOG_info("Shader Program Linking Failed: %s\n", infoLog); + } else { + LOG_info("Shader Program Linking Success %s shader ID is %i\n", filename,shader->shader_p); + + // Populate uniforms and pragma uniforms + shader->u_FrameDirection = glGetUniformLocation( shader->shader_p, "FrameDirection"); + shader->u_FrameCount = glGetUniformLocation( shader->shader_p, "FrameCount"); + shader->u_OutputSize = glGetUniformLocation( shader->shader_p, "OutputSize"); + shader->u_TextureSize = glGetUniformLocation( shader->shader_p, "TextureSize"); + shader->u_InputSize = glGetUniformLocation( shader->shader_p, "InputSize"); + shader->u_OrigTextureSize = glGetUniformLocation( shader->shader_p, "OrigTextureSize"); + shader->u_OrigInputSize = glGetUniformLocation( shader->shader_p, "OrigInputSize"); + shader->u_Texture = glGetUniformLocation(shader->shader_p, "Texture"); + shader->u_OrigTexture = glGetUniformLocation(shader->shader_p, "OrigTexture"); + shader->u_texelSize = glGetUniformLocation(shader->shader_p, "texelSize"); + for (int i = 0; i < shader->num_pragmas; ++i) { + shader->pragmas[i].uniformLocation = glGetUniformLocation(shader->shader_p, shader->pragmas[i].name); + shader->pragmas[i].value = shader->pragmas[i].def; + + LOG_info("Param: %s = %f (min: %f, max: %f, step: %f)\n", + shader->pragmas[i].name, + shader->pragmas[i].def, + shader->pragmas[i].min, + shader->pragmas[i].max, + shader->pragmas[i].step); + } + + } + shader->filename = strdup(filename); + +} + void PLAT_initShaders() { SDL_GL_MakeCurrent(vid.window, vid.gl_context); glViewport(0, 0, device_width, device_height); - - GLuint vertex; - GLuint fragment; - // Final display shader (simple texture blit) - vertex = load_shader_from_file(GL_VERTEX_SHADER, "default.glsl",SYSSHADERS_FOLDER); - fragment = load_shader_from_file(GL_FRAGMENT_SHADER, "default.glsl",SYSSHADERS_FOLDER); - g_shader_default = link_program(vertex, fragment,"default.glsl"); + // Init user shaders + for (int i = 0; i < MAXSHADERS; i++) { + memcpy(&shader_programs[i], &blank_shader_program, sizeof(ShaderProgram)); + memcpy(&shaders[i], &blank_shader_pass, sizeof(ShaderPass)); + shaders[i].program = &shader_programs[i]; + } + + // Init .system shaders + // Final display shader (simple texture blit) + init_shader_program(&s_shader_default, SYSSHADERS_FOLDER, "default.glsl"); // Overlay shader, for png overlays and static line/grid overlays - vertex = load_shader_from_file(GL_VERTEX_SHADER, "overlay.glsl",SYSSHADERS_FOLDER); - fragment = load_shader_from_file(GL_FRAGMENT_SHADER, "overlay.glsl",SYSSHADERS_FOLDER); - g_shader_overlay = link_program(vertex, fragment,"overlay.glsl"); + init_shader_program(&s_shader_overlay, SYSSHADERS_FOLDER, "overlay.glsl"); // Stand-In if a shader is supposed to be applied, but wasnt compiled properly (shaper_p == NULL) - vertex = load_shader_from_file(GL_VERTEX_SHADER, "noshader.glsl",SYSSHADERS_FOLDER); - fragment = load_shader_from_file(GL_FRAGMENT_SHADER, "noshader.glsl",SYSSHADERS_FOLDER); - g_noshader = link_program(vertex, fragment,"noshader.glsl"); + init_shader_program(&s_noshader, SYSSHADERS_FOLDER, "noshader.glsl"); - LOG_info("default shaders loaded, %i\n\n",g_shader_default); + LOG_info("default shaders loaded, %i\n\n", s_shader_default.shader_p); } void PLAT_initNotificationTexture(void) { @@ -599,96 +700,35 @@ SDL_Surface* PLAT_initVideo(void) { return vid.screen; } -#define MAX_SHADER_PRAGMAS 32 -void loadShaderPragmas(Shader *shader, const char *shaderSource) { - shader->pragmas = calloc(MAX_SHADER_PRAGMAS, sizeof(ShaderParam)); - if (!shader->pragmas) { - fprintf(stderr, "Out of memory allocating pragmas for %s\n", shader->filename); - return; - } - shader->num_pragmas = extractPragmaParameters(shaderSource, shader->pragmas, MAX_SHADER_PRAGMAS); -} - -ShaderParam* PLAT_getShaderPragmas(int i) { - return shaders[i]->pragmas; -} - void PLAT_updateShader(int i, const char *filename, int *scale, int *filter, int *scaletype, int *srctype) { - if (i < 0 || i >= nrofshaders) { + if (i < 0) { return; } - Shader* shader = shaders[i]; + ShaderPass* shader_pass = &shaders[i]; if (filename != NULL) { SDL_GL_MakeCurrent(vid.window, vid.gl_context); LOG_info("loading shader \n"); - char filepath[512]; - snprintf(filepath, sizeof(filepath), SHADERS_FOLDER "/glsl/%s",filename); - const char *shaderSource = load_shader_source(filepath); - loadShaderPragmas(shader,shaderSource); - - GLuint vertex_shader1 = load_shader_from_file(GL_VERTEX_SHADER, filename,SHADERS_FOLDER "/glsl"); - GLuint fragment_shader1 = load_shader_from_file(GL_FRAGMENT_SHADER, filename,SHADERS_FOLDER "/glsl"); - - // Link the shader program - if (shader->shader_p != 0) { - LOG_info("Deleting previous shader %i\n",shader->shader_p); - glDeleteProgram(shader->shader_p); - } - shader->shader_p = link_program(vertex_shader1, fragment_shader1,filename); - - shader->u_FrameDirection = glGetUniformLocation( shader->shader_p, "FrameDirection"); - shader->u_FrameCount = glGetUniformLocation( shader->shader_p, "FrameCount"); - shader->u_OutputSize = glGetUniformLocation( shader->shader_p, "OutputSize"); - shader->u_TextureSize = glGetUniformLocation( shader->shader_p, "TextureSize"); - shader->u_InputSize = glGetUniformLocation( shader->shader_p, "InputSize"); - shader->OrigInputSize = glGetUniformLocation( shader->shader_p, "OrigInputSize"); - shader->texLocation = glGetUniformLocation(shader->shader_p, "Texture"); - shader->texelSizeLocation = glGetUniformLocation(shader->shader_p, "texelSize"); - for (int i = 0; i < shader->num_pragmas; ++i) { - shader->pragmas[i].uniformLocation = glGetUniformLocation(shader->shader_p, shader->pragmas[i].name); - shader->pragmas[i].value = shader->pragmas[i].def; - - LOG_info("Param: %s = %f (min: %f, max: %f, step: %f)\n", - shader->pragmas[i].name, - shader->pragmas[i].def, - shader->pragmas[i].min, - shader->pragmas[i].max, - shader->pragmas[i].step); - } - - if (shader->shader_p == 0) { - LOG_info("Shader linking failed for %s\n", filename); - } + init_shader_program(shader_pass->program, SHADERS_FOLDER "/glsl", filename); + } - GLint success = 0; - glGetProgramiv(shader->shader_p, GL_LINK_STATUS, &success); - if (!success) { - char infoLog[512]; - glGetProgramInfoLog(shader->shader_p, 512, NULL, infoLog); - LOG_info("Shader Program Linking Failed: %s\n", infoLog); - } else { - LOG_info("Shader Program Linking Success %s shader ID is %i\n", filename,shader->shader_p); - } - shader->filename = strdup(filename); - } if (scale != NULL) { - shader->scale = *scale +1; + shader_pass->scale = *scale +1; reloadShaderTextures = 1; } if (scaletype != NULL) { - shader->scaletype = *scaletype; + shader_pass->scaletype = *scaletype; } if (srctype != NULL) { - shader->srctype = *srctype; + shader_pass->srctype = *srctype; } if (filter != NULL) { - shader->filter = (*filter == 1) ? GL_LINEAR : GL_NEAREST; + shader_pass->filter = (*filter == 1) ? GL_LINEAR : GL_NEAREST; reloadShaderTextures = 1; } - shader->updated = 1; + shader_pass->target_updated = 1; } @@ -830,10 +870,10 @@ SDL_Surface* PLAT_resizeVideo(int w, int h, int p) { void PLAT_setSharpness(int sharpness) { if(sharpness==1) { - finalScaleFilter=GL_LINEAR; + s_pass_finalscale.filter = GL_LINEAR; } else { - finalScaleFilter = GL_NEAREST; + s_pass_finalscale.filter = GL_NEAREST; } reloadShaderTextures = 1; } @@ -1621,8 +1661,14 @@ void PLAT_flip(SDL_Surface* IGNORED, int ignored) { } static int frame_count = 0; -void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_texture, - int x, int y, int dst_width, int dst_height, Shader* shader, int alpha, int filter) { +static GLuint orig_texture = 0; +static int orig_w = 0; +static int orig_h = 0; +static int origtex_w = 0; +static int origtex_h = 0; +void runShaderPass(ShaderPass * shader_pass, GLuint src_texture, + GLuint * target_texture, int next_filter, + int x, int y, int dst_width, int dst_height) { static GLuint static_VAO = 0, static_VBO = 0; static GLuint last_program = 0; @@ -1634,6 +1680,16 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex static int logged_bad_size = 0; GLenum pre_err; + if (!shader_pass) return; + + ShaderProgram * shader_program = shader_pass->program; + + if (!shader_program || !shader_program->shader_p) { + shader_program = &s_noshader; + } + + const GLuint shader_program_handle = shader_program->shader_p; + while ((pre_err = glGetError()) != GL_NO_ERROR) { (void)pre_err; } @@ -1663,12 +1719,12 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex last_bound_texture = 0; } - texelSize[0] = 1.0f / shader->texw; - texelSize[1] = 1.0f / shader->texh; + texelSize[0] = 1.0f / shader_pass->texw; + texelSize[1] = 1.0f / shader_pass->texh; - if (shader_program != last_program) - glUseProgram(shader_program); + if (shader_program_handle != last_program) + glUseProgram(shader_program_handle); if (static_VAO == 0) { glGenVertexArrays(1, &static_VAO); @@ -1687,29 +1743,30 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); } - if (shader_program != last_program) { - GLint posAttrib = glGetAttribLocation(shader_program, "VertexCoord"); + if (shader_program_handle != last_program) { + GLint posAttrib = glGetAttribLocation(shader_program_handle, "VertexCoord"); if (posAttrib >= 0) { glVertexAttribPointer(posAttrib, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(posAttrib); } - GLint texAttrib = glGetAttribLocation(shader_program, "TexCoord"); + GLint texAttrib = glGetAttribLocation(shader_program_handle, "TexCoord"); if (texAttrib >= 0) { glVertexAttribPointer(texAttrib, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(4 * sizeof(float))); glEnableVertexAttribArray(texAttrib); } - if (shader->u_FrameDirection >= 0) glUniform1i(shader->u_FrameDirection, 1); - if (shader->u_FrameCount >= 0) glUniform1i(shader->u_FrameCount, frame_count); - if (shader->u_OutputSize >= 0) glUniform2f(shader->u_OutputSize, dst_width, dst_height); - if (shader->u_TextureSize >= 0) glUniform2f(shader->u_TextureSize, shader->texw, shader->texh); - if (shader->OrigInputSize >= 0) glUniform2f(shader->OrigInputSize, shader->srcw, shader->srch); - if (shader->u_InputSize >= 0) glUniform2f(shader->u_InputSize, shader->srcw, shader->srch); - for (int i = 0; i < shader->num_pragmas; ++i) { - glUniform1f(shader->pragmas[i].uniformLocation, shader->pragmas[i].value); + if (shader_program->u_FrameDirection >= 0) glUniform1i(shader_program->u_FrameDirection, 1); + if (shader_program->u_FrameCount >= 0) glUniform1i(shader_program->u_FrameCount, frame_count); + if (shader_program->u_OutputSize >= 0) glUniform2f(shader_program->u_OutputSize, dst_width, dst_height); + if (shader_program->u_TextureSize >= 0) glUniform2f(shader_program->u_TextureSize, shader_pass->texw, shader_pass->texh); + if (shader_program->u_InputSize >= 0) glUniform2f(shader_program->u_InputSize, shader_pass->srcw, shader_pass->srch); + if (shader_program->u_OrigTextureSize >= 0) glUniform2f(shader_program->u_OrigTextureSize, origtex_w, origtex_h); + if (shader_program->u_OrigInputSize >= 0) glUniform2f(shader_program->u_OrigInputSize, orig_w, orig_h); + for (int i = 0; i < shader_program->num_pragmas; ++i) { + glUniform1f(shader_program->pragmas[i].uniformLocation, shader_program->pragmas[i].value); } - GLint u_MVP = glGetUniformLocation(shader_program, "MVPMatrix"); + GLint u_MVP = glGetUniformLocation(shader_program_handle, "MVPMatrix"); if (u_MVP >= 0) { float identity[16] = { 1,0,0,0, @@ -1724,9 +1781,9 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex if (target_texture) { if (*target_texture != 0 && !glIsTexture(*target_texture)) { *target_texture = 0; - shader->updated = 1; + shader_pass->target_updated = 1; } - if (*target_texture==0 || shader->updated || reloadShaderTextures) { + if (*target_texture==0 || shader_pass->target_updated || reloadShaderTextures) { // if(target_texture) { // glDeleteTextures(1,target_texture); @@ -1735,12 +1792,12 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex glGenTextures(1, target_texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, *target_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, next_filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, next_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dst_width, dst_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - shader->updated = 0; + shader_pass->target_updated = 0; } if (fbo == 0) { glGenFramebuffers(1, &fbo); @@ -1766,7 +1823,7 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex glBindFramebuffer(GL_FRAMEBUFFER, 0); } - if(alpha==1) { + if(shader_pass->alpha==1) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -1781,15 +1838,22 @@ void runShaderPass(GLuint src_texture, GLuint shader_program, GLuint* target_tex glViewport(x, y, dst_width, dst_height); - if (shader->texLocation >= 0) glUniform1i(shader->texLocation, 0); + if (shader_program->u_Texture >= 0) glUniform1i(shader_program->u_Texture, 0); + + if (shader_program->u_OrigTexture >= 0) { + glUniform1i(shader_program->u_OrigTexture, 1); + glActiveTexture(GL_TEXTURE0+1); + glBindTexture(GL_TEXTURE_2D, orig_texture); + glActiveTexture(GL_TEXTURE0); + } - if (shader->texelSizeLocation >= 0) { - glUniform2fv(shader->texelSizeLocation, 1, texelSize); + if (shader_program->u_texelSize >= 0) { + glUniform2fv(shader_program->u_texelSize, 1, texelSize); last_texelSize[0] = texelSize[0]; last_texelSize[1] = texelSize[1]; } glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - last_program = shader_program; + last_program = shader_program_handle; } typedef struct { @@ -1920,12 +1984,11 @@ void PLAT_GL_Swap() { static int overlay_w = 0, overlay_h = 0; static int overlayload = 0; - static GLuint src_texture = 0; static int src_w_last = 0, src_h_last = 0; static int last_w = 0, last_h = 0; if (shaderResetRequested) { - if (src_texture) { glDeleteTextures(1, &src_texture); src_texture = 0; } + if (orig_texture) { glDeleteTextures(1, &orig_texture); orig_texture = 0; } src_w_last = src_h_last = 0; last_w = last_h = 0; if (effect_tex) { @@ -1970,6 +2033,8 @@ void PLAT_GL_Swap() { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, loaded_effect->w, loaded_effect->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, loaded_effect->pixels); effect_w = loaded_effect->w; effect_h = loaded_effect->h; + s_pass_effect.srcw = s_pass_effect.texw = effect_w; + s_pass_effect.srch = s_pass_effect.texh = effect_h; } else { if (effect_tex) { glDeleteTextures(1, &effect_tex); @@ -1998,7 +2063,8 @@ void PLAT_GL_Swap() { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, loaded_overlay->w, loaded_overlay->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, loaded_overlay->pixels); overlay_w = loaded_overlay->w; overlay_h = loaded_overlay->h; - + s_pass_overlay.srcw = s_pass_overlay.texw = overlay_w; + s_pass_overlay.srch = s_pass_overlay.texh = overlay_h; } else { if (overlay_tex) { glDeleteTextures(1, &overlay_tex); @@ -2010,25 +2076,29 @@ void PLAT_GL_Swap() { pthread_mutex_unlock(&video_prep_mutex); } - if (!src_texture || reloadShaderTextures) { - // if (src_texture) { - // glDeleteTextures(1, &src_texture); - // src_texture = 0; + if (!orig_texture || reloadShaderTextures) { + // if (orig_texture) { + // glDeleteTextures(1, &orig_texture); + // orig_texture = 0; // } - if (src_texture==0) - glGenTextures(1, &src_texture); - glBindTexture(GL_TEXTURE_2D, src_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, nrofshaders > 0 ? shaders[0]->filter : finalScaleFilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, nrofshaders > 0 ? shaders[0]->filter : finalScaleFilter); + if (orig_texture==0) + glGenTextures(1, &orig_texture); + glBindTexture(GL_TEXTURE_2D, orig_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, nrofshaders > 0 ? shaders[0].filter : s_pass_finalscale.filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, nrofshaders > 0 ? shaders[0].filter : s_pass_finalscale.filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - glBindTexture(GL_TEXTURE_2D, src_texture); + glBindTexture(GL_TEXTURE_2D, orig_texture); if (vid.blit->src_w != src_w_last || vid.blit->src_h != src_h_last || reloadShaderTextures) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.blit->src_w, vid.blit->src_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, vid.blit->src); src_w_last = vid.blit->src_w; src_h_last = vid.blit->src_h; + orig_w = vid.blit->src_w; + orig_h = vid.blit->src_h; + origtex_w = vid.blit->src_w; + origtex_h = vid.blit->src_h; } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, vid.blit->src_w, vid.blit->src_h, GL_RGBA, GL_UNSIGNED_BYTE, vid.blit->src); } @@ -2039,10 +2109,10 @@ void PLAT_GL_Swap() { for (int i = 0; i < nrofshaders; i++) { int src_w = last_w; int src_h = last_h; - int dst_w = src_w * shaders[i]->scale; - int dst_h = src_h * shaders[i]->scale; + int dst_w = src_w * shaders[i].scale; + int dst_h = src_h * shaders[i].scale; - if (shaders[i]->scale == 9) { + if (shaders[i].scale == 9) { dst_w = dst_rect.w; dst_h = dst_rect.h; } @@ -2052,10 +2122,10 @@ void PLAT_GL_Swap() { int real_input_w = (i == 0) ? vid.blit->src_w : last_w; int real_input_h = (i == 0) ? vid.blit->src_h : last_h; - shaders[i]->srcw = shaders[i]->srctype == 0 ? vid.blit->src_w : shaders[i]->srctype == 2 ? dst_rect.w : real_input_w; - shaders[i]->srch = shaders[i]->srctype == 0 ? vid.blit->src_h : shaders[i]->srctype == 2 ? dst_rect.h : real_input_h; - shaders[i]->texw = shaders[i]->scaletype == 0 ? vid.blit->src_w : shaders[i]->scaletype == 2 ? dst_rect.w : real_input_w; - shaders[i]->texh = shaders[i]->scaletype == 0 ? vid.blit->src_h : shaders[i]->scaletype == 2 ? dst_rect.h : real_input_h; + shaders[i].srcw = shaders[i].srctype == 0 ? vid.blit->src_w : shaders[i].srctype == 2 ? dst_rect.w : real_input_w; + shaders[i].srch = shaders[i].srctype == 0 ? vid.blit->src_h : shaders[i].srctype == 2 ? dst_rect.h : real_input_h; + shaders[i].texw = shaders[i].scaletype == 0 ? vid.blit->src_w : shaders[i].scaletype == 2 ? dst_rect.w : real_input_w; + shaders[i].texh = shaders[i].scaletype == 0 ? vid.blit->src_h : shaders[i].scaletype == 2 ? dst_rect.h : real_input_h; } } @@ -2063,10 +2133,10 @@ void PLAT_GL_Swap() { static int shaderinfoscreen = 0; if (shaderinfocount > 600 && shaderinfoscreen == i) { currentshaderpass = i + 1; - currentshadertexw = shaders[i]->texw; - currentshadertexh = shaders[i]->texh; - currentshadersrcw = shaders[i]->srcw; - currentshadersrch = shaders[i]->srch; + currentshadertexw = shaders[i].texw; + currentshadertexh = shaders[i].texh; + currentshadersrcw = shaders[i].srcw; + currentshadersrch = shaders[i].srch; currentshaderdstw = dst_w; currentshaderdsth = dst_h; shaderinfocount = 0; @@ -2076,28 +2146,12 @@ void PLAT_GL_Swap() { } shaderinfocount++; - if (shaders[i]->shader_p) { - //LOG_info("Shader Pass: Pipeline step %d/%d\n", i + 1, nrofshaders); - runShaderPass( - (i == 0) ? src_texture : shaders[i - 1]->texture, - shaders[i]->shader_p, - &shaders[i]->texture, - 0, 0, dst_w, dst_h, - shaders[i], - 0, - (i == nrofshaders - 1) ? finalScaleFilter : shaders[i + 1]->filter - ); - } else { - runShaderPass( - (i == 0) ? src_texture : shaders[i - 1]->texture, - g_noshader, - &shaders[i]->texture, - 0, 0, dst_w, dst_h, - shaders[i], - 0, - (i == nrofshaders - 1) ? finalScaleFilter : shaders[i + 1]->filter - ); - } + runShaderPass( + &shaders[i], + (i == 0) ? orig_texture : shaders[i - 1].target_texture, + &shaders[i].target_texture, + (i == nrofshaders - 1) ? s_pass_finalscale.filter : shaders[i+1].filter, + 0, 0, dst_w, dst_h); last_w = dst_w; last_h = dst_h; @@ -2105,65 +2159,57 @@ void PLAT_GL_Swap() { if (nrofshaders > 0) { //LOG_info("Shader Pass: Scale to screen (pipeline size: %d)\n", nrofshaders); - runShaderPass( - shaders[nrofshaders - 1]->texture, - g_shader_default, - NULL, - dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h, - &(Shader){.srcw = last_w, .srch = last_h, .texw = last_w, .texh = last_h}, - 0, GL_NONE - ); + s_pass_finalscale.srcw = s_pass_finalscale.texw = last_w; + s_pass_finalscale.srch = s_pass_finalscale.texh = last_h; + runShaderPass( + &s_pass_finalscale, + shaders[nrofshaders - 1].target_texture, + NULL, + GL_NONE, + dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h); } else { //LOG_info("Shader Pass: Scale to screen (pipeline size: %d)\n", nrofshaders); - runShaderPass(src_texture, - g_shader_default, - NULL, - dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h, - &(Shader){.srcw = vid.blit->src_w, .srch = vid.blit->src_h, .texw = vid.blit->src_w, .texh = vid.blit->src_h}, - 0, GL_NONE); + s_pass_finalscale.srcw = s_pass_finalscale.texw = orig_w; + s_pass_finalscale.srch = s_pass_finalscale.texh = orig_h; + runShaderPass( + &s_pass_finalscale, + orig_texture, + NULL, + GL_NONE, + dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h); } if (effect_tex) { //LOG_info("Shader Pass: Screen Effect\n"); - runShaderPass( - effect_tex, - g_shader_overlay, - NULL, - dst_rect.x, dst_rect.y, effect_w, effect_h, - &(Shader){.srcw = effect_w, .srch = effect_h, .texw = effect_w, .texh = effect_h}, - 1, GL_NONE - ); + runShaderPass( + &s_pass_overlay, effect_tex, NULL, + GL_NONE, + dst_rect.x, dst_rect.y, effect_w, effect_h); } if (overlay_tex) { //LOG_info("Shader Pass: Overlay\n"); - runShaderPass( - overlay_tex, - g_shader_overlay, - NULL, - 0, 0, device_width, device_height, - &(Shader){.srcw = vid.blit->src_w, .srch = vid.blit->src_h, .texw = overlay_w, .texh = overlay_h}, - 1, GL_NONE - ); + runShaderPass( + &s_pass_overlay, overlay_tex, NULL, + GL_NONE, + 0, 0, device_width, device_height); } // Render notification overlay if present (texture pre-allocated in PLAT_initShaders) if (notif.dirty && notif.surface) { - glBindTexture(GL_TEXTURE_2D, notif.tex); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, notif.surface->w, notif.surface->h, GL_RGBA, GL_UNSIGNED_BYTE, notif.surface->pixels); - notif.dirty = 0; + glBindTexture(GL_TEXTURE_2D, notif.tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, notif.surface->w, notif.surface->h, GL_RGBA, GL_UNSIGNED_BYTE, notif.surface->pixels); + s_pass_notif.srcw = s_pass_notif.texw = notif.tex_w; + s_pass_notif.srch = s_pass_notif.texh = notif.tex_h; + notif.dirty = 0; } if (notif.tex && notif.surface) { - runShaderPass( - notif.tex, - g_shader_overlay, - NULL, - notif.x, notif.y, notif.tex_w, notif.tex_h, - &(Shader){.srcw = notif.tex_w, .srch = notif.tex_h, .texw = notif.tex_w, .texh = notif.tex_h}, - 1, GL_NONE - ); + runShaderPass( + &s_pass_overlay, notif.tex, NULL, + GL_NONE, + notif.x, notif.y, notif.tex_w, notif.tex_h); } SDL_GL_SwapWindow(vid.window);