jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=7a7738e9bbb751db5b262cc0c0ef20c9671887c1

commit 7a7738e9bbb751db5b262cc0c0ef20c9671887c1
Author: Jean-Philippe Andre <[email protected]>
Date:   Fri Feb 21 16:46:04 2014 +0900

    Evas filters: Implement mapped blend for alpha buffers
    
    Allow repeat fillmode in blend() for:
    alpha --> alpha
    alpha --> rgba
    rgba --> alpha
    
    Alpha scaling is not implemented yet, but it is not actually
    required. Indeed, only proxies can have a different size and
    proxies are RGBA images, not alpha.
    
    Alpha scaling may or may not become a requirement in the future,
    or for other purposes, but not yet.
---
 src/lib/evas/filters/evas_filter_blend.c | 349 +++++++++++++++----------------
 1 file changed, 168 insertions(+), 181 deletions(-)

diff --git a/src/lib/evas/filters/evas_filter_blend.c 
b/src/lib/evas/filters/evas_filter_blend.c
index 95e4887..038eb5f 100644
--- a/src/lib/evas/filters/evas_filter_blend.c
+++ b/src/lib/evas/filters/evas_filter_blend.c
@@ -24,59 +24,178 @@ _smallest_pow2_larger_than(int val)
 typedef Eina_Bool (*image_draw_func) (void *data, void *context, void 
*surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, 
int dst_y, int dst_w, int dst_h, int smooth, Eina_Bool do_async);
 static void _mapped_blend_cpu(void *data, void *drawctx, RGBA_Image *in, 
RGBA_Image *out, Evas_Filter_Fill_Mode fillmode, int sx, int sy, int sw, int 
sh, int dx, int dy, int dw, int dh, image_draw_func image_draw);
 
+struct Alpha_Blend_Draw_Context
+{
+   int render_op;
+   DATA32 color;
+};
+
 static Eina_Bool
-_filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
+_image_draw_cpu_alpha2alpha(void *data EINA_UNUSED, void *context,
+                            void *surface, void *image,
+                            int src_x, int src_y, int src_w, int src_h,
+                            int dst_x, int dst_y, int dst_w, int dst_h,
+                            int smooth EINA_UNUSED,
+                            Eina_Bool do_async EINA_UNUSED)
 {
-   RGBA_Image *in, *out;
+   struct Alpha_Blend_Draw_Context *dc = context;
+   RGBA_Image *src = image;
+   RGBA_Image *dst = surface;
+   DATA8* srcdata = src->mask.data;
+   DATA8* dstdata = dst->mask.data;
    Alpha_Gfx_Func func;
-   DATA8 *maskdata, *dstdata;
-   int sw, sh, dw, dh, ox, oy, sx = 0, sy = 0, dx = 0, dy = 0, rows, cols, y;
+   int y, sw, dw;
 
-   /*
-    * NOTE: Alpha to alpha blending does not support stretching operations
-    * yet, because we don't have any scaling functions for alpha buffers.
-    * Also, I'm not going to implement it by converting to RGBA either.
-    */
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), 
EINA_FALSE);
+
+   func = evas_common_alpha_func_get(dc->render_op);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
+
+   sw = src->cache_entry.w;
+   dw = dst->cache_entry.w;
+
+   srcdata += src_y * sw;
+   dstdata += dst_y * dw;
+   for (y = src_h; y; y--)
+     {
+        func(srcdata + src_x, dstdata + dst_x, src_w);
+        srcdata += sw;
+        dstdata += dw;
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_image_draw_cpu_alpha2rgba(void *data EINA_UNUSED, void *context,
+                           void *surface, void *image,
+                           int src_x, int src_y, int src_w, int src_h,
+                           int dst_x, int dst_y, int dst_w, int dst_h,
+                           int smooth EINA_UNUSED,
+                           Eina_Bool do_async EINA_UNUSED)
+{
+   struct Alpha_Blend_Draw_Context *dc = context;
+   RGBA_Image *src = image;
+   RGBA_Image *dst = surface;
+   DATA8* srcdata = src->mask.data;
+   DATA32* dstdata = dst->image.data;
+   RGBA_Gfx_Func func;
+   int y, sw, dw;
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), 
EINA_FALSE);
+
+   func = evas_common_gfx_func_composite_mask_color_span_get
+     (dc->color, surface, 1, dc->render_op);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
 
-   // TODO: Call _mapped_blend_cpu to implement repeat fill mode.
-   if (cmd->draw.fillmode != EVAS_FILTER_FILL_MODE_NONE)
+   sw = src->cache_entry.w;
+   dw = dst->cache_entry.w;
+
+   srcdata += src_y * sw;
+   dstdata += dst_y * dw;
+   for (y = src_h; y; y--)
      {
-        ERR("Fill modes are not implemented for Alpha --> Alpha blending");
-        return EINA_FALSE;
+        func(NULL, srcdata + src_x, dc->color, dstdata + dst_x, src_w);
+        srcdata += sw;
+        dstdata += dw;
      }
 
