jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=21d08f86e6087f7e30ff2015c7551c06e359bba9

commit 21d08f86e6087f7e30ff2015c7551c06e359bba9
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Fri Feb 6 12:21:25 2015 +0900

    Evas GL: Add support for uniforms in the shaders
    
    This will simplify greatly the code for map masking.
---
 .../evas/engines/gl_common/evas_gl_common.h        |   1 +
 .../evas/engines/gl_common/evas_gl_context.c       | 155 +++++++++++++++------
 .../engines/gl_common/shader/evas_gl_shaders.x     |  30 ++--
 .../gl_common/shader/map_mask_bgra_frag.shd        |   4 +-
 .../gl_common/shader/map_mask_bgra_vert.shd        |  12 +-
 .../engines/gl_common/shader/map_mask_frag.shd     |   4 +-
 .../engines/gl_common/shader/map_mask_vert.shd     |  12 +-
 7 files changed, 134 insertions(+), 84 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 382c3bc..4f2a552 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -468,6 +468,7 @@ struct _Evas_Engine_GL_Context
          GLfloat *texa;
          GLfloat *texsam;
          GLfloat *texm;
+         Eina_List *uniforms; /* Evas_GL_Uniform */
          Eina_Bool line: 1;
          Eina_Bool use_vertex : 1;
          Eina_Bool use_color : 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 4a06a56..bd683bd 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -1318,6 +1318,100 @@ array_alloc(Evas_Engine_GL_Context *gc, int n)
    RALOC(texm,   GLfloat, 2);
 }
 
