From 400f3388c362c4fa99b4d5f05efb281a7886d3f0 Mon Sep 17 00:00:00 2001 From: Jaeun Choi Date: Tue, 8 Nov 2016 14:58:02 +0900 Subject: [PATCH] evas: Fix masking with window rotation, take 2 The first patch did not work for maps. This explains why the original code was so weird. But it actually made sense. After struggling a bit I realized that we really just need to shuffle around the pixel position on the window to map that of the position in the canvas (unrotate it). Note that compatibility with GLSL-ES (for OpenGL ES) implies we can not use an array initializer like: vec2 pos[4] = vec2[4](a,b,c,d); So the code could probably be optimized. But at least this works. This patch also avoids calling glGetUniformLocation again and again. Change-Id: I90de310eb82d478ba66809d2c0b3e73facd2c3b6 Signed-off-by: Jean-Philippe Andre --- .../evas/engines/gl_common/evas_gl_common.h | 3 ++ .../evas/engines/gl_common/evas_gl_context.c | 33 +++++++++++++--------- .../evas/engines/gl_common/evas_gl_shader.c | 4 +++ .../engines/gl_common/shader/evas_gl_shaders.x | 13 +++++++-- .../evas/engines/gl_common/shader/fragment.glsl | 2 +- .../evas/engines/gl_common/shader/vertex.glsl | 12 ++++++-- 6 files changed, 48 insertions(+), 19 deletions(-) mode change 100755 => 100644 src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x mode change 100755 => 100644 src/modules/evas/engines/gl_common/shader/fragment.glsl 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 9c1e9d8..710c525 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -100,6 +100,9 @@ typedef Eina_Bool (*evas_gl_make_current_cb)(void *engine_data, void *doit); struct _Evas_GL_Program { unsigned int flags, hitcount, tex_count; + struct { + GLuint mvp, rotation_id; + } uniform; GLuint prog; Eina_Bool reset : 1; diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 5f286c6..4be8946 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -635,8 +635,10 @@ _evas_gl_common_viewport_set(Evas_Engine_GL_Context *gc, int force_update) if (gc->state.current.prog != PRG_INVALID) { - glUseProgram(gc->state.current.prog->prog); - glUniformMatrix4fv(glGetUniformLocation(gc->state.current.prog->prog, "mvp"), 1, GL_FALSE, gc->shared->proj); + prog = gc->state.current.prog; + glUseProgram(prog->prog); + glUniform1i(prog->uniform.rotation_id, gc->rot / 90); + glUniformMatrix4fv(prog->uniform.mvp, 1, GL_FALSE, gc->shared->proj); } } @@ -1356,9 +1358,20 @@ _push_mask(Evas_Engine_GL_Context *gc, const int pn, int nm, Evas_GL_Texture *mt if (!gw || !gh || !mw || !mh || !mtex->pt->w || !mtex->pt->h) return EINA_FALSE; - /* vertex shader: - * vec4 mask_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0); - * tex_m = mask_Position.xy * abs(mask_coord.zw) + mask_coord.xy; + /* Vertex shader: + * + * INPUTS: + * vec4 mask_coord = vec4(glmx, glmy, glmw, glmh); + * int rotation_id = gc->rot / 90; + * + * CODE: + * vec4 mask_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0); + * vec2 pos[4]; // no ctor-style init because of GLSL-ES (version 100) + * pos[0] = vec2(mask_Position.xy); + * pos[1] = vec2(1.0 - mask_Position.y, mask_Position.x); + * pos[2] = vec2(1.0 - mask_Position.xy); + * pos[3] = vec2(mask_Position.y, 1.0 - mask_Position.x); + * tex_m = pos[rotation_id].xy * abs(mask_coord.zw) + mask_coord.xy; */ glmx = (double)((mtex->x * mw) - (mtex->w * mx)) / (double)(mw * mtex->pt->w); glmy = (double)((mtex->y * mh) - (mtex->h * my)) / (double)(mh * mtex->pt->h); @@ -1379,13 +1392,6 @@ _push_mask(Evas_Engine_GL_Context *gc, const int pn, int nm, Evas_GL_Texture *mt PUSH_MASKSAM(pn, samx, samy, cnt); } - /* - DBG("%d,%d %dx%d --> %f , %f - %f x %f [gc %dx%d, tex %d,%d %dx%d, pt %dx%d]", - mx, my, mw, mh, - glmx, glmy, glmw, glmh, - gc->w, gc->h, mtex->x, mtex->y, mtex->w, mtex->h, mtex->pt->w, mtex->pt->h); - */ - return EINA_TRUE; } @@ -3164,7 +3170,8 @@ shader_array_flush(Evas_Engine_GL_Context *gc) glUseProgram(prog->prog); if (prog->reset) { - glUniformMatrix4fv(glGetUniformLocation(prog->prog, "mvp"), 1, GL_FALSE, gc->shared->proj); + glUniform1i(prog->uniform.rotation_id, gc->rot / 90); + glUniformMatrix4fv(prog->uniform.mvp, 1, GL_FALSE, gc->shared->proj); prog->reset = EINA_FALSE; } } 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 9a3e9b3..4498a53 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_shader.c +++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c @@ -160,6 +160,8 @@ _evas_gl_common_shader_program_binary_load(Eet_File *ef, unsigned int flags) p->prog = prg; p->reset = EINA_TRUE; p->bin_saved = EINA_TRUE; + p->uniform.mvp = glGetUniformLocation(prg, "mvp"); + p->uniform.rotation_id = glGetUniformLocation(prg, "rotation_id"); evas_gl_common_shader_textures_bind(p); finish: @@ -566,6 +568,8 @@ evas_gl_common_shader_generate_and_compile(Evas_GL_Shared *shared, unsigned int if (p) { 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); eina_hash_add(shared->shaders_hash, &flags, p); } diff --git a/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x b/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x old mode 100755 new mode 100644 index 168d91f..3aa7446 --- a/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x +++ b/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x @@ -157,7 +157,7 @@ static const char fragment_glsl[] = " * col\n" "#endif\n" "#ifdef SHD_MASK\n" - " * ma\n" + " * ma\n" "#endif\n" "#ifdef SHD_TEXA\n" " * texture2D(texa, tex_a).r\n" @@ -176,6 +176,8 @@ static const char vertex_glsl[] = "#endif\n" "attribute vec4 vertex;\n" "uniform mat4 mvp;\n" + "/* Window rotation by id 0,1,2,3 (represents 0,90,180,270) */\n" + "uniform int rotation_id;\n" "/* All except nomul */\n" "#ifndef SHD_NOMUL\n" "attribute vec4 color;\n" @@ -280,8 +282,13 @@ static const char vertex_glsl[] = "#ifdef SHD_MASK\n" " // mask_coord.w contains the Y-invert flag\n" " // position on screen in [0..1] range of current pixel\n" - " vec4 mask_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n" - " tex_m = mask_Position.xy * abs(mask_coord.zw) + mask_coord.xy;\n" + " vec4 window_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n" + " vec2 pos[4];\n" + " pos[0] = vec2(window_Position.xy);\n" + " pos[1] = vec2(1.0 - window_Position.y, window_Position.x);\n" + " pos[2] = vec2(1.0 - window_Position.xy);\n" + " pos[3] = vec2(window_Position.y, 1.0 - window_Position.x);\n" + " tex_m = pos[rotation_id] * abs(mask_coord.zw) + mask_coord.xy;\n" "#endif\n" "}\n"; diff --git a/src/modules/evas/engines/gl_common/shader/fragment.glsl b/src/modules/evas/engines/gl_common/shader/fragment.glsl old mode 100755 new mode 100644 index 9cbe9a1..b5ae2ab --- a/src/modules/evas/engines/gl_common/shader/fragment.glsl +++ b/src/modules/evas/engines/gl_common/shader/fragment.glsl @@ -161,7 +161,7 @@ void main() * col #endif #ifdef SHD_MASK - * ma + * ma #endif #ifdef SHD_TEXA * texture2D(texa, tex_a).r diff --git a/src/modules/evas/engines/gl_common/shader/vertex.glsl b/src/modules/evas/engines/gl_common/shader/vertex.glsl index d67eb06..0e95116 100644 --- a/src/modules/evas/engines/gl_common/shader/vertex.glsl +++ b/src/modules/evas/engines/gl_common/shader/vertex.glsl @@ -9,6 +9,9 @@ VERTEX_SHADER attribute vec4 vertex; uniform mat4 mvp; +/* Window rotation by id 0,1,2,3 (represents 0,90,180,270) */ +uniform int rotation_id; + /* All except nomul */ #ifndef SHD_NOMUL attribute vec4 color; @@ -130,8 +133,13 @@ void main() #ifdef SHD_MASK // mask_coord.w contains the Y-invert flag // position on screen in [0..1] range of current pixel - vec4 mask_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0); - tex_m = mask_Position.xy * abs(mask_coord.zw) + mask_coord.xy; + vec4 window_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0); + vec2 pos[4]; + pos[0] = vec2(window_Position.xy); + pos[1] = vec2(1.0 - window_Position.y, window_Position.x); + pos[2] = vec2(1.0 - window_Position.xy); + pos[3] = vec2(window_Position.y, 1.0 - window_Position.x); + tex_m = pos[rotation_id] * abs(mask_coord.zw) + mask_coord.xy; #endif } -- 2.7.4