-   func = evas_common_alpha_func_get(cmd->draw.render_op);
-   if (!func)
-     return EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_filter_blend_cpu_generic_do(Evas_Filter_Command *cmd,
+                             image_draw_func image_draw)
+{
+   RGBA_Image *in, *out;
+   int sw, sh, dx, dy, dw, dh, sx, sy;
+   struct Alpha_Blend_Draw_Context dc;
 
    in = cmd->input->backing;
    out = cmd->output->backing;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(in->mask.data, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(out->mask.data, EINA_FALSE);
+
+   sx = 0;
+   sy = 0;
    sw = in->cache_entry.w;
    sh = in->cache_entry.h;
+
+   dx = cmd->draw.ox;
+   dy = cmd->draw.oy;
    dw = out->cache_entry.w;
    dh = out->cache_entry.h;
-   ox = cmd->draw.ox;
-   oy = cmd->draw.oy;
-   maskdata = in->mask.data;
-   dstdata = out->mask.data;
 
-   if (!ox && !oy && (dw == sw) && (dh == sh))
+   if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
+     return EINA_TRUE;
+
+   // Stretch if necessary.
+
+   /* NOTE: As of 2014/02/21, this case is impossible. An alpha buffer will
+    * always be of the context buffer size, since only proxy buffers have
+    * different sizes... and proxies are all RGBA (never alpha only).
+    */
+
+   if ((sw != dw || sh != dh) && (cmd->draw.fillmode & 
EVAS_FILTER_FILL_MODE_STRETCH_XY))
      {
-        func(maskdata, dstdata, sw * sh);
-        return EINA_TRUE;
+        Evas_Filter_Buffer *fb;
+
+        if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
+          sw = dw;
+        if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
+          sh = dh;
+
+        BUFFERS_LOCK();
+        fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, sw, sh);
+        BUFFERS_UNLOCK();
+
+        EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
+        fb->locked = EINA_FALSE;
+        in = fb->backing;
      }
 
-   _clip_to_target(&sx, &sy, sw, sh, ox, oy, dw, dh, &dx, &dy, &rows, &cols);
+   dc.render_op = cmd->draw.render_op;
+   dc.color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
+   _mapped_blend_cpu(cmd->ENDT, &dc, in, out, cmd->draw.fillmode,
+                     sx, sy, sw, sh, dx, dy, dw, dh, image_draw);
 
-   if (cols <= 0 || rows <= 0)
-     return EINA_TRUE;
+   return EINA_TRUE;
+}
 
-   maskdata += sy * sw;
-   dstdata += dy * dw;
-   for (y = rows; y; y--)
+static Eina_Bool
+_image_draw_cpu_rgba2alpha(void *data EINA_UNUSED, void *context EINA_UNUSED,
+                           void *surface, void *image,
+                           int src_x, int src_y, int src_w, int src_h,
+                           int dst_x, int dst_y, int dst_w, int dst_h,
+                           int smooth EINA_UNUSED,
+                           Eina_Bool do_async EINA_UNUSED)
+{
+   RGBA_Image *src = image;
+   RGBA_Image *dst = surface;
+   DATA32* srcdata = src->image.data;
+   DATA8* dstdata = dst->mask.data;
+   int x, y, sw, dw;
+   DEFINE_DIVIDER(3);
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), 
EINA_FALSE);
+
+   sw = src->cache_entry.w;
+   dw = dst->cache_entry.w;
+
+   srcdata += src_y * sw;
+   dstdata += dst_y * dw;
+   for (y = src_h; y; y--)
      {
-        func(maskdata + sx, dstdata + dx, cols);
-        maskdata += sw;
+        DATA32 *s = srcdata + src_x;
+        DATA8 *d = dstdata + dst_x;
+        for (x = src_w; x; x--, d++, s++)
+          {
+             // TODO: Add weights like in YUV <--> RGB?
+             *d = DIVIDE(R_VAL(s) + G_VAL(s) + B_VAL(s));
+          }
+        srcdata += sw;
         dstdata += dw;
      }
 
@@ -84,6 +203,24 @@ _filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
 }
 
 static Eina_Bool
+_filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
+{
+   return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_alpha2alpha);
+}
+
+static Eina_Bool
+_filter_blend_cpu_mask_rgba(Evas_Filter_Command *cmd)
+{
+   return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_alpha2rgba);
+}
+
+static Eina_Bool
+_filter_blend_cpu_rgba2alpha(Evas_Filter_Command *cmd)
+{
+   return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_rgba2alpha);
+}
+
+static Eina_Bool
 _filter_blend_cpu_rgba(Evas_Filter_Command *cmd)
 {
    RGBA_Image *in, *out;
@@ -306,156 +443,6 @@ _mapped_blend_cpu(void *data, void *drawctx,
      }
 }
 
