jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=8f4018b690de4e052c7ac74c4d5933f6a0ccd9ee

commit 8f4018b690de4e052c7ac74c4d5933f6a0ccd9ee
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Fri Dec 4 15:43:27 2015 +0900

    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.
---
 src/Makefile_Evas.am                    |   3 +-
 src/lib/evas/filters/evas_filter_mask.c | 124 +++++++++++++++++---------------
 src/static_libs/draw/draw.h             |   3 +
 src/static_libs/draw/draw_main.c        |  82 ++++++++++++++++++++-
 4 files changed, 151 insertions(+), 61 deletions(-)

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)
 {

-- 


Reply via email to