jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=6af3c20aebc822cfb4148e60a1cb4e19e489c4d1

commit 6af3c20aebc822cfb4148e60a1cb4e19e489c4d1
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Mon Mar 20 23:25:05 2017 +0900

    evas filters: Pass gaussian values to GL blur shader
---
 src/lib/evas/filters/evas_filter.c                 |   7 +-
 .../evas/engines/gl_common/evas_gl_common.h        |   4 +-
 .../evas/engines/gl_common/evas_gl_context.c       |  34 +++++-
 .../evas/engines/gl_common/evas_gl_shader.c        |   3 +-
 .../engines/gl_common/shader/evas_gl_shaders.x     |  41 +++++---
 .../evas/engines/gl_common/shader/fragment.glsl    |  39 +++++--
 .../evas/engines/gl_common/shader/vertex.glsl      |   5 +-
 src/modules/evas/engines/gl_generic/evas_engine.c  |  22 ++--
 .../engines/gl_generic/filters/gl_engine_filter.h  |  14 +--
 .../engines/gl_generic/filters/gl_filter_blend.c   |   2 +-
 .../engines/gl_generic/filters/gl_filter_blur.c    | 114 ++++++++++++++++++---
 .../engines/gl_generic/filters/gl_filter_curve.c   |   2 +-
 .../gl_generic/filters/gl_filter_displace.c        |   2 +-
 .../engines/gl_generic/filters/gl_filter_fill.c    |   2 +-
 .../engines/gl_generic/filters/gl_filter_mask.c    |   2 +-
 15 files changed, 224 insertions(+), 69 deletions(-)

diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index ef2710b..f6e1e27 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -548,7 +548,7 @@ evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
 {
    Evas_Filter_Command *cmd;
    Evas_Filter_Buffer *dx_in, *dx_out, *dy_in, *tmp = NULL;
-   int down_x, down_y, dx, dy;
+   int dx, dy;
 
    /* GL blur implementation:
     * - Create intermediate buffer T (variable size)
@@ -567,8 +567,13 @@ evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
 
    if (type == EVAS_FILTER_BLUR_DEFAULT)
      {
+        int down_x = 1, down_y = 1;
+
+        /* For now, disable scaling - testing perfect gaussian blur until it's
+         * ready:
         down_x = MAX((1 << evas_filter_smallest_pow2_larger_than(dx / 2) / 2), 
1);
         down_y = MAX((1 << evas_filter_smallest_pow2_larger_than(dy / 2) / 2), 
1);
+        */
 
         tmp = evas_filter_temporary_buffer_get(ctx, ctx->w / down_x, ctx->h / 
down_y,
                                                in->alpha_only, EINA_TRUE);
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 b48955e..3dcc558 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -651,7 +651,9 @@ void              
evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc
                                                       int x, int y, int w, int 
h, double dx, double dy, Eina_Bool nearest);
 void              evas_gl_common_filter_curve_push(Evas_Engine_GL_Context *gc, 
Evas_GL_Texture *tex,
                                                    int x, int y, int w, int h, 
const uint8_t *points, int channel);
-void              evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc, 
Evas_GL_Texture *tex, double sx, double sy, double sw, double sh, double dx, 
double dy, double dw, double dh, double radius, Eina_Bool horiz);
+void              evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc, 
Evas_GL_Texture *tex, double sx, double sy, double sw, double sh,
+                                                  double dx, double dy, double 
dw, double dh, GLfloat *values, GLfloat *offsets, int count,
+                                                  Eina_Bool horiz);
 
 int               evas_gl_common_shader_program_init(Evas_GL_Shared *shared);
 void              evas_gl_common_shader_program_shutdown(Evas_GL_Shared 
*shared);
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 48de69e..c19492d 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -3432,7 +3432,8 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
                                 Evas_GL_Texture *tex,
                                 double sx, double sy, double sw, double sh,
                                 double dx, double dy, double dw, double dh,
