From: Jean-Philippe Andre Date: Fri, 4 Dec 2015 06:43:27 +0000 (+0900) Subject: Evas filters: Implement mix3 func for rgba masking X-Git-Tag: upstream/1.20.0~8003 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8f4018b690de4e052c7ac74c4d5933f6a0ccd9ee;p=platform%2Fupstream%2Fefl.git Evas filters: Implement mix3 func for rgba masking This operation was faked by running a mul and a blend ops. Now they are combined into one. A GL shader should also be able to do this in a single pass. --- diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 1f52b28..01ac756 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -261,7 +261,8 @@ lib/evas/canvas/evas_vg_shape.c # Static draw lib lib_evas_libevas_la_SOURCES += \ -static_libs/draw/draw_alpha_main.c +static_libs/draw/draw_alpha_main.c \ +static_libs/draw/draw_main.c # Engine lib_evas_libevas_la_SOURCES += \ diff --git a/src/lib/evas/filters/evas_filter_mask.c b/src/lib/evas/filters/evas_filter_mask.c index 2ae84b7..135d0df 100644 --- a/src/lib/evas/filters/evas_filter_mask.c +++ b/src/lib/evas/filters/evas_filter_mask.c @@ -349,71 +349,81 @@ _mask_cpu_alpha_alpha_rgba(Evas_Filter_Command *cmd) static Eina_Bool _mask_cpu_rgba_rgba_rgba(Evas_Filter_Command *cmd) { - //Evas_Filter_Command fake_cmd; - Evas_Filter_Fill_Mode fillmode; - //Evas_Filter_Apply_Func blend; - Evas_Filter_Buffer *fb; - Eina_Bool ret = EINA_FALSE; - int w, h; + Draw_Func_ARGB_Mix3 func; + RGBA_Image *in, *out, *mask; + DATA32 *dst, *msk, *src; + int w, h, mw, mh, y, my, r; + int stepsize, stepcount, step; + DATA32 color; + + /* Mechanism: + * 1. Stretch mask as requested in fillmode + * 2. Mix 3 colors + */ + + in = (RGBA_Image *) cmd->input->backing; + out = (RGBA_Image *) cmd->output->backing; + mask = (RGBA_Image *) cmd->mask->backing; - fake_cmd = *cmd; w = cmd->input->w; h = cmd->input->h; + mw = cmd->mask->w; + mh = cmd->mask->h; + src = in->image.data; + dst = out->image.data; - // FIXME: do a single pass - /* Blend 2 rgba images into rgba destination. - * Mechanism: - * 1. Copy input to temp (COPY) - * 2. Blend mask to temp (MUL) - * 3. Blend temp to output (render_op) - */ + // Stretch if necessary. + if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) + { + Evas_Filter_Buffer *fb; + + if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) + mw = w; + if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) + mh = h; - // Copy - BUFFERS_LOCK(); - fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, w, h); - BUFFERS_UNLOCK(); - EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); - fb->locked = EINA_TRUE; + BUFFERS_LOCK(); + fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh); + BUFFERS_UNLOCK(); - // Repeat mask if unspecified - NONE is not possible - fillmode = cmd->draw.fillmode; - if ((fillmode & (EVAS_FILTER_FILL_MODE_REPEAT_X | EVAS_FILTER_FILL_MODE_STRETCH_X)) == 0) - { - DBG("X fillmode not specified: defaults to repeat"); - fillmode |= EVAS_FILTER_FILL_MODE_REPEAT_X; + EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); + fb->locked = EINA_FALSE; + mask = fb->backing; } - if ((fillmode & (EVAS_FILTER_FILL_MODE_REPEAT_Y | EVAS_FILTER_FILL_MODE_STRETCH_Y)) == 0) + + color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B); + msk = mask->image.data; + + EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(msk, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE); + + stepsize = MIN(mw, w); + stepcount = w / stepsize; + + func = efl_draw_func_argb_mix3_get(cmd->draw.rop, color); + + // Apply mask using Gfx functions + for (y = 0, my = 0; y < h; y++, my++, msk += mw) { - DBG("Y fillmode not specified: defaults to repeat"); - fillmode |= EVAS_FILTER_FILL_MODE_REPEAT_Y; + if (my >= mh) + { + my = 0; + msk = mask->image.data; + } + + for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize) + func(dst, src, msk, stepsize, color); + + r = w - (stepsize * stepcount); + if (r > 0) + { + func(dst, src, msk, r, color); + dst += r; + src += r; + } } -#warning FIXME: filter full RGBA masking is now broken - goto finish; - -#if 0 - // Mask --> Temp - fake_cmd.input = cmd->mask; - fake_cmd.mask = NULL; - fake_cmd.output = fb; - fake_cmd.draw.rop = EVAS_RENDER_MUL; // FIXME - fake_cmd.draw.fillmode = fillmode; - blend = evas_filter_blend_cpu_func_get(&fake_cmd); - EINA_SAFETY_ON_NULL_RETURN_VAL(blend, EINA_FALSE); - ret = blend(&fake_cmd); - if (!ret) goto finish; - - // Temp --> Output - fake_cmd.draw.rop = EFL_GFX_RENDER_OP_BLEND; - fake_cmd.input = fb; - fake_cmd.output = cmd->output; - fake_cmd.draw.fillmode = EVAS_FILTER_FILL_MODE_NONE; - blend = evas_filter_blend_cpu_func_get(&fake_cmd); - EINA_SAFETY_ON_NULL_RETURN_VAL(blend, EINA_FALSE); - ret = blend(&fake_cmd); -#endif - -finish: - fb->locked = EINA_FALSE; - return ret; + return EINA_TRUE; } diff --git a/src/static_libs/draw/draw.h b/src/static_libs/draw/draw.h index 2a3d635..51bf917 100644 --- a/src/static_libs/draw/draw.h +++ b/src/static_libs/draw/draw.h @@ -11,6 +11,7 @@ typedef void (*RGBA_Comp_Func) (uint32_t *dest, const uint32_t *src, int length, uint32_t mul_col, uint32_t const_alpha); typedef void (*RGBA_Comp_Func_Solid) (uint32_t *dest, int length, uint32_t color, uint32_t const_alpha); typedef void (*RGBA_Comp_Func_Mask) (uint32_t *dest, uint8_t *mask, int length, uint32_t color); +typedef void (*Draw_Func_ARGB_Mix3) (uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color); typedef void (*Alpha_Gfx_Func) (uint8_t *src, uint8_t *dst, int len); int efl_draw_init(void); @@ -18,6 +19,7 @@ int efl_draw_init(void); RGBA_Comp_Func efl_draw_func_span_get (Efl_Gfx_Render_Op op, uint32_t color, Eina_Bool src_alpha); RGBA_Comp_Func_Solid efl_draw_func_solid_span_get (Efl_Gfx_Render_Op op, uint32_t color); RGBA_Comp_Func_Mask efl_draw_func_mask_span_get (Efl_Gfx_Render_Op op, uint32_t color); +Draw_Func_ARGB_Mix3 efl_draw_func_argb_mix3_get (Efl_Gfx_Render_Op op, uint32_t color); Alpha_Gfx_Func efl_draw_alpha_func_get (Efl_Gfx_Render_Op op, Eina_Bool has_mask); @@ -54,6 +56,7 @@ Alpha_Gfx_Func efl_draw_alpha_func_get (Efl_Gfx_Render_Op op, Eina_ #define DRAW_ARGB_JOIN(a,r,g,b) \ (((a) << 24) + ((r) << 16) + ((g) << 8) + (b)) +/* argb multiply */ #define DRAW_MUL4_SYM(x, y) \ ( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \ ((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \ diff --git a/src/static_libs/draw/draw_main.c b/src/static_libs/draw/draw_main.c index 915adf1..0e423aa 100644 --- a/src/static_libs/draw/draw_main.c +++ b/src/static_libs/draw/draw_main.c @@ -138,12 +138,15 @@ _comp_func_mask_blend(uint32_t *dest, uint8_t *mask, int length, uint32_t color) for (k = 0; k < length; k++, dest++, mask++) { - uint32_t c = draw_mul_256(*mask, color); + uint32_t c = draw_mul_256((*mask + 1), color); int a = 256 - (c >> 24); *dest = c + draw_mul_256(a, *dest); } } +/* s = m * color + * d = s * sa + */ static void _comp_func_mask_copy(uint32_t *dest, uint8_t *mask, int length, uint32_t color) { @@ -151,8 +154,65 @@ _comp_func_mask_copy(uint32_t *dest, uint8_t *mask, int length, uint32_t color) for (k = 0; k < length; k++, dest++, mask++) { - int a = (*mask & 0x80) ? *mask + 1 : *mask; - *dest = draw_mul_256(a, color); + *dest = draw_mul_256(*mask + 1, color); + } +} + +/* w = s * m * c + * d = d * (1-wa) + w * wa + */ +static void +_comp_func_mix3_blend(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color) +{ + int k, a; + + for (k = 0; k < len; k++, dest++, src++, mul++) + { + uint32_t c = DRAW_MUL4_SYM(*mul, color); + c = DRAW_MUL4_SYM(c, *src); + a = 256 - (c >> 24); + *dest = c + draw_mul_256(a, *dest); + } +} + +/* d = s * m * c */ +static void +_comp_func_mix3_copy(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color) +{ + int k; + + for (k = 0; k < len; k++, dest++, src++, mul++) + { + uint32_t c = DRAW_MUL4_SYM(*mul, color); + *dest = DRAW_MUL4_SYM(c, *src); + } +} + +/* w = s * m + * d = d * (1-wa) + w * wa + */ +static void +_comp_func_mix3_blend_nomul(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color EINA_UNUSED) +{ + int k, a; + + for (k = 0; k < len; k++, dest++, src++, mul++) + { + uint32_t c = DRAW_MUL4_SYM(*mul, *src); + a = 256 - (c >> 24); + *dest = c + draw_mul_256(a, *dest); + } +} + +/* d = s * m */ +static void +_comp_func_mix3_copy_nomul(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color EINA_UNUSED) +{ + int k; + + for (k = 0; k < len; k++, dest++, src++, mul++) + { + *dest = DRAW_MUL4_SYM(*mul, *src); } } @@ -171,12 +231,28 @@ RGBA_Comp_Func func_for_mode[EFL_GFX_RENDER_OP_LAST] = { _comp_func_source }; +Draw_Func_ARGB_Mix3 func_for_mode_argb_mix3[EFL_GFX_RENDER_OP_LAST * 2] = { + _comp_func_mix3_blend, + _comp_func_mix3_copy, + _comp_func_mix3_blend_nomul, + _comp_func_mix3_copy_nomul +}; + RGBA_Comp_Func_Mask efl_draw_func_mask_span_get(Efl_Gfx_Render_Op op, uint32_t color EINA_UNUSED) { return func_for_mode_mask[op]; } +Draw_Func_ARGB_Mix3 +efl_draw_func_argb_mix3_get(Efl_Gfx_Render_Op op, uint32_t color) +{ + if (color == 0xffffffff) + return func_for_mode_argb_mix3[op + 2]; + else + return func_for_mode_argb_mix3[op]; +} + RGBA_Comp_Func_Solid efl_draw_func_solid_span_get(Efl_Gfx_Render_Op op, uint32_t color) {