1 #define EFL_CANVAS_FILTER_INTERNAL_PROTECTED
5 #include "evas_filter.h"
7 #define MY_CLASS EFL_CANVAS_FILTER_INTERNAL_MIXIN
9 #define FCOW_BEGIN(_pd) ({ Evas_Object_Filter_Data *_fcow = eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data)); _state_check(_fcow); _fcow; })
10 #define FCOW_END(_fcow, _pd) eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data), _fcow, EINA_TRUE)
11 #define FCOW_WRITE(pd, name, value) do { \
12 if (pd->data->name != (value)) { \
13 fcow = FCOW_BEGIN(pd); \
14 fcow->name = (value); \
18 typedef struct _Evas_Filter_Data Evas_Filter_Data;
19 typedef struct _Evas_Filter_Post_Render_Data Evas_Filter_Post_Render_Data;
21 struct _Evas_Object_Filter_Data
23 Evas_Object_Protected_Data *obj;
24 Eina_Stringshare *name;
25 Eina_Stringshare *code;
26 Evas_Filter_Program *chain;
27 Evas_Filter_Context *context;
28 Eina_Hash *sources; // Evas_Filter_Proxy_Binding
29 Eina_Inlist *data; // Evas_Filter_Data_Binding
30 Eina_Rectangle prev_obscured, obscured;
31 Evas_Filter_Padding prev_padding, padding;
35 Eina_Stringshare *name;
39 Eina_Stringshare *name;
45 Eina_Bool changed : 1;
46 Eina_Bool invalid : 1; // Code parse failed
51 struct _Evas_Filter_Data
53 const Evas_Object_Filter_Data *data;
56 struct _Evas_Filter_Post_Render_Data
59 Evas_Filter_Context *ctx;
63 // FIXME: This should be enabled (with proper heuristics)
64 #define FILTER_CONTEXT_REUSE EINA_TRUE
66 static const Evas_Object_Filter_Data evas_filter_data_cow_default = {
67 .reuse = FILTER_CONTEXT_REUSE
69 Eina_Cow *evas_object_filter_cow = NULL;
72 evas_filter_mixin_init(void)
74 evas_object_filter_cow = eina_cow_add
75 ("Evas Filter Data", sizeof(Evas_Object_Filter_Data), 8,
76 &evas_filter_data_cow_default, EINA_TRUE);
80 evas_filter_mixin_shutdown(void)
82 eina_cow_del(evas_object_filter_cow);
83 evas_object_filter_cow = NULL;
87 _state_check(Evas_Object_Filter_Data *fcow)
89 if (!fcow->state.cur.name)
90 fcow->state.cur.name = eina_stringshare_add("default");
91 if (!fcow->state.next.name)
92 fcow->state.next.name = eina_stringshare_add("default");
96 _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
97 Evas_Filter_Data *pd, Eina_Bool success)
99 void *previous = pd->data->output;
100 Eina_Bool destroy = !pd->data->reuse;
101 Evas_Object_Filter_Data *fcow;
102 Eo *eo_obj = obj->object;
107 ERR("Filter failed at runtime!");
108 evas_filter_invalid_set(eo_obj, EINA_TRUE);
109 evas_filter_dirty(eo_obj);
114 output = evas_filter_buffer_backing_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID, EINA_FALSE);
115 FCOW_WRITE(pd, output, output);
119 ENFN->image_free(ENC, previous);
121 if (destroy && (ctx == pd->data->context))
123 evas_filter_context_unref(ctx); // local ref
124 FCOW_WRITE(pd, context, NULL);
127 evas_filter_context_unref(ctx); // run ref
132 _filter_async_post_render_cb(void *data)
134 Evas_Filter_Post_Render_Data *task = data;
135 Evas_Filter_Data *pd = task->pd;
138 EINA_SAFETY_ON_FALSE_RETURN(eina_main_loop_is());
141 _filter_end_sync(task->ctx, pd->data->obj, pd, task->success);
146 _filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
148 Evas_Filter_Post_Render_Data *post_data;
149 Evas_Object_Protected_Data *obj;
150 Evas_Filter_Data *pd = data;
153 EVAS_OBJECT_DATA_VALID_CHECK(obj);
155 if (!pd->data->async)
157 _filter_end_sync(ctx, pd->data->obj, pd, success);
162 EINA_SAFETY_ON_FALSE_RETURN(!eina_main_loop_is());
165 post_data = calloc(1, sizeof(*post_data));
166 post_data->success = success;
167 post_data->ctx = ctx;
169 evas_post_render_job_add(obj->layer->evas, _filter_async_post_render_cb, post_data);
173 _evas_filter_source_hash_free_cb(void *data)
175 Evas_Filter_Proxy_Binding *pb = data;
176 Evas_Object_Protected_Data *proxy, *source;
177 Evas_Filter_Data *pd;
179 proxy = efl_data_scope_get(pb->eo_proxy, EFL_CANVAS_OBJECT_CLASS);
180 source = efl_data_scope_get(pb->eo_source, EFL_CANVAS_OBJECT_CLASS);
184 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
185 Evas_Object_Proxy_Data, source_write)
186 source_write->proxies = eina_list_remove(source_write->proxies, pb->eo_proxy);
187 EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
190 pd = efl_data_scope_get(pb->eo_proxy, MY_CLASS);
194 if (!eina_hash_population(pd->data->sources))
196 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, proxy->proxy,
197 Evas_Object_Proxy_Data, proxy_write)
198 proxy_write->is_proxy = EINA_FALSE;
199 EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write)
203 eina_stringshare_del(pb->name);
207 static inline Eina_Bool
208 _evas_filter_state_set_internal(Evas_Filter_Program *pgm, Evas_Filter_Data *pd)
210 Efl_Canvas_Filter_State state = EFL_CANVAS_FILTER_STATE_DEFAULT;
212 evas_filter_state_prepare(pd->data->obj->object, &state, NULL);
213 state.cur.name = pd->data->state.cur.name;
214 state.cur.value = pd->data->state.cur.value;
215 state.next.name = pd->data->state.next.name;
216 state.next.value = pd->data->state.next.value;
217 state.pos = pd->data->state.pos;
219 return evas_filter_program_state_set(pgm, &state);
222 static inline Eina_Bool
223 _evas_filter_obscured_region_changed(Evas_Filter_Data *pd)
225 Eina_Rectangle inter;
227 inter = pd->data->prev_obscured;
228 if (eina_rectangle_is_empty(&pd->data->obscured) &&
229 eina_rectangle_is_empty(&inter))
231 if (!eina_rectangle_intersection(&inter, &pd->data->obscured))
233 if ((inter.w != pd->data->prev_obscured.w) ||
234 (inter.h != pd->data->prev_obscured.h))
241 evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
242 void *engine, void *output, void *context, void *surface,
243 int x, int y, Eina_Bool do_async, Eina_Bool alpha)
245 Evas_Filter_Data *pd = efl_data_scope_get(eo_obj, MY_CLASS);
247 Evas_Filter_Context *filter;
250 void *previous = pd->data->output;
251 Evas_Object_Filter_Data *fcow;
252 Eina_Bool use_map = EINA_FALSE;
253 Evas_Filter_Padding pad;
255 if (pd->data->invalid || (!pd->data->chain && !pd->data->code))
258 // TIZEN_ONLY(20200619): make filter faster
259 // TODO: apply for all type of object and filter
261 if (ENFN->context_flush && /* quick hack to check gl engine */
262 obj->is_image_object && evas_filter_program_count(pd->data->chain) == 1)
264 instr_type = evas_filter_program_nth_instruction_type_get(pd->data->chain, 0);
265 if (instr_type == EVAS_FILTER_MODE_GRAYSCALE ||
266 instr_type == EVAS_FILTER_MODE_INVERSE_COLOR)
268 ((RGBA_Draw_Context *)context)->filter_mode = instr_type;
274 W = obj->cur->geometry.w;
275 H = obj->cur->geometry.h;
276 X = obj->cur->geometry.x;
277 Y = obj->cur->geometry.y;
279 // Prepare color multiplier
280 ENFN->context_color_set(engine, context,
281 obj->cur->cache.clip.r,
282 obj->cur->cache.clip.g,
283 obj->cur->cache.clip.b,
284 obj->cur->cache.clip.a);
285 if (obj->cur->clipper)
286 ENFN->context_multiplier_set(engine, context,
287 obj->cur->clipper->cur->cache.clip.r,
288 obj->cur->clipper->cur->cache.clip.g,
289 obj->cur->clipper->cur->cache.clip.b,
290 obj->cur->clipper->cur->cache.clip.a);
292 ENFN->context_multiplier_unset(engine, context);
294 if (obj->map->cur.usemap && obj->map->cur.map && (obj->map->cur.map->count >= 4))
299 ENFN->image_size_get(engine, previous, &iw, &ih);
300 evas_object_map_update(eo_obj, x, y, iw, ih, iw, ih);
303 if (!pd->data->chain)
305 Evas_Filter_Program *pgm;
308 pgm = evas_filter_program_new(pd->data->name, alpha);
309 evas_filter_program_source_set_all(pgm, pd->data->sources);
310 evas_filter_program_data_set_all(pgm, pd->data->data);
311 _evas_filter_state_set_internal(pgm, pd);
312 invalid = !evas_filter_program_parse(pgm, pd->data->code);
315 ERR("Filter program parsing failed");
316 evas_filter_program_del(pgm);
319 fcow = FCOW_BEGIN(pd);
320 if (!invalid) evas_filter_program_padding_get(pgm, NULL, &fcow->padding);
322 fcow->invalid = invalid;
324 if (invalid) return EINA_FALSE;
326 else if (previous && !pd->data->changed)
328 Eina_Bool redraw = EINA_TRUE;
330 if (_evas_filter_state_set_internal(pd->data->chain, pd))
331 DBG("Filter redraw by state change!");
332 else if (obj->changed)
333 DBG("Filter redraw by object content change!");
334 else if (obj->snapshot_needs_redraw)
335 DBG("Filter redraw by snapshot change!");
336 else if (_evas_filter_obscured_region_changed(pd))
337 DBG("Filter redraw by obscure regions change!");
338 else redraw = EINA_FALSE;
340 // Scan proxies to find if any changed
341 if (!redraw && pd->data->sources)
343 Evas_Filter_Proxy_Binding *pb;
344 Evas_Object_Protected_Data *source;
347 iter = eina_hash_iterator_data_new(pd->data->sources);
348 EINA_ITERATOR_FOREACH(iter, pb)
350 source = efl_data_scope_get(pb->eo_source, EFL_CANVAS_OBJECT_CLASS);
357 eina_iterator_free(iter);
362 // Render this image only
365 ENFN->image_map_draw(engine, output, context, surface, previous,
366 obj->map->spans, EINA_TRUE, 0, do_async);
370 ENFN->image_draw(engine, output, context,
373 X + x, Y + y, W, H, // dst
374 EINA_FALSE, // smooth
382 _evas_filter_state_set_internal(pd->data->chain, pd);
385 filter = pd->data->context;
391 was_async = evas_filter_context_async_get(filter);
392 evas_filter_context_size_get(filter, &prev_w, &prev_h);
393 if ((!pd->data->reuse) || (was_async != do_async) ||
394 (prev_w != W) || (prev_h != H))
396 evas_filter_context_unref(filter);
397 FCOW_WRITE(pd, context, NULL);
404 ok = evas_filter_context_program_use(engine, output, filter, pd->data->chain, EINA_TRUE, X, Y);
407 evas_filter_context_unref(filter);
408 FCOW_WRITE(pd, context, NULL);
415 filter = evas_filter_context_new(obj->layer->evas, do_async, 0);
418 ok = evas_filter_context_program_use(engine, output, filter, pd->data->chain, EINA_FALSE, X, Y);
421 ERR("Parsing failed?");
422 evas_filter_context_unref(filter);
423 FCOW_WRITE(pd, invalid, EINA_TRUE);
424 FCOW_WRITE(pd, context, NULL);
430 evas_filter_context_proxy_render_all(filter, eo_obj, output, EINA_FALSE);
433 drawctx = ENFN->context_new(engine);
434 ENFN->context_color_set(engine, drawctx,
435 obj->cur->cache.clip.r,
436 obj->cur->cache.clip.g,
437 obj->cur->cache.clip.b,
438 obj->cur->cache.clip.a);
440 // Set obscured region
441 evas_filter_context_obscured_region_set(filter, pd->data->obscured);
443 // Allocate all buffers now
444 evas_filter_context_buffers_allocate_all(filter);
445 evas_filter_target_set(filter, context, surface, X + x, Y + y,
446 use_map ? obj->map->spans : NULL);
448 // Request rendering from the object itself (child class)
449 evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
450 ok = evas_filter_input_render(eo_obj, filter, engine, output, drawctx, NULL,
451 pad.l, pad.r, pad.t, pad.b, 0, 0, do_async);
452 if (!ok) ERR("Filter input render failed.");
454 ENFN->context_free(engine, drawctx);
456 // Add post-run callback and run filter
457 evas_filter_context_post_run_callback_set(filter, _filter_cb, pd);
459 fcow = FCOW_BEGIN(pd);
460 fcow->context = filter;
461 fcow->changed = EINA_FALSE;
462 fcow->async = do_async;
463 fcow->prev_obscured = fcow->obscured;
464 fcow->prev_padding = fcow->padding;
466 fcow->invalid = EINA_FALSE;
469 // Run the filter now (maybe async)
471 ok = evas_filter_context_run(engine, output, filter);
472 if (!ok) ERR("Filter program failed to run!");
478 _efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd,
479 const char *code, const char *name)
481 Evas_Object_Protected_Data *obj;
482 Evas_Filter_Program *pgm = NULL;
483 Evas_Object_Filter_Data *fcow;
484 Eina_Bool invalid = pd->data->invalid;
487 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
488 if (eina_streq(pd->data->code, code) && eina_streq(pd->data->name, name))
491 evas_object_async_block(obj);
492 fcow = FCOW_BEGIN(pd);
496 evas_filter_context_unref(fcow->context);
497 fcow->context = NULL;
499 // Parse filter program
500 evas_filter_program_del(fcow->chain);
501 eina_stringshare_replace(&fcow->name, name);
504 alpha = evas_filter_input_alpha(eo_obj);
505 pgm = evas_filter_program_new(fcow->name, alpha);
506 evas_filter_program_source_set_all(pgm, fcow->sources);
507 evas_filter_program_data_set_all(pgm, fcow->data);
508 _evas_filter_state_set_internal(pgm, pd);
509 invalid = !evas_filter_program_parse(pgm, code);
512 ERR("Parsing failed!");
513 evas_filter_program_del(pgm);
518 evas_filter_program_padding_get(pgm, NULL, &fcow->padding);
522 fcow->changed = EINA_TRUE;
523 fcow->invalid = invalid;
524 eina_stringshare_replace(&fcow->code, code);
528 evas_filter_dirty(eo_obj);
532 _efl_canvas_filter_internal_efl_gfx_filter_filter_program_get(const Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, const char **code, const char **name)
534 if (code) *code = pd->data->code;
535 if (name) *name = pd->data->name;
539 _efl_canvas_filter_internal_efl_gfx_filter_filter_source_set(Eo *eo_obj, Evas_Filter_Data *pd,
540 const char *name, Efl_Gfx_Entity *eo_source)
542 Evas_Object_Protected_Data *obj;
543 Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
544 Evas_Object_Protected_Data *source = NULL;
545 Evas_Object_Filter_Data *fcow = NULL;
546 Eina_Bool invalid = pd->data->invalid;
548 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
550 source = efl_data_scope_get(eo_source, EFL_CANVAS_OBJECT_CLASS);
552 evas_object_async_block(obj);
555 if (!eo_source || !pd->data->sources) return;
556 if (eina_hash_del_by_data(pd->data->sources, eo_source))
561 if (!source && !pd->data->sources)
564 if (pd->data->sources)
566 pb_old = eina_hash_find(pd->data->sources, name);
567 if (pb_old && (pb_old->eo_source == eo_source)) return;
570 fcow = FCOW_BEGIN(pd);
572 fcow->sources = eina_hash_string_small_new(_evas_filter_source_hash_free_cb);
574 eina_hash_del(fcow->sources, name, pb_old);
578 pb_old = eina_hash_find(fcow->sources, name);
584 eina_hash_del_by_key(fcow->sources, name);
588 pb = calloc(1, sizeof(*pb));
589 pb->eo_proxy = eo_obj;
590 pb->eo_source = eo_source;
591 pb->name = eina_stringshare_add(name);
593 if (!eina_list_data_find(source->proxy->proxies, eo_obj))
595 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy, Evas_Object_Proxy_Data, source_write)
596 source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
597 EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
600 if (!obj->proxy->is_proxy)
602 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
603 proxy_write->is_proxy = EINA_TRUE;
604 EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write)
607 eina_hash_add(fcow->sources, pb->name, pb);
608 evas_filter_program_source_set_all(fcow->chain, fcow->sources);
609 evas_filter_program_data_set_all(fcow->chain, fcow->data);
610 invalid = !evas_filter_program_parse(fcow->chain, fcow->code);
611 if (!invalid) evas_filter_program_padding_get(fcow->chain, NULL, &fcow->padding);
617 fcow->changed = EINA_TRUE;
618 fcow->invalid = invalid;
622 evas_filter_dirty(eo_obj);
625 EOLIAN static Efl_Gfx_Entity *
626 _efl_canvas_filter_internal_efl_gfx_filter_filter_source_get(const Eo *obj EINA_UNUSED, Evas_Filter_Data *pd,
629 Evas_Filter_Proxy_Binding *pb = eina_hash_find(pd->data->sources, name);
630 if (!pb) return NULL;
631 return pb->eo_source;
635 _efl_canvas_filter_internal_efl_gfx_filter_filter_state_set(Eo *eo_obj, Evas_Filter_Data *pd,
636 const char *cur_state, double cur_val,
637 const char *next_state, double next_val,
640 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
642 evas_object_async_block(obj);
643 if ((cur_state != pd->data->state.cur.name) ||
644 (!EINA_DBL_EQ(cur_val, pd->data->state.cur.value)) ||
645 (next_state != pd->data->state.next.name) ||
646 (!EINA_DBL_EQ(next_val, pd->data->state.next.value)) ||
647 (!EINA_DBL_EQ(pos, pd->data->state.pos)))
649 Evas_Object_Filter_Data *fcow = FCOW_BEGIN(pd);
651 eina_stringshare_replace(&fcow->state.cur.name, cur_state);
652 fcow->state.cur.value = cur_val;
653 eina_stringshare_replace(&fcow->state.next.name, next_state);
654 fcow->state.next.value = next_val;
655 fcow->state.pos = pos;
660 _evas_filter_state_set_internal(pd->data->chain, pd);
663 evas_filter_dirty(eo_obj);
668 _efl_canvas_filter_internal_efl_gfx_filter_filter_state_get(const Eo *obj EINA_UNUSED, Evas_Filter_Data *pd,
669 const char **cur_state, double *cur_val,
670 const char **next_state, double *next_val,
673 if (cur_state) *cur_state = pd->data->state.cur.name;
674 if (cur_val) *cur_val = pd->data->state.cur.value;
675 if (next_state) *next_state = pd->data->state.next.name;
676 if (next_val) *next_val = pd->data->state.next.value;
677 if (pos) *pos = pd->data->state.pos;
681 _efl_canvas_filter_internal_efl_gfx_filter_filter_padding_get(const Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd,
682 int *l, int *r, int *t, int *b)
684 Evas_Filter_Padding pad = { 0, 0, 0, 0 };
687 evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
696 _efl_canvas_filter_internal_filter_changed_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val)
698 if ((&evas_filter_data_cow_default != pd->data) && (pd->data->changed != val))
700 Evas_Object_Filter_Data *fcow = FCOW_BEGIN(pd);
707 _efl_canvas_filter_internal_filter_invalid_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val)
709 if (pd->data->invalid != val)
711 Evas_Object_Filter_Data *fcow = FCOW_BEGIN(pd);
717 EOLIAN static Efl_Object *
718 _efl_canvas_filter_internal_efl_object_constructor(Eo *eo_obj, Evas_Filter_Data *pd)
722 obj = efl_constructor(efl_super(eo_obj, MY_CLASS));
723 pd->data = eina_cow_alloc(evas_object_filter_cow);
729 _efl_canvas_filter_internal_efl_object_destructor(Eo *eo_obj, Evas_Filter_Data *pd)
731 Evas_Object_Protected_Data *obj;
732 Evas_Object_Filter_Data *fcow;
733 Evas_Filter_Data_Binding *db;
737 if (!pd->data || (&evas_filter_data_cow_default == pd->data))
740 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
741 e = obj->layer->evas;
743 if (pd->data->context)
745 evas_filter_context_unref(pd->data->context);
746 FCOW_WRITE(pd, context, NULL);
749 if (pd->data->output)
751 if (!pd->data->async)
752 ENFN->image_free(ENC, pd->data->output);
754 evas_unref_queue_image_put(e, pd->data->output);
756 eina_hash_free(pd->data->sources);
757 EINA_INLIST_FOREACH_SAFE(pd->data->data, il, db)
759 eina_stringshare_del(db->name);
760 eina_stringshare_del(db->value);
763 evas_filter_program_del(pd->data->chain);
764 eina_stringshare_del(pd->data->code);
765 eina_stringshare_del(pd->data->state.cur.name);
766 eina_stringshare_del(pd->data->state.next.name);
769 eina_cow_free(evas_object_filter_cow, (const Eina_Cow_Data **) &pd->data);
771 efl_destructor(efl_super(eo_obj, MY_CLASS));
775 _efl_canvas_filter_internal_efl_gfx_filter_filter_data_set(Eo *eo_obj, Evas_Filter_Data *pd,
776 const char *name, const char *value,
779 Evas_Filter_Data_Binding *db, *found = NULL;
780 Evas_Object_Filter_Data *fcow;
781 Eina_Bool invalid = pd->data->invalid;
783 EINA_SAFETY_ON_NULL_RETURN(pd->data);
784 EINA_SAFETY_ON_NULL_RETURN(name);
786 EINA_INLIST_FOREACH(pd->data->data, db)
788 if (!strcmp(name, db->name))
790 if (db->execute == execute)
792 if ((value == db->value) || (value && db->value && !strcmp(value, db->value)))
800 fcow = FCOW_BEGIN(pd);
804 // Note: we are keeping references to NULL values here.
805 eina_stringshare_replace(&found->value, value);
806 found->execute = execute;
810 db = calloc(1, sizeof(Evas_Filter_Data_Binding));
811 db->name = eina_stringshare_add(name);
812 db->value = eina_stringshare_add(value);
813 db->execute = execute;
814 fcow->data = eina_inlist_append(fcow->data, EINA_INLIST_GET(db));
818 evas_filter_program_data_set_all(fcow->chain, fcow->data);
819 invalid = !evas_filter_program_parse(fcow->chain, fcow->code);
820 if (!invalid) evas_filter_program_padding_get(fcow->chain, NULL, &fcow->padding);
822 fcow->invalid = invalid;
827 evas_filter_dirty(eo_obj);
831 _efl_canvas_filter_internal_efl_gfx_filter_filter_data_get(const Eo *obj EINA_UNUSED, Evas_Filter_Data *pd,
832 const char *name, const char **value,
835 Evas_Filter_Data_Binding *db;
837 if (!value && !execute) return;
838 EINA_SAFETY_ON_NULL_RETURN(pd->data);
840 EINA_INLIST_FOREACH(pd->data->data, db)
842 if (!strcmp(name, db->name))
844 if (value) *value = db->value;
845 if (execute) *execute = db->execute;
850 if (value) *value = NULL;
851 if (execute) *execute = EINA_FALSE;
855 _efl_canvas_filter_internal_filter_output_buffer_get(const Eo *obj EINA_UNUSED, Evas_Filter_Data *pd)
857 return pd->data->output;
861 _evas_filter_obscured_regions_set(Evas_Object_Protected_Data *obj, const Eina_Tiler *tiler)
863 Evas_Object_Filter_Data *fcow;
864 Eina_Rectangle prev, rect = {};
866 Evas_Filter_Data *pd;
868 Eina_Bool was_empty = EINA_FALSE, redraw = EINA_FALSE;
869 int obscured_changes = 0;
872 // TODO: Can we handle more than one opaque region?
874 pd = efl_data_scope_get(obj->object, MY_CLASS);
875 if (!pd->data) return EINA_FALSE;
877 // Find largest opaque rect
878 it = eina_tiler_iterator_new(tiler);
879 EINA_ITERATOR_FOREACH(it, r)
881 int wh = r->w * r->h;
888 eina_iterator_free(it);
890 prev = pd->data->prev_obscured;
891 if (!pd->data->changed && (!prev.w || !prev.h))
893 was_empty = EINA_TRUE;
894 obscured_changes = 0;
896 else if (memcmp(&rect, &prev, sizeof(rect)))
898 fcow = FCOW_BEGIN(pd);
899 fcow->obscured = rect;
900 obscured_changes = fcow->obscured_changes + 1;
901 if (obscured_changes > 2)
903 // Reset obscure as it changes too much
904 memset(&fcow->obscured, 0, sizeof(fcow->obscured));
905 obscured_changes = 0;
911 FCOW_WRITE(pd, obscured_changes, obscured_changes);
912 if (redraw) return EINA_TRUE;
914 // Snapshot objects need to be redrawn if the padding has increased
915 if ((pd->data->prev_padding.l < pd->data->padding.l) ||
916 (pd->data->prev_padding.r < pd->data->padding.r) ||
917 (pd->data->prev_padding.t < pd->data->padding.t) ||
918 (pd->data->prev_padding.b < pd->data->padding.b))
921 // Snapshot objects need to be redrawn if the obscured region has shrank
922 if (!was_empty && !_evas_eina_rectangle_inside(&pd->data->obscured, &prev))
929 _evas_filter_radius_get(Evas_Object_Protected_Data *obj, int *l, int *r, int *t, int *b)
931 Evas_Filter_Padding pad = {};
932 Evas_Filter_Data *pd;
934 pd = efl_data_scope_get(obj->object, MY_CLASS);
935 if (!pd->data || !pd->data->chain) goto end;
937 evas_filter_program_padding_get(pd->data->chain, NULL, &pad);
946 #include "canvas/efl_canvas_filter_internal.eo.c"