-static Eina_Bool
-_filter_blend_cpu_mask_rgba(Evas_Filter_Command *cmd)
-{
-   RGBA_Image *in, *out;
-   RGBA_Gfx_Func func;
-   DATA32 color;
-   DATA32 *dstdata;
-   DATA8 *maskdata;
-   int sw, sh, dw, dh, ox, oy, sx = 0, sy = 0, dx = 0, dy = 0, rows, cols, y;
-
-   // TODO: Call _mapped_blend_cpu to implement repeat fill mode.
-   // Also, alpha scaling is not implemented yet.
-   if (cmd->draw.fillmode != EVAS_FILTER_FILL_MODE_NONE)
-     {
-        ERR("Fill modes are not implemented for Alpha --> RGBA blending");
-        return EINA_FALSE;
-     }
-
-   in = cmd->input->backing;
-   out = cmd->output->backing;
-   sw = in->cache_entry.w;
-   sh = in->cache_entry.h;
-   dw = out->cache_entry.w;
-   dh = out->cache_entry.h;
-   ox = cmd->draw.ox;
-   oy = cmd->draw.oy;
-   dstdata = out->image.data;
-   maskdata = in->mask.data;
-   color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(dstdata, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(maskdata, EINA_FALSE);
-
-   func = evas_common_gfx_func_composite_mask_color_span_get
-     (color, out, 1, cmd->draw.render_op);
-
-   if (!func)
-     return EINA_FALSE;
-
-   if (!ox && !oy && (dw == sw) && (dh == sh))
-     {
-        func(NULL, maskdata, color, dstdata, sw * sh);
-        return EINA_TRUE;
-     }
-
-   _clip_to_target(&sx, &sy, sw, sh, ox, oy, dw, dh, &dx, &dy, &rows, &cols);
-
-   if (cols <= 0 || rows <= 0)
-     return EINA_TRUE;
-
-   maskdata += sy * sw;
-   dstdata += dy * dw;
-   for (y = rows; y; y--)
-     {
-        func(NULL, maskdata + sx, color, dstdata + dx, cols);
-        maskdata += sw;
-        dstdata += dw;
-     }
-
-   return EINA_TRUE;
-}
-
-static Eina_Bool
-_image_draw_cpu_rgba2alpha(void *data EINA_UNUSED, void *context EINA_UNUSED,
-                           void *surface, void *image,
-                           int src_x, int src_y, int src_w, int src_h,
-                           int dst_x, int dst_y, int dst_w, int dst_h,
-                           int smooth EINA_UNUSED,
-                           Eina_Bool do_async EINA_UNUSED)
-{
-   RGBA_Image *src = image;
-   RGBA_Image *dst = surface;
-   DATA32* srcdata = src->image.data;
-   DATA8* dstdata = dst->mask.data;
-   int x, y, sw, dw;
-   DEFINE_DIVIDER(3);
-
-   EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), 
EINA_FALSE);
-
-   sw = src->cache_entry.w;
-   dw = dst->cache_entry.w;
-
-   srcdata += src_y * sw;
-   dstdata += dst_y * dw;
-   for (y = src_h; y; y--)
-     {
-        DATA32 *s = srcdata + src_x;
-        DATA8 *d = dstdata + dst_x;
-        for (x = src_w; x; x--, d++, s++)
-          {
-             // TODO: Add weights like in YUV <--> RGB?
-             *d = DIVIDE(R_VAL(s) + G_VAL(s) + B_VAL(s));
-          }
-        srcdata += sw;
-        dstdata += dw;
-     }
-
-   return EINA_TRUE;
-}
-
-static Eina_Bool
-_filter_blend_cpu_rgba2alpha(Evas_Filter_Command *cmd)
-{
-   RGBA_Image *in, *out;
-   int sw, sh, dx, dy, dw, dh, sx, sy;
-
-   in = cmd->input->backing;
-   out = cmd->output->backing;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
-
-   sx = 0;
-   sy = 0;
-   sw = in->cache_entry.w;
-   sh = in->cache_entry.h;
-
-   dw = out->cache_entry.w;
-   dh = out->cache_entry.h;
-   dx = cmd->draw.ox;
-   dy = cmd->draw.oy;
-
-   if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
-     return EINA_TRUE;
-
-   // Stretch if necessary.
-   if ((sw != dw || sh != dh) && (cmd->draw.fillmode & 
EVAS_FILTER_FILL_MODE_STRETCH_XY))
-     {
-        Evas_Filter_Buffer *fb;
-
-        if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
-          sw = dw;
-        if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
-          sh = dh;
-
-        BUFFERS_LOCK();
-        fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, sw, sh);
-        BUFFERS_UNLOCK();
-
-        EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
-        fb->locked = EINA_FALSE;
-        in = fb->backing;
-     }
-
-   _mapped_blend_cpu(cmd->ENDT, NULL, in, out, cmd->draw.fillmode,
-                     sx, sy, sw, sh, dx, dy, dw, dh,
-                     _image_draw_cpu_rgba2alpha);
-
-   return EINA_TRUE;
-}
-
 Evas_Filter_Apply_Func
 evas_filter_blend_cpu_func_get(Evas_Filter_Command *cmd)
 {

-- 


Reply via email to