forked from enlightenment/efl
Evas filters: Add internal function _program_run
This will allow changing the state of the filter and re-run it without re-creating the Lua_State object. This is to handle size, color, animation state and scale changes (amongst other things).
This commit is contained in:
parent
6db0ff4229
commit
2faaef966e
|
@ -3315,7 +3315,7 @@ start_draw:
|
|||
if (!ok) goto state_write;
|
||||
|
||||
evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
|
||||
ok = evas_filter_context_buffers_allocate_all(filter, W, H);
|
||||
ok = evas_filter_context_buffers_allocate_all(filter);
|
||||
if (!ok) goto state_write;
|
||||
|
||||
if (ENFN->gl_surface_read_pixels)
|
||||
|
|
|
@ -1760,7 +1760,6 @@ evas_object_text_render(Evas_Object *eo_obj,
|
|||
* image to GL.
|
||||
*/
|
||||
|
||||
|
||||
W = obj->cur->geometry.w;
|
||||
H = obj->cur->geometry.h;
|
||||
X = obj->cur->geometry.x;
|
||||
|
@ -1837,6 +1836,7 @@ evas_object_text_render(Evas_Object *eo_obj,
|
|||
}
|
||||
|
||||
filter = evas_filter_context_new(obj->layer->evas, do_async);
|
||||
evas_filter_program_run(fcow->chain);
|
||||
ok = evas_filter_context_program_use(filter, fcow->chain);
|
||||
if (!filter || !ok)
|
||||
{
|
||||
|
@ -1856,7 +1856,7 @@ evas_object_text_render(Evas_Object *eo_obj,
|
|||
ENFN->context_color_set(ENDT, filter_ctx, 255, 255, 255, 255);
|
||||
|
||||
// Allocate all buffers now
|
||||
evas_filter_context_buffers_allocate_all(filter, W, H);
|
||||
evas_filter_context_buffers_allocate_all(filter);
|
||||
evas_filter_target_set(filter, context, surface, X + x, Y + y);
|
||||
|
||||
// Steal output and release previous
|
||||
|
@ -2379,7 +2379,6 @@ EOLIAN static void
|
|||
_evas_text_filter_program_set(Eo *eo_obj, Evas_Text_Data *o, const char *arg)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
|
||||
|
||||
Evas_Filter_Program *pgm = NULL;
|
||||
|
||||
if (!o) return;
|
||||
|
@ -2393,8 +2392,9 @@ _evas_text_filter_program_set(Eo *eo_obj, Evas_Text_Data *o, const char *arg)
|
|||
evas_filter_program_del(fcow->chain);
|
||||
if (arg)
|
||||
{
|
||||
pgm = evas_filter_program_new("Evas_Text: Filter Program", EINA_TRUE);
|
||||
pgm = evas_filter_program_new("Evas_Text", EINA_TRUE);
|
||||
evas_filter_program_source_set_all(pgm, fcow->sources);
|
||||
evas_filter_program_state_set(pgm, obj->cur->geometry.w, obj->cur->geometry.h);
|
||||
if (!evas_filter_program_parse(pgm, arg))
|
||||
{
|
||||
ERR("Parsing failed!");
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
# include "evas_cs2_private.h"
|
||||
#endif
|
||||
|
||||
#define _assert(a) if (!(a)) CRI("Failed on %s", #a);
|
||||
|
||||
static void _buffer_free(Evas_Filter_Buffer *fb);
|
||||
static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
|
||||
static RGBA_Image *_rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data);
|
||||
|
@ -205,13 +207,13 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
|
|||
{
|
||||
// TODO: Lock current object as proxyrendering (see image obj)
|
||||
source = eo_data_scope_get(fb->source, EVAS_OBJECT_CLASS);
|
||||
_assert(fb->w == source->cur->geometry.w);
|
||||
_assert(fb->h == source->cur->geometry.h);
|
||||
if (source->proxy->surface && !source->proxy->redraw)
|
||||
{
|
||||
DBG("Source already rendered: '%s' of type '%s'",
|
||||
fb->source_name, eo_class_name_get(eo_class_get(fb->source)));
|
||||
_filter_buffer_backing_free(fb);
|
||||
fb->w = source->cur->geometry.w;
|
||||
fb->h = source->cur->geometry.h;
|
||||
if (!ctx->gl_engine)
|
||||
{
|
||||
fb->backing = source->proxy->surface;
|
||||
|
@ -232,8 +234,6 @@ 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, do_async);
|
||||
_filter_buffer_backing_free(fb);
|
||||
fb->w = source->cur->geometry.w;
|
||||
fb->h = source->cur->geometry.h;
|
||||
if (!ctx->gl_engine)
|
||||
{
|
||||
fb->backing = source->proxy->surface;
|
||||
|
@ -355,16 +355,16 @@ _rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data)
|
|||
}
|
||||
|
||||
Eina_Bool
|
||||
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx,
|
||||
unsigned w, unsigned h)
|
||||
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
|
||||
{
|
||||
Evas_Filter_Command *cmd;
|
||||
Evas_Filter_Buffer *fb;
|
||||
Eina_List *li;
|
||||
unsigned w, h;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
||||
ctx->w = w;
|
||||
ctx->h = h;
|
||||
w = ctx->w;
|
||||
h = ctx->w;
|
||||
|
||||
//DBG("Allocating all buffers based on output size %ux%u", w, h);
|
||||
|
||||
|
|
|
@ -282,6 +282,7 @@ typedef struct _Buffer
|
|||
struct {
|
||||
int l, r, t, b; // Used for padding calculation. Can change over time.
|
||||
} pad;
|
||||
int w, h;
|
||||
Eina_Bool alpha : 1;
|
||||
} Buffer;
|
||||
|
||||
|
@ -320,9 +321,12 @@ struct _Evas_Filter_Program
|
|||
struct {
|
||||
int l, r, t, b;
|
||||
} pad;
|
||||
int w, h;
|
||||
lua_State *L;
|
||||
Eina_Bool valid : 1;
|
||||
Eina_Bool padding_calc : 1; // Padding has been calculated
|
||||
Eina_Bool padding_set : 1; // Padding has been forced
|
||||
Eina_Bool changed : 1; // State (w,h) changed, needs re-run of Lua
|
||||
};
|
||||
|
||||
/* Instructions */
|
||||
|
@ -1568,6 +1572,9 @@ evas_filter_program_del(Evas_Filter_Program *pgm)
|
|||
|
||||
if (!pgm) return;
|
||||
|
||||
if (pgm->L)
|
||||
lua_close(pgm->L);
|
||||
|
||||
EINA_INLIST_FREE(pgm->buffers, buf)
|
||||
{
|
||||
pgm->buffers = eina_inlist_remove(pgm->buffers, EINA_INLIST_GET(buf));
|
||||
|
@ -1679,7 +1686,7 @@ fail:
|
|||
}
|
||||
|
||||
static Instruction_Param *
|
||||
_paramameter_get_by_id(Evas_Filter_Instruction *instr, int id)
|
||||
_parameter_get_by_id(Evas_Filter_Instruction *instr, int id)
|
||||
{
|
||||
Instruction_Param *param;
|
||||
int i = 0;
|
||||
|
@ -1734,7 +1741,7 @@ _lua_instruction_run(lua_State *L, Evas_Filter_Instruction *instr)
|
|||
else if (lua_isnumber(L, -2))
|
||||
{
|
||||
int idx = (int) lua_tonumber(L, -2);
|
||||
param = _paramameter_get_by_id(instr, idx - 1);
|
||||
param = _parameter_get_by_id(instr, idx - 1);
|
||||
if (!param)
|
||||
{
|
||||
ERR("Too many parameters for the function %s", instr->name);
|
||||
|
@ -2092,20 +2099,48 @@ evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
|
|||
|
||||
if (ok)
|
||||
ok = !lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||
else
|
||||
|
||||
if (!ok || !pgm->instructions)
|
||||
{
|
||||
const char *msg = lua_tostring(L, -1);
|
||||
ERR("Lua parsing failed: %s", msg);
|
||||
lua_close(L);
|
||||
}
|
||||
lua_close(L);
|
||||
|
||||
ok &= (pgm->instructions != NULL);
|
||||
else
|
||||
pgm->L = L;
|
||||
pgm->valid = ok;
|
||||
pgm->padding_calc = EINA_FALSE;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/** Run a program, must be already loaded */
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_filter_program_run(Evas_Filter_Program *pgm)
|
||||
{
|
||||
Eina_Bool ok;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
|
||||
if (!pgm->L)
|
||||
{
|
||||
ERR("Lua state is not set. Something is wrong.");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if (!pgm->changed)
|
||||
return EINA_TRUE;
|
||||
|
||||
ok = !lua_pcall(pgm->L, 0, LUA_MULTRET, 0);
|
||||
if (!ok)
|
||||
{
|
||||
const char *msg = lua_tostring(pgm->L, -1);
|
||||
ERR("Lua execution failed: %s", msg);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/** Evaluate required padding to correctly apply an effect */
|
||||
|
||||
EAPI Eina_Bool
|
||||
|
@ -2180,6 +2215,21 @@ evas_filter_program_new(const char *name, Eina_Bool input_alpha)
|
|||
return pgm;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_filter_program_state_set(Evas_Filter_Program *pgm, int w, int h)
|
||||
{
|
||||
Eina_Bool changed = EINA_FALSE;
|
||||
#define SET(a) do { if (pgm->a != a) { changed = 1; pgm->a = a; } } while (0)
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(pgm);
|
||||
|
||||
SET(w);
|
||||
SET(h);
|
||||
pgm->changed |= changed;
|
||||
|
||||
#undef SET
|
||||
}
|
||||
|
||||
/** Bind objects for proxy rendering */
|
||||
EAPI void
|
||||
evas_filter_program_source_set_all(Evas_Filter_Program *pgm,
|
||||
|
@ -2739,6 +2789,10 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
|||
|
||||
DBG("Using program '%s' for context %p", pgm->name, ctx);
|
||||
|
||||
// Copy current state (size, edje state val, color class, etc...)
|
||||
ctx->w = pgm->w;
|
||||
ctx->h = pgm->h;
|
||||
|
||||
// Create empty context with all required buffers
|
||||
evas_filter_context_clear(ctx);
|
||||
EINA_INLIST_FOREACH(pgm->buffers, buf)
|
||||
|
@ -2746,6 +2800,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
|||
buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha);
|
||||
if (buf->proxy)
|
||||
{
|
||||
Evas_Object_Protected_Data *source;
|
||||
Evas_Filter_Proxy_Binding *pb;
|
||||
Evas_Filter_Buffer *fb;
|
||||
|
||||
|
@ -2757,6 +2812,15 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
|||
fb->source = pb->eo_source;
|
||||
fb->source_name = eina_stringshare_ref(pb->name);
|
||||
fb->ctx->has_proxies = EINA_TRUE;
|
||||
|
||||
source = eo_data_scope_get(fb->source, EVAS_OBJECT_CLASS);
|
||||
fb->w = source->cur->geometry.w;
|
||||
fb->h = source->cur->geometry.h;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->w = ctx->w;
|
||||
buf->h = ctx->h;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,6 +118,8 @@ enum _Evas_Filter_Transform_Flags
|
|||
|
||||
/* Parser stuff (high level API) */
|
||||
EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool input_alpha);
|
||||
EAPI Eina_Bool evas_filter_program_run(Evas_Filter_Program *pgm);
|
||||
EAPI void evas_filter_program_state_set(Evas_Filter_Program *pgm, int w, int h);
|
||||
EAPI Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str);
|
||||
EAPI void evas_filter_program_del(Evas_Filter_Program *pgm);
|
||||
Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);
|
||||
|
@ -130,7 +132,7 @@ Evas_Filter_Context *evas_filter_context_new(Evas_Public_Data *evas, Eina_Bo
|
|||
void evas_filter_context_destroy(Evas_Filter_Context *ctx);
|
||||
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, unsigned w, unsigned h);
|
||||
Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx);
|
||||
|
||||
int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only);
|
||||
int evas_filter_buffer_image_new(Evas_Filter_Context *ctx, void *image);
|
||||
|
|
Loading…
Reference in New Issue