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