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
This commit is contained in:
Hermet Park 2018-11-27 11:25:13 +09:00
parent c9d20d488b
commit c71a561997
2 changed files with 18 additions and 6 deletions

View File

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

View File

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