+
+/* Very basic uniform upload support.
+ * TODO: Optimize out call to glGetUniformLocation(). */
+
+typedef enum _Evas_GL_Uniform_Type Evas_GL_Uniform_Type;
+typedef struct _Evas_GL_Uniform Evas_GL_Uniform;
+
+enum _Evas_GL_Uniform_Type {
+   EVAS_GL_UNIFORM_FLOAT,
+   EVAS_GL_UNIFORM_VEC2,
+   EVAS_GL_UNIFORM_VEC4,
+   // Add more types if needed.
+};
+
+struct _Evas_GL_Uniform {
+   Eina_Stringshare *name;
+   Evas_GL_Uniform_Type type;
+   union {
+      GLfloat f;
+      GLfloat vec2[2];
+      GLfloat vec4[4];
+   } value;
+};
+
+static inline void
+push_uniform(Evas_Engine_GL_Context *gc, int n, Evas_GL_Uniform_Type type, 
const char *name, ...)
+{
+   Evas_GL_Uniform *u = calloc(1, sizeof(Evas_GL_Uniform));
+   va_list args;
+   va_start(args, name);
+
+   if (!gc || !u) return;
+   u->name = eina_stringshare_add(name);
+   u->type = type;
+
+   switch (type)
+     {
+      case EVAS_GL_UNIFORM_FLOAT:
+        u->value.f = (GLfloat) va_arg(args, double);
+        break;
+      case EVAS_GL_UNIFORM_VEC2:
+        u->value.vec2[0] = (GLfloat) va_arg(args, double);
+        u->value.vec2[1] = (GLfloat) va_arg(args, double);
+        break;
+      case EVAS_GL_UNIFORM_VEC4:
+        u->value.vec4[0] = (GLfloat) va_arg(args, double);
+        u->value.vec4[1] = (GLfloat) va_arg(args, double);
+        u->value.vec4[2] = (GLfloat) va_arg(args, double);
+        u->value.vec4[3] = (GLfloat) va_arg(args, double);
+        break;
+      default:
+        free(u);
+        va_end(args);
+        return;
+     }
+
+   va_end(args);
+   gc->pipe[n].array.uniforms = eina_list_append(gc->pipe[n].array.uniforms, 
u);
+}
+
+static inline void
+shader_array_uniforms_set(Evas_Engine_GL_Context *gc, int n)
+{
+   Evas_GL_Uniform *u;
+
+   if (!gc || !gc->pipe[n].array.uniforms) return;
+   EINA_LIST_FREE(gc->pipe[n].array.uniforms, u)
+     {
+        GLint loc = glGetUniformLocation(gc->pipe[n].shader.cur_prog, u->name);
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "glUniform");
+        if (loc >= 0)
+          {
+             switch (u->type)
+               {
+                case EVAS_GL_UNIFORM_FLOAT:
+                  glUniform1f(loc, u->value.f);
+                  break;
+                case EVAS_GL_UNIFORM_VEC2:
+                  glUniform2fv(loc, 1, u->value.vec2);
+                  break;
+                case EVAS_GL_UNIFORM_VEC4:
+                  glUniform4fv(loc, 1, u->value.vec4);
+                  break;
+                default: ERR("Unhandled uniform type"); break;
+               }
+             GLERR(__FUNCTION__, __FILE__, __LINE__, "glUniform");
+          }
+        eina_stringshare_del(u->name);
+        free(u);
+     }
+}
+
+#define PUSH_UNIFORM(pn, type, name, ...) push_uniform(gc, pn, type, name, 
__VA_ARGS__)
+
 #ifdef GLPIPES
 static int
 pipe_region_intersects(Evas_Engine_GL_Context *gc, int n,
@@ -2706,8 +2800,8 @@ 
evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
    gc->pipe[pn].array.use_texuv2 = (utexture || uvtexture) ? 1 : 0;
    gc->pipe[pn].array.use_texuv3 = (utexture) ? 1 : 0;
    gc->pipe[pn].array.use_texm = !!mtex;
-   gc->pipe[pn].array.use_texa = !!mtex;
-   gc->pipe[pn].array.use_texsam = gc->pipe[pn].array.use_texm;
+   gc->pipe[pn].array.use_texa = 0;
+   gc->pipe[pn].array.use_texsam = 0;
 
    pipe_region_expand(gc, pn, x, y, w, h);
    PIPE_GROW(gc, pn, 6);
@@ -2769,8 +2863,8 @@ 
evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
 
    if (mtex)
      {
-        GLfloat glmdx = 0.f, glmdy = 0.f, glmdw = 1.f, glmdh = 1.f, yinv = 
-1.f;
-        GLfloat gw = gc->w, gh = gc->h;
+        double glmdx = 0.f, glmdy = 0.f, glmdw = 1.f, glmdh = 1.f, yinv = -1.f;
+        double gw = gc->w, gh = gc->h;
 
         // Note: I couldn't write any test case where it was necessary
         // to know the mask position in its texture. Thus these unused vars.
@@ -2784,36 +2878,13 @@ 
evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
              yinv = 1.f;
           }
 
-        if (gw) glmdx = (GLfloat) mdx / (GLfloat) gw;
-        if (gh) glmdy = (GLfloat) mdy / (GLfloat) gh;
-        if (mdw) glmdw = (GLfloat) gw / (GLfloat) mdw;
-        if (mdh) glmdh = (GLfloat) gh / (GLfloat) mdh;
-
-        // FIXME!!!
-        // We seriously need uniforms here. Abusing tex_coordm for storage.
-        // Passing mask x,y (on canvas) to the fragment shader
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-
-        // Abusing tex_sample to pass mask 1/w, 1/h as well
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-
-        // Abusing tex_coorda to pass Y-invert flag
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
+        if (gw) glmdx = (double) mdx / (double) gw;
+        if (gh) glmdy = (double) mdy / (double) gh;
+        if (mdw) glmdw = (double) gw / (double) mdw;
+        if (mdh) glmdh = (double) gh / (double) mdh;
+
+        PUSH_UNIFORM(pn, EVAS_GL_UNIFORM_VEC4, "mask_Absolute", glmdx, glmdy, 
glmdw, glmdh);
+        PUSH_UNIFORM(pn, EVAS_GL_UNIFORM_FLOAT, "yinvert", yinv);
 
         //DBG("Orig %d,%d - %dx%d --> %f,%f - %f x %f", mdx, mdy, mdw, mdh,
         //    glmdx, glmdy, glmdw, glmdh);
@@ -3347,18 +3418,6 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
 
                    MASK_TEXTURE += 1;
                }
