jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=2faaef966e41b35656fd77be94701009ad183c42

commit 2faaef966e41b35656fd77be94701009ad183c42
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Mon May 18 17:35:49 2015 +0900

    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).
---
 src/lib/evas/canvas/evas_object_image.c   |  2 +-
 src/lib/evas/canvas/evas_object_text.c    |  8 ++--
 src/lib/evas/filters/evas_filter.c        | 16 +++----
 src/lib/evas/filters/evas_filter_parser.c | 76 ++++++++++++++++++++++++++++---
 src/lib/evas/include/evas_filter.h        |  4 +-
 5 files changed, 86 insertions(+), 20 deletions(-)

diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index b2f8b95..a272206 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -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)
diff --git a/src/lib/evas/canvas/evas_object_text.c 
b/src/lib/evas/canvas/evas_object_text.c
index d7ee55e..42620cb 100644
--- a/src/lib/evas/canvas/evas_object_text.c
+++ b/src/lib/evas/canvas/evas_object_text.c
@@ -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!");
diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index 0f24870..523018f 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -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);
 
diff --git a/src/lib/evas/filters/evas_filter_parser.c 
b/src/lib/evas/filters/evas_filter_parser.c
index 692afc9..1f9f9d3 100644
--- a/src/lib/evas/filters/evas_filter_parser.c
+++ b/src/lib/evas/filters/evas_filter_parser.c
@@ -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;
           }
      }
 
diff --git a/src/lib/evas/include/evas_filter.h 
b/src/lib/evas/include/evas_filter.h
index 2280441..b8b2361 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.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);

-- 


Reply via email to