From 6af3c20aebc822cfb4148e60a1cb4e19e489c4d1 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 20 Mar 2017 23:25:05 +0900 Subject: [PATCH] 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..bb26c2fc 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); -- 2.7.4