diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index b270f763e8..5345b9d7ba 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -844,6 +844,7 @@ modules/evas/engines/gl_generic/evas_ector_gl_buffer.c \ modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c \ modules/evas/engines/gl_generic/filters/gl_engine_filter.h \ modules/evas/engines/gl_generic/filters/gl_filter_blend.c \ +modules/evas/engines/gl_generic/filters/gl_filter_blur.c \ modules/evas/engines/gl_generic/filters/gl_filter_curve.c \ modules/evas/engines/gl_generic/filters/gl_filter_displace.c \ modules/evas/engines/gl_generic/filters/gl_filter_fill.c \ diff --git a/src/bin/elementary/test_gfx_filters.c b/src/bin/elementary/test_gfx_filters.c index d67f616ac8..94036c364f 100644 --- a/src/bin/elementary/test_gfx_filters.c +++ b/src/bin/elementary/test_gfx_filters.c @@ -47,6 +47,8 @@ static const Filter_Image images_anim[] = { /* builtin filter examples */ static const Filter templates[] = { { "Custom", NULL, NULL }, + { "BLUR", + "blur { 15, color = 'darkblue' }", NULL }, { "Simple blend", "blend { color = 'darkblue' }", NULL }, { "Black shadow", diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index b343b9181d..bb761f32a8 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -548,11 +548,6 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, Eina_Bool override; DATA32 color; - // Note (SW engine): - // The basic blur operation overrides the pixels in the target buffer, - // only supports one direction (X or Y) and no offset. As a consequence - // most cases require intermediate work buffers. - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(drawctx, NULL); @@ -570,8 +565,6 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, out = _filter_buffer_get(ctx, outbuf); EINA_SAFETY_ON_FALSE_GOTO(out, fail); - if (in == out) out->dirty = EINA_FALSE; - ENFN->context_color_get(ENDT, drawctx, &R, &G, &B, &A); color = ARGB_JOIN(A, R, G, B); if (!color) @@ -580,6 +573,29 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, return _command_new(ctx, EVAS_FILTER_MODE_SKIP, NULL, NULL, NULL); } + if (ctx->gl) + { + // GL engine: single pass! + XDBG("Add GL blur %d -> %d (%dx%d px)", in->id, out->id, dx, dy); + cmd = _command_new(ctx, EVAS_FILTER_MODE_BLUR, in, NULL, out); + if (!cmd) goto fail; + cmd->blur.type = type; + cmd->blur.dx = dx; + cmd->blur.dy = dy; + cmd->blur.count = count; + cmd->draw.ox = ox; + cmd->draw.oy = oy; + DRAW_COLOR_SET(R, G, B, A); + return cmd; + } + + // Note (SW engine): + // The basic blur operation overrides the pixels in the target buffer, + // only supports one direction (X or Y) and no offset. As a consequence + // most cases require intermediate work buffers. + + if (in == out) out->dirty = EINA_FALSE; + render_op = ENFN->context_render_op_get(ENDT, drawctx); override = (render_op == EVAS_RENDER_COPY); 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 463bd248c2..2ecc94fe0b 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -108,7 +108,7 @@ struct _Evas_GL_Program GLuint mvp, rotation_id; } uniform; struct { - GLuint loc_filter_data[3]; + GLint loc_filter_data[3]; Eina_Bool known_locations; } attribute; GLuint prog; @@ -245,6 +245,7 @@ enum _Shader_Type { SHD_MAP, SHD_FILTER_DISPLACE, SHD_FILTER_CURVE, + SHD_FILTER_BLUR, SHD_TYPE_LAST }; @@ -650,6 +651,7 @@ 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, int x, int y, int w, int h, double dx, double dy); 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 cd3584d200..cc432eaf70 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -1205,6 +1205,9 @@ error: #define PIPE_FREE(x) \ do { _pipebuf_free(x); (x) = NULL; } while (0) +#define FREE(x) \ + do { free(x); (x) = NULL; } while (0) + typedef struct _Pipebuf { int skipped, alloc; @@ -1380,7 +1383,7 @@ evas_gl_common_context_free(Evas_Engine_GL_Context *gc) PIPE_FREE(gc->pipe[i].array.texsam); PIPE_FREE(gc->pipe[i].array.mask); PIPE_FREE(gc->pipe[i].array.masksam); - PIPE_FREE(gc->pipe[i].array.filter_data); + FREE(gc->pipe[i].array.filter_data); } } @@ -3135,6 +3138,25 @@ _filter_data_flush(Evas_Engine_GL_Context *gc, Evas_GL_Program *prog) } } +static inline void +_filter_data_prepare(Evas_Engine_GL_Context *gc, int pn, + Evas_GL_Program *prog, int count) +{ + gc->pipe[pn].array.filter_data_count = count; + gc->pipe[pn].array.filter_data = malloc(count * 2 * sizeof(GLfloat)); + + if (!prog->attribute.known_locations) + { + for (int k = 0; k < count; k++) + { + char name[32]; + + sprintf(name, "filter_data_%d", k); + prog->attribute.loc_filter_data[k] = glGetAttribLocation(prog->prog, name); + } + } +} + void evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex, Evas_GL_Texture *map_tex, @@ -3199,19 +3221,7 @@ evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc, // displace properties gc->pipe[pn].shader.filter.map_tex = map_tex->pt->texture; gc->pipe[pn].shader.filter.map_nearest = nearest; - gc->pipe[pn].array.filter_data_count = 3; - gc->pipe[pn].array.filter_data = malloc(6 * sizeof(GLfloat)); - - if (!prog->attribute.known_locations) - { - for (int k = 0; k < gc->pipe[pn].array.filter_data_count; k++) - { - char name[32]; - - sprintf(name, "filter_data_%d", k); - prog->attribute.loc_filter_data[k] = glGetAttribLocation(prog->prog, name); - } - } + _filter_data_prepare(gc, pn, prog, 3); sx = x; sy = y; @@ -3415,6 +3425,111 @@ evas_gl_common_filter_curve_push(Evas_Engine_GL_Context *gc, if (!nomul) PUSH_6_COLORS(pn, r, g, b, a); +} + +void +evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc, + Evas_GL_Texture *tex, + int x, int y, int w, int h, + double dx, double dy) +{ + double sx, sy, sw, sh, pw, ph; + double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4; + GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; + GLfloat offsetx, offsety; + int r, g, b, a, nomul = 0, pn; + Evas_GL_Program *prog; + GLfloat *filter_data; + Eina_Bool blend = EINA_TRUE; + Eina_Bool smooth = EINA_TRUE; + + r = R_VAL(&gc->dc->mul.col); + g = G_VAL(&gc->dc->mul.col); + b = B_VAL(&gc->dc->mul.col); + a = A_VAL(&gc->dc->mul.col); + if (gc->dc->render_op == EVAS_RENDER_COPY) + blend = EINA_FALSE; + + prog = evas_gl_common_shader_program_get(gc, SHD_FILTER_BLUR, NULL, 0, r, g, b, a, + w, h, w, h, smooth, tex, EINA_FALSE, + NULL, EINA_FALSE, EINA_FALSE, 0, 0, + NULL, &nomul, NULL); + _filter_data_flush(gc, prog); + EINA_SAFETY_ON_NULL_RETURN(prog); + + pn = _evas_gl_common_context_push(SHD_FILTER_BLUR, gc, tex, NULL, prog, + x, y, w, h, blend, smooth, + 0, 0, 0, 0, 0, EINA_FALSE); + + gc->pipe[pn].region.type = SHD_FILTER_BLUR; + gc->pipe[pn].shader.prog = prog; + gc->pipe[pn].shader.cur_tex = tex->pt->texture; + gc->pipe[pn].shader.cur_texm = 0; + gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D; + gc->pipe[pn].shader.smooth = smooth; + gc->pipe[pn].shader.mask_smooth = 0; + gc->pipe[pn].shader.blend = blend; + gc->pipe[pn].shader.render_op = gc->dc->render_op; + gc->pipe[pn].shader.clip = 0; + gc->pipe[pn].shader.cx = 0; + gc->pipe[pn].shader.cy = 0; + gc->pipe[pn].shader.cw = 0; + gc->pipe[pn].shader.ch = 0; + gc->pipe[pn].array.line = 0; + gc->pipe[pn].array.use_vertex = 1; + gc->pipe[pn].array.use_color = !nomul; + gc->pipe[pn].array.use_texuv = 1; + gc->pipe[pn].array.use_texuv2 = 0; + gc->pipe[pn].array.use_texuv3 = 0; + gc->pipe[pn].array.use_texsam = 0; + gc->pipe[pn].array.use_mask = 0; + gc->pipe[pn].array.use_masksam = 0; + + pipe_region_expand(gc, pn, x, y, w, h); + PIPE_GROW(gc, pn, 6); + + // Set blur properties... TODO + _filter_data_prepare(gc, pn, prog, 2); + filter_data = gc->pipe[pn].array.filter_data; + filter_data[0] = dx; + filter_data[1] = dy; + filter_data[2] = w; + filter_data[3] = h; + + sx = 0; + sy = 0; + sw = w; + sh = h; + + pw = tex->pt->w; + ph = tex->pt->h; + + ox1 = sx; + oy1 = sy; + ox2 = sx + sw; + oy2 = sy; + ox3 = sx + sw; + oy3 = sy + sh; + ox4 = sx; + oy4 = sy + sh; + + offsetx = tex->x; + offsety = tex->y; + + tx1 = ((double)(offsetx) + ox1) / pw; + ty1 = ((double)(offsety) + oy1) / ph; + tx2 = ((double)(offsetx) + ox2) / pw; + ty2 = ((double)(offsety) + oy2) / ph; + tx3 = ((double)(offsetx) + ox3) / pw; + ty3 = ((double)(offsety) + oy3) / ph; + tx4 = ((double)(offsetx) + ox4) / pw; + ty4 = ((double)(offsety) + oy4) / ph; + + PUSH_6_VERTICES(pn, x, y, w, h); + PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4); + + if (!nomul) + PUSH_6_COLORS(pn, r, g, b, a); shader_array_flush(gc); } @@ -4180,7 +4295,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc) PIPE_FREE(gc->pipe[i].array.texsam); PIPE_FREE(gc->pipe[i].array.mask); PIPE_FREE(gc->pipe[i].array.masksam); - PIPE_FREE(gc->pipe[i].array.filter_data); + FREE(gc->pipe[i].array.filter_data); gc->pipe[i].array.num = 0; gc->pipe[i].array.alloc = 0; 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 fd19efb729..6f8eb37d49 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_shader.c +++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c @@ -42,8 +42,9 @@ typedef enum { SHADER_FLAG_RGB_A_PAIR = (1 << 20), SHADER_FLAG_FILTER_DISPLACE = (1 << 21), SHADER_FLAG_FILTER_CURVE = (1 << 22), + SHADER_FLAG_FILTER_BLUR = (1 << 23), } Shader_Flag; -#define SHADER_FLAG_COUNT 23 +#define SHADER_FLAG_COUNT 24 static const char *_shader_flags[SHADER_FLAG_COUNT] = { "TEX", @@ -68,7 +69,8 @@ static const char *_shader_flags[SHADER_FLAG_COUNT] = { "ALPHA", "RGB_A_PAIR", "FILTER_DISPLACE", - "FILTER_CURVE" + "FILTER_CURVE", + "FILTER_BLUR" }; static Eina_Bool compiler_released = EINA_FALSE; @@ -785,6 +787,9 @@ evas_gl_common_shader_flags_get(Evas_GL_Shared *shared, Shader_Type type, case SHD_FILTER_CURVE: flags |= SHADER_FLAG_FILTER_CURVE; break; + case SHD_FILTER_BLUR: + flags |= SHADER_FLAG_FILTER_BLUR; + break; default: CRI("Impossible shader type."); return 0; 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 830a3fb1ac..9bbef31c5b 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 @@ -20,6 +20,8 @@ static const char fragment_glsl[] = "#else\n" "# define SAMPLER_EXTERNAL_OES sampler2D\n" "#endif\n" + "#define M_PI 3.141592653589793238462643383279502884\n" + "#define M_PI_2 1.570796326794896619231321691639751442\n" "#ifndef SHD_NOMUL\n" "varying vec4 col;\n" "#endif\n" @@ -89,11 +91,22 @@ static const char fragment_glsl[] = "#ifdef SHD_FILTER_CURVE\n" "uniform sampler2D tex_filter;\n" "#endif\n" + "#ifdef SHD_FILTER_BLUR\n" + "varying vec2 blur_radius;\n" + "varying vec2 blur_divider;\n" + "#endif\n" + "// ----------------------------------------------------------------------------\n" + "#ifndef SHD_FILTER_BLUR\n" "void main()\n" "{\n" "#if defined(SHD_EXTERNAL) || defined(SHD_TEX)\n" " vec2 coord = tex_c;\n" "#endif\n" + "#else // SHD_FILTER_BLUR\n" + "vec4 fetch_pixel(float ox, float oy)\n" + "{\n" + " vec2 coord = tex_c + vec2(ox, oy);\n" + "#endif // SHD_FILTER_BLUR\n" " vec4 c;\n" "#ifdef SHD_FILTER_DISPLACE\n" " vec2 dxy = texture2D(tex_filter, tex_c).rg * displace_vector;\n" @@ -195,8 +208,8 @@ static const char fragment_glsl[] = " texture2D(tex_filter, vec2(c.g / old_alpha, 0.0)).g * new_alpha,\n" " texture2D(tex_filter, vec2(c.b / old_alpha, 0.0)).b * new_alpha,\n" " new_alpha);\n" - " //c = vec4(new_alpha, new_alpha, new_alpha, new_alpha);\n" "#endif\n" + "#ifndef SHD_FILTER_BLUR\n" " gl_FragColor =\n" " c\n" "#ifndef SHD_NOMUL\n" @@ -209,7 +222,50 @@ static const char fragment_glsl[] = " * fa\n" "#endif\n" " ;\n" - "}\n"; + "}\n" + "#else // SHD_FILTER_BLUR\n" + " return c;\n" + "}\n" + "void main()\n" + "{\n" + " float x, y, div_x, div_y;\n" + " float rx = blur_radius.x;\n" + " float ry = blur_radius.y;\n" + " vec4 acc = vec4(0.,0.,0.,0.);\n" + " vec4 c;\n" + " div_x = blur_divider.x;\n" + " div_y = blur_divider.y;\n" + " float diam_x = rx * 2.0 + 1.0;\n" + " float diam_y = ry * 2.0 + 1.0;\n" + " float div = 0.0;\n" + "#if 1\n" + " // This is completely insane... but renders properly :)\n" + " for (y = -ry; y <= ry; y += 8.0)\n" + " {\n" + " float wy = (y + ry) / (diam_y - 1.0) * 6.0 - 3.0;\n" + " wy = (sin(wy + M_PI_2) + 1.0) / 2.0;\n" + " for (x = -rx; x <= rx; x += 8.0)\n" + " {\n" + " float wx = (x + rx) / (diam_x - 1.0) * 6.0 - 3.0;\n" + " wx = (sin(wx + M_PI_2) + 1.0) / 2.0;\n" + " vec4 px = fetch_pixel(x / div_x, y / div_y);\n" + " acc += px * wx * wy;\n" + " div += wx * wy;\n" + " }\n" + " }\n" + "#else\n" + " vec4 px = fetch_pixel(0.0, 0.0);\n" + " div = 1.0;\n" + " acc += px;\n" + "#endif\n" + " c = acc / div;\n" + "#ifndef SHD_NOMUL\n" + " gl_FragColor = c * col;\n" + "#else\n" + " gl_FragColor = c;\n" + "#endif\n" + "}\n" + "#endif // SHD_FILTER_BLUR\n"; static const char vertex_glsl[] = "/* General-purpose vertex shader for all operations in Evas.\n" @@ -282,6 +338,13 @@ static const char vertex_glsl[] = "varying vec2 displace_min;\n" "varying vec2 displace_max;\n" "#endif\n" + "/* Gfx Filters: blur */\n" + "#ifdef SHD_FILTER_BLUR\n" + "attribute vec2 filter_data_0;\n" + "attribute vec2 filter_data_1;\n" + "varying vec2 blur_radius;\n" + "varying vec2 blur_divider;\n" + "#endif\n" "void main()\n" "{\n" " gl_Position = mvp * vertex;\n" @@ -350,5 +413,9 @@ static const char vertex_glsl[] = " displace_min = filter_data_1;\n" " displace_max = filter_data_2;\n" "#endif\n" + "#ifdef SHD_FILTER_BLUR\n" + " blur_radius = filter_data_0;\n" + " blur_divider = filter_data_1;\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 d419b14253..7a2b5bd9c1 100644 --- a/src/modules/evas/engines/gl_common/shader/fragment.glsl +++ b/src/modules/evas/engines/gl_common/shader/fragment.glsl @@ -6,6 +6,9 @@ FRAGMENT_SHADER +#define M_PI 3.141592653589793238462643383279502884 +#define M_PI_2 1.570796326794896619231321691639751442 + #ifndef SHD_NOMUL varying vec4 col; #endif @@ -85,12 +88,28 @@ varying vec2 displace_max; uniform sampler2D tex_filter; #endif +#ifdef SHD_FILTER_BLUR +varying vec2 blur_radius; +varying vec2 blur_divider; +#endif + +// ---------------------------------------------------------------------------- + +#ifndef SHD_FILTER_BLUR void main() { #if defined(SHD_EXTERNAL) || defined(SHD_TEX) vec2 coord = tex_c; #endif +#else // SHD_FILTER_BLUR + +vec4 fetch_pixel(float ox, float oy) +{ + vec2 coord = tex_c + vec2(ox, oy); + +#endif // SHD_FILTER_BLUR + vec4 c; #ifdef SHD_FILTER_DISPLACE @@ -205,6 +224,8 @@ void main() new_alpha); #endif +#ifndef SHD_FILTER_BLUR + gl_FragColor = c #ifndef SHD_NOMUL @@ -219,3 +240,51 @@ void main() ; } +#else // SHD_FILTER_BLUR + + return c; +} + +void main() +{ + float x, y, div_x, div_y; + float rx = blur_radius.x; + float ry = blur_radius.y; + vec4 acc = vec4(0.,0.,0.,0.); + vec4 c; + + div_x = blur_divider.x; + div_y = blur_divider.y; + + float diam_x = rx * 2.0 + 1.0; + float diam_y = ry * 2.0 + 1.0; + float div = 0.0; + + // This is completely insane... but renders properly :) + for (y = -ry; y <= ry; y += 1.0) + { + float wy = (y + ry) / (diam_y - 1.0) * 6.0 - 3.0; + wy = (sin(wy + M_PI_2) + 1.0) / 2.0; + + for (x = -rx; x <= rx; x += 1.0) + { + float wx = (x + rx) / (diam_x - 1.0) * 6.0 - 3.0; + wx = (sin(wx + M_PI_2) + 1.0) / 2.0; + + vec4 px = fetch_pixel(x / div_x, y / div_y); + + acc += px * wx * wy; + div += wx * wy; + } + } + + c = acc / div; + +#ifndef SHD_NOMUL + gl_FragColor = c * col; +#else + gl_FragColor = c; +#endif +} + +#endif // SHD_FILTER_BLUR diff --git a/src/modules/evas/engines/gl_common/shader/vertex.glsl b/src/modules/evas/engines/gl_common/shader/vertex.glsl index 1f2746a42e..1f2a1701f8 100644 --- a/src/modules/evas/engines/gl_common/shader/vertex.glsl +++ b/src/modules/evas/engines/gl_common/shader/vertex.glsl @@ -78,6 +78,14 @@ varying vec2 displace_min; varying vec2 displace_max; #endif +/* Gfx Filters: blur */ +#ifdef SHD_FILTER_BLUR +attribute vec2 filter_data_0; +attribute vec2 filter_data_1; +varying vec2 blur_radius; +varying vec2 blur_divider; +#endif + void main() { @@ -157,5 +165,9 @@ void main() displace_min = filter_data_1; displace_max = filter_data_2; #endif -} +#ifdef SHD_FILTER_BLUR + blur_radius = filter_data_0; + blur_divider = filter_data_1; +#endif +} diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 03ef61071d..4b0d38f118 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -3029,7 +3029,7 @@ _gfx_filter_func_get(Evas_Filter_Command *cmd) 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_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; 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 b49180dac4..4d4baca126 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 @@ -10,7 +10,7 @@ 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_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); 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 new file mode 100644 index 0000000000..12458cb303 --- /dev/null +++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c @@ -0,0 +1,63 @@ +#include "gl_engine_filter.h" + +static Eina_Bool +_gl_filter_blur(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd) +{ + Evas_Engine_GL_Context *gc; + Evas_GL_Image *image, *surface; + RGBA_Draw_Context *dc_save; + int x, y, w, h; + + DEBUG_TIME_BEGIN(); + + x = cmd->draw.ox; + y = cmd->draw.oy; + w = cmd->input->w; + h = cmd->input->h; + + re->window_use(re->software.ob); + gc = re->window_gl_context_get(re->software.ob); + + image = evas_ector_buffer_drawable_image_get(cmd->input->buffer); + EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); + + surface = evas_ector_buffer_render_image_get(cmd->output->buffer); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); + + 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); + + DBG("blur %d @%p -> %d @%p", cmd->input->id, cmd->input->buffer, + cmd->output->id, cmd->output->buffer); + + evas_gl_common_filter_blur_push(gc, image->tex, x, y, w, h, + cmd->blur.dx, cmd->blur.dy); + + evas_common_draw_context_free(gc->dc); + gc->dc = dc_save; + + evas_ector_buffer_engine_image_release(cmd->input->buffer, image); + evas_ector_buffer_engine_image_release(cmd->output->buffer, surface); + + DEBUG_TIME_END(); + + return EINA_TRUE; +} + +GL_Filter_Apply_Func +gl_filter_blur_func_get(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); + + return _gl_filter_blur; +}