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:
Jean-Philippe Andre 2017-03-22 16:55:26 +09:00
parent 7407a0d073
commit 1bf24f8762
9 changed files with 288 additions and 97 deletions

View File

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

View File

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

View File

@ -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 = {

View File

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

View File

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

View File

@ -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;
}

View File

@ -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 */

View File

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

View File

@ -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