summaryrefslogtreecommitdiff
path: root/src/lib/evas
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-03-22 16:55:26 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-04-14 11:26:44 +0900
commit1bf24f87626b438598936ad4f780f7877447f496 (patch)
treee6111138de96a1479054e1ab8649c00096273378 /src/lib/evas
parent7407a0d073a57e66f6ab68069780026b56bf7b39 (diff)
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.
Diffstat (limited to '')
-rw-r--r--src/lib/evas/canvas/evas_filter_mixin.c109
-rw-r--r--src/lib/evas/canvas/evas_object_main.c2
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c4
-rw-r--r--src/lib/evas/filters/evas_filter.c171
-rw-r--r--src/lib/evas/filters/evas_filter_parser.c73
-rw-r--r--src/lib/evas/filters/evas_filter_private.h8
-rw-r--r--src/lib/evas/include/evas_filter.h10
-rw-r--r--src/lib/evas/include/evas_private.h3
8 files changed, 286 insertions, 94 deletions
diff --git a/src/lib/evas/canvas/evas_filter_mixin.c b/src/lib/evas/canvas/evas_filter_mixin.c
index 45db424c0a..fab03baa60 100644
--- a/src/lib/evas/canvas/evas_filter_mixin.c
+++ b/src/lib/evas/canvas/evas_filter_mixin.c
@@ -43,6 +43,8 @@ _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
43 Evas_Filter_Data *pd, Eina_Bool success) 43 Evas_Filter_Data *pd, Eina_Bool success)
44{ 44{
45 void *previous = pd->data->output; 45 void *previous = pd->data->output;
46 Eina_Bool destroy = !pd->data->reuse;
47 Evas_Object_Filter_Data *fcow;
46 Eo *eo_obj = obj->object; 48 Eo *eo_obj = obj->object;
47 49
48 if (!success) 50 if (!success)
@@ -50,10 +52,10 @@ _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
50 ERR("Filter failed at runtime!"); 52 ERR("Filter failed at runtime!");
51 evas_filter_invalid_set(eo_obj, EINA_TRUE); 53 evas_filter_invalid_set(eo_obj, EINA_TRUE);
52 evas_filter_dirty(eo_obj); 54 evas_filter_dirty(eo_obj);
55 destroy = EINA_TRUE;
53 } 56 }
54 else 57 else
55 { 58 {
56 Evas_Object_Filter_Data *fcow;
57 void *output = evas_filter_buffer_backing_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID, EINA_FALSE); 59 void *output = evas_filter_buffer_backing_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID, EINA_FALSE);
58 60
59 fcow = FCOW_BEGIN(pd); 61 fcow = FCOW_BEGIN(pd);
@@ -61,9 +63,29 @@ _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
61 FCOW_END(fcow, pd); 63 FCOW_END(fcow, pd);
62 } 64 }
63 65
64 // Destroy context as we won't reuse it. 66 if (EINA_UNLIKELY(ctx != pd->data->context))
65 evas_filter_buffer_backing_release(ctx, previous); 67 {
66 evas_filter_context_destroy(ctx); 68 ERR("Filter context has changed! Destroying it now...");
69 fcow = FCOW_BEGIN(pd);
70 evas_filter_context_destroy(fcow->context);
71 fcow->context = NULL;
72 FCOW_END(fcow, pd);
73 destroy = EINA_TRUE;
74 }
75
76 if (destroy)
77 {
78 evas_filter_buffer_backing_release(ctx, previous);
79 evas_filter_context_destroy(ctx);
80 ctx = NULL;
81 }
82
83 if (pd->data->context != ctx)
84 {
85 fcow = FCOW_BEGIN(pd);
86 fcow->context = ctx;
87 FCOW_END(fcow, pd);
88 }
67} 89}
68 90
69static void 91static void
@@ -192,13 +214,6 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
192 Evas_Object_Filter_Data *fcow; 214 Evas_Object_Filter_Data *fcow;
193 Evas_Filter_Padding pad; 215 Evas_Filter_Padding pad;
194 216
195 /* NOTE: Filter rendering is now done ENTIRELY on CPU.
196 * So we rely on cache/cache2 to allocate a real image buffer,
197 * that we can draw to. The OpenGL texture will be created only
198 * after the rendering has been done, as we simply push the output
199 * image to GL.
200 */
201
202 W = obj->cur->geometry.w; 217 W = obj->cur->geometry.w;
203 H = obj->cur->geometry.h; 218 H = obj->cur->geometry.h;
204 X = obj->cur->geometry.x; 219 X = obj->cur->geometry.x;
@@ -217,7 +232,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
217 obj->cur->clipper->cur->cache.clip.b, 232 obj->cur->clipper->cur->cache.clip.b,
218 obj->cur->clipper->cur->cache.clip.a); 233 obj->cur->clipper->cur->cache.clip.a);
219 else 234 else
220 ENFN->context_multiplier_unset(output, context); 235 ENFN->context_multiplier_unset(output, context);
221 236
222 if (!pd->data->chain) 237 if (!pd->data->chain)
223 { 238 {
@@ -295,22 +310,57 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
295 _evas_filter_state_set_internal(pd->data->chain, pd); 310 _evas_filter_state_set_internal(pd->data->chain, pd);
296 } 311 }
297 312
298 filter = evas_filter_context_new(obj->layer->evas, do_async, 0); 313 filter = pd->data->context;
299 314 if (filter)
300 // Run script
301 ok = evas_filter_context_program_use(filter, pd->data->chain);
302 if (!filter || !ok)
303 { 315 {
304 ERR("Parsing failed?"); 316 int prev_w, prev_h;
305 evas_filter_context_destroy(filter); 317 Eina_Bool was_async;
306 318
307 if (!pd->data->invalid) 319 was_async = evas_filter_context_async_get(filter);
320 evas_filter_context_size_get(filter, &prev_w, &prev_h);
321 if ((!pd->data->reuse) || (was_async != do_async) ||
322 (prev_w != W) || (prev_h != H))
308 { 323 {
309 fcow = FCOW_BEGIN(pd); 324 fcow = FCOW_BEGIN(pd);
310 fcow->invalid = EINA_TRUE; 325 fcow->context = NULL;
311 FCOW_END(fcow, pd); 326 FCOW_END(fcow, pd);
327 evas_filter_context_destroy(filter);
328 filter = NULL;
329 }
330 }
331
332 if (filter)
333 {
334 ok = evas_filter_context_program_reuse(filter, pd->data->chain);
335 if (!ok)
336 {
337 fcow = FCOW_BEGIN(pd);
338 fcow->context = NULL;
339 FCOW_END(fcow, pd);
340 evas_filter_context_destroy(filter);
341 filter = NULL;
342 }
343 }
344
345 if (!filter)
346 {
347 filter = evas_filter_context_new(obj->layer->evas, do_async, 0);
348
349 // Run script
350 ok = evas_filter_context_program_use(filter, pd->data->chain, EINA_FALSE);
351 if (!filter || !ok)
352 {
353 ERR("Parsing failed?");
354 evas_filter_context_destroy(filter);
355
356 if (!pd->data->invalid)
357 {
358 fcow = FCOW_BEGIN(pd);
359 fcow->invalid = EINA_TRUE;
360 FCOW_END(fcow, pd);
361 }
362 return EINA_FALSE;
312 } 363 }
313 return EINA_FALSE;
314 } 364 }
315 365
316 // Proxies 366 // Proxies
@@ -336,15 +386,17 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
336 386
337 // Add post-run callback and run filter 387 // Add post-run callback and run filter
338 evas_filter_context_post_run_callback_set(filter, _filter_cb, pd); 388 evas_filter_context_post_run_callback_set(filter, _filter_cb, pd);
339 ok = evas_filter_run(filter);
340 389
341 fcow = FCOW_BEGIN(pd); 390 fcow = FCOW_BEGIN(pd);
391 fcow->context = filter;
342 fcow->changed = EINA_FALSE; 392 fcow->changed = EINA_FALSE;
343 fcow->async = do_async; 393 fcow->async = do_async;
344 fcow->prev_obscured = fcow->obscured; 394 fcow->prev_obscured = fcow->obscured;
345 fcow->invalid = !ok; 395 fcow->invalid = EINA_FALSE;
346 FCOW_END(fcow, pd); 396 FCOW_END(fcow, pd);
347 397
398 ok = evas_filter_context_run(filter);
399
348 if (ok) 400 if (ok)
349 { 401 {
350 DBG("Effect rendering done."); 402 DBG("Effect rendering done.");
@@ -352,6 +404,9 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
352 } 404 }
353 else 405 else
354 { 406 {
407 fcow = FCOW_BEGIN(pd);
408 fcow->invalid = EINA_TRUE;
409 FCOW_END(fcow, pd);
355 ERR("Rendering failed."); 410 ERR("Rendering failed.");
356 return EINA_FALSE; 411 return EINA_FALSE;
357 } 412 }
@@ -377,6 +432,9 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_F
377 { 432 {
378 fcow->obj = obj; 433 fcow->obj = obj;
379 434
435 if (fcow->context)
436 evas_filter_context_destroy(fcow->context);
437
380 // Parse filter program 438 // Parse filter program
381 evas_filter_program_del(fcow->chain); 439 evas_filter_program_del(fcow->chain);
382 eina_stringshare_replace(&fcow->name, name); 440 eina_stringshare_replace(&fcow->name, name);
@@ -613,6 +671,9 @@ _efl_canvas_filter_internal_efl_object_destructor(Eo *eo_obj, Evas_Filter_Data *
613 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); 671 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
614 e = obj->layer->evas; 672 e = obj->layer->evas;
615 673
674 if (pd->data->context)
675 evas_filter_context_destroy(pd->data->context);
676
616 if (pd->data->output) 677 if (pd->data->output)
617 { 678 {
618 if (!pd->data->async) 679 if (!pd->data->async)
diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c
index cab4bd1731..b62ffe67c4 100644
--- a/src/lib/evas/canvas/evas_object_main.c
+++ b/src/lib/evas/canvas/evas_object_main.c
@@ -33,7 +33,7 @@ static const Evas_Object_Protected_State default_state = {
33 1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE 33 1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE
34}; 34};
35static const Evas_Object_Filter_Data default_filter = { 35static const Evas_Object_Filter_Data default_filter = {
36 NULL, NULL, NULL, NULL, NULL, NULL, {}, {}, NULL, {}, EINA_FALSE, EINA_FALSE, EINA_TRUE 36 NULL, NULL, NULL, NULL, NULL, NULL, NULL, {}, {}, NULL, {}, EINA_FALSE, EINA_FALSE, EINA_TRUE, EINA_TRUE
37}; 37};
38const void * const evas_object_filter_cow_default = &default_filter; 38const void * const evas_object_filter_cow_default = &default_filter;
39static const Evas_Object_Mask_Data default_mask = { 39static const Evas_Object_Mask_Data default_mask = {
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index 05166b914a..8032abfc59 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -13476,7 +13476,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13476 ctx = evas_filter_context_new(obj->layer->evas, do_async, ti->gfx_filter); 13476 ctx = evas_filter_context_new(obj->layer->evas, do_async, ti->gfx_filter);
13477 evas_filter_state_prepare(eo_obj, &state, ti); 13477 evas_filter_state_prepare(eo_obj, &state, ti);
13478 evas_filter_program_state_set(pgm, &state); 13478 evas_filter_program_state_set(pgm, &state);
13479 ok = evas_filter_context_program_use(ctx, pgm); 13479 ok = evas_filter_context_program_use(ctx, pgm, EINA_FALSE);
13480 if (!ok) 13480 if (!ok)
13481 { 13481 {
13482 evas_filter_context_destroy(ctx); 13482 evas_filter_context_destroy(ctx);
@@ -13790,7 +13790,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13790 else if (ctx) 13790 else if (ctx)
13791 { 13791 {
13792 evas_filter_context_post_run_callback_set(ctx, _filter_cb, obj->layer->evas); 13792 evas_filter_context_post_run_callback_set(ctx, _filter_cb, obj->layer->evas);
13793 evas_filter_run(ctx); 13793 evas_filter_context_run(ctx);
13794 } 13794 }
13795 } 13795 }
13796 } 13796 }
diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c
index 3b4c7ff6a0..c0990a0ef7 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -30,6 +30,7 @@
30static void _buffer_free(Evas_Filter_Buffer *fb); 30static void _buffer_free(Evas_Filter_Buffer *fb);
31static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd); 31static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
32static Evas_Filter_Buffer *_buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only, Eina_Bool render, Eina_Bool draw); 32static Evas_Filter_Buffer *_buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only, Eina_Bool render, Eina_Bool draw);
33static void _filter_buffer_unlock_all(Evas_Filter_Context *ctx);
33 34
34#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) 35#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)
35#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) 36#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,24 +73,37 @@ evas_filter_context_async_get(Evas_Filter_Context *ctx)
72 return ctx->async; 73 return ctx->async;
73} 74}
74 75
76void
77evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *h)
78{
79 if (w) *w = ctx->w;
80 if (h) *h = ctx->h;
81}
82
75/* Private function to reset the filter context. Used from parser.c */ 83/* Private function to reset the filter context. Used from parser.c */
76void 84void
77evas_filter_context_clear(Evas_Filter_Context *ctx) 85evas_filter_context_clear(Evas_Filter_Context *ctx, Eina_Bool keep_buffers)
78{ 86{
79 Evas_Filter_Buffer *fb;
80 Evas_Filter_Command *cmd; 87 Evas_Filter_Command *cmd;
88 Evas_Filter_Buffer *fb;
81 89
82 if (!ctx) return; 90 if (!ctx) return;
83 91
84 EINA_LIST_FREE(ctx->buffers, fb) 92 if (ctx->target.surface) ENFN->image_free(ENDT, ctx->target.surface);
85 _buffer_free(fb); 93 if (ctx->target.mask) ENFN->image_free(ENDT, ctx->target.mask);
86 EINA_INLIST_FREE(ctx->commands, cmd) 94 ctx->target.surface = NULL;
87 _command_del(ctx, cmd); 95 ctx->target.mask = NULL;
96
97 if (!keep_buffers)
98 {
99 ctx->last_buffer_id = 0;
100 EINA_LIST_FREE(ctx->buffers, fb)
101 _buffer_free(fb);
102 }
88 103
89 ctx->buffers = NULL;
90 ctx->commands = NULL;
91 ctx->last_buffer_id = 0;
92 ctx->last_command_id = 0; 104 ctx->last_command_id = 0;
105 EINA_INLIST_FREE(ctx->commands, cmd)
106 _command_del(ctx, cmd);
93 107
94 // Note: don't reset post_run, as it it set by the client 108 // Note: don't reset post_run, as it it set by the client
95} 109}
@@ -109,6 +123,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
109{ 123{
110 Evas_Object_Protected_Data *source; 124 Evas_Object_Protected_Data *source;
111 Evas_Object_Protected_Data *obj; 125 Evas_Object_Protected_Data *obj;
126 void *proxy_surface;
112 Evas_Filter_Buffer *fb; 127 Evas_Filter_Buffer *fb;
113 Eina_List *li; 128 Eina_List *li;
114 129
@@ -122,6 +137,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
122 source = efl_data_scope_get(fb->source, EFL_CANVAS_OBJECT_CLASS); 137 source = efl_data_scope_get(fb->source, EFL_CANVAS_OBJECT_CLASS);
123 _assert(fb->w == source->cur->geometry.w); 138 _assert(fb->w == source->cur->geometry.w);
124 _assert(fb->h == source->cur->geometry.h); 139 _assert(fb->h == source->cur->geometry.h);
140 proxy_surface = source->proxy->surface;
125 if (source->proxy->surface && !source->proxy->redraw) 141 if (source->proxy->surface && !source->proxy->redraw)
126 { 142 {
127 XDBG("Source already rendered: '%s' of type '%s'", 143 XDBG("Source already rendered: '%s' of type '%s'",
@@ -134,33 +150,75 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
134 source->proxy->redraw ? "redraw" : "no surface"); 150 source->proxy->redraw ? "redraw" : "no surface");
135 evas_render_proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, EINA_FALSE, do_async); 151 evas_render_proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, EINA_FALSE, do_async);
136 } 152 }
137 _filter_buffer_backing_free(fb); 153 if (fb->buffer)
154 {
155 void *old_surface;
156
157 old_surface = evas_ector_buffer_drawable_image_get(fb->buffer);
158 if (old_surface && (old_surface != proxy_surface))
159 _filter_buffer_backing_free(fb);
160 }
138 XDBG("Source #%d '%s' has dimensions %dx%d", fb->id, fb->source_name, fb->w, fb->h); 161 XDBG("Source #%d '%s' has dimensions %dx%d", fb->id, fb->source_name, fb->w, fb->h);
139 fb->buffer = ENFN->ector_buffer_wrap(ENDT, obj->layer->evas->evas, source->proxy->surface); 162 if (!fb->buffer) fb->buffer = ENFN->ector_buffer_wrap(ENDT, obj->layer->evas->evas, source->proxy->surface);
140 fb->alpha_only = EINA_FALSE; 163 fb->alpha_only = EINA_FALSE;
141 } 164 }
142} 165}
143 166
144void 167Eina_Bool
145evas_filter_context_destroy(Evas_Filter_Context *ctx) 168evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm)
146{ 169{
147 Evas_Filter_Buffer *fb; 170 Evas_Filter_Buffer *fb;
148 Evas_Filter_Command *cmd; 171 Eina_List *li;
149 172
150 if (!ctx) return; 173 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
174 EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
151 175
152 EINA_LIST_FREE(ctx->buffers, fb) 176 _filter_buffer_unlock_all(ctx);
153 _buffer_free(fb);
154 EINA_INLIST_FREE(ctx->commands, cmd)
155 _command_del(ctx, cmd);
156 177
157 if (ctx->target.mask) 178 EINA_LIST_FOREACH(ctx->buffers, li, fb)
158 ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask); 179 {
180 void *dc, *surface;
181
182 fb->used = EINA_FALSE;
183 fb->locked = EINA_FALSE;
184
185 if (!fb->is_render) continue;
186 if (fb->source) continue;
187
188 surface = evas_ector_buffer_render_image_get(fb->buffer);
189 if (!surface) continue;
190
191 dc = ENFN->context_new(ENDT);
192 ENFN->context_color_set(ENDT, dc, 0, 0, 0, 0);
193 ENFN->context_render_op_set(ENDT, dc, EVAS_RENDER_COPY);
194 ENFN->rectangle_draw(ENDT, dc, surface, 0, 0, fb->w, fb->h, ctx->async);
195 ENFN->context_free(ENDT, dc);
196 fb->dirty = EINA_FALSE;
197 }
198
199 return evas_filter_context_program_use(ctx, pgm, EINA_TRUE);
200}
201
202static void
203_context_destroy(void *data)
204{
205 Evas_Filter_Context *ctx = data;
159 206
207 evas_filter_context_clear(ctx, EINA_FALSE);
160 free(ctx); 208 free(ctx);
161} 209}
162 210
163void 211void
212evas_filter_context_destroy(Evas_Filter_Context *ctx)
213{
214 // FIXME: This is not locked...
215 if (ctx->running)
216 evas_post_render_job_add(ctx->evas, _context_destroy, ctx);
217 else
218 _context_destroy(ctx);
219}
220
221void
164evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, 222evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx,
165 Evas_Filter_Cb cb, void *data) 223 Evas_Filter_Cb cb, void *data)
166{ 224{
@@ -213,6 +271,8 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
213 Eina_List *li; 271 Eina_List *li;
214 unsigned w, h; 272 unsigned w, h;
215 273
274 if (ctx->run_count > 0) return EINA_TRUE;
275
216 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE); 276 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
217 w = ctx->w; 277 w = ctx->w;
218 h = ctx->h; 278 h = ctx->h;
@@ -231,6 +291,7 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
231 in->h = h; 291 in->h = h;
232 } 292 }
233 293
294 // FIXME: No need for stretch buffers with GL!
234 if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY) 295 if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)
235 { 296 {
236 unsigned sw = w, sh = h; 297 unsigned sw = w, sh = h;
@@ -322,15 +383,69 @@ alloc_fail:
322} 383}
323 384
324int 385int
325evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only) 386evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only)
326{ 387{
327 Evas_Filter_Buffer *fb; 388 Evas_Filter_Buffer *fb;
389 Eina_List *li;
328 390
329 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); 391 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
330 392
331 fb = _buffer_empty_new(ctx, 0, 0, alpha_only, EINA_FALSE); 393 EINA_LIST_FOREACH(ctx->buffers, li, fb)
394 {
395 if ((fb->alpha_only == alpha_only) &&
396 (fb->w == w) && (fb->h == h) && !fb->dirty && !fb->used)
397 {
398 fb->used = EINA_TRUE;
399 return fb->id;
400 }
401 }
402
403 fb = _buffer_empty_new(ctx, w, h, alpha_only, EINA_FALSE);
332 if (!fb) return -1; 404 if (!fb) return -1;
333 405
406 fb->used = EINA_TRUE;
407 return fb->id;
408}
409
410int
411evas_filter_buffer_proxy_new(Evas_Filter_Context *ctx, Evas_Filter_Proxy_Binding *pb,
412 int *w, int *h)
413{
414 Evas_Object_Protected_Data *source;
415 Evas_Filter_Buffer *fb;
416 Eina_List *li;
417
418 EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
419 EINA_SAFETY_ON_NULL_RETURN_VAL(pb, -1);
420
421 source = efl_data_scope_get(pb->eo_source, EFL_CANVAS_OBJECT_CLASS);
422 if (!source) return -1;
423
424 // FIXME: This is not true if the source is an evas image
425 *w = source->cur->geometry.w;
426 *h = source->cur->geometry.h;
427
428 EINA_LIST_FOREACH(ctx->buffers, li, fb)
429 {
430 if (pb->eo_source == fb->source)
431 {
432 if (fb->used) return -1;
433 if (fb->alpha_only) return -1;
434 if (!eina_streq(pb->name, fb->source_name)) return -1;
435 if ((*w != fb->w) || (*h != fb->h)) return -1;
436
437 fb->used = EINA_TRUE;
438 return fb->id;
439 }
440 }
441
442 fb = _buffer_empty_new(ctx, *w, *h, EINA_FALSE, EINA_FALSE);
443 if (!fb) return -1;
444
445 fb->source = efl_ref(pb->eo_source);
446 fb->source_name = eina_stringshare_add(pb->name);
447
448 fb->used = EINA_TRUE;
334 return fb->id; 449 return fb->id;
335} 450}
336 451
@@ -351,6 +466,7 @@ _buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only,
351 fb->w = w; 466 fb->w = w;
352 fb->h = h; 467 fb->h = h;
353 fb->alpha_only = alpha_only; 468 fb->alpha_only = alpha_only;
469 fb->is_render = render;
354 fb->buffer = _ector_buffer_create(fb, render, draw); 470 fb->buffer = _ector_buffer_create(fb, render, draw);
355 if (!fb->buffer) 471 if (!fb->buffer)
356 { 472 {
@@ -367,6 +483,8 @@ static void
367_buffer_free(Evas_Filter_Buffer *fb) 483_buffer_free(Evas_Filter_Buffer *fb)
368{ 484{
369 _filter_buffer_backing_free(fb); 485 _filter_buffer_backing_free(fb);
486 eina_stringshare_del(fb->source_name);
487 efl_unref(fb->source);
370 free(fb); 488 free(fb);
371} 489}
372 490
@@ -434,6 +552,7 @@ _command_new(Evas_Filter_Context *ctx, Evas_Filter_Mode mode,
434 if (output) 552 if (output)
435 { 553 {
436 cmd->draw.output_was_dirty = output->dirty; 554 cmd->draw.output_was_dirty = output->dirty;
555 output->is_render = EINA_TRUE;
437 output->dirty = EINA_TRUE; 556 output->dirty = EINA_TRUE;
438 } 557 }
439 558
@@ -482,6 +601,7 @@ evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h,
482 601
483 fb = _buffer_empty_new(ctx, w, h, alpha_only, EINA_TRUE); 602 fb = _buffer_empty_new(ctx, w, h, alpha_only, EINA_TRUE);
484 fb->locked = EINA_TRUE; 603 fb->locked = EINA_TRUE;
604 fb->is_render = EINA_TRUE;
485 XDBG("Created temporary buffer %d %s", fb->id, alpha_only ? "alpha" : "rgba"); 605 XDBG("Created temporary buffer %d %s", fb->id, alpha_only ? "alpha" : "rgba");
486 606
487 return fb; 607 return fb;
@@ -1564,7 +1684,6 @@ _filter_chain_run(Evas_Filter_Context *ctx)
1564 1684
1565 DEBUG_TIME_BEGIN(); 1685 DEBUG_TIME_BEGIN();
1566 1686
1567 ctx->running = EINA_TRUE;
1568 EINA_INLIST_FOREACH(ctx->commands, cmd) 1687 EINA_INLIST_FOREACH(ctx->commands, cmd)
1569 { 1688 {
1570 ok = _filter_command_run(cmd); 1689 ok = _filter_command_run(cmd);
@@ -1646,7 +1765,7 @@ _filter_obscured_region_calc(Evas_Filter_Context *ctx)
1646} 1765}
1647 1766
1648Eina_Bool 1767Eina_Bool
1649evas_filter_run(Evas_Filter_Context *ctx) 1768evas_filter_context_run(Evas_Filter_Context *ctx)
1650{ 1769{
1651 Eina_Bool ret; 1770 Eina_Bool ret;
1652 1771
@@ -1657,12 +1776,14 @@ evas_filter_run(Evas_Filter_Context *ctx)
1657 1776
1658 _filter_obscured_region_calc(ctx); 1777 _filter_obscured_region_calc(ctx);
1659 1778
1779 ctx->running = EINA_TRUE;
1660 if (ctx->async) 1780 if (ctx->async)
1661 { 1781 {
1662 evas_thread_queue_flush(_filter_thread_run_cb, ctx); 1782 evas_thread_queue_flush(_filter_thread_run_cb, ctx);
1663 return EINA_TRUE; 1783 return EINA_TRUE;
1664 } 1784 }
1665 1785
1786 ctx->run_count++;
1666 ret = _filter_chain_run(ctx); 1787 ret = _filter_chain_run(ctx);
1667 1788
1668 if (ctx->post_run.cb) 1789 if (ctx->post_run.cb)
diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c
index 9c14e5dc06..60a7ecb476 100644
--- a/src/lib/evas/filters/evas_filter_parser.c
+++ b/src/lib/evas/filters/evas_filter_parser.c
@@ -2834,48 +2834,49 @@ evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
2834 2834
2835/** Run a program, must be already loaded */ 2835/** Run a program, must be already loaded */
2836 2836
2837static void 2837static Eina_Bool
2838_buffers_update(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm) 2838_buffers_update(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm)
2839{ 2839{
2840 Evas_Object_Protected_Data *source;
2841 Evas_Filter_Proxy_Binding *pb; 2840 Evas_Filter_Proxy_Binding *pb;
2842 Evas_Filter_Buffer *fb;
2843 Buffer *buf; 2841 Buffer *buf;
2842 int w, h, id;
2844 2843
2845 EINA_INLIST_FOREACH(pgm->buffers, buf) 2844 EINA_INLIST_FOREACH(pgm->buffers, buf)
2846 { 2845 {
2847 if (buf->proxy) 2846 if (buf->proxy)
2848 { 2847 {
2849 pb = eina_hash_find(pgm->proxies, buf->proxy); 2848 pb = eina_hash_find(pgm->proxies, buf->proxy);
2850 if (!pb) continue; 2849 if (!pb) return EINA_FALSE;
2851 2850
2852 buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha); 2851 ctx->has_proxies = EINA_TRUE;
2853 fb = _filter_buffer_get(ctx, buf->cid); 2852 id = evas_filter_buffer_proxy_new(ctx, pb, &w, &h);
2854 fb->source = pb->eo_source; 2853 if (id < 0) return EINA_FALSE;
2855 fb->source_name = eina_stringshare_ref(pb->name); 2854
2856 fb->ctx->has_proxies = EINA_TRUE; 2855 buf->cid = id;
2857 2856 buf->w = w;
2858 source = efl_data_scope_get(fb->source, EFL_CANVAS_OBJECT_CLASS); 2857 buf->h = h;
2859 if ((source->cur->geometry.w != buf->w) || 2858
2860 (source->cur->geometry.h != buf->h)) 2859 XDBG("Created proxy buffer #%d %dx%d %s '%s'", buf->cid,
2861 pgm->changed = EINA_TRUE; 2860 w, h, buf->alpha ? "alpha" : "rgba", buf->name);
2862 buf->w = fb->w = source->cur->geometry.w;
2863 buf->h = fb->h = source->cur->geometry.h;
2864 XDBG("Created proxy buffer %d %s '%s'", fb->id,
2865 buf->alpha ? "alpha" : "rgba", buf->name);
2866 } 2861 }
2867 else 2862 else
2868 { 2863 {
2869 if ((buf->w != pgm->state.w) || (buf->h != pgm->state.h)) 2864 w = pgm->state.w;
2870 pgm->changed = EINA_TRUE; 2865 h = pgm->state.h;
2871 buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha); 2866
2872 fb = _filter_buffer_get(ctx, buf->cid); 2867 id = evas_filter_buffer_empty_new(ctx, w, h, buf->alpha);
2873 fb->w = buf->w = pgm->state.w; 2868 if (id < 0) return EINA_FALSE;
2874 fb->h = buf->h = pgm->state.h; 2869
2875 XDBG("Created context buffer %d %s '%s'", fb->id, 2870 buf->cid = id;
2876 buf->alpha ? "alpha" : "rgba", buf->name); 2871 buf->w = w;
2872 buf->h = h;
2873
2874 XDBG("Created context buffer #%d %dx%d %s '%s'", buf->cid,
2875 w, h, buf->alpha ? "alpha" : "rgba", buf->name);
2877 } 2876 }
2878 } 2877 }
2878
2879 return EINA_TRUE;
2879} 2880}
2880 2881
2881/** Evaluate required padding to correctly apply an effect */ 2882/** Evaluate required padding to correctly apply an effect */
@@ -3401,11 +3402,8 @@ _command_from_instruction(Evas_Filter_Context *ctx,
3401 cmd = instr2cmd(ctx, instr, dc); 3402 cmd = instr2cmd(ctx, instr, dc);
3402 if (!cmd) return EINA_FALSE; 3403 if (!cmd) return EINA_FALSE;
3403 3404
3404 if (cmd->output && ctx->gl) 3405 if (cmd->output)
3405 { 3406 cmd->output->is_render = EINA_TRUE;
3406 if (ENFN->gfx_filter_supports(ENDT, cmd) == EVAS_FILTER_SUPPORT_GL)
3407 cmd->output->is_render = EINA_TRUE;
3408 }
3409 3407
3410 return EINA_TRUE; 3408 return EINA_TRUE;
3411} 3409}
@@ -3475,7 +3473,8 @@ _instruction_dump(Evas_Filter_Instruction *instr)
3475 3473
3476Eina_Bool 3474Eina_Bool
3477evas_filter_context_program_use(Evas_Filter_Context *ctx, 3475evas_filter_context_program_use(Evas_Filter_Context *ctx,
3478 Evas_Filter_Program *pgm) 3476 Evas_Filter_Program *pgm,
3477 Eina_Bool reuse)
3479{ 3478{
3480 Evas_Filter_Instruction *instr; 3479 Evas_Filter_Instruction *instr;
3481 Eina_Bool success = EINA_FALSE; 3480 Eina_Bool success = EINA_FALSE;
@@ -3492,7 +3491,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
3492 ctx->h = pgm->state.h; 3491 ctx->h = pgm->state.h;
3493 3492
3494 // Create empty context with all required buffers 3493 // Create empty context with all required buffers
3495 evas_filter_context_clear(ctx); 3494 evas_filter_context_clear(ctx, reuse);
3496 3495
3497 if (pgm->changed) 3496 if (pgm->changed)
3498 { 3497 {
@@ -3508,7 +3507,9 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
3508 goto end; 3507 goto end;
3509 } 3508 }
3510 } 3509 }
3511 _buffers_update(ctx, pgm); 3510
3511 // Create or update all buffers
3512 if (!_buffers_update(ctx, pgm)) goto end;
3512 3513
3513 // Compute and save padding info 3514 // Compute and save padding info
3514 evas_filter_program_padding_get(pgm, &ctx->pad.final, &ctx->pad.calculated); 3515 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,
3528 pgm->changed = EINA_FALSE; 3529 pgm->changed = EINA_FALSE;
3529 3530
3530end: 3531end:
3531 if (!success) evas_filter_context_clear(ctx); 3532 if (!success) evas_filter_context_clear(ctx, EINA_FALSE);
3532 if (dc) ENFN->context_free(ENDT, dc); 3533 if (dc) ENFN->context_free(ENDT, dc);
3533 return success; 3534 return success;
3534} 3535}
diff --git a/src/lib/evas/filters/evas_filter_private.h b/src/lib/evas/filters/evas_filter_private.h
index c62262a691..fb55aaf65e 100644
--- a/src/lib/evas/filters/evas_filter_private.h
+++ b/src/lib/evas/filters/evas_filter_private.h
@@ -157,10 +157,13 @@ struct _Evas_Filter_Context
157 Eina_Bool color_use : 1; 157 Eina_Bool color_use : 1;
158 } target; 158 } target;
159 159
160 volatile int running;
161 int run_count;
162
160 Eina_Bool async : 1; 163 Eina_Bool async : 1;
161 Eina_Bool running : 1;
162 Eina_Bool has_proxies : 1; 164 Eina_Bool has_proxies : 1;
163 Eina_Bool gl : 1; 165 Eina_Bool gl : 1;
166
164}; 167};
165 168
166struct _Evas_Filter_Command 169struct _Evas_Filter_Command
@@ -249,6 +252,7 @@ struct _Evas_Filter_Buffer
249 Ector_Buffer *buffer; 252 Ector_Buffer *buffer;
250 int w, h; 253 int w, h;
251 254
255 Eina_Bool used : 1; // This buffer is in use (useful for reuse of context)
252 Eina_Bool alpha_only : 1; // 1 channel (A) instead of 4 (RGBA) 256 Eina_Bool alpha_only : 1; // 1 channel (A) instead of 4 (RGBA)
253 Eina_Bool transient : 1; // temporary buffer (automatic allocation) 257 Eina_Bool transient : 1; // temporary buffer (automatic allocation)
254 Eina_Bool locked : 1; // internal flag 258 Eina_Bool locked : 1; // internal flag
@@ -269,7 +273,7 @@ enum _Evas_Filter_Support
269 EVAS_FILTER_SUPPORT_GL 273 EVAS_FILTER_SUPPORT_GL
270}; 274};
271 275
272void evas_filter_context_clear(Evas_Filter_Context *ctx); 276void evas_filter_context_clear(Evas_Filter_Context *ctx, Eina_Bool keep_buffers);
273void evas_filter_context_source_set(Evas_Filter_Context *ctx, Evas_Object *eo_proxy, Evas_Object *eo_source, int bufid, Eina_Stringshare *name); 277void evas_filter_context_source_set(Evas_Filter_Context *ctx, Evas_Object *eo_proxy, Evas_Object *eo_source, int bufid, Eina_Stringshare *name);
274 278
275/* Utility functions */ 279/* Utility functions */
diff --git a/src/lib/evas/include/evas_filter.h b/src/lib/evas/include/evas_filter.h
index c6854fd3c4..edb12cdcde 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.h
@@ -32,7 +32,6 @@
32# endif 32# endif
33#endif /* ! _WIN32 */ 33#endif /* ! _WIN32 */
34 34
35typedef struct _Evas_Filter_Context Evas_Filter_Context;
36typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction; 35typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction;
37typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer; 36typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer;
38typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding; 37typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding;
@@ -146,19 +145,22 @@ void evas_filter_program_data_set_all(Evas_Filter_Program *p
146Evas_Filter_Context *evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data); 145Evas_Filter_Context *evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data);
147void *evas_filter_context_data_get(Evas_Filter_Context *ctx); 146void *evas_filter_context_data_get(Evas_Filter_Context *ctx);
148Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx); 147Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx);
148void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H);
149void evas_filter_context_destroy(Evas_Filter_Context *ctx); 149void evas_filter_context_destroy(Evas_Filter_Context *ctx);
150Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm); 150Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse);
151Eina_Bool evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);
151void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, Eina_Bool do_async); 152void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, Eina_Bool do_async);
152void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data); 153void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data);
153#define evas_filter_context_autodestroy(ctx) evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) evas_filter_context_destroy), ctx) 154#define evas_filter_context_autodestroy(ctx) evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) evas_filter_context_destroy), ctx)
154Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx); 155Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx);
155void evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect); 156void evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect);
156 157
157int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only); 158int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only);
159int evas_filter_buffer_proxy_new(Evas_Filter_Context *ctx, Evas_Filter_Proxy_Binding *pb, int *w, int *h);
158void *evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid, Eina_Bool render); 160void *evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid, Eina_Bool render);
159Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void *stolen_buffer); 161Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void *stolen_buffer);
160 162
161Eina_Bool evas_filter_run(Evas_Filter_Context *ctx); 163Eina_Bool evas_filter_context_run(Evas_Filter_Context *ctx);
162 164
163Eina_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); 165Eina_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);
164Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y); 166Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y);
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index cd5683817b..6a0c77686c 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -93,6 +93,7 @@ typedef struct _Evas_Object_Protected_Data Evas_Object_Protected_Data;
93 93
94/* gfx filters typedef only */ 94/* gfx filters typedef only */
95typedef struct _Evas_Filter_Program Evas_Filter_Program; 95typedef struct _Evas_Filter_Program Evas_Filter_Program;
96typedef struct _Evas_Filter_Context Evas_Filter_Context;
96typedef struct _Evas_Object_Filter_Data Evas_Object_Filter_Data; 97typedef struct _Evas_Object_Filter_Data Evas_Object_Filter_Data;
97typedef struct _Evas_Filter_Data_Binding Evas_Filter_Data_Binding; 98typedef struct _Evas_Filter_Data_Binding Evas_Filter_Data_Binding;
98typedef struct _Evas_Pointer_Data Evas_Pointer_Data; 99typedef struct _Evas_Pointer_Data Evas_Pointer_Data;
@@ -1288,6 +1289,7 @@ struct _Evas_Object_Filter_Data
1288 Eina_Stringshare *name; 1289 Eina_Stringshare *name;
1289 Eina_Stringshare *code; 1290 Eina_Stringshare *code;
1290 Evas_Filter_Program *chain; 1291 Evas_Filter_Program *chain;
1292 Evas_Filter_Context *context;
1291 Eina_Hash *sources; // Evas_Filter_Proxy_Binding 1293 Eina_Hash *sources; // Evas_Filter_Proxy_Binding
1292 Eina_Inlist *data; // Evas_Filter_Data_Binding 1294 Eina_Inlist *data; // Evas_Filter_Data_Binding
1293 Eina_Rectangle prev_obscured, obscured; 1295 Eina_Rectangle prev_obscured, obscured;
@@ -1306,6 +1308,7 @@ struct _Evas_Object_Filter_Data
1306 Eina_Bool changed : 1; 1308 Eina_Bool changed : 1;
1307 Eina_Bool invalid : 1; // Code parse failed 1309 Eina_Bool invalid : 1; // Code parse failed
1308 Eina_Bool async : 1; 1310 Eina_Bool async : 1;
1311 Eina_Bool reuse : 1;
1309}; 1312};
1310 1313
1311struct _Evas_Object_Func 1314struct _Evas_Object_Func