jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=293438111c9a7cdb711f19411a4c5343ed04f0ca

commit 293438111c9a7cdb711f19411a4c5343ed04f0ca
Author: Jean-Philippe Andre <[email protected]>
Date:   Mon Apr 3 15:34:10 2017 +0900

    evas filters: Avoid creating input buffer for images
    
    When the filtered object is an image, without borders, map,
    fill info or anything of this sort, then the filter input
    buffer is really just a copy of the original image. We can
    skip that to save on memory usage and pixel fetches.
---
 src/lib/evas/canvas/evas_object_image.c | 43 +++++++++++++++++++++++++++++++++
 src/lib/evas/filters/evas_filter.c      | 38 ++++++++++++++++++++++++++---
 src/lib/evas/include/evas_filter.h      |  1 +
 3 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index 94feded..0205ed6 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -1719,6 +1719,35 @@ 
_efl_canvas_image_internal_efl_canvas_filter_internal_filter_state_prepare(
    state->scale = obj->cur->scale;
 }
 
+static inline Eina_Bool
+_image_has_border(Evas_Object_Protected_Data *obj EINA_UNUSED, Evas_Image_Data 
*o)
+{
+   return o->cur->border.l || o->cur->border.r || o->cur->border.t ||
+         o->cur->border.b || (o->cur->border.fill == 0);
+}
+
+static inline Eina_Bool
+_image_has_map(Evas_Object_Protected_Data *obj, Evas_Image_Data *o EINA_UNUSED)
+{
+   return ((obj->map->cur.map) && (obj->map->cur.map->count > 3) && 
(obj->map->cur.usemap));
+}
+
+static inline Eina_Bool
+_image_is_filled(Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
+{
+   if (o->filled) return EINA_TRUE;
+   return !o->cur->fill.x && !o->cur->fill.y &&
+         (o->cur->fill.w == obj->cur->geometry.w) &&
+         (o->cur->fill.h == obj->cur->geometry.h);
+}
+
+static inline Eina_Bool
+_image_is_scaled(Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
+{
+   return ((obj->cur->geometry.w != o->cur->image.w) ||
+           (obj->cur->geometry.h != o->cur->image.h));
+}
+
 EOLIAN static Eina_Bool
 _efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_render(
       Eo *eo_obj, Evas_Image_Data *o, void *_filter, void *context EINA_UNUSED,
@@ -1728,12 +1757,26 @@ 
_efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_render(
    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, 
EFL_CANVAS_OBJECT_CLASS);
    Evas_Filter_Context *filter = _filter;
    void *surface, *output, *ctx;
+   Eina_Bool ok;
    int W, H;
 
    W = obj->cur->geometry.w;
    H = obj->cur->geometry.h;
    output = ENDT;
 
+   // FIXME: In GL we could use the image even if scaled
+   if (!_image_has_border(obj, o) && !_image_has_map(obj, o) && 
_image_is_filled(obj, o)
+       && !_image_is_scaled(obj, o))
+     {
+        int imagew, imageh, uvw, uvh;
+
+        surface = _evas_image_pixels_get(eo_obj, obj, output, NULL, NULL, x, y,
+                                         &imagew, &imageh, &uvw, &uvh, 
EINA_FALSE, EINA_FALSE);
+
+        ok = evas_filter_buffer_backing_set(filter, 
EVAS_FILTER_BUFFER_INPUT_ID, surface);
+        if (ok) return EINA_TRUE;
+     }
+
    surface = evas_filter_buffer_backing_get(filter, 
EVAS_FILTER_BUFFER_INPUT_ID, EINA_TRUE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
 
diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index f08926e..270c79f 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -365,8 +365,11 @@ 
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
              continue;
           }
 
-        render |= (fb->id == EVAS_FILTER_BUFFER_INPUT_ID);
-        render |= fb->is_render || fb->transient;
+        // Skip input buffer, allocate it in input render phase
+        if (fb->id == EVAS_FILTER_BUFFER_INPUT_ID)
+          continue;
+
+        render = fb->is_render || fb->transient;
         draw |= (fb->id == EVAS_FILTER_BUFFER_OUTPUT_ID);
 
         fb->buffer = _ector_buffer_create(fb, render, draw);
@@ -510,6 +513,9 @@ evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, 
int bufid, Eina_Bool re
    fb = _filter_buffer_get(ctx, bufid);
    if (!fb) return NULL;
 
+   if (!fb->buffer)
+     evas_filter_buffer_backing_set(ctx, bufid, NULL);
+
    if (render)
      return evas_ector_buffer_render_image_get(fb->buffer); // ref++
    else
@@ -517,6 +523,32 @@ evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, 
int bufid, Eina_Bool re
 }
 
 Eina_Bool
+evas_filter_buffer_backing_set(Evas_Filter_Context *ctx, int bufid,
+                               void *engine_buffer)
+{
+   Evas_Filter_Buffer *fb;
+
+   fb = _filter_buffer_get(ctx, bufid);
+   if (!fb) return EINA_FALSE;
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(!fb->buffer, EINA_FALSE);
+
+   if (!engine_buffer)
+     {
+        fb->buffer = _ector_buffer_create(fb, fb->is_render, EINA_FALSE);
+        XDBG("Allocated buffer #%d of size %ux%u %s: %p",
+             fb->id, fb->w, fb->h, fb->alpha_only ? "alpha" : "rgba", 
fb->buffer);
+        return fb->buffer ? EINA_TRUE : EINA_FALSE;
+     }
+
+   if (fb->buffer) return EINA_FALSE;
+   if (fb->is_render) return EINA_FALSE;
+
+   fb->buffer = ENFN->ector_buffer_wrap(ENDT, ctx->evas->evas, engine_buffer);
+   return EINA_TRUE;
+}
+
+Eina_Bool
 evas_filter_buffer_backing_release(Evas_Filter_Context *ctx,
                                    void *stolen_buffer)
 {
@@ -1558,7 +1590,7 @@ evas_filter_font_draw(Evas_Filter_Context *ctx, void 
*draw_context, int bufid,
    fb = _filter_buffer_get(ctx, bufid);
    EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
 
-   surface = evas_ector_buffer_render_image_get(fb->buffer);
+   surface = evas_filter_buffer_backing_get(ctx, bufid, EINA_TRUE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
 
    // Copied from evas_font_draw_async_check
diff --git a/src/lib/evas/include/evas_filter.h 
b/src/lib/evas/include/evas_filter.h
index edb12cd..3c20aa0 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.h
@@ -158,6 +158,7 @@ void                     
evas_filter_context_obscured_region_set(Evas_Filter_Con
 int                      evas_filter_buffer_empty_new(Evas_Filter_Context 
*ctx, int w, int h, Eina_Bool alpha_only);
 int                      evas_filter_buffer_proxy_new(Evas_Filter_Context 
*ctx, Evas_Filter_Proxy_Binding *pb, int *w, int *h);
 void                    *evas_filter_buffer_backing_get(Evas_Filter_Context 
*ctx, int bufid, Eina_Bool render);
+Eina_Bool                evas_filter_buffer_backing_set(Evas_Filter_Context 
*ctx, int bufid, void *engine_buffer);
 Eina_Bool                
evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void 
*stolen_buffer);
 
 Eina_Bool                evas_filter_context_run(Evas_Filter_Context *ctx);

-- 


Reply via email to