From c71a561997f257b8b6e45a798e77c9a843834060 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 27 Nov 2018 11:25:13 +0900 Subject: [PATCH] evas gl: recover current program state. Summary: When we meets a new shader program in shape_context_push(), it loads a shader binary, if it is necessary, create a new program for the shader. In this step, the current program state could changed to this new one. But still our gl context by shader_flush() could keep the previous program for next shader flush. But it doens't know current program was changed by dropping by. Here is a simple scenario: 1. evas_gl_common_context_image_push(): This image requires Program A. it calls evas_gl_common_context_push() internally. then shader_array_flush() instantly. It stores the current context including shader program(Program A) 2. evas_gl_common_context_xxx_push(): call evas_gl_common_shader_program_get(). xxx draws first time, it loads a new shader program. Now this changed the current program to a new instant one. ... 3. shader_array_flush(): draw image which requires Prorgam A (No.1). Unfortunately, stored context is same to this. So, it skips some gl context setting including shader program. @fix Reviewers: #committers Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D7309 --- .../evas/engines/gl_common/evas_gl_common.h | 2 +- .../evas/engines/gl_common/evas_gl_shader.c | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 06cdbbf6cf..ab9a54948d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -695,7 +695,7 @@ Evas_GL_Program *evas_gl_common_shader_program_get(Evas_Engine_GL_Context *gc, Eina_Bool alphaonly, Shader_Sampling *psam, int *pnomul, Shader_Sampling *pmasksam); -void evas_gl_common_shader_textures_bind(Evas_GL_Program *p); +void evas_gl_common_shader_textures_bind(Evas_GL_Program *p, Eina_Bool recover_prog); Eina_Bool evas_gl_common_file_cache_is_dir(const char *file); Eina_Bool evas_gl_common_file_cache_mkdir(const char *dir); diff --git a/src/modules/evas/engines/gl_common/evas_gl_shader.c b/src/modules/evas/engines/gl_common/evas_gl_shader.c index e6c7a7b8de..a4dd632896 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_shader.c +++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c @@ -174,13 +174,21 @@ _evas_gl_common_shader_program_binary_load(Eet_File *ef, unsigned int flags) } p = calloc(1, sizeof(*p)); + + GLuint curr_prog = 0; + glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&curr_prog); + p->flags = flags; p->prog = prg; p->reset = EINA_TRUE; p->bin_saved = EINA_TRUE; + + glUseProgram(prg); p->uniform.mvp = glGetUniformLocation(prg, "mvp"); p->uniform.rotation_id = glGetUniformLocation(prg, "rotation_id"); - evas_gl_common_shader_textures_bind(p); + evas_gl_common_shader_textures_bind(p, EINA_FALSE); + + glUseProgram(curr_prog); finish: if (vtx) glDeleteShader(vtx); @@ -598,7 +606,7 @@ evas_gl_common_shader_generate_and_compile(Evas_GL_Shared *shared, unsigned int shared->needs_shaders_flush = 1; p->uniform.mvp = glGetUniformLocation(p->prog, "mvp"); p->uniform.rotation_id = glGetUniformLocation(p->prog, "rotation_id"); - evas_gl_common_shader_textures_bind(p); + evas_gl_common_shader_textures_bind(p, EINA_TRUE); eina_hash_add(shared->shaders_hash, &flags, p); } else WRN("Failed to compile a shader (flags: %08x)", flags); @@ -654,7 +662,7 @@ evas_gl_common_shader_program_init(Evas_GL_Shared *shared) p = _evas_gl_common_shader_program_binary_load(shared->shaders_cache, autoload[i]); if (p) { - evas_gl_common_shader_textures_bind(p); + evas_gl_common_shader_textures_bind(p, EINA_TRUE); eina_hash_add(shared->shaders_hash, &autoload[i], p); } } @@ -878,7 +886,7 @@ end: } void -evas_gl_common_shader_textures_bind(Evas_GL_Program *p) +evas_gl_common_shader_textures_bind(Evas_GL_Program *p, Eina_Bool prog_recover) { struct { const char *name; @@ -935,6 +943,9 @@ evas_gl_common_shader_textures_bind(Evas_GL_Program *p) if (hastex) { + GLuint curr_prog = 0; + if (prog_recover) glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&curr_prog); + glUseProgram(p->prog); // is this necessary?? for (i = 0; textures[i].name; i++) { @@ -947,6 +958,7 @@ evas_gl_common_shader_textures_bind(Evas_GL_Program *p) } glUniform1i(loc, p->tex_count++); } + if (prog_recover) glUseProgram(curr_prog); } } @@ -981,7 +993,7 @@ evas_gl_common_shader_program_get(Evas_Engine_GL_Context *gc, p = _evas_gl_common_shader_program_binary_load(gc->shared->shaders_cache, flags); if (p) { - evas_gl_common_shader_textures_bind(p); + evas_gl_common_shader_textures_bind(p, EINA_TRUE); eina_hash_add(gc->shared->shaders_hash, &flags, p); goto end; }