kimcinoo pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=51169ac325c59912417412b9138eeacbbb6a93bc
commit 51169ac325c59912417412b9138eeacbbb6a93bc Author: Shinwoo Kim <cinoo....@samsung.com> Date: Tue Nov 5 10:44:58 2019 +0900 evas filter: Implement inverse color filter Summary: This is the first version of inverse color filter both GL and SW. Test Plan: 1. Create filter_example with following . efl_gfx_filter_program_set(image, "inverse_color ()", "inverse color"); 2. Run. ./filter_example (Use ELM_ACCEL=gl for GL engine) Reviewers: Hermet, jsuya Reviewed By: Hermet Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D10335 --- src/lib/evas/filters/evas_filter.c | 22 +++++ src/lib/evas/filters/evas_filter_parser.c | 39 +++++++++ src/lib/evas/include/evas_filter.h | 12 +++ src/lib/evas/software_generic/filters/meson.build | 1 + .../evas/engines/gl_common/evas_gl_common.h | 4 +- .../evas/engines/gl_common/evas_gl_context.c | 93 ++++++++++++++++++++++ .../evas/engines/gl_common/evas_gl_shader.c | 7 +- .../engines/gl_common/shader/evas_gl_shaders.x | 3 + .../evas/engines/gl_common/shader/fragment.glsl | 4 + src/modules/evas/engines/gl_generic/evas_engine.c | 1 + .../engines/gl_generic/filters/gl_engine_filter.h | 1 + .../gl_generic/filters/gl_filter_inverse_color.c | 53 ++++++++++++ src/modules/evas/engines/gl_generic/meson.build | 1 + .../evas/engines/software_generic/evas_engine.c | 1 + .../software_generic/filters/evas_engine_filter.h | 1 + .../filters/evas_filter_inverse_color.c | 57 +++++++++++++ 16 files changed, 298 insertions(+), 2 deletions(-) diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index 36c9c5d2b1..c9d8005e26 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -1619,6 +1619,28 @@ evas_filter_command_grayscale_add(Evas_Filter_Context *ctx, return cmd; } +Evas_Filter_Command * +evas_filter_command_inverse_color_add(Evas_Filter_Context *ctx, + void *draw_context EINA_UNUSED, + int inbuf, int outbuf) +{ + Evas_Filter_Command *cmd; + Evas_Filter_Buffer *in, *out; + + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + + in = _filter_buffer_get(ctx, inbuf); + EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); + + out = _filter_buffer_get(ctx, outbuf); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); + + cmd = _command_new(ctx, EVAS_FILTER_MODE_INVERSE_COLOR, in, NULL, out); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); + + return cmd; +} + void evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect) { diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c index 6d89a3518f..6654841061 100644 --- a/src/lib/evas/filters/evas_filter_parser.c +++ b/src/lib/evas/filters/evas_filter_parser.c @@ -1809,6 +1809,26 @@ _grayscale_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction return EINA_TRUE; } +/** + @page evasfiltersref + Apply inverse color + TODO: write down more information + */ + +static Eina_Bool +_inverse_color_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(instr, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(instr->name, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(!strcasecmp(instr->name, "inverse_color"), EINA_FALSE); + + instr->type = EVAS_FILTER_MODE_INVERSE_COLOR; + _instruction_param_seq_add(instr, "src", VT_BUFFER, _buffer_get(pgm, "input")); + _instruction_param_seq_add(instr, "dst", VT_BUFFER, _buffer_get(pgm, "output")); + + return EINA_TRUE; +} + static int _padding_set_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr, @@ -2270,6 +2290,7 @@ LUA_GENERIC_FUNCTION(mask) LUA_GENERIC_FUNCTION(padding_set) LUA_GENERIC_FUNCTION(transform) LUA_GENERIC_FUNCTION(grayscale) +LUA_GENERIC_FUNCTION(inverse_color) static const luaL_Reg _lua_buffer_metamethods[] = { { "__call", _lua_buffer_new }, @@ -2507,6 +2528,7 @@ _lua_state_create(Evas_Filter_Program *pgm) PUSH_LUA_FUNCTION(padding_set) PUSH_LUA_FUNCTION(transform) PUSH_LUA_FUNCTION(grayscale) + PUSH_LUA_FUNCTION(inverse_color) for (unsigned k = 0; k < (sizeof(fill_modes) / sizeof(fill_modes[0])); k++) { @@ -3439,6 +3461,20 @@ _instr2cmd_grayscale(Evas_Filter_Context *ctx, return evas_filter_command_grayscale_add(ctx, dc, src->cid, dst->cid); } +static Evas_Filter_Command * +_instr2cmd_inverse_color(Evas_Filter_Context *ctx, + Evas_Filter_Instruction *instr, void *dc) +{ + Buffer *src, *dst; + + src = _instruction_param_getbuf(instr, "src", NULL); + dst = _instruction_param_getbuf(instr, "dst", NULL); + INSTR_PARAM_CHECK(src); + INSTR_PARAM_CHECK(dst); + + return evas_filter_command_inverse_color_add(ctx, dc, src->cid, dst->cid); +} + static Eina_Bool _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) @@ -3478,6 +3514,9 @@ _command_from_instruction(Evas_Filter_Context *ctx, case EVAS_FILTER_MODE_GRAYSCALE: instr2cmd = _instr2cmd_grayscale; break; + case EVAS_FILTER_MODE_INVERSE_COLOR: + instr2cmd = _instr2cmd_inverse_color; + break; case EVAS_FILTER_MODE_PADDING_SET: case EVAS_FILTER_MODE_BUFFER: return EINA_TRUE; diff --git a/src/lib/evas/include/evas_filter.h b/src/lib/evas/include/evas_filter.h index 8dab0a9a34..5a22c2b6ae 100644 --- a/src/lib/evas/include/evas_filter.h +++ b/src/lib/evas/include/evas_filter.h @@ -70,6 +70,7 @@ enum _Evas_Filter_Mode EVAS_FILTER_MODE_TRANSFORM, /**< Apply a simple geometrical transformation */ EVAS_FILTER_MODE_PADDING_SET, /**< Special padding_set instruction to force a specific padding value */ EVAS_FILTER_MODE_GRAYSCALE, /**< Leave only grayscale information */ + EVAS_FILTER_MODE_INVERSE_COLOR,/**< Apply inverse color */ EVAS_FILTER_MODE_LAST }; @@ -318,6 +319,17 @@ Evas_Filter_Command *evas_filter_command_transform_add(Evas_Filter_Context * */ Evas_Filter_Command *evas_filter_command_grayscale_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf); +/** + * @brief Apply inverse color of the buffer + * @param ctx Current filter chain + * @param draw_context Current Evas draw context (ignored) + * @param inbuf Input buffer (Alpha or RGBA) + * @param outbuf Output buffer (Alpha or RGBA), same size as inbuf + * @return Filter command or NULL in case of error + * @internal + */ +Evas_Filter_Command *evas_filter_command_inverse_color_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf); + /* Simple binding between a filter object and its sources */ struct _Evas_Filter_Proxy_Binding { diff --git a/src/lib/evas/software_generic/filters/meson.build b/src/lib/evas/software_generic/filters/meson.build index 17c7bce8c2..abe0594c99 100644 --- a/src/lib/evas/software_generic/filters/meson.build +++ b/src/lib/evas/software_generic/filters/meson.build @@ -11,6 +11,7 @@ raw_evas_src = [ 'evas_filter_mask.c', 'evas_filter_transform.c', 'evas_filter_grayscale.c', + 'evas_filter_inverse_color.c', ] foreach file : raw_evas_src 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 b2cf74bee5..0cc7f30573 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -266,7 +266,8 @@ enum _Shader_Type { SHD_FILTER_CURVE, SHD_FILTER_BLUR_X, SHD_FILTER_BLUR_Y, - SHD_FILTER_GRAYSCALE + SHD_FILTER_GRAYSCALE, + SHD_FILTER_INVERSE_COLOR }; #define ARRAY_BUFFER_USE 500 @@ -682,6 +683,7 @@ void evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc, Ev double dx, double dy, double dw, double dh, const double * const values, const double * const offsets, int count, double radius, Eina_Bool horiz, Eina_Bool alphaonly); void evas_gl_common_filter_grayscale_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex, int x, int y, int w, int h); +void evas_gl_common_filter_inverse_color_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex, int x, int y, int w, int h); 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 9178d3f6b8..6637a839df 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -3771,6 +3771,99 @@ evas_gl_common_filter_grayscale_push(Evas_Engine_GL_Context *gc, if (!nomul) PUSH_6_COLORS(pn, r, g, b, a); } + +void +evas_gl_common_filter_inverse_color_push(Evas_Engine_GL_Context *gc, + Evas_GL_Texture *tex, + int x, int y, int w, int h) +{ + double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph; + GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; + GLfloat offsetx, offsety; + int r, g, b, a, nomul = 0, pn; + Evas_GL_Program *prog; + Eina_Bool blend = EINA_TRUE; + Eina_Bool smooth = EINA_TRUE; + Shader_Type type = SHD_FILTER_INVERSE_COLOR; + + 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, type, NULL, 0, r, g, b, a, + w, h, w, h, smooth, tex, EINA_FALSE, + NULL, EINA_FALSE, EINA_FALSE, 0, 0, + EINA_FALSE, NULL, &nomul, NULL); + + _filter_data_flush(gc, prog); + EINA_SAFETY_ON_NULL_RETURN(prog); + + pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog, + x, y, w, h, blend, smooth, + 0, 0, 0, 0, 0, EINA_FALSE); + + gc->pipe[pn].region.type = type; + 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); + + _filter_data_alloc(gc, pn, 0); + + pw = tex->pt->w; + ph = tex->pt->h; + + ox1 = x; + oy1 = y; + ox2 = x + w; + oy2 = y; + ox3 = x + w; + oy3 = y + h; + ox4 = x; + oy4 = y + h; + + 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); +} // ---------------------------------------------------------------------------- EAPI void 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 7c338674ec..5702ce49c3 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_shader.c +++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c @@ -46,8 +46,9 @@ typedef enum { SHADER_FLAG_FILTER_DIR_Y = (1 << 24), SHADER_FLAG_FILTER_ALPHA_ONLY = (1 << 25), SHADER_FLAG_FILTER_GRAYSCALE = (1 << 26), + SHADER_FLAG_FILTER_INVERSE_COLOR = (1 << 27), } Shader_Flag; -#define SHADER_FLAG_COUNT 27 +#define SHADER_FLAG_COUNT 28 static const char *_shader_flags[SHADER_FLAG_COUNT] = { "TEX", @@ -77,6 +78,7 @@ static const char *_shader_flags[SHADER_FLAG_COUNT] = { "FILTER_DIR_Y", "ALPHA_ONLY", "FILTER_GRAYSCALE", + "FILTER_INVERSE_COLOR", }; static Eina_Bool compiler_released = EINA_FALSE; @@ -829,6 +831,9 @@ evas_gl_common_shader_flags_get(Evas_GL_Shared *shared, Shader_Type type, case SHD_FILTER_GRAYSCALE: flags |= SHADER_FLAG_FILTER_GRAYSCALE; break; + case SHD_FILTER_INVERSE_COLOR: + flags |= SHADER_FLAG_FILTER_INVERSE_COLOR; + 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 73ca4bef11..e5c16b5b75 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 @@ -217,6 +217,9 @@ static const char fragment_glsl[] = "#ifdef SHD_FILTER_GRAYSCALE\n" " c.rgb = 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;\n" "#endif\n" + "#ifdef SHD_FILTER_INVERSE_COLOR\n" + " c.rgb = c.a - c.rgb;\n" + "#endif\n" "#ifndef SHD_FILTER_BLUR\n" " gl_FragColor =\n" " c\n" diff --git a/src/modules/evas/engines/gl_common/shader/fragment.glsl b/src/modules/evas/engines/gl_common/shader/fragment.glsl index 39fccf1119..b51bbb4d38 100644 --- a/src/modules/evas/engines/gl_common/shader/fragment.glsl +++ b/src/modules/evas/engines/gl_common/shader/fragment.glsl @@ -234,6 +234,10 @@ vec4 fetch_pixel(float ox, float oy) c.rgb = 0.3 * c.r + 0.59 * c.g + 0.11 * c.b; #endif +#ifdef SHD_FILTER_INVERSE_COLOR + c.rgb = c.a - c.rgba; +#endif + #ifndef SHD_FILTER_BLUR gl_FragColor = diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 3428cf5620..2ca2d5b634 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -3128,6 +3128,7 @@ _gfx_filter_func_get(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd) 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; case EVAS_FILTER_MODE_GRAYSCALE: funcptr = gl_filter_grayscale_func_get(re, cmd); break; + case EVAS_FILTER_MODE_INVERSE_COLOR: funcptr = gl_filter_inverse_color_func_get(re, cmd); break; default: return NULL; } 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 b1045d019e..5b5d67799c 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 @@ -18,6 +18,7 @@ GL_Filter_Apply_Func gl_filter_fill_func_get(Render_Engine_GL_Generic *re, Evas_ 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); GL_Filter_Apply_Func gl_filter_grayscale_func_get(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd); +GL_Filter_Apply_Func gl_filter_inverse_color_func_get(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd); #undef DBG #undef INF diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_inverse_color.c b/src/modules/evas/engines/gl_generic/filters/gl_filter_inverse_color.c new file mode 100644 index 0000000000..8319db69b0 --- /dev/null +++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_inverse_color.c @@ -0,0 +1,53 @@ +#include "gl_engine_filter.h" + +static Eina_Bool +_gl_filter_inverse_color(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 w, h; + + w = cmd->input->w; + h = cmd->input->h; + EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE); + + 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); + + gc = gl_generic_context_find(re, 1); + 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); + + evas_gl_common_filter_inverse_color_push(gc, image->tex, 0, 0, w, h); + + 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); + + return EINA_TRUE; +} + +GL_Filter_Apply_Func +gl_filter_inverse_color_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); + + return _gl_filter_inverse_color; +} diff --git a/src/modules/evas/engines/gl_generic/meson.build b/src/modules/evas/engines/gl_generic/meson.build index d137eb26ef..6f7e9dc259 100644 --- a/src/modules/evas/engines/gl_generic/meson.build +++ b/src/modules/evas/engines/gl_generic/meson.build @@ -13,6 +13,7 @@ engine_src = files([ join_paths('filters','gl_filter_fill.c'), join_paths('filters','gl_filter_mask.c'), join_paths('filters','gl_filter_grayscale.c'), + join_paths('filters','gl_filter_inverse_color.c'), ]) common_engine_src = [ 'evas_gl_private.h', diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 085f053b1d..404370db29 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -4545,6 +4545,7 @@ _gfx_filter_func_get(Evas_Filter_Command *cmd) case EVAS_FILTER_MODE_MASK: func = eng_filter_mask_func_get(cmd); break; case EVAS_FILTER_MODE_TRANSFORM: func = eng_filter_transform_func_get(cmd); break; case EVAS_FILTER_MODE_GRAYSCALE: func = eng_filter_grayscale_func_get(cmd); break; + case EVAS_FILTER_MODE_INVERSE_COLOR: func = eng_filter_inverse_color_func_get(cmd); break; default: return NULL; } diff --git a/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h b/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h index 33998f9344..bc6bbbdadc 100644 --- a/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h +++ b/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h @@ -14,5 +14,6 @@ Software_Filter_Func eng_filter_fill_func_get(Evas_Filter_Command *cmd); Software_Filter_Func eng_filter_mask_func_get(Evas_Filter_Command *cmd); Software_Filter_Func eng_filter_transform_func_get(Evas_Filter_Command *cmd); Software_Filter_Func eng_filter_grayscale_func_get(Evas_Filter_Command *cmd); +Software_Filter_Func eng_filter_inverse_color_func_get(Evas_Filter_Command *cmd); #endif // EVAS_ENGINE_FILTER_H diff --git a/src/modules/evas/engines/software_generic/filters/evas_filter_inverse_color.c b/src/modules/evas/engines/software_generic/filters/evas_filter_inverse_color.c new file mode 100644 index 0000000000..8079e3adb5 --- /dev/null +++ b/src/modules/evas/engines/software_generic/filters/evas_filter_inverse_color.c @@ -0,0 +1,57 @@ +#include "evas_engine_filter.h" + +static Eina_Bool +_evas_filter_inverse_color(Evas_Filter_Command *cmd) +{ + int sw, sh, dw, dh, x, y, slen, dlen; + unsigned int src_len, src_stride, dst_len, dst_stride; + Eina_Bool ret = EINA_FALSE; + DATA32 *ts, *td, *src = NULL, *dst = NULL; + + ector_buffer_size_get(cmd->input->buffer, &sw, &sh); + EINA_SAFETY_ON_FALSE_RETURN_VAL((sw > 0) && (sh > 0), ret); + + ector_buffer_size_get(cmd->output->buffer, &dw, &dh); + EINA_SAFETY_ON_FALSE_RETURN_VAL((dw > 0) && (dh > 0), ret); + + src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ARGB, &src_stride); + EINA_SAFETY_ON_FALSE_GOTO(src, end); + + dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride); + EINA_SAFETY_ON_FALSE_GOTO(dst, end); + + slen = src_stride / sizeof(*src); + dlen = dst_stride / sizeof(*dst); + + ts = src; + td = dst; + for (y = 0; y < sh ; y++) + { + for (x = 0; x < sw; x++) + { + A_VAL(td + x) = A_VAL(ts + x); + R_VAL(td + x) = A_VAL(ts + x) - R_VAL(ts + x); + G_VAL(td + x) = A_VAL(ts + x) - G_VAL(ts + x); + B_VAL(td + x) = A_VAL(ts + x) - B_VAL(ts + x); + } + ts += slen; + td += dlen; + } + + ret = EINA_TRUE; + +end: + if (src) ector_buffer_unmap(cmd->input->buffer, src, src_len); + if (dst) ector_buffer_unmap(cmd->output->buffer, dst, dst_len); + return ret; +} + +Software_Filter_Func +eng_filter_inverse_color_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 _evas_filter_inverse_color; +} --