forked from enlightenment/efl
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.
This commit is contained in:
parent
45548e8358
commit
293438111c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,12 +513,41 @@ 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
|
||||
return evas_ector_buffer_drawable_image_get(fb->buffer); // ref++
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue