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;
|
if (!ok) goto state_write;
|
||||||
|
|
||||||
evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
|
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 (!ok) goto state_write;
|
||||||
|
|
||||||
if (ENFN->gl_surface_read_pixels)
|
if (ENFN->gl_surface_read_pixels)
|
||||||
|
|
|
@ -1760,7 +1760,6 @@ evas_object_text_render(Evas_Object *eo_obj,
|
||||||
* image to GL.
|
* image to GL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
W = obj->cur->geometry.w;
|
W = obj->cur->geometry.w;
|
||||||
H = obj->cur->geometry.h;
|
H = obj->cur->geometry.h;
|
||||||
X = obj->cur->geometry.x;
|
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);
|
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);
|
ok = evas_filter_context_program_use(filter, fcow->chain);
|
||||||
if (!filter || !ok)
|
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);
|
ENFN->context_color_set(ENDT, filter_ctx, 255, 255, 255, 255);
|
||||||
|
|
||||||
// Allocate all buffers now
|
// 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);
|
evas_filter_target_set(filter, context, surface, X + x, Y + y);
|
||||||
|
|
||||||
// Steal output and release previous
|
// 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_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_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
|
||||||
|
|
||||||
Evas_Filter_Program *pgm = NULL;
|
Evas_Filter_Program *pgm = NULL;
|
||||||
|
|
||||||
if (!o) return;
|
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);
|
evas_filter_program_del(fcow->chain);
|
||||||
if (arg)
|
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_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))
|
if (!evas_filter_program_parse(pgm, arg))
|
||||||
{
|
{
|
||||||
ERR("Parsing failed!");
|
ERR("Parsing failed!");
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
# include "evas_cs2_private.h"
|
# include "evas_cs2_private.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define _assert(a) if (!(a)) CRI("Failed on %s", #a);
|
||||||
|
|
||||||
static void _buffer_free(Evas_Filter_Buffer *fb);
|
static void _buffer_free(Evas_Filter_Buffer *fb);
|
||||||
static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
|
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);
|
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)
|
// TODO: Lock current object as proxyrendering (see image obj)
|
||||||
source = eo_data_scope_get(fb->source, EVAS_OBJECT_CLASS);
|
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)
|
if (source->proxy->surface && !source->proxy->redraw)
|
||||||
{
|
{
|
||||||
DBG("Source already rendered: '%s' of type '%s'",
|
DBG("Source already rendered: '%s' of type '%s'",
|
||||||
fb->source_name, eo_class_name_get(eo_class_get(fb->source)));
|
fb->source_name, eo_class_name_get(eo_class_get(fb->source)));
|
||||||
_filter_buffer_backing_free(fb);
|
_filter_buffer_backing_free(fb);
|
||||||
fb->w = source->cur->geometry.w;
|
|
||||||
fb->h = source->cur->geometry.h;
|
|
||||||
if (!ctx->gl_engine)
|
if (!ctx->gl_engine)
|
||||||
{
|
{
|
||||||
fb->backing = source->proxy->surface;
|
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");
|
source->proxy->redraw ? "redraw" : "no surface");
|
||||||
evas_render_proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, do_async);
|
evas_render_proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, do_async);
|
||||||
_filter_buffer_backing_free(fb);
|
_filter_buffer_backing_free(fb);
|
||||||
fb->w = source->cur->geometry.w;
|
|
||||||
fb->h = source->cur->geometry.h;
|
|
||||||
if (!ctx->gl_engine)
|
if (!ctx->gl_engine)
|
||||||
{
|
{
|
||||||
fb->backing = source->proxy->surface;
|
fb->backing = source->proxy->surface;
|
||||||
|
@ -355,16 +355,16 @@ _rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
Eina_Bool
|
Eina_Bool
|
||||||
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx,
|
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
|
||||||
unsigned w, unsigned h)
|
|
||||||
{
|
{
|
||||||
Evas_Filter_Command *cmd;
|
Evas_Filter_Command *cmd;
|
||||||
Evas_Filter_Buffer *fb;
|
Evas_Filter_Buffer *fb;
|
||||||
Eina_List *li;
|
Eina_List *li;
|
||||||
|
unsigned w, h;
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
||||||
ctx->w = w;
|
w = ctx->w;
|
||||||
ctx->h = h;
|
h = ctx->w;
|
||||||
|
|
||||||
//DBG("Allocating all buffers based on output size %ux%u", w, h);
|
//DBG("Allocating all buffers based on output size %ux%u", w, h);
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ typedef struct _Buffer
|
||||||
struct {
|
struct {
|
||||||
int l, r, t, b; // Used for padding calculation. Can change over time.
|
int l, r, t, b; // Used for padding calculation. Can change over time.
|
||||||
} pad;
|
} pad;
|
||||||
|
int w, h;
|
||||||
Eina_Bool alpha : 1;
|
Eina_Bool alpha : 1;
|
||||||
} Buffer;
|
} Buffer;
|
||||||
|
|
||||||
|
@ -320,9 +321,12 @@ struct _Evas_Filter_Program
|
||||||
struct {
|
struct {
|
||||||
int l, r, t, b;
|
int l, r, t, b;
|
||||||
} pad;
|
} pad;
|
||||||
|
int w, h;
|
||||||
|
lua_State *L;
|
||||||
Eina_Bool valid : 1;
|
Eina_Bool valid : 1;
|
||||||
Eina_Bool padding_calc : 1; // Padding has been calculated
|
Eina_Bool padding_calc : 1; // Padding has been calculated
|
||||||
Eina_Bool padding_set : 1; // Padding has been forced
|
Eina_Bool padding_set : 1; // Padding has been forced
|
||||||
|
Eina_Bool changed : 1; // State (w,h) changed, needs re-run of Lua
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Instructions */
|
/* Instructions */
|
||||||
|
@ -1568,6 +1572,9 @@ evas_filter_program_del(Evas_Filter_Program *pgm)
|
||||||
|
|
||||||
if (!pgm) return;
|
if (!pgm) return;
|
||||||
|
|
||||||
|
if (pgm->L)
|
||||||
|
lua_close(pgm->L);
|
||||||
|
|
||||||
EINA_INLIST_FREE(pgm->buffers, buf)
|
EINA_INLIST_FREE(pgm->buffers, buf)
|
||||||
{
|
{
|
||||||
pgm->buffers = eina_inlist_remove(pgm->buffers, EINA_INLIST_GET(buf));
|
pgm->buffers = eina_inlist_remove(pgm->buffers, EINA_INLIST_GET(buf));
|
||||||
|
@ -1679,7 +1686,7 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction_Param *
|
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;
|
Instruction_Param *param;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -1734,7 +1741,7 @@ _lua_instruction_run(lua_State *L, Evas_Filter_Instruction *instr)
|
||||||
else if (lua_isnumber(L, -2))
|
else if (lua_isnumber(L, -2))
|
||||||
{
|
{
|
||||||
int idx = (int) lua_tonumber(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)
|
if (!param)
|
||||||
{
|
{
|
||||||
ERR("Too many parameters for the function %s", instr->name);
|
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)
|
if (ok)
|
||||||
ok = !lua_pcall(L, 0, LUA_MULTRET, 0);
|
ok = !lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||||
else
|
|
||||||
|
if (!ok || !pgm->instructions)
|
||||||
{
|
{
|
||||||
const char *msg = lua_tostring(L, -1);
|
const char *msg = lua_tostring(L, -1);
|
||||||
ERR("Lua parsing failed: %s", msg);
|
ERR("Lua parsing failed: %s", msg);
|
||||||
}
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
|
}
|
||||||
ok &= (pgm->instructions != NULL);
|
else
|
||||||
|
pgm->L = L;
|
||||||
pgm->valid = ok;
|
pgm->valid = ok;
|
||||||
pgm->padding_calc = EINA_FALSE;
|
pgm->padding_calc = EINA_FALSE;
|
||||||
|
|
||||||
return ok;
|
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 */
|
/** Evaluate required padding to correctly apply an effect */
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
|
@ -2180,6 +2215,21 @@ evas_filter_program_new(const char *name, Eina_Bool input_alpha)
|
||||||
return pgm;
|
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 */
|
/** Bind objects for proxy rendering */
|
||||||
EAPI void
|
EAPI void
|
||||||
evas_filter_program_source_set_all(Evas_Filter_Program *pgm,
|
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);
|
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
|
// Create empty context with all required buffers
|
||||||
evas_filter_context_clear(ctx);
|
evas_filter_context_clear(ctx);
|
||||||
EINA_INLIST_FOREACH(pgm->buffers, buf)
|
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);
|
buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha);
|
||||||
if (buf->proxy)
|
if (buf->proxy)
|
||||||
{
|
{
|
||||||
|
Evas_Object_Protected_Data *source;
|
||||||
Evas_Filter_Proxy_Binding *pb;
|
Evas_Filter_Proxy_Binding *pb;
|
||||||
Evas_Filter_Buffer *fb;
|
Evas_Filter_Buffer *fb;
|
||||||
|
|
||||||
|
@ -2757,6 +2812,15 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
||||||
fb->source = pb->eo_source;
|
fb->source = pb->eo_source;
|
||||||
fb->source_name = eina_stringshare_ref(pb->name);
|
fb->source_name = eina_stringshare_ref(pb->name);
|
||||||
fb->ctx->has_proxies = EINA_TRUE;
|
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) */
|
/* Parser stuff (high level API) */
|
||||||
EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool input_alpha);
|
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 Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str);
|
||||||
EAPI void evas_filter_program_del(Evas_Filter_Program *pgm);
|
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);
|
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_destroy(Evas_Filter_Context *ctx);
|
||||||
void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data);
|
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)
|
#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_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only);
|
||||||
int evas_filter_buffer_image_new(Evas_Filter_Context *ctx, void *image);
|
int evas_filter_buffer_image_new(Evas_Filter_Context *ctx, void *image);
|
||||||
|
|
Loading…
Reference in New Issue