-             else if (gc->pipe[i].array.use_texa && (gc->pipe[i].region.type 
== RTYPE_MAP))
-               {
-                  /* FIXME:
-                   * This is a workaround as we hijack some tex ids
-                   * (namely tex_coordm, tex_coorda and tex_sample) for map 
masking.
-                   * These masking shaders should definitely use uniforms.
-                   */
-                  glEnableVertexAttribArray(SHAD_TEXA);
-                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-                  glVertexAttribPointer(SHAD_TEXA, 2, GL_FLOAT, GL_FALSE, 0, 
(void *)texa_ptr);
-                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-               }
              else
                {
                   glDisableVertexAttribArray(SHAD_TEXA);
@@ -3520,6 +3579,10 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
 
+             // Push all uniforms
+             if (gc->pipe[i].array.uniforms)
+               shader_array_uniforms_set(gc, i);
+
              if (dbgflushnum == 1)
                {
                   const char *types[6] =
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
index 09ea407..1aa4b27 100644
--- a/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x
+++ b/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x
@@ -2711,13 +2711,13 @@ static const char const map_mask_frag_glsl[] =
    "#endif\n"
    "#endif\n"
    "uniform sampler2D tex, texm;\n"
+   "uniform vec4 mask_Absolute;\n"
    "varying vec2 tex_c;\n"
-   "varying vec4 mask_Position, col, mask_Absolute;\n"
+   "varying vec4 mask_Position, col;\n"
    "void main()\n"
    "{\n"
    "   // FIXME: Use mask coordinates within its texture\n"
    "   // FIXME: Fix Mach band effect using proper 4-point color 
interpolation\n"
-   "   // FIXME: We're abusing varying where we should have uniforms\n"
    "   vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * 
mask_Absolute.zw;\n"
    "   gl_FragColor = texture2D(tex, tex_c.xy).bgra * texture2D(texm, mpos).a 
*  col;\n"
    "}\n";
@@ -2733,20 +2733,17 @@ static const char const map_mask_vert_glsl[] =
    "precision highp float;\n"
    "#endif\n"
    "attribute vec4 vertex, color;\n"
-   "attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;\n"
+   "attribute vec2 tex_coord;\n"
+   "uniform float yinvert;\n"
    "uniform mat4 mvp;\n"
    "varying vec2 tex_c;\n"
-   "varying vec4 mask_Position, col, mask_Absolute;\n"
+   "varying vec4 mask_Position, col;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = mvp * vertex;\n"
    "   tex_c = tex_coord;\n"
    "   col = color;\n"
-   "   // tex_coorda contains the Y-invert flag\n"
-   "   // tex_coordm contains the X,Y position of the mask\n"
-   "   // tex_sample contains the W,H size of the mask (inverted)\n"
-   "   mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 
0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
-   "   mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on 
canvas in GL coords\n"
+   "   mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + 
vec4(0.5, 0.5, 0, 0);\n"
    "}\n";
 Evas_GL_Program_Source shader_map_mask_vert_src =
 {
@@ -2813,13 +2810,13 @@ static const char const map_mask_bgra_frag_glsl[] =
    "#endif\n"
    "#endif\n"
    "uniform sampler2D tex, texm;\n"
+   "uniform vec4 mask_Absolute;\n"
    "varying vec2 tex_c;\n"
-   "varying vec4 mask_Position, col, mask_Absolute;\n"
+   "varying vec4 mask_Position, col;\n"
    "void main()\n"
    "{\n"
    "   // FIXME: Use mask coordinates within its texture\n"
    "   // FIXME: Fix Mach band effect using proper 4-point color 
interpolation\n"
-   "   // FIXME: We're abusing varying where we should have uniforms\n"
    "   vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * 
mask_Absolute.zw;\n"
    "   gl_FragColor = texture2D(tex, tex_c.xy) * texture2D(texm, mpos).a *  
col;\n"
    "}\n";
@@ -2835,20 +2832,17 @@ static const char const map_mask_bgra_vert_glsl[] =
    "precision highp float;\n"
    "#endif\n"
    "attribute vec4 vertex, color;\n"
-   "attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;\n"
+   "attribute vec2 tex_coord;\n"
+   "uniform float yinvert;\n"
    "uniform mat4 mvp;\n"
    "varying vec2 tex_c;\n"
-   "varying vec4 mask_Position, col, mask_Absolute;\n"
+   "varying vec4 mask_Position, col;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = mvp * vertex;\n"
    "   tex_c = tex_coord;\n"
    "   col = color;\n"
-   "   // tex_coorda contains the Y-invert flag\n"
-   "   // tex_coordm contains the X,Y position of the mask\n"
-   "   // tex_sample contains the W,H size of the mask (inverted)\n"
-   "   mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 
0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
-   "   mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on 
canvas in GL coords\n"
+   "   mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + 
vec4(0.5, 0.5, 0, 0);\n"
    "}\n";
 Evas_GL_Program_Source shader_map_mask_bgra_vert_src =
 {
diff --git a/src/modules/evas/engines/gl_common/shader/map_mask_bgra_frag.shd 
b/src/modules/evas/engines/gl_common/shader/map_mask_bgra_frag.shd
index d6922f0..10c0145 100644
--- a/src/modules/evas/engines/gl_common/shader/map_mask_bgra_frag.shd
+++ b/src/modules/evas/engines/gl_common/shader/map_mask_bgra_frag.shd
@@ -6,13 +6,13 @@ precision mediump float;
 #endif
 #endif
 uniform sampler2D tex, texm;
+uniform vec4 mask_Absolute;
 varying vec2 tex_c;
-varying vec4 mask_Position, col, mask_Absolute;
+varying vec4 mask_Position, col;
 void main()
 {
    // FIXME: Use mask coordinates within its texture
    // FIXME: Fix Mach band effect using proper 4-point color interpolation
-   // FIXME: We're abusing varying where we should have uniforms
    vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * mask_Absolute.zw;
    gl_FragColor = texture2D(tex, tex_c.xy) * texture2D(texm, mpos).a *  col;
 }
diff --git a/src/modules/evas/engines/gl_common/shader/map_mask_bgra_vert.shd 
b/src/modules/evas/engines/gl_common/shader/map_mask_bgra_vert.shd
index 7b0c968..726a0f5 100644
--- a/src/modules/evas/engines/gl_common/shader/map_mask_bgra_vert.shd
+++ b/src/modules/evas/engines/gl_common/shader/map_mask_bgra_vert.shd
@@ -2,20 +2,16 @@
 precision highp float;
 #endif
 attribute vec4 vertex, color;
-attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;
+attribute vec2 tex_coord;
+uniform float yinvert;
 uniform mat4 mvp;
 varying vec2 tex_c;
-varying vec4 mask_Position, col, mask_Absolute;
+varying vec4 mask_Position, col;
 void main()
 {
    gl_Position = mvp * vertex;
    tex_c = tex_coord;
    col = color;
 
-   // tex_coorda contains the Y-invert flag
-   // tex_coordm contains the X,Y position of the mask
-   // tex_sample contains the W,H size of the mask (inverted)
-
-   mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 
0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
-   mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on canvas 
in GL coords
+   mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + 
vec4(0.5, 0.5, 0, 0);
 }
diff --git a/src/modules/evas/engines/gl_common/shader/map_mask_frag.shd 
b/src/modules/evas/engines/gl_common/shader/map_mask_frag.shd
index 189807b..bbed95b 100644
--- a/src/modules/evas/engines/gl_common/shader/map_mask_frag.shd
+++ b/src/modules/evas/engines/gl_common/shader/map_mask_frag.shd
@@ -6,13 +6,13 @@ precision mediump float;
 #endif
 #endif
 uniform sampler2D tex, texm;
+uniform vec4 mask_Absolute;
 varying vec2 tex_c;
-varying vec4 mask_Position, col, mask_Absolute;
+varying vec4 mask_Position, col;
 void main()
 {
    // FIXME: Use mask coordinates within its texture
    // FIXME: Fix Mach band effect using proper 4-point color interpolation
-   // FIXME: We're abusing varying where we should have uniforms
    vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * mask_Absolute.zw;
    gl_FragColor = texture2D(tex, tex_c.xy).bgra * texture2D(texm, mpos).a *  
col;
 }
diff --git a/src/modules/evas/engines/gl_common/shader/map_mask_vert.shd 
b/src/modules/evas/engines/gl_common/shader/map_mask_vert.shd
index 7b0c968..726a0f5 100644
--- a/src/modules/evas/engines/gl_common/shader/map_mask_vert.shd
+++ b/src/modules/evas/engines/gl_common/shader/map_mask_vert.shd
@@ -2,20 +2,16 @@
 precision highp float;
 #endif
 attribute vec4 vertex, color;
-attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;
+attribute vec2 tex_coord;
+uniform float yinvert;
 uniform mat4 mvp;
 varying vec2 tex_c;
-varying vec4 mask_Position, col, mask_Absolute;
+varying vec4 mask_Position, col;
 void main()
 {
    gl_Position = mvp * vertex;
    tex_c = tex_coord;
    col = color;
 
-   // tex_coorda contains the Y-invert flag
-   // tex_coordm contains the X,Y position of the mask
-   // tex_sample contains the W,H size of the mask (inverted)
-
-   mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 
0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
-   mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on canvas 
in GL coords
+   mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + 
vec4(0.5, 0.5, 0, 0);
 }

-- 


Reply via email to