forked from enlightenment/efl
evas filters: Refactor to support reuse of buffers
This will reuse existing buffers by resetting only the minimum required in the filter context (also reused). Work in progress, as the actual reuse is disabled for now.
This commit is contained in:
parent
7407a0d073
commit
1bf24f8762
|
@ -111,7 +111,6 @@ test_evas_snapshot(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *e
|
|||
efl_pack_grid(grid, efl_added, 1, 1, GRID_SIZE - 2, GRID_SIZE - 2),
|
||||
efl_gfx_visible_set(efl_added, 1));
|
||||
|
||||
|
||||
// Objects above snapshot
|
||||
// 1. Opaque rect, not changing
|
||||
o = evas_object_rectangle_add(win);
|
||||
|
|
|
@ -43,6 +43,8 @@ _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
|
|||
Evas_Filter_Data *pd, Eina_Bool success)
|
||||
{
|
||||
void *previous = pd->data->output;
|
||||
Eina_Bool destroy = !pd->data->reuse;
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
Eo *eo_obj = obj->object;
|
||||
|
||||
if (!success)
|
||||
|
@ -50,10 +52,10 @@ _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
|
|||
ERR("Filter failed at runtime!");
|
||||
evas_filter_invalid_set(eo_obj, EINA_TRUE);
|
||||
evas_filter_dirty(eo_obj);
|
||||
destroy = EINA_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
void *output = evas_filter_buffer_backing_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID, EINA_FALSE);
|
||||
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
|
@ -61,9 +63,29 @@ _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
|
|||
FCOW_END(fcow, pd);
|
||||
}
|
||||
|
||||
// Destroy context as we won't reuse it.
|
||||
evas_filter_buffer_backing_release(ctx, previous);
|
||||
evas_filter_context_destroy(ctx);
|
||||
if (EINA_UNLIKELY(ctx != pd->data->context))
|
||||
{
|
||||
ERR("Filter context has changed! Destroying it now...");
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
evas_filter_context_destroy(fcow->context);
|
||||
fcow->context = NULL;
|
||||
FCOW_END(fcow, pd);
|
||||
destroy = EINA_TRUE;
|
||||
}
|
||||
|
||||
if (destroy)
|
||||
{
|
||||
evas_filter_buffer_backing_release(ctx, previous);
|
||||
evas_filter_context_destroy(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
if (pd->data->context != ctx)
|
||||
{
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->context = ctx;
|
||||
FCOW_END(fcow, pd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -192,13 +214,6 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
Evas_Object_Filter_Data *fcow;
|
||||
Evas_Filter_Padding pad;
|
||||
|
||||
/* NOTE: Filter rendering is now done ENTIRELY on CPU.
|
||||
* So we rely on cache/cache2 to allocate a real image buffer,
|
||||
* that we can draw to. The OpenGL texture will be created only
|
||||
* after the rendering has been done, as we simply push the output
|
||||
* image to GL.
|
||||
*/
|
||||
|
||||
W = obj->cur->geometry.w;
|
||||
H = obj->cur->geometry.h;
|
||||
X = obj->cur->geometry.x;
|
||||
|
@ -217,7 +232,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
obj->cur->clipper->cur->cache.clip.b,
|
||||
obj->cur->clipper->cur->cache.clip.a);
|
||||
else
|
||||
ENFN->context_multiplier_unset(output, context);
|
||||
ENFN->context_multiplier_unset(output, context);
|
||||
|
||||
if (!pd->data->chain)
|
||||
{
|
||||
|
@ -295,22 +310,57 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
_evas_filter_state_set_internal(pd->data->chain, pd);
|
||||
}
|
||||
|
||||
filter = evas_filter_context_new(obj->layer->evas, do_async, 0);
|
||||
|
||||
// Run script
|
||||
ok = evas_filter_context_program_use(filter, pd->data->chain);
|
||||
if (!filter || !ok)
|
||||
filter = pd->data->context;
|
||||
if (filter)
|
||||
{
|
||||
ERR("Parsing failed?");
|
||||
evas_filter_context_destroy(filter);
|
||||
int prev_w, prev_h;
|
||||
Eina_Bool was_async;
|
||||
|
||||
if (!pd->data->invalid)
|
||||
was_async = evas_filter_context_async_get(filter);
|
||||
evas_filter_context_size_get(filter, &prev_w, &prev_h);
|
||||
if ((!pd->data->reuse) || (was_async != do_async) ||
|
||||
(prev_w != W) || (prev_h != H))
|
||||
{
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->invalid = EINA_TRUE;
|
||||
fcow->context = NULL;
|
||||
FCOW_END(fcow, pd);
|
||||
evas_filter_context_destroy(filter);
|
||||
filter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter)
|
||||
{
|
||||
ok = evas_filter_context_program_reuse(filter, pd->data->chain);
|
||||
if (!ok)
|
||||
{
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->context = NULL;
|
||||
FCOW_END(fcow, pd);
|
||||
evas_filter_context_destroy(filter);
|
||||
filter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!filter)
|
||||
{
|
||||
filter = evas_filter_context_new(obj->layer->evas, do_async, 0);
|
||||
|
||||
// Run script
|
||||
ok = evas_filter_context_program_use(filter, pd->data->chain, EINA_FALSE);
|
||||
if (!filter || !ok)
|
||||
{
|
||||
ERR("Parsing failed?");
|
||||
evas_filter_context_destroy(filter);
|
||||
|
||||
if (!pd->data->invalid)
|
||||
{
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->invalid = EINA_TRUE;
|
||||
FCOW_END(fcow, pd);
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
// Proxies
|
||||
|
@ -336,15 +386,17 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
|
||||
// Add post-run callback and run filter
|
||||
evas_filter_context_post_run_callback_set(filter, _filter_cb, pd);
|
||||
ok = evas_filter_run(filter);
|
||||
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->context = filter;
|
||||
fcow->changed = EINA_FALSE;
|
||||
fcow->async = do_async;
|
||||
fcow->prev_obscured = fcow->obscured;
|
||||
fcow->invalid = !ok;
|
||||
fcow->invalid = EINA_FALSE;
|
||||
FCOW_END(fcow, pd);
|
||||
|
||||
ok = evas_filter_context_run(filter);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
DBG("Effect rendering done.");
|
||||
|
@ -352,6 +404,9 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
}
|
||||
else
|
||||
{
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->invalid = EINA_TRUE;
|
||||
FCOW_END(fcow, pd);
|
||||
ERR("Rendering failed.");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
@ -377,6 +432,9 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_F
|
|||
{
|
||||
fcow->obj = obj;
|
||||
|
||||
if (fcow->context)
|
||||
evas_filter_context_destroy(fcow->context);
|
||||
|
||||
// Parse filter program
|
||||
evas_filter_program_del(fcow->chain);
|
||||
eina_stringshare_replace(&fcow->name, name);
|
||||
|
@ -613,6 +671,9 @@ _efl_canvas_filter_internal_efl_object_destructor(Eo *eo_obj, Evas_Filter_Data *
|
|||
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
e = obj->layer->evas;
|
||||
|
||||
if (pd->data->context)
|
||||
evas_filter_context_destroy(pd->data->context);
|
||||
|
||||
if (pd->data->output)
|
||||
{
|
||||
if (!pd->data->async)
|
||||
|
|
|
@ -33,7 +33,7 @@ static const Evas_Object_Protected_State default_state = {
|
|||
1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE
|
||||
};
|
||||
static const Evas_Object_Filter_Data default_filter = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, {}, {}, NULL, {}, EINA_FALSE, EINA_FALSE, EINA_TRUE
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, {}, {}, NULL, {}, EINA_FALSE, EINA_FALSE, EINA_TRUE, EINA_TRUE
|
||||
};
|
||||
const void * const evas_object_filter_cow_default = &default_filter;
|
||||
static const Evas_Object_Mask_Data default_mask = {
|
||||
|
|
|
@ -13476,7 +13476,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
ctx = evas_filter_context_new(obj->layer->evas, do_async, ti->gfx_filter);
|
||||
evas_filter_state_prepare(eo_obj, &state, ti);
|
||||
evas_filter_program_state_set(pgm, &state);
|
||||
ok = evas_filter_context_program_use(ctx, pgm);
|
||||
ok = evas_filter_context_program_use(ctx, pgm, EINA_FALSE);
|
||||
if (!ok)
|
||||
{
|
||||
evas_filter_context_destroy(ctx);
|
||||
|
@ -13790,7 +13790,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
else if (ctx)
|
||||
{
|
||||
evas_filter_context_post_run_callback_set(ctx, _filter_cb, obj->layer->evas);
|
||||
evas_filter_run(ctx);
|
||||
evas_filter_context_run(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
static void _buffer_free(Evas_Filter_Buffer *fb);
|
||||
static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
|
||||
static Evas_Filter_Buffer *_buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only, Eina_Bool render, Eina_Bool draw);
|
||||
static void _filter_buffer_unlock_all(Evas_Filter_Context *ctx);
|
||||
|
||||
#define DRAW_COLOR_SET(r, g, b, a) do { cmd->draw.R = r; cmd->draw.G = g; cmd->draw.B = b; cmd->draw.A = a; } while (0)
|
||||
#define DRAW_CLIP_SET(_x, _y, _w, _h) do { cmd->draw.clip.x = _x; cmd->draw.clip.y = _y; cmd->draw.clip.w = _w; cmd->draw.clip.h = _h; } while (0)
|
||||
|
@ -72,25 +73,38 @@ evas_filter_context_async_get(Evas_Filter_Context *ctx)
|
|||
return ctx->async;
|
||||
}
|
||||
|
||||
void
|
||||
evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *h)
|
||||
{
|
||||
if (w) *w = ctx->w;
|
||||
if (h) *h = ctx->h;
|
||||
}
|
||||
|
||||
/* Private function to reset the filter context. Used from parser.c */
|
||||
void
|
||||
evas_filter_context_clear(Evas_Filter_Context *ctx)
|
||||
evas_filter_context_clear(Evas_Filter_Context *ctx, Eina_Bool keep_buffers)
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
Evas_Filter_Command *cmd;
|
||||
Evas_Filter_Buffer *fb;
|
||||
|
||||
if (!ctx) return;
|
||||
|
||||
EINA_LIST_FREE(ctx->buffers, fb)
|
||||
_buffer_free(fb);
|
||||
if (ctx->target.surface) ENFN->image_free(ENDT, ctx->target.surface);
|
||||
if (ctx->target.mask) ENFN->image_free(ENDT, ctx->target.mask);
|
||||
ctx->target.surface = NULL;
|
||||
ctx->target.mask = NULL;
|
||||
|
||||
if (!keep_buffers)
|
||||
{
|
||||
ctx->last_buffer_id = 0;
|
||||
EINA_LIST_FREE(ctx->buffers, fb)
|
||||
_buffer_free(fb);
|
||||
}
|
||||
|
||||
ctx->last_command_id = 0;
|
||||
EINA_INLIST_FREE(ctx->commands, cmd)
|
||||
_command_del(ctx, cmd);
|
||||
|
||||
ctx->buffers = NULL;
|
||||
ctx->commands = NULL;
|
||||
ctx->last_buffer_id = 0;
|
||||
ctx->last_command_id = 0;
|
||||
|
||||
// Note: don't reset post_run, as it it set by the client
|
||||
}
|
||||
|
||||
|
@ -109,6 +123,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
|
|||
{
|
||||
Evas_Object_Protected_Data *source;
|
||||
Evas_Object_Protected_Data *obj;
|
||||
void *proxy_surface;
|
||||
Evas_Filter_Buffer *fb;
|
||||
Eina_List *li;
|
||||
|
||||
|
@ -122,6 +137,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
|
|||
source = efl_data_scope_get(fb->source, EFL_CANVAS_OBJECT_CLASS);
|
||||
_assert(fb->w == source->cur->geometry.w);
|
||||
_assert(fb->h == source->cur->geometry.h);
|
||||
proxy_surface = source->proxy->surface;
|
||||
if (source->proxy->surface && !source->proxy->redraw)
|
||||
{
|
||||
XDBG("Source already rendered: '%s' of type '%s'",
|
||||
|
@ -134,30 +150,72 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
|
|||
source->proxy->redraw ? "redraw" : "no surface");
|
||||
evas_render_proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, EINA_FALSE, do_async);
|
||||
}
|
||||
_filter_buffer_backing_free(fb);
|
||||
if (fb->buffer)
|
||||
{
|
||||
void *old_surface;
|
||||
|
||||
old_surface = evas_ector_buffer_drawable_image_get(fb->buffer);
|
||||
if (old_surface && (old_surface != proxy_surface))
|
||||
_filter_buffer_backing_free(fb);
|
||||
}
|
||||
XDBG("Source #%d '%s' has dimensions %dx%d", fb->id, fb->source_name, fb->w, fb->h);
|
||||
fb->buffer = ENFN->ector_buffer_wrap(ENDT, obj->layer->evas->evas, source->proxy->surface);
|
||||
if (!fb->buffer) fb->buffer = ENFN->ector_buffer_wrap(ENDT, obj->layer->evas->evas, source->proxy->surface);
|
||||
fb->alpha_only = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm)
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
Eina_List *li;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
|
||||
|
||||
_filter_buffer_unlock_all(ctx);
|
||||
|
||||
EINA_LIST_FOREACH(ctx->buffers, li, fb)
|
||||
{
|
||||
void *dc, *surface;
|
||||
|
||||
fb->used = EINA_FALSE;
|
||||
fb->locked = EINA_FALSE;
|
||||
|
||||
if (!fb->is_render) continue;
|
||||
if (fb->source) continue;
|
||||
|
||||
surface = evas_ector_buffer_render_image_get(fb->buffer);
|
||||
if (!surface) continue;
|
||||
|
||||
dc = ENFN->context_new(ENDT);
|
||||
ENFN->context_color_set(ENDT, dc, 0, 0, 0, 0);
|
||||
ENFN->context_render_op_set(ENDT, dc, EVAS_RENDER_COPY);
|
||||
ENFN->rectangle_draw(ENDT, dc, surface, 0, 0, fb->w, fb->h, ctx->async);
|
||||
ENFN->context_free(ENDT, dc);
|
||||
fb->dirty = EINA_FALSE;
|
||||
}
|
||||
|
||||
return evas_filter_context_program_use(ctx, pgm, EINA_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_context_destroy(void *data)
|
||||
{
|
||||
Evas_Filter_Context *ctx = data;
|
||||
|
||||
evas_filter_context_clear(ctx, EINA_FALSE);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
evas_filter_context_destroy(Evas_Filter_Context *ctx)
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
Evas_Filter_Command *cmd;
|
||||
|
||||
if (!ctx) return;
|
||||
|
||||
EINA_LIST_FREE(ctx->buffers, fb)
|
||||
_buffer_free(fb);
|
||||
EINA_INLIST_FREE(ctx->commands, cmd)
|
||||
_command_del(ctx, cmd);
|
||||
|
||||
if (ctx->target.mask)
|
||||
ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask);
|
||||
|
||||
free(ctx);
|
||||
// FIXME: This is not locked...
|
||||
if (ctx->running)
|
||||
evas_post_render_job_add(ctx->evas, _context_destroy, ctx);
|
||||
else
|
||||
_context_destroy(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -213,6 +271,8 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
|
|||
Eina_List *li;
|
||||
unsigned w, h;
|
||||
|
||||
if (ctx->run_count > 0) return EINA_TRUE;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
||||
w = ctx->w;
|
||||
h = ctx->h;
|
||||
|
@ -231,6 +291,7 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
|
|||
in->h = h;
|
||||
}
|
||||
|
||||
// FIXME: No need for stretch buffers with GL!
|
||||
if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)
|
||||
{
|
||||
unsigned sw = w, sh = h;
|
||||
|
@ -322,15 +383,69 @@ alloc_fail:
|
|||
}
|
||||
|
||||
int
|
||||
evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only)
|
||||
evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only)
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
Eina_List *li;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
|
||||
|
||||
fb = _buffer_empty_new(ctx, 0, 0, alpha_only, EINA_FALSE);
|
||||
EINA_LIST_FOREACH(ctx->buffers, li, fb)
|
||||
{
|
||||
if ((fb->alpha_only == alpha_only) &&
|
||||
(fb->w == w) && (fb->h == h) && !fb->dirty && !fb->used)
|
||||
{
|
||||
fb->used = EINA_TRUE;
|
||||
return fb->id;
|
||||
}
|
||||
}
|
||||
|
||||
fb = _buffer_empty_new(ctx, w, h, alpha_only, EINA_FALSE);
|
||||
if (!fb) return -1;
|
||||
|
||||
fb->used = EINA_TRUE;
|
||||
return fb->id;
|
||||
}
|
||||
|
||||
int
|
||||
evas_filter_buffer_proxy_new(Evas_Filter_Context *ctx, Evas_Filter_Proxy_Binding *pb,
|
||||
int *w, int *h)
|
||||
{
|
||||
Evas_Object_Protected_Data *source;
|
||||
Evas_Filter_Buffer *fb;
|
||||
Eina_List *li;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pb, -1);
|
||||
|
||||
source = efl_data_scope_get(pb->eo_source, EFL_CANVAS_OBJECT_CLASS);
|
||||
if (!source) return -1;
|
||||
|
||||
// FIXME: This is not true if the source is an evas image
|
||||
*w = source->cur->geometry.w;
|
||||
*h = source->cur->geometry.h;
|
||||
|
||||
EINA_LIST_FOREACH(ctx->buffers, li, fb)
|
||||
{
|
||||
if (pb->eo_source == fb->source)
|
||||
{
|
||||
if (fb->used) return -1;
|
||||
if (fb->alpha_only) return -1;
|
||||
if (!eina_streq(pb->name, fb->source_name)) return -1;
|
||||
if ((*w != fb->w) || (*h != fb->h)) return -1;
|
||||
|
||||
fb->used = EINA_TRUE;
|
||||
return fb->id;
|
||||
}
|
||||
}
|
||||
|
||||
fb = _buffer_empty_new(ctx, *w, *h, EINA_FALSE, EINA_FALSE);
|
||||
if (!fb) return -1;
|
||||
|
||||
fb->source = efl_ref(pb->eo_source);
|
||||
fb->source_name = eina_stringshare_add(pb->name);
|
||||
|
||||
fb->used = EINA_TRUE;
|
||||
return fb->id;
|
||||
}
|
||||
|
||||
|
@ -351,6 +466,7 @@ _buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only,
|
|||
fb->w = w;
|
||||
fb->h = h;
|
||||
fb->alpha_only = alpha_only;
|
||||
fb->is_render = render;
|
||||
fb->buffer = _ector_buffer_create(fb, render, draw);
|
||||
if (!fb->buffer)
|
||||
{
|
||||
|
@ -367,6 +483,8 @@ static void
|
|||
_buffer_free(Evas_Filter_Buffer *fb)
|
||||
{
|
||||
_filter_buffer_backing_free(fb);
|
||||
eina_stringshare_del(fb->source_name);
|
||||
efl_unref(fb->source);
|
||||
free(fb);
|
||||
}
|
||||
|
||||
|
@ -434,6 +552,7 @@ _command_new(Evas_Filter_Context *ctx, Evas_Filter_Mode mode,
|
|||
if (output)
|
||||
{
|
||||
cmd->draw.output_was_dirty = output->dirty;
|
||||
output->is_render = EINA_TRUE;
|
||||
output->dirty = EINA_TRUE;
|
||||
}
|
||||
|
||||
|
@ -482,6 +601,7 @@ evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h,
|
|||
|
||||
fb = _buffer_empty_new(ctx, w, h, alpha_only, EINA_TRUE);
|
||||
fb->locked = EINA_TRUE;
|
||||
fb->is_render = EINA_TRUE;
|
||||
XDBG("Created temporary buffer %d %s", fb->id, alpha_only ? "alpha" : "rgba");
|
||||
|
||||
return fb;
|
||||
|
@ -1564,7 +1684,6 @@ _filter_chain_run(Evas_Filter_Context *ctx)
|
|||
|
||||
DEBUG_TIME_BEGIN();
|
||||
|
||||
ctx->running = EINA_TRUE;
|
||||
EINA_INLIST_FOREACH(ctx->commands, cmd)
|
||||
{
|
||||
ok = _filter_command_run(cmd);
|
||||
|
@ -1646,7 +1765,7 @@ _filter_obscured_region_calc(Evas_Filter_Context *ctx)
|
|||
}
|
||||
|
||||
Eina_Bool
|
||||
evas_filter_run(Evas_Filter_Context *ctx)
|
||||
evas_filter_context_run(Evas_Filter_Context *ctx)
|
||||
{
|
||||
Eina_Bool ret;
|
||||
|
||||
|
@ -1657,12 +1776,14 @@ evas_filter_run(Evas_Filter_Context *ctx)
|
|||
|
||||
_filter_obscured_region_calc(ctx);
|
||||
|
||||
ctx->running = EINA_TRUE;
|
||||
if (ctx->async)
|
||||
{
|
||||
evas_thread_queue_flush(_filter_thread_run_cb, ctx);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
ctx->run_count++;
|
||||
ret = _filter_chain_run(ctx);
|
||||
|
||||
if (ctx->post_run.cb)
|
||||
|
|
|
@ -2834,48 +2834,49 @@ evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
|
|||
|
||||
/** Run a program, must be already loaded */
|
||||
|
||||
static void
|
||||
static Eina_Bool
|
||||
_buffers_update(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm)
|
||||
{
|
||||
Evas_Object_Protected_Data *source;
|
||||
Evas_Filter_Proxy_Binding *pb;
|
||||
Evas_Filter_Buffer *fb;
|
||||
Buffer *buf;
|
||||
int w, h, id;
|
||||
|
||||
EINA_INLIST_FOREACH(pgm->buffers, buf)
|
||||
{
|
||||
if (buf->proxy)
|
||||
{
|
||||
pb = eina_hash_find(pgm->proxies, buf->proxy);
|
||||
if (!pb) continue;
|
||||
if (!pb) return EINA_FALSE;
|
||||
|
||||
buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha);
|
||||
fb = _filter_buffer_get(ctx, buf->cid);
|
||||
fb->source = pb->eo_source;
|
||||
fb->source_name = eina_stringshare_ref(pb->name);
|
||||
fb->ctx->has_proxies = EINA_TRUE;
|
||||
ctx->has_proxies = EINA_TRUE;
|
||||
id = evas_filter_buffer_proxy_new(ctx, pb, &w, &h);
|
||||
if (id < 0) return EINA_FALSE;
|
||||
|
||||
source = efl_data_scope_get(fb->source, EFL_CANVAS_OBJECT_CLASS);
|
||||
if ((source->cur->geometry.w != buf->w) ||
|
||||
(source->cur->geometry.h != buf->h))
|
||||
pgm->changed = EINA_TRUE;
|
||||
buf->w = fb->w = source->cur->geometry.w;
|
||||
buf->h = fb->h = source->cur->geometry.h;
|
||||
XDBG("Created proxy buffer %d %s '%s'", fb->id,
|
||||
buf->alpha ? "alpha" : "rgba", buf->name);
|
||||
buf->cid = id;
|
||||
buf->w = w;
|
||||
buf->h = h;
|
||||
|
||||
XDBG("Created proxy buffer #%d %dx%d %s '%s'", buf->cid,
|
||||
w, h, buf->alpha ? "alpha" : "rgba", buf->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((buf->w != pgm->state.w) || (buf->h != pgm->state.h))
|
||||
pgm->changed = EINA_TRUE;
|
||||
buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha);
|
||||
fb = _filter_buffer_get(ctx, buf->cid);
|
||||
fb->w = buf->w = pgm->state.w;
|
||||
fb->h = buf->h = pgm->state.h;
|
||||
XDBG("Created context buffer %d %s '%s'", fb->id,
|
||||
buf->alpha ? "alpha" : "rgba", buf->name);
|
||||
w = pgm->state.w;
|
||||
h = pgm->state.h;
|
||||
|
||||
id = evas_filter_buffer_empty_new(ctx, w, h, buf->alpha);
|
||||
if (id < 0) return EINA_FALSE;
|
||||
|
||||
buf->cid = id;
|
||||
buf->w = w;
|
||||
buf->h = h;
|
||||
|
||||
XDBG("Created context buffer #%d %dx%d %s '%s'", buf->cid,
|
||||
w, h, buf->alpha ? "alpha" : "rgba", buf->name);
|
||||
}
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
/** Evaluate required padding to correctly apply an effect */
|
||||
|
@ -3401,11 +3402,8 @@ _command_from_instruction(Evas_Filter_Context *ctx,
|
|||
cmd = instr2cmd(ctx, instr, dc);
|
||||
if (!cmd) return EINA_FALSE;
|
||||
|
||||
if (cmd->output && ctx->gl)
|
||||
{
|
||||
if (ENFN->gfx_filter_supports(ENDT, cmd) == EVAS_FILTER_SUPPORT_GL)
|
||||
cmd->output->is_render = EINA_TRUE;
|
||||
}
|
||||
if (cmd->output)
|
||||
cmd->output->is_render = EINA_TRUE;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
@ -3475,7 +3473,8 @@ _instruction_dump(Evas_Filter_Instruction *instr)
|
|||
|
||||
Eina_Bool
|
||||
evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
||||
Evas_Filter_Program *pgm)
|
||||
Evas_Filter_Program *pgm,
|
||||
Eina_Bool reuse)
|
||||
{
|
||||
Evas_Filter_Instruction *instr;
|
||||
Eina_Bool success = EINA_FALSE;
|
||||
|
@ -3492,7 +3491,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
|||
ctx->h = pgm->state.h;
|
||||
|
||||
// Create empty context with all required buffers
|
||||
evas_filter_context_clear(ctx);
|
||||
evas_filter_context_clear(ctx, reuse);
|
||||
|
||||
if (pgm->changed)
|
||||
{
|
||||
|
@ -3508,7 +3507,9 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
|||
goto end;
|
||||
}
|
||||
}
|
||||
_buffers_update(ctx, pgm);
|
||||
|
||||
// Create or update all buffers
|
||||
if (!_buffers_update(ctx, pgm)) goto end;
|
||||
|
||||
// Compute and save padding info
|
||||
evas_filter_program_padding_get(pgm, &ctx->pad.final, &ctx->pad.calculated);
|
||||
|
@ -3528,7 +3529,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
|||
pgm->changed = EINA_FALSE;
|
||||
|
||||
end:
|
||||
if (!success) evas_filter_context_clear(ctx);
|
||||
if (!success) evas_filter_context_clear(ctx, EINA_FALSE);
|
||||
if (dc) ENFN->context_free(ENDT, dc);
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -157,10 +157,13 @@ struct _Evas_Filter_Context
|
|||
Eina_Bool color_use : 1;
|
||||
} target;
|
||||
|
||||
volatile int running;
|
||||
int run_count;
|
||||
|
||||
Eina_Bool async : 1;
|
||||
Eina_Bool running : 1;
|
||||
Eina_Bool has_proxies : 1;
|
||||
Eina_Bool gl : 1;
|
||||
|
||||
};
|
||||
|
||||
struct _Evas_Filter_Command
|
||||
|
@ -249,6 +252,7 @@ struct _Evas_Filter_Buffer
|
|||
Ector_Buffer *buffer;
|
||||
int w, h;
|
||||
|
||||
Eina_Bool used : 1; // This buffer is in use (useful for reuse of context)
|
||||
Eina_Bool alpha_only : 1; // 1 channel (A) instead of 4 (RGBA)
|
||||
Eina_Bool transient : 1; // temporary buffer (automatic allocation)
|
||||
Eina_Bool locked : 1; // internal flag
|
||||
|
@ -269,7 +273,7 @@ enum _Evas_Filter_Support
|
|||
EVAS_FILTER_SUPPORT_GL
|
||||
};
|
||||
|
||||
void evas_filter_context_clear(Evas_Filter_Context *ctx);
|
||||
void evas_filter_context_clear(Evas_Filter_Context *ctx, Eina_Bool keep_buffers);
|
||||
void evas_filter_context_source_set(Evas_Filter_Context *ctx, Evas_Object *eo_proxy, Evas_Object *eo_source, int bufid, Eina_Stringshare *name);
|
||||
|
||||
/* Utility functions */
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
# endif
|
||||
#endif /* ! _WIN32 */
|
||||
|
||||
typedef struct _Evas_Filter_Context Evas_Filter_Context;
|
||||
typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction;
|
||||
typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer;
|
||||
typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding;
|
||||
|
@ -146,19 +145,22 @@ void evas_filter_program_data_set_all(Evas_Filter_Program *p
|
|||
Evas_Filter_Context *evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data);
|
||||
void *evas_filter_context_data_get(Evas_Filter_Context *ctx);
|
||||
Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx);
|
||||
void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H);
|
||||
void evas_filter_context_destroy(Evas_Filter_Context *ctx);
|
||||
Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);
|
||||
Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse);
|
||||
Eina_Bool evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);
|
||||
void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, Eina_Bool do_async);
|
||||
void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data);
|
||||
#define evas_filter_context_autodestroy(ctx) evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) evas_filter_context_destroy), ctx)
|
||||
Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx);
|
||||
void evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect);
|
||||
|
||||
int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only);
|
||||
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_release(Evas_Filter_Context *ctx, void *stolen_buffer);
|
||||
|
||||
Eina_Bool evas_filter_run(Evas_Filter_Context *ctx);
|
||||
Eina_Bool evas_filter_context_run(Evas_Filter_Context *ctx);
|
||||
|
||||
Eina_Bool evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, Evas_Font_Set *font, int x, int y, Evas_Text_Props *text_props, Eina_Bool do_async);
|
||||
Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y);
|
||||
|
|
|
@ -93,6 +93,7 @@ typedef struct _Evas_Object_Protected_Data Evas_Object_Protected_Data;
|
|||
|
||||
/* gfx filters typedef only */
|
||||
typedef struct _Evas_Filter_Program Evas_Filter_Program;
|
||||
typedef struct _Evas_Filter_Context Evas_Filter_Context;
|
||||
typedef struct _Evas_Object_Filter_Data Evas_Object_Filter_Data;
|
||||
typedef struct _Evas_Filter_Data_Binding Evas_Filter_Data_Binding;
|
||||
typedef struct _Evas_Pointer_Data Evas_Pointer_Data;
|
||||
|
@ -1288,6 +1289,7 @@ struct _Evas_Object_Filter_Data
|
|||
Eina_Stringshare *name;
|
||||
Eina_Stringshare *code;
|
||||
Evas_Filter_Program *chain;
|
||||
Evas_Filter_Context *context;
|
||||
Eina_Hash *sources; // Evas_Filter_Proxy_Binding
|
||||
Eina_Inlist *data; // Evas_Filter_Data_Binding
|
||||
Eina_Rectangle prev_obscured, obscured;
|
||||
|
@ -1306,6 +1308,7 @@ struct _Evas_Object_Filter_Data
|
|||
Eina_Bool changed : 1;
|
||||
Eina_Bool invalid : 1; // Code parse failed
|
||||
Eina_Bool async : 1;
|
||||
Eina_Bool reuse : 1;
|
||||
};
|
||||
|
||||
struct _Evas_Object_Func
|
||||
|
|
Loading…
Reference in New Issue