-                                double radius, Eina_Bool horiz)
+                                GLfloat *values, GLfloat *offsets, int count,
+                                Eina_Bool horiz)
 {
    double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph;
    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
@@ -3443,6 +3444,8 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
    Eina_Bool blend = EINA_TRUE;
    Eina_Bool smooth = EINA_TRUE;
    Shader_Type type = horiz ? SHD_FILTER_BLUR_X : SHD_FILTER_BLUR_Y;
+   GLuint map_tex;
+   double sum;
 
    r = R_VAL(&gc->dc->mul.col);
    g = G_VAL(&gc->dc->mul.col);
@@ -3489,11 +3492,34 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
    pipe_region_expand(gc, pn, dx, dy, dw, dh);
    PIPE_GROW(gc, pn, 6);
 
-   // Set blur properties... TODO
-   _filter_data_prepare(gc, pn, prog, 1);
+   sum = values[0];
+   for (int k = 1; k < count; k++)
+     sum += 2.0 * values[k];
+
+   // Synchronous upload of Nx1 RGBA texture (FIXME: no reuse)
+   glGenTextures(1, &map_tex);
+   glBindTexture(GL_TEXTURE_2D, map_tex);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   // FIXME: GLES2 requires extensions here!!!
+   glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, count, 1, 0, GL_RED, GL_FLOAT, 
values);
+   // FIXME: double values don't work??
+   //glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, count, 1, 0, GL_RED, GL_DOUBLE, 
values);
+
+   // Set curve properties (no need for filter_data)
+   gc->pipe[pn].shader.filter.map_tex = map_tex;
+   gc->pipe[pn].shader.filter.map_nearest = EINA_TRUE;
+   gc->pipe[pn].shader.filter.map_delete = EINA_TRUE;
+
+   // Set blur properties... WIP
+   _filter_data_prepare(gc, pn, prog, 2);
    filter_data = gc->pipe[pn].array.filter_data;
-   filter_data[0] = radius;
+   filter_data[0] = count;
    filter_data[1] = horiz ? sw : sh;
+   filter_data[2] = sum;
+   filter_data[3] = 0.0; // unused
 
    pw = tex->pt->w;
    ph = tex->pt->h;
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 fec2167..4737715 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_shader.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c
@@ -903,7 +903,8 @@ evas_gl_common_shader_textures_bind(Evas_GL_Program *p)
         hastex = 1;
      }
    if ((p->flags & SHADER_FLAG_FILTER_DISPLACE) ||
-       (p->flags & SHADER_FLAG_FILTER_CURVE))
+       (p->flags & SHADER_FLAG_FILTER_CURVE) ||
+       (p->flags & SHADER_FLAG_FILTER_BLUR))
      {
         textures[6].enabled = 1;
         hastex = 1;
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 9e59729..0a4a26d 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
@@ -92,7 +92,8 @@ static const char fragment_glsl[] =
    "uniform sampler2D tex_filter;\n"
    "#endif\n"
    "#ifdef SHD_FILTER_BLUR\n"
-   "varying vec2 blur_data;\n"
+   "uniform sampler2D tex_filter;\n"
+   "varying vec3 blur_data;\n"
    "#endif\n"
    "// 
----------------------------------------------------------------------------\n"
    "#ifndef SHD_FILTER_BLUR\n"
@@ -225,26 +226,39 @@ static const char fragment_glsl[] =
    "#else // SHD_FILTER_BLUR\n"
    "   return c;\n"
    "}\n"
+   "#ifndef SHD_FILTER_DIR_Y\n"
+   "# define FETCH_PIXEL(x) fetch_pixel((x), 0.0)\n"
+   "#else\n"
+   "# define FETCH_PIXEL(x) fetch_pixel(0.0, (x))\n"
+   "#endif\n"
    "void main()\n"
    "{\n"
-   "   float u, u_div, radius, diam;\n"
-   "   vec4 acc = vec4(0.,0.,0.,0.);\n"
-   "   float div = 0.0;\n"
-   "   radius = blur_data.x;\n"
+   "   float u, u_div, count, div, w;\n"
+   "   vec4 acc, px;\n"
+   "   count = blur_data.x;\n"
    "   u_div = blur_data.y;\n"
-   "   diam = radius * 2.0 + 1.0;\n"
-   "   for (u = -radius; u <= radius; u += 1.0)\n"
+   "   //div = blur_data.z;\n"
+   "   // Center pixel\n"
+   "   w = texture2D(tex_filter, vec2(0.0, 0.0)).r;\n"
+   "   px = FETCH_PIXEL(u / u_div);\n"
+   "   acc = px * w;\n"
+   "   div = w;\n"
+   "   // Left & right\n"
+   "   for (u = 1; u <= count; u += 1.0)\n"
+   "#if 0\n"
+   "   div = 0.0;\n"
+   "   for (u = -count; u <= count; u += 1.0)\n"
    "   {\n"
-   "      float w = (u + radius) / (diam - 1.0) * 6.0 - 3.0;\n"
-   "      w = (sin(w + M_PI_2) + 1.0) / 2.0;\n"
+   "      w = texture2D(tex_filter, vec2(abs(u) / count, 0.0)).r;\n"
    "#ifndef SHD_FILTER_DIR_Y\n"
-   "      vec4 px = fetch_pixel(u / u_div, 0.0);\n"
+   "      px = fetch_pixel(u / u_div, 0.0);\n"
    "#else\n"
-   "      vec4 px = fetch_pixel(0.0, u / u_div);\n"
+   "      px = fetch_pixel(0.0, u / u_div);\n"
    "#endif\n"
    "      acc += px * w;\n"
    "      div += w;\n"
    "   }\n"
+   "#endif\n"
    "#ifndef SHD_NOMUL\n"
    "   gl_FragColor = (acc / div) * col;\n"
    "#else\n"
@@ -327,7 +341,8 @@ static const char vertex_glsl[] =
    "/* Gfx Filters: blur */\n"
    "#ifdef SHD_FILTER_BLUR\n"
    "attribute vec2 filter_data_0;\n"
-   "varying vec2 blur_data;\n"
+   "attribute vec2 filter_data_1;\n"
+   "varying vec3 blur_data;\n"
    "#endif\n"
    "void main()\n"
    "{\n"
@@ -398,7 +413,7 @@ static const char vertex_glsl[] =
    "   displace_max = filter_data_2;\n"
    "#endif\n"
    "#ifdef SHD_FILTER_BLUR\n"
-   "   blur_data = filter_data_0;\n"
+   "   blur_data = vec3(filter_data_0.xy, filter_data_1.x);\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
index 0e44fae..aa600f6 100644
--- a/src/modules/evas/engines/gl_common/shader/fragment.glsl
+++ b/src/modules/evas/engines/gl_common/shader/fragment.glsl
@@ -89,7 +89,8 @@ uniform sampler2D tex_filter;
 #endif
 
 #ifdef SHD_FILTER_BLUR
-varying vec2 blur_data;
+uniform sampler2D tex_filter;
+varying vec3 blur_data;
 #endif
 
 // ----------------------------------------------------------------------------
@@ -244,30 +245,46 @@ vec4 fetch_pixel(float ox, float oy)
    return c;
 }
 
+#ifndef SHD_FILTER_DIR_Y
+# define FETCH_PIXEL(x) fetch_pixel((x), 0.0)
+#else
+# define FETCH_PIXEL(x) fetch_pixel(0.0, (x))
+#endif
+
 void main()
 {
-   float u, u_div, radius, diam;
-   vec4 acc = vec4(0.,0.,0.,0.);
-   float div = 0.0;
+   float u, u_div, count, div, w;
+   vec4 acc, px;
 
-   radius = blur_data.x;
+   count = blur_data.x;
    u_div = blur_data.y;
-   diam = radius * 2.0 + 1.0;
+   //div = blur_data.z;
+
+   // Center pixel
+   w = texture2D(tex_filter, vec2(0.0, 0.0)).r;
+   px = FETCH_PIXEL(u / u_div);
+   acc = px * w;
+   div = w;
 
-   for (u = -radius; u <= radius; u += 1.0)
+   // Left & right
+   for (u = 1; u <= count; u += 1.0)
+
+#if 0
+   div = 0.0;
+   for (u = -count; u <= count; u += 1.0)
    {
-      float w = (u + radius) / (diam - 1.0) * 6.0 - 3.0;
-      w = (sin(w + M_PI_2) + 1.0) / 2.0;
+      w = texture2D(tex_filter, vec2(abs(u) / count, 0.0)).r;
 
 #ifndef SHD_FILTER_DIR_Y
-      vec4 px = fetch_pixel(u / u_div, 0.0);
+      px = fetch_pixel(u / u_div, 0.0);
 #else
-      vec4 px = fetch_pixel(0.0, u / u_div);
+      px = fetch_pixel(0.0, u / u_div);
 #endif
 
       acc += px * w;
       div += w;
    }
+#endif
 
 #ifndef SHD_NOMUL
    gl_FragColor = (acc / div) * col;
diff --git a/src/modules/evas/engines/gl_common/shader/vertex.glsl 
b/src/modules/evas/engines/gl_common/shader/vertex.glsl
index e8e33b3..961ec6b 100644
--- a/src/modules/evas/engines/gl_common/shader/vertex.glsl
+++ b/src/modules/evas/engines/gl_common/shader/vertex.glsl
@@ -81,7 +81,8 @@ varying vec2 displace_max;
 /* Gfx Filters: blur */
 #ifdef SHD_FILTER_BLUR
 attribute vec2 filter_data_0;
-varying vec2 blur_data;
+attribute vec2 filter_data_1;
+varying vec3 blur_data;
 #endif
 
 
@@ -165,6 +166,6 @@ void main()
 #endif
 
 #ifdef SHD_FILTER_BLUR
-   blur_data = filter_data_0;
+   blur_data = vec3(filter_data_0.xy, filter_data_1.x);
 #endif
 }
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c 
b/src/modules/evas/engines/gl_generic/evas_engine.c
index 4b0d38f..bb26c2f 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -3022,20 +3022,20 @@ eng_image_surface_noscale_region_get(void *engdata 
EINA_UNUSED, void *image, int
 //------------------------------------------------//
 
 static GL_Filter_Apply_Func
-_gfx_filter_func_get(Evas_Filter_Command *cmd)
+_gfx_filter_func_get(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
 {
    GL_Filter_Apply_Func funcptr = NULL;
 
    switch (cmd->mode)
      {
-      case EVAS_FILTER_MODE_BLEND: funcptr = gl_filter_blend_func_get(cmd); 
break;
-      case EVAS_FILTER_MODE_BLUR: funcptr = gl_filter_blur_func_get(cmd); 
break;
-      //case EVAS_FILTER_MODE_BUMP: funcptr = gl_filter_bump_func_get(cmd); 
break;
-      case EVAS_FILTER_MODE_CURVE: funcptr = gl_filter_curve_func_get(cmd); 
break;
-      case EVAS_FILTER_MODE_DISPLACE: funcptr = 
gl_filter_displace_func_get(cmd); break;
-      case EVAS_FILTER_MODE_FILL: funcptr = gl_filter_fill_func_get(cmd); 
break;
-      case EVAS_FILTER_MODE_MASK: funcptr = gl_filter_mask_func_get(cmd); 
break;
-      //case EVAS_FILTER_MODE_TRANSFORM: funcptr = 
gl_filter_transform_func_get(cmd); break;
+      case EVAS_FILTER_MODE_BLEND: funcptr = gl_filter_blend_func_get(re, 
cmd); break;
+      case EVAS_FILTER_MODE_BLUR: funcptr = gl_filter_blur_func_get(re, cmd); 
break;
+      //case EVAS_FILTER_MODE_BUMP: funcptr = gl_filter_bump_func_get(re, 
cmd); break;
+      case EVAS_FILTER_MODE_CURVE: funcptr = gl_filter_curve_func_get(re, 
cmd); break;
+      case EVAS_FILTER_MODE_DISPLACE: funcptr = 
gl_filter_displace_func_get(re, cmd); break;
+      case EVAS_FILTER_MODE_FILL: funcptr = gl_filter_fill_func_get(re, cmd); 
break;
+      case EVAS_FILTER_MODE_MASK: funcptr = gl_filter_mask_func_get(re, cmd); 
break;
+      //case EVAS_FILTER_MODE_TRANSFORM: funcptr = 
gl_filter_transform_func_get(re, cmd); break;
       default: return NULL;
      }
 
@@ -3047,7 +3047,7 @@ eng_gfx_filter_supports(void *data, Evas_Filter_Command 
*cmd)
 {
    Render_Engine_GL_Generic *re = data;
 
-   if (!_gfx_filter_func_get(cmd))
+   if (!_gfx_filter_func_get(re, cmd))
      return pfunc.gfx_filter_supports(&re->software, cmd);
 
    return EVAS_FILTER_SUPPORT_GL;
@@ -3059,7 +3059,7 @@ eng_gfx_filter_process(void *data, Evas_Filter_Command 
*cmd)
    Render_Engine_GL_Generic *re = data;
    GL_Filter_Apply_Func funcptr;
 
-   funcptr = _gfx_filter_func_get(cmd);
+   funcptr = _gfx_filter_func_get(re, cmd);
    if (funcptr)
      return funcptr(re, cmd);
    else
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h 
b/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h
index 4d4baca..b310dce 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h
+++ b/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h
@@ -9,13 +9,13 @@
 extern int _evas_engine_GL_log_dom;
 
 typedef Eina_Bool (* GL_Filter_Apply_Func) (Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
-GL_Filter_Apply_Func gl_filter_blend_func_get(Evas_Filter_Command *cmd);
-GL_Filter_Apply_Func gl_filter_blur_func_get(Evas_Filter_Command *cmd);
-//GL_Filter_Apply_Func gl_filter_bump_func_get(Evas_Filter_Command *cmd);
-GL_Filter_Apply_Func gl_filter_curve_func_get(Evas_Filter_Command *cmd);
-GL_Filter_Apply_Func gl_filter_displace_func_get(Evas_Filter_Command *cmd);
-GL_Filter_Apply_Func gl_filter_fill_func_get(Evas_Filter_Command *cmd);
-GL_Filter_Apply_Func gl_filter_mask_func_get(Evas_Filter_Command *cmd);
+GL_Filter_Apply_Func gl_filter_blend_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
+GL_Filter_Apply_Func gl_filter_blur_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
+//GL_Filter_Apply_Func gl_filter_bump_func_get(Render_Engine_GL_Generic 
*reEvas_Filter_Command *cmd);
+GL_Filter_Apply_Func gl_filter_curve_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
+GL_Filter_Apply_Func gl_filter_displace_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
+GL_Filter_Apply_Func gl_filter_fill_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
+GL_Filter_Apply_Func gl_filter_mask_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
 //GL_Filter_Apply_Func gl_filter_transform_func_get(Evas_Filter_Command *cmd);
 
 #undef DBG
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c
index 4af89f1..ad846ba 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c
@@ -201,7 +201,7 @@ _gl_filter_blend(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
 }
 
 GL_Filter_Apply_Func
-gl_filter_blend_func_get(Evas_Filter_Command *cmd)
+gl_filter_blend_func_get(Render_Engine_GL_Generic *re EINA_UNUSED, 
Evas_Filter_Command *cmd)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c
index 66416dd..307282a 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c
@@ -1,5 +1,84 @@
 #include "gl_engine_filter.h"
 
+// sqrt(2 * M_PI)
+#define SQRT_2_PI 2.506628274631
+
+static inline double
+_radius_to_sigma(double radius)
+{
+   // FIXME: This was supposed to be sqrt(r/3) ~ or something close
+   return /*sqrt*/ (radius / 3.0);
+}
+
+static inline double
+_gaussian_val(double a, double b, double x)
+{
+   return a * exp(-(x*x/b));
+}
+
+static void
+_gaussian_calc(double *values, int count, double radius)
+{
+   // f(x) = a * exp(-(x^2 / b))
+   // sigma is such that variance v = sigma^2
+   // v is such that after 3 v the value is almost 0 (ressembles a radius)
+   // a = 1 / (sigma * sqrt (2 * pi))
+   // b = 2 * sigma^2
+
+   // FIXME: Some of this math doesn't fit right (values too small too fast)
+
+   double a, b, sigma;
+   int k;
+
+   sigma = _radius_to_sigma(radius);
+   a = 1.0 / (sigma * SQRT_2_PI);
+   b = 2.0 * sigma * sigma;
+
+   for (k = 0; k <= count; k++)
+     {
+        values[k] = _gaussian_val(a, b, k);
+        ERR("Gauss %d: %f", k, values[k]);
+     }
+}
+
+static int
+_gaussian_interpolate(GLfloat **weights, GLfloat **offsets, double radius)
+{
+   int k, num, count;
+   GLfloat *w, *o;
+   double *values;
+
+   count = (int) ceil(radius);
+   if (count & 0x1) count++;
+   values = alloca((count + 1) * sizeof(*values));
+    _gaussian_calc(values, count, radius);
+
+   num = (count / 2) + 1;
+   *offsets = o = calloc(1, num * sizeof(*o));
+   *weights = w = calloc(1, num * sizeof(*w));
+
+   // Center pixel's weight
+   k = 0;
+   o[k] = 0.0;
+   w[k] = values[0];
+   ERR("Interpolating weights %d: w %f o %f", k, w[k], o[k]);
+
+   // Left & right pixels' interpolated weights
+   for (k = 1; k < num; k++)
+     {
+        double w1, w2;
+
+        w1 = values[(k - 1) * 2 + 1];
+        w2 = values[(k - 1) * 2 + 2];
+        w[k] = w1 + w2;
+        if (EINA_DBL_EQ(w[k], 0.0)) continue;
+        o[k] = (w2 / w[k]) + (k - 1.0) * 2.0;
+        ERR("Interpolating weights %d: %f %f -> w %f o %f", k, w1, w2, w[k], 
o[k]);
+     }
+
+   return num;
+}
+
 static Eina_Bool
 _gl_filter_blur(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
 {
@@ -8,7 +87,8 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
    RGBA_Draw_Context *dc_save;
    Eina_Bool horiz;
    double sx, sy, sw, sh, ssx, ssy, ssw, ssh, dx, dy, dw, dh, radius;
-   int nx, ny, nw, nh;
+   int nx, ny, nw, nh, count = 0;
+   GLfloat *weights, *offsets;
 
    DEBUG_TIME_BEGIN();
 
@@ -23,15 +103,6 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
 
    evas_gl_common_context_target_surface_set(gc, surface);
 
-   dc_save = gc->dc;
-   gc->dc = evas_common_draw_context_new();
-   evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, 
cmd->draw.B, cmd->draw.A);
-
-   if (cmd->input == cmd->output)
-     gc->dc->render_op = EVAS_RENDER_COPY;
-   else
-     gc->dc->render_op = _gfx_to_evas_render_op(cmd->draw.rop);
-
    if (cmd->blur.dx)
      {
         horiz = EINA_TRUE;
@@ -44,7 +115,8 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
      }
 
    DBG("blur %d @%p -> %d @%p (%.0fpx %s)",
-       cmd->input->id, cmd->input->buffer, cmd->output->id, 
cmd->output->buffer,
+       cmd->input->id, cmd->input->buffer,
+       cmd->output->id, cmd->output->buffer,
        radius, horiz ? "X" : "Y");
 
    sx = 0;
@@ -63,7 +135,21 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
    ssw = ((double)sw * (double)(nw)) / (double)(dw);
    ssh = ((double)sh * (double)(nh)) / (double)(dh);
 
-   evas_gl_common_filter_blur_push(gc, image->tex, ssx, ssy, ssw, ssh, dx, dy, 
dw, dh, radius, horiz);
+   dc_save = gc->dc;
+   gc->dc = evas_common_draw_context_new();
+   evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, 
cmd->draw.B, cmd->draw.A);
+
+   // FIXME: Don't render to same FBO as input! This is not supposed to work!
+   if (cmd->input == cmd->output)
+     gc->dc->render_op = EVAS_RENDER_COPY;
+   else
+     gc->dc->render_op = _gfx_to_evas_render_op(cmd->draw.rop);
+
+   count = _gaussian_interpolate(&weights, &offsets, radius);
+   evas_gl_common_filter_blur_push(gc, image->tex, ssx, ssy, ssw, ssh, dx, dy, 
dw, dh,
+                                   weights, offsets, count, horiz);
+   free(weights);
+   free(offsets);
 
    evas_common_draw_context_free(gc->dc);
    gc->dc = dc_save;
@@ -77,11 +163,13 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
 }
 
 GL_Filter_Apply_Func
-gl_filter_blur_func_get(Evas_Filter_Command *cmd)
+gl_filter_blur_func_get(Render_Engine_GL_Generic *re EINA_UNUSED, 
Evas_Filter_Command *cmd)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
+
+   // 1D blurs only, radius != 0
    EINA_SAFETY_ON_FALSE_RETURN_VAL((!cmd->blur.dx) ^ (!cmd->blur.dy), NULL);
 
    return _gl_filter_blur;
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_curve.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_curve.c
index 97f3f15..5332f1b 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_filter_curve.c
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_curve.c
@@ -56,7 +56,7 @@ _gl_filter_curve(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
 }
 
 GL_Filter_Apply_Func
-gl_filter_curve_func_get(Evas_Filter_Command *cmd)
+gl_filter_curve_func_get(Render_Engine_GL_Generic *re EINA_UNUSED, 
Evas_Filter_Command *cmd)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_displace.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_displace.c
index 4911c80..6705d72 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_filter_displace.c
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_displace.c
@@ -74,7 +74,7 @@ _gl_filter_displace(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
 }
 
 GL_Filter_Apply_Func
-gl_filter_displace_func_get(Evas_Filter_Command *cmd)
+gl_filter_displace_func_get(Render_Engine_GL_Generic *re EINA_UNUSED, 
Evas_Filter_Command *cmd)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_fill.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_fill.c
index a15198d..b88a7c3 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_filter_fill.c
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_fill.c
@@ -63,7 +63,7 @@ _gl_filter_fill(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
 }
 
 GL_Filter_Apply_Func
-gl_filter_fill_func_get(Evas_Filter_Command *cmd)
+gl_filter_fill_func_get(Render_Engine_GL_Generic *re EINA_UNUSED, 
Evas_Filter_Command *cmd)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c
index 37f534d..53b89a3 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c
@@ -68,7 +68,7 @@ _gl_filter_mask(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
 }
 
 GL_Filter_Apply_Func
-gl_filter_mask_func_get(Evas_Filter_Command *cmd)
+gl_filter_mask_func_get(Render_Engine_GL_Generic *re EINA_UNUSED, 
Evas_Filter_Command *cmd)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);

-- 


Reply via email to