1 #include "evas_common.h"
2 #include "evas_private.h"
5 #include "evas_cs2_private.h"
9 /* #define REND_DGB 1 */
10 /* #define STDOUT_DBG 1 */
13 static FILE *dbf = NULL;
16 rend_dbg(const char *txt)
23 dbf = fopen("EVAS-RENDER-DEBUG.log", "w");
32 char __tmpbuf[4096]; \
34 snprintf(__tmpbuf, sizeof(__tmpbuf), ##args); \
39 char __tmpbuf[4096]; int __tmpi; \
40 for (__tmpi = 0; __tmpi < xxxx; __tmpi++) \
41 __tmpbuf[__tmpi] = ' '; \
42 __tmpbuf[__tmpi] = 0; \
51 evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char do_draw);
54 evas_damage_rectangle_add(Evas *e, int x, int y, int w, int h)
58 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
61 NEW_RECT(r, x, y, w, h);
63 e->damages = eina_list_append(e->damages, r);
64 e->changed = EINA_TRUE;
68 evas_obscured_rectangle_add(Evas *e, int x, int y, int w, int h)
72 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
75 NEW_RECT(r, x, y, w, h);
77 e->obscures = eina_list_append(e->obscures, r);
81 evas_obscured_clear(Evas *e)
85 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
88 EINA_LIST_FREE(e->obscures, r)
90 eina_rectangle_free(r);
95 _evas_render_had_map(Evas_Object *obj)
97 return ((obj->prev.map) && (obj->prev.usemap));
98 // return ((!obj->cur.map) && (obj->prev.usemap));
102 _evas_render_is_relevant(Evas_Object *obj)
104 return ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
105 (evas_object_was_visible(obj) && (!obj->prev.have_clipees)));
109 _evas_render_can_render(Evas_Object *obj)
111 return (evas_object_is_visible(obj) && (!obj->cur.have_clipees));
115 _evas_render_prev_cur_clip_cache_add(Evas *e, Evas_Object *obj)
117 e->engine.func->output_redraws_rect_add(e->engine.data.output,
118 obj->prev.cache.clip.x,
119 obj->prev.cache.clip.y,
120 obj->prev.cache.clip.w,
121 obj->prev.cache.clip.h);
122 e->engine.func->output_redraws_rect_add(e->engine.data.output,
123 obj->cur.cache.clip.x,
124 obj->cur.cache.clip.y,
125 obj->cur.cache.clip.w,
126 obj->cur.cache.clip.h);
130 _evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
132 Evas_Coord x, y, w, h;
134 x = obj->cur.cache.clip.x;
135 y = obj->cur.cache.clip.y;
136 w = obj->cur.cache.clip.w;
137 h = obj->cur.cache.clip.h;
138 if (obj->cur.clipper)
140 RECTS_CLIP_TO_RECT(x, y, w, h,
141 obj->cur.clipper->cur.cache.clip.x,
142 obj->cur.clipper->cur.cache.clip.y,
143 obj->cur.clipper->cur.cache.clip.w,
144 obj->cur.clipper->cur.cache.clip.h);
146 e->engine.func->output_redraws_rect_del(e->engine.data.output,
151 _evas_render_phase1_direct(Evas *e,
152 Eina_Array *active_objects,
153 Eina_Array *restack_objects __UNUSED__,
154 Eina_Array *delete_objects __UNUSED__,
155 Eina_Array *render_objects)
161 RD(" [--- PHASE 1 DIRECT\n");
162 for (i = 0; i < active_objects->count; i++)
166 obj = eina_array_data_get(active_objects, i);
169 /* Flag need redraw on proxy too */
170 evas_object_clip_recalc(obj);
171 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
172 proxy->proxy.redraw = EINA_TRUE;
175 for (i = 0; i < render_objects->count; i++)
179 obj = eina_array_data_get(render_objects, i);
180 RD(" OBJ [%p] changed %i\n", obj, obj->changed);
183 /* Flag need redraw on proxy too */
184 evas_object_clip_recalc(obj);
185 obj->func->render_pre(obj);
186 if (obj->proxy.redraw)
187 _evas_render_prev_cur_clip_cache_add(e, obj);
188 if (obj->proxy.proxies)
190 obj->proxy.redraw = EINA_TRUE;
191 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
193 proxy->func->render_pre(proxy);
194 _evas_render_prev_cur_clip_cache_add(e, proxy);
198 RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
200 evas_object_smart_members_get_direct(obj),
201 obj->cur.map, obj->cur.usemap,
202 obj->prev.map, obj->prev.usemap,
203 _evas_render_has_map(obj),
204 _evas_render_had_map(obj));
205 if ((obj->smart.smart) &&
206 (_evas_render_has_map(obj)))
208 RD(" has map + smart\n");
209 _evas_render_prev_cur_clip_cache_add(e, obj);
214 if (obj->smart.smart)
216 // obj->func->render_pre(obj);
218 else if ((obj->rect_del) ||
219 (evas_object_is_opaque(obj) && evas_object_is_visible(obj)))
222 _evas_render_cur_clip_cache_del(e, obj);
230 _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
231 Eina_Array *active_objects,
232 Eina_Array *restack_objects,
233 Eina_Array *delete_objects,
234 Eina_Array *render_objects,
237 Eina_Bool mapped_parent
243 Eina_Bool clean_them = EINA_FALSE;
248 //Need pre render for the children of mapped object.
249 //But only when they have changed.
250 if (mapped_parent && (!obj->changed)) return EINA_FALSE;
252 obj->rect_del = EINA_FALSE;
253 obj->render_pre = EINA_FALSE;
255 if (obj->delete_me == 2)
256 eina_array_push(delete_objects, obj);
257 else if (obj->delete_me != 0) obj->delete_me++;
258 /* If the object will be removed, we should not cache anything during this run. */
259 if (obj->delete_me != 0) clean_them = EINA_TRUE;
261 /* build active object list */
262 evas_object_clip_recalc(obj);
263 is_active = evas_object_is_active(obj);
264 obj->is_active = is_active;
267 RD(" [--- PROCESS [%p] '%s' active = %i, del = %i | %i %i %ix%i\n", obj, obj->type, is_active, obj->delete_me, obj->cur.geometry.x, obj->cur.geometry.y, obj->cur.geometry.w, obj->cur.geometry.h);
269 if ((!mapped_parent) && ((is_active) || (obj->delete_me != 0)))
270 eina_array_push(active_objects, obj);
276 RD(" [%p] vis: %i, cache.clip.vis: %i cache.clip.a: %i [%p]\n", obj, obj->cur.visible, obj->cur.cache.clip.visible, obj->cur.cache.clip.a, obj->func->is_visible);
280 map = _evas_render_has_map(obj);
281 hmap = _evas_render_had_map(obj);
283 if ((restack) && (!map))
287 eina_array_push(&e->pending_objects, obj);
288 obj->changed = EINA_TRUE;
290 obj->restack = EINA_TRUE;
291 clean_them = EINA_TRUE;
300 if (map != hmap) *redraw_all = 1;
302 if ((is_active) && (!obj->clip.clipees) &&
303 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
304 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
306 eina_array_push(render_objects, obj);
307 _evas_render_prev_cur_clip_cache_add(e, obj);
308 obj->render_pre = EINA_TRUE;
310 if (obj->smart.smart)
312 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
314 _evas_render_phase1_object_process(e, obj2,
335 RD(" had map - restack objs\n");
336 // eina_array_push(restack_objects, obj);
337 _evas_render_prev_cur_clip_cache_add(e, obj);
342 if ((obj->cur.map) && (obj->cur.usemap)) map = EINA_TRUE;
351 /* handle normal rendering. this object knows how to handle maps */
354 if (obj->smart.smart)
357 RD(" changed + smart - render ok\n");
358 eina_array_push(render_objects, obj);
359 obj->render_pre = EINA_TRUE;
360 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj),
363 _evas_render_phase1_object_process(e, obj2,
379 if ((is_active) && (!obj->clip.clipees) &&
380 _evas_render_is_relevant(obj))
383 RD(" relevant + active\n");
385 eina_array_push(restack_objects, obj);
388 eina_array_push(render_objects, obj);
389 obj->render_pre = EINA_TRUE;
395 RD(" skip - not smart, not active or clippees or not relevant\n");
401 RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n",
402 evas_object_is_visible(obj),
403 obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart,
404 obj->cur.cache.clip.a, evas_object_was_visible(obj));
406 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
407 (_evas_render_can_render(obj) ||
408 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
410 if (obj->smart.smart)
413 RD(" smart + visible/was visible + not clip\n");
414 eina_array_push(render_objects, obj);
415 obj->render_pre = EINA_TRUE;
417 (evas_object_smart_members_get_direct(obj), obj2)
419 _evas_render_phase1_object_process(e, obj2,
435 if (evas_object_is_opaque(obj) &&
436 evas_object_is_visible(obj))
439 RD(" opaque + visible\n");
440 eina_array_push(render_objects, obj);
441 obj->rect_del = EINA_TRUE;
443 else if (evas_object_is_visible(obj))
447 eina_array_push(render_objects, obj);
448 obj->render_pre = EINA_TRUE;
457 /* else if (obj->smart.smart)
460 RD(" smart + mot visible/was visible\n");
461 eina_array_push(render_objects, obj);
463 EINA_INLIST_FOREACH (evas_object_smart_members_get_direct(obj),
466 _evas_render_phase1_object_process(e, obj2,
481 if (!is_active) obj->restack = EINA_FALSE;
488 _evas_render_phase1_process(Evas *e,
489 Eina_Array *active_objects,
490 Eina_Array *restack_objects,
491 Eina_Array *delete_objects,
492 Eina_Array *render_objects,
496 Eina_Bool clean_them = EINA_FALSE;
498 RD(" [--- PHASE 1\n");
499 EINA_INLIST_FOREACH(e->layers, lay)
503 EINA_INLIST_FOREACH(lay->objects, obj)
505 clean_them |= _evas_render_phase1_object_process
506 (e, obj, active_objects, restack_objects, delete_objects,
507 render_objects, 0, redraw_all, EINA_FALSE
519 _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
523 for (i = 0; i < pending_objects->count; ++i)
527 Eina_Bool ok = EINA_FALSE;
528 obj = eina_array_data_get(pending_objects, i);
529 if (!obj->layer) goto clean_stuff;
531 //If the children are in active objects, They should be cleaned up.
532 if (obj->changed_map && _evas_render_has_map(obj))
535 evas_object_clip_recalc(obj);
536 is_active = evas_object_is_active(obj);
538 if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
545 if (obj->is_active == is_active)
549 if (obj->smart.smart)
551 if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
554 if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
555 (_evas_render_can_render(obj) ||
556 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
558 if (!(obj->render_pre || obj->rect_del))
562 if (is_active && (!obj->clip.clipees) &&
563 (_evas_render_can_render(obj) ||
564 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
566 if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
571 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
572 (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
573 && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
575 if (obj->rect_del || obj->smart.smart) ok = EINA_TRUE;
583 eina_array_clean(&e->active_objects);
584 eina_array_clean(&e->render_objects);
585 eina_array_clean(&e->restack_objects);
586 eina_array_clean(&e->delete_objects);
587 e->invalidate = EINA_TRUE;
594 pending_change(void *data, void *gdata __UNUSED__)
599 if (obj->delete_me) return EINA_FALSE;
600 if (obj->pre_render_done)
602 RD(" OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
603 obj->pre_render_done = EINA_FALSE;
604 evas_object_change_reset(obj);
606 return obj->changed ? EINA_TRUE : EINA_FALSE;
610 _evas_render_can_use_overlay(Evas *e, Evas_Object *obj)
614 Eina_List *alphas = NULL;
615 Eina_List *opaques = NULL;
616 Evas_Object *video_parent = NULL;
618 Evas_Coord xc1, yc1, xc2, yc2;
622 video_parent = _evas_object_image_video_parent_get(obj);
624 /* Check if any one is the stack make this object mapped */
626 while (tmp && !_evas_render_has_map(tmp))
627 tmp = tmp->smart.parent;
629 if (tmp && _evas_render_has_map(tmp)) return EINA_FALSE; /* we are mapped, we can't be an overlay */
631 if (!evas_object_is_visible(obj)) return EINA_FALSE; /* no need to update the overlay if it's not visible */
633 /* If any recoloring of the surface is needed, n overlay to */
634 if ((obj->cur.cache.clip.r != 255) ||
635 (obj->cur.cache.clip.g != 255) ||
636 (obj->cur.cache.clip.b != 255) ||
637 (obj->cur.cache.clip.a != 255))
640 /* Check presence of transparent object on top of the video object */
641 EINA_RECTANGLE_SET(&zone,
642 obj->cur.cache.clip.x,
643 obj->cur.cache.clip.y,
644 obj->cur.cache.clip.w,
645 obj->cur.cache.clip.h);
647 for (i = e->active_objects.count - 1; i > 0; i--)
650 Eina_Rectangle *match;
651 Evas_Object *current;
653 int xm1, ym1, xm2, ym2;
655 current = eina_array_data_get(&e->active_objects, i);
657 /* Did we find the video object in the stack ? */
658 if (current == video_parent || current == obj)
661 EINA_RECTANGLE_SET(&self,
662 current->cur.cache.clip.x,
663 current->cur.cache.clip.y,
664 current->cur.cache.clip.w,
665 current->cur.cache.clip.h);
667 /* This doesn't cover the area of the video object, so don't bother with that object */
668 if (!eina_rectangles_intersect(&zone, &self))
671 xc1 = current->cur.cache.clip.x;
672 yc1 = current->cur.cache.clip.y;
673 xc2 = current->cur.cache.clip.x + current->cur.cache.clip.w;
674 yc2 = current->cur.cache.clip.y + current->cur.cache.clip.h;
676 if (evas_object_is_visible(current) &&
677 (!current->clip.clipees) &&
678 (current->cur.visible) &&
679 (!current->delete_me) &&
680 (current->cur.cache.clip.visible) &&
681 (!current->smart.smart))
683 Eina_Bool included = EINA_FALSE;
685 if (evas_object_is_opaque(current) ||
686 ((current->func->has_opaque_rect) &&
687 (current->func->has_opaque_rect(current))))
689 /* The object is opaque */
691 /* Check if the opaque object is inside another opaque object */
692 EINA_LIST_FOREACH(opaques, l, match)
696 xm2 = match->x + match->w;
697 ym2 = match->y + match->h;
699 /* Both object are included */
700 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
702 included = EINA_TRUE;
707 /* Not included yet */
713 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
714 current->cur.cache.clip.w, current->cur.cache.clip.h);
716 opaques = eina_list_append(opaques, r);
721 /* Remove all the transparent object that are covered by the new opaque object */
722 EINA_LIST_FOREACH_SAFE(alphas, l, ln, match)
726 xm2 = match->x + match->w;
727 ym2 = match->y + match->h;
729 if (xm1 >= r->x && ym1 >= r->y && xm2 <= xn2 && ym2 <= yn2)
731 /* The new rectangle is over some transparent object,
732 so remove the transparent object */
733 alphas = eina_list_remove_list(alphas, l);
740 /* The object has some transparency */
742 /* Check if the transparent object is inside any other transparent object */
743 EINA_LIST_FOREACH(alphas, l, match)
747 xm2 = match->x + match->w;
748 ym2 = match->y + match->h;
750 /* Both object are included */
751 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
753 included = EINA_TRUE;
758 /* If not check if it is inside any opaque one */
761 EINA_LIST_FOREACH(opaques, l, match)
765 xm2 = match->x + match->w;
766 ym2 = match->y + match->h;
768 /* Both object are included */
769 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
771 included = EINA_TRUE;
777 /* No inclusion at all, so add it */
780 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
781 current->cur.cache.clip.w, current->cur.cache.clip.h);
783 alphas = eina_list_append(alphas, r);
789 /* If there is any pending transparent object, then no overlay */
790 nooverlay = !!eina_list_count(alphas);
792 EINA_LIST_FREE(alphas, r)
793 eina_rectangle_free(r);
794 EINA_LIST_FREE(opaques, r)
795 eina_rectangle_free(r);
804 evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
805 int off_x, int off_y, int mapped,
806 int ecx, int ecy, int ecw, int ech
814 Eina_Bool clean_them = EINA_FALSE;
816 evas_object_clip_recalc(obj);
819 RD(" { evas_render_mapped(%p, %p, %p, %p, %i, %i, %i, %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
822 if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
823 (obj->cur.have_clipees))
830 else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
831 (_evas_render_can_render(obj))))
839 // set render_pre - for child objs that may not have gotten it.
840 obj->pre_render_done = EINA_TRUE;
841 RD(" Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map,
842 obj->func->can_map ? obj->func->can_map(obj): -1,
843 obj->cur.map, obj->cur.usemap,
844 _evas_render_has_map(obj));
845 if (_evas_render_has_map(obj))
848 Eina_Bool changed = EINA_FALSE, rendered = EINA_FALSE;
850 clean_them = EINA_TRUE;
852 sw = obj->cur.geometry.w;
853 sh = obj->cur.geometry.h;
855 RD(" mapped obj: %ix%i\n", sw, sh);
856 if ((sw <= 0) || (sh <= 0))
862 evas_object_map_update(obj, off_x, off_y, sw, sh, sw, sh);
864 if (obj->cur.map->surface)
866 if ((obj->cur.map->surface_w != sw) ||
867 (obj->cur.map->surface_h != sh))
870 RD(" new surf: %ix%i\n", sw, sh);
871 obj->layer->evas->engine.func->image_map_surface_free
872 (e->engine.data.output, obj->cur.map->surface);
873 obj->cur.map->surface = NULL;
876 if (!obj->cur.map->surface)
878 obj->cur.map->surface_w = sw;
879 obj->cur.map->surface_h = sh;
881 obj->cur.map->surface =
882 obj->layer->evas->engine.func->image_map_surface_new
883 (e->engine.data.output, obj->cur.map->surface_w,
884 obj->cur.map->surface_h,
885 obj->cur.map->alpha);
887 RD(" fisrt surf: %ix%i\n", sw, sh);
890 if (obj->smart.smart)
894 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), o2)
896 if (!evas_object_is_visible(o2) &&
897 !evas_object_was_visible(o2))
899 evas_object_change_reset(o2);
905 evas_object_change_reset(o2);
909 if (obj->changed_color) changed = EINA_TRUE;
910 evas_object_change_reset(obj);
912 else if (obj->changed)
914 if (((obj->changed_pchange) && (obj->changed_map)) ||
915 (obj->changed_color))
917 evas_object_change_reset(obj);
920 /* mark the old map as invalid, so later we don't reuse it as a
922 if (changed && obj->prev.map)
923 obj->prev.valid_map = EINA_FALSE;
925 // clear surface before re-render
926 if ((changed) && (obj->cur.map->surface))
931 RD(" children redraw\n");
932 // FIXME: calculate "changes" within map surface and only clear
933 // and re-render those
934 if (obj->cur.map->alpha)
936 ctx = e->engine.func->context_new(e->engine.data.output);
937 e->engine.func->context_color_set
938 (e->engine.data.output, ctx, 0, 0, 0, 0);
939 e->engine.func->context_render_op_set
940 (e->engine.data.output, ctx, EVAS_RENDER_COPY);
941 e->engine.func->rectangle_draw(e->engine.data.output,
943 obj->cur.map->surface,
945 obj->cur.map->surface_w,
946 obj->cur.map->surface_h);
947 e->engine.func->context_free(e->engine.data.output, ctx);
949 ctx = e->engine.func->context_new(e->engine.data.output);
950 off_x2 = -obj->cur.geometry.x;
951 off_y2 = -obj->cur.geometry.y;
952 if (obj->smart.smart)
955 (evas_object_smart_members_get_direct(obj), obj2)
957 clean_them |= evas_render_mapped(e, obj2, ctx,
958 obj->cur.map->surface,
969 int x = 0, y = 0, w = 0, h = 0;
971 w = obj->cur.map->surface_w;
972 h = obj->cur.map->surface_h;
973 RECTS_CLIP_TO_RECT(x, y, w, h,
974 obj->cur.geometry.x + off_x2,
975 obj->cur.geometry.y + off_y2,
977 obj->cur.geometry.h);
979 e->engine.func->context_clip_set(e->engine.data.output,
981 obj->func->render(obj, e->engine.data.output, ctx,
982 obj->cur.map->surface, off_x2, off_y2);
984 e->engine.func->context_free(e->engine.data.output, ctx);
985 rendered = EINA_TRUE;
993 obj->cur.map->surface = e->engine.func->image_dirty_region
994 (e->engine.data.output, obj->cur.map->surface,
995 0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
996 obj->cur.valid_map = EINA_TRUE;
998 e->engine.func->context_clip_unset(e->engine.data.output,
1000 if (obj->cur.map->surface)
1002 if (obj->smart.smart)
1004 if (obj->cur.clipper)
1009 obj->cur.cache.clip.dirty = EINA_TRUE;
1010 tobj = obj->cur.map_parent;
1011 obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
1012 evas_object_clip_recalc(obj);
1013 obj->cur.map_parent = tobj;
1014 x = obj->cur.cache.clip.x;
1015 y = obj->cur.cache.clip.y;
1016 w = obj->cur.cache.clip.w;
1017 h = obj->cur.cache.clip.h;
1018 RECTS_CLIP_TO_RECT(x, y, w, h,
1019 obj->cur.clipper->cur.cache.clip.x,
1020 obj->cur.clipper->cur.cache.clip.y,
1021 obj->cur.clipper->cur.cache.clip.w,
1022 obj->cur.clipper->cur.cache.clip.h);
1023 e->engine.func->context_clip_set(e->engine.data.output,
1025 x + off_x, y + off_y, w, h);
1030 if (obj->cur.clipper)
1034 evas_object_clip_recalc(obj);
1035 x = obj->cur.cache.clip.x;
1036 y = obj->cur.cache.clip.y;
1037 w = obj->cur.cache.clip.w;
1038 h = obj->cur.cache.clip.h;
1039 RECTS_CLIP_TO_RECT(x, y, w, h,
1040 obj->cur.clipper->cur.cache.clip.x,
1041 obj->cur.clipper->cur.cache.clip.y,
1042 obj->cur.clipper->cur.cache.clip.w,
1043 obj->cur.clipper->cur.cache.clip.h);
1044 e->engine.func->context_clip_set(e->engine.data.output,
1046 x + off_x, y + off_y, w, h);
1050 // if (surface == e->engine.data.output)
1051 e->engine.func->context_clip_clip(e->engine.data.output,
1053 ecx, ecy, ecw, ech);
1054 if (obj->cur.cache.clip.visible)
1056 obj->layer->evas->engine.func->context_multiplier_unset
1057 (e->engine.data.output, context);
1058 obj->layer->evas->engine.func->image_map_draw
1059 (e->engine.data.output, context, surface,
1060 obj->cur.map->surface, obj->spans,
1061 obj->cur.map->smooth, 0);
1063 // FIXME: needs to cache these maps and
1064 // keep them only rendering updates
1065 // obj->layer->evas->engine.func->image_map_surface_free
1066 // (e->engine.data.output, obj->cur.map->surface);
1067 // obj->cur.map->surface = NULL;
1071 if (0 && obj->cur.cached_surface)
1072 fprintf(stderr, "We should cache '%s' [%i, %i, %i, %i]\n",
1073 evas_object_type_get(obj),
1074 obj->cur.bounding_box.x, obj->cur.bounding_box.x,
1075 obj->cur.bounding_box.w, obj->cur.bounding_box.h);
1079 RD(" draw child of mapped obj\n");
1080 ctx = e->engine.func->context_new(e->engine.data.output);
1081 if (obj->smart.smart)
1084 (evas_object_smart_members_get_direct(obj), obj2)
1086 clean_them |= evas_render_mapped(e, obj2, ctx,
1100 if (obj->cur.clipper)
1102 RD(" clip: %i %i %ix%i [%i %i %ix%i]\n",
1103 obj->cur.cache.clip.x + off_x,
1104 obj->cur.cache.clip.y + off_y,
1105 obj->cur.cache.clip.w,
1106 obj->cur.cache.clip.h,
1107 obj->cur.geometry.x + off_x,
1108 obj->cur.geometry.y + off_y,
1109 obj->cur.geometry.w,
1110 obj->cur.geometry.h);
1112 RD(" clipper: %i %i %ix%i\n",
1113 obj->cur.clipper->cur.cache.clip.x + off_x,
1114 obj->cur.clipper->cur.cache.clip.y + off_y,
1115 obj->cur.clipper->cur.cache.clip.w,
1116 obj->cur.clipper->cur.cache.clip.h);
1120 if (_evas_render_has_map(obj))
1121 evas_object_clip_recalc(obj);
1123 x = obj->cur.cache.clip.x + off_x;
1124 y = obj->cur.cache.clip.y + off_y;
1125 w = obj->cur.cache.clip.w;
1126 h = obj->cur.cache.clip.h;
1128 RECTS_CLIP_TO_RECT(x, y, w, h,
1129 obj->cur.clipper->cur.cache.clip.x + off_x,
1130 obj->cur.clipper->cur.cache.clip.y + off_y,
1131 obj->cur.clipper->cur.cache.clip.w,
1132 obj->cur.clipper->cur.cache.clip.h);
1134 e->engine.func->context_clip_set(e->engine.data.output,
1137 obj->func->render(obj, e->engine.data.output, ctx,
1138 surface, off_x, off_y);
1140 e->engine.func->context_free(e->engine.data.output, ctx);
1144 if (obj->cur.clipper)
1148 if (_evas_render_has_map(obj))
1149 evas_object_clip_recalc(obj);
1150 x = obj->cur.cache.clip.x;
1151 y = obj->cur.cache.clip.y;
1152 w = obj->cur.cache.clip.w;
1153 h = obj->cur.cache.clip.h;
1154 RECTS_CLIP_TO_RECT(x, y, w, h,
1155 obj->cur.clipper->cur.cache.clip.x,
1156 obj->cur.clipper->cur.cache.clip.y,
1157 obj->cur.clipper->cur.cache.clip.w,
1158 obj->cur.clipper->cur.cache.clip.h);
1159 e->engine.func->context_clip_set(e->engine.data.output,
1161 x + off_x, y + off_y, w, h);
1162 e->engine.func->context_clip_clip(e->engine.data.output,
1164 ecx, ecy, ecw, ech);
1168 RD(" draw normal obj\n");
1169 obj->func->render(obj, e->engine.data.output, context, surface,
1172 if (obj->changed_map) clean_them = EINA_TRUE;
1181 _evas_render_cutout_add(Evas *e, Evas_Object *obj, int off_x, int off_y)
1183 if (evas_object_is_opaque(obj))
1185 Evas_Coord cox, coy, cow, coh;
1187 cox = obj->cur.cache.clip.x;
1188 coy = obj->cur.cache.clip.y;
1189 cow = obj->cur.cache.clip.w;
1190 coh = obj->cur.cache.clip.h;
1191 if ((obj->cur.map) && (obj->cur.usemap))
1196 while (oo->cur.clipper)
1198 if ((oo->cur.clipper->cur.map_parent
1199 != oo->cur.map_parent) &&
1200 (!((oo->cur.map) && (oo->cur.usemap))))
1202 RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
1206 oo->cur.geometry.h);
1207 oo = oo->cur.clipper;
1210 e->engine.func->context_cutout_add
1211 (e->engine.data.output, e->engine.data.context,
1212 cox + off_x, coy + off_y, cow, coh);
1216 if (obj->func->get_opaque_rect)
1218 Evas_Coord obx, oby, obw, obh;
1220 obj->func->get_opaque_rect(obj, &obx, &oby, &obw, &obh);
1221 if ((obw > 0) && (obh > 0))
1225 RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1226 obj->cur.cache.clip.x + off_x,
1227 obj->cur.cache.clip.y + off_y,
1228 obj->cur.cache.clip.w,
1229 obj->cur.cache.clip.h);
1230 e->engine.func->context_cutout_add
1231 (e->engine.data.output, e->engine.data.context,
1232 obx, oby, obw, obh);
1239 evas_render_updates_internal(Evas *e,
1240 unsigned char make_updates,
1241 unsigned char do_draw)
1244 Eina_List *updates = NULL;
1247 Eina_Bool clean_them = EINA_FALSE;
1254 Eina_Bool haveup = 0;
1256 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1259 if (!e->changed) return NULL;
1262 if (evas_cserve2_use_get())
1263 evas_cserve2_dispatch();
1265 evas_call_smarts_calculate(e);
1267 RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
1269 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_PRE, NULL);
1271 /* Check if the modified object mean recalculating every thing */
1273 _evas_render_check_pending_objects(&e->pending_objects, e);
1275 /* phase 1. add extra updates for changed objects */
1276 if (e->invalidate || e->render_objects.count <= 0)
1277 clean_them = _evas_render_phase1_process(e,
1279 &e->restack_objects,
1284 /* phase 1.5. check if the video should be inlined or stay in their overlay */
1285 alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1286 e->engine.data.context);
1288 EINA_LIST_FOREACH(e->video_objects, ll, obj)
1290 /* we need the surface to be transparent to display the underlying overlay */
1291 if (alpha && _evas_render_can_use_overlay(e, obj))
1292 _evas_object_image_video_overlay_show(obj);
1294 _evas_object_image_video_overlay_hide(obj);
1296 /* phase 1.8. pre render for proxy */
1297 _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
1298 &e->delete_objects, &e->render_objects);
1300 /* phase 2. force updates for restacks */
1301 for (i = 0; i < e->restack_objects.count; ++i)
1303 obj = eina_array_data_get(&e->restack_objects, i);
1304 obj->func->render_pre(obj);
1305 _evas_render_prev_cur_clip_cache_add(e, obj);
1307 eina_array_clean(&e->restack_objects);
1309 /* phase 3. add exposes */
1310 EINA_LIST_FREE(e->damages, r)
1312 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1313 r->x, r->y, r->w, r->h);
1314 eina_rectangle_free(r);
1317 /* phase 4. framespace, output & viewport changes */
1318 if (e->viewport.changed)
1320 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1322 e->output.w, e->output.h);
1324 if (e->output.changed)
1326 e->engine.func->output_resize(e->engine.data.output,
1327 e->output.w, e->output.h);
1328 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1330 e->output.w, e->output.h);
1332 if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1334 ERR("viewport size != output size!");
1337 if (e->framespace.changed)
1341 fx = e->viewport.x - e->framespace.x;
1342 fy = e->viewport.y - e->framespace.y;
1343 fw = e->viewport.w + e->framespace.w;
1344 fh = e->viewport.h + e->framespace.h;
1347 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1351 /* phase 4.5: check if object is not in framespace. if not, we need to clip
1352 * it to the 'master' clip.
1354 * NB: This is for the wayland engine(s). If we do not do this, then
1355 * objects will draw outside the viewport and potentially onto the frame
1357 if (!strncmp(e->engine.module->definition->name, "wayland", 7))
1359 Eina_Rectangle clip_rect;
1361 /* see if the master clip has been added yet, if not, then create */
1362 if (!e->framespace.clip)
1364 e->framespace.clip = evas_object_rectangle_add(e);
1365 evas_object_color_set(e->framespace.clip, 255, 255, 255, 255);
1366 evas_object_move(e->framespace.clip,
1367 e->framespace.x, e->framespace.y);
1368 evas_object_resize(e->framespace.clip,
1369 e->viewport.w - e->framespace.w,
1370 e->viewport.h - e->framespace.h);
1371 evas_object_show(e->framespace.clip);
1375 /* master clip is already present. check for size changes in the
1376 * viewport, and update master clip size if needed */
1377 if ((e->viewport.changed) || (e->output.changed))
1379 evas_object_resize(e->framespace.clip,
1380 e->viewport.w - e->framespace.w,
1381 e->viewport.h - e->framespace.h);
1385 EINA_RECTANGLE_SET(&clip_rect,
1386 e->framespace.clip->cur.geometry.x,
1387 e->framespace.clip->cur.geometry.y,
1388 e->framespace.clip->cur.geometry.w,
1389 e->framespace.clip->cur.geometry.h)
1391 /* With the master clip all setup, we need to loop the objects on this
1392 * canvas and determine if the object is in the viewport space. If it
1393 * is in the viewport space (and not in framespace), then we need to
1394 * clip the object to the master clip so that it does not draw on top
1395 * of the frame (eg: elm 3d test) */
1396 for (i = 0; i < e->render_objects.count; ++i)
1398 Eina_Rectangle obj_rect;
1401 obj = eina_array_data_get(&e->render_objects, i);
1402 if (evas_object_is_frame_object_get(obj))
1405 EINA_RECTANGLE_SET(&obj_rect,
1406 obj->cur.geometry.x, obj->cur.geometry.y,
1407 obj->cur.geometry.w, obj->cur.geometry.h);
1409 /* if the object does not intersect our clip rect, ignore it */
1410 if (!eina_rectangles_intersect(&clip_rect, &obj_rect))
1413 if (!(pclip = evas_object_clip_get(obj)))
1415 /* clip this object so it does not draw on the window frame */
1416 evas_object_clip_set(obj, e->framespace.clip);
1423 e->engine.func->output_redraws_rect_add(e->engine.data.output, 0, 0,
1424 e->output.w, e->output.h);
1427 /* phase 5. add obscures */
1428 EINA_LIST_FOREACH(e->obscures, ll, r)
1430 e->engine.func->output_redraws_rect_del(e->engine.data.output,
1431 r->x, r->y, r->w, r->h);
1433 /* build obscure objects list of active objects that obscure */
1434 for (i = 0; i < e->active_objects.count; ++i)
1436 obj = eina_array_data_get(&e->active_objects, i);
1437 if (UNLIKELY((evas_object_is_opaque(obj) ||
1438 ((obj->func->has_opaque_rect) &&
1439 (obj->func->has_opaque_rect(obj)))) &&
1440 evas_object_is_visible(obj) &&
1441 (!obj->clip.clipees) &&
1442 (obj->cur.visible) &&
1443 (!obj->delete_me) &&
1444 (obj->cur.cache.clip.visible) &&
1445 (!obj->smart.smart)))
1446 /* obscuring_objects = eina_list_append(obscuring_objects, obj); */
1447 eina_array_push(&e->obscuring_objects, obj);
1450 /* save this list */
1451 /* obscuring_objects_orig = obscuring_objects; */
1452 /* obscuring_objects = NULL; */
1453 /* phase 6. go thru each update rect and render objects in it*/
1456 unsigned int offset = 0;
1459 e->engine.func->output_redraws_next_update_get
1460 (e->engine.data.output,
1462 &cx, &cy, &cw, &ch)))
1466 RD(" [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1469 Eina_Rectangle *rect;
1471 NEW_RECT(rect, ux, uy, uw, uh);
1473 updates = eina_list_append(updates, rect);
1478 /* build obscuring objects list (in order from bottom to top) */
1481 e->engine.func->context_clip_set(e->engine.data.output,
1482 e->engine.data.context,
1483 ux + off_x, uy + off_y, uw, uh);
1485 for (i = 0; i < e->obscuring_objects.count; ++i)
1487 obj = (Evas_Object *)eina_array_data_get
1488 (&e->obscuring_objects, i);
1489 if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1491 eina_array_push(&e->temporary_objects, obj);
1493 /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1495 _evas_render_cutout_add(e, obj, off_x, off_y);
1500 e->engine.func->context_color_set(e->engine.data.output,
1501 e->engine.data.context,
1503 e->engine.func->context_multiplier_unset
1504 (e->engine.data.output, e->engine.data.context);
1505 e->engine.func->context_render_op_set(e->engine.data.output,
1506 e->engine.data.context,
1508 e->engine.func->rectangle_draw(e->engine.data.output,
1509 e->engine.data.context,
1512 e->engine.func->context_cutout_clear(e->engine.data.output,
1513 e->engine.data.context);
1514 e->engine.func->context_clip_unset(e->engine.data.output,
1515 e->engine.data.context);
1518 /* render all object that intersect with rect */
1519 for (i = 0; i < e->active_objects.count; ++i)
1521 obj = eina_array_data_get(&e->active_objects, i);
1523 /* if it's in our outpout rect and it doesn't clip anything */
1524 RD(" OBJ: [%p] '%s' %i %i %ix%i\n", obj, obj->type, obj->cur.geometry.x, obj->cur.geometry.y, obj->cur.geometry.w, obj->cur.geometry.h);
1525 if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1526 (obj->smart.smart)) &&
1527 (!obj->clip.clipees) &&
1528 (obj->cur.visible) &&
1529 (!obj->delete_me) &&
1530 (obj->cur.cache.clip.visible) &&
1531 // (!obj->smart.smart) &&
1532 ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1536 RD(" DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1537 if ((e->temporary_objects.count > offset) &&
1538 (eina_array_data_get(&e->temporary_objects, offset) == obj))
1540 x = cx; y = cy; w = cw; h = ch;
1541 if (((w > 0) && (h > 0)) || (obj->smart.smart))
1543 if (!obj->smart.smart)
1545 RECTS_CLIP_TO_RECT(x, y, w, h,
1546 obj->cur.cache.clip.x + off_x,
1547 obj->cur.cache.clip.y + off_y,
1548 obj->cur.cache.clip.w,
1549 obj->cur.cache.clip.h);
1552 e->engine.func->context_mask_set(e->engine.data.output,
1553 e->engine.data.context,
1554 obj->cur.mask->func->engine_data_get(obj->cur.mask),
1555 obj->cur.mask->cur.geometry.x + off_x,
1556 obj->cur.mask->cur.geometry.y + off_y,
1557 obj->cur.mask->cur.geometry.w,
1558 obj->cur.mask->cur.geometry.h);
1560 e->engine.func->context_mask_unset(e->engine.data.output,
1561 e->engine.data.context);
1562 e->engine.func->context_clip_set(e->engine.data.output,
1563 e->engine.data.context,
1565 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1566 for (j = offset; j < e->temporary_objects.count; ++j)
1570 obj2 = (Evas_Object *)eina_array_data_get
1571 (&e->temporary_objects, j);
1572 _evas_render_cutout_add(e, obj2, off_x, off_y);
1575 clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1576 surface, off_x, off_y, 0,
1583 e->engine.func->context_cutout_clear(e->engine.data.output,
1584 e->engine.data.context);
1588 /* punch rect out */
1589 e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1592 /* free obscuring objects list */
1593 eina_array_clean(&e->temporary_objects);
1599 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1600 e->engine.func->output_flush(e->engine.data.output);
1601 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1605 e->engine.func->output_redraws_clear(e->engine.data.output);
1606 /* and do a post render pass */
1607 for (i = 0; i < e->active_objects.count; ++i)
1609 obj = eina_array_data_get(&e->active_objects, i);
1610 obj->pre_render_done = EINA_FALSE;
1611 RD(" OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1612 if ((obj->changed) && (do_draw))
1614 RD(" OBJ [%p] post... func1\n", obj);
1615 obj->func->render_post(obj);
1616 obj->restack = EINA_FALSE;
1617 evas_object_change_reset(obj);
1619 else if (clean_them)
1621 RD(" OBJ [%p] post... func2\n", obj);
1622 obj->func->render_post(obj);
1623 obj->restack = EINA_FALSE;
1624 evas_object_change_reset(obj);
1626 /* moved to other pre-process phase 1
1627 if (obj->delete_me == 2)
1629 delete_objects = eina_list_append(delete_objects, obj);
1631 else if (obj->delete_me != 0) obj->delete_me++;
1634 /* free our obscuring object list */
1635 eina_array_clean(&e->obscuring_objects);
1637 /* If some object are still marked as changed, do not remove
1638 them from the pending list. */
1639 eina_array_remove(&e->pending_objects, pending_change, NULL);
1641 for (i = 0; i < e->render_objects.count; ++i)
1643 obj = eina_array_data_get(&e->render_objects, i);
1644 obj->pre_render_done = EINA_FALSE;
1647 /* delete all objects flagged for deletion now */
1648 for (i = 0; i < e->delete_objects.count; ++i)
1650 obj = eina_array_data_get(&e->delete_objects, i);
1651 evas_object_free(obj, 1);
1653 eina_array_clean(&e->delete_objects);
1655 e->changed = EINA_FALSE;
1656 e->viewport.changed = EINA_FALSE;
1657 e->output.changed = EINA_FALSE;
1658 e->framespace.changed = EINA_FALSE;
1659 e->invalidate = EINA_FALSE;
1661 // always clean... lots of mem waste!
1662 /* If their are some object to restack or some object to delete,
1663 * it's useless to keep the render object list around. */
1666 eina_array_clean(&e->active_objects);
1667 eina_array_clean(&e->render_objects);
1668 eina_array_clean(&e->restack_objects);
1669 eina_array_clean(&e->temporary_objects);
1670 eina_array_clean(&e->clip_changes);
1671 /* we should flush here and have a mempool system for this
1672 eina_array_flush(&e->active_objects);
1673 eina_array_flush(&e->render_objects);
1674 eina_array_flush(&e->restack_objects);
1675 eina_array_flush(&e->delete_objects);
1676 eina_array_flush(&e->obscuring_objects);
1677 eina_array_flush(&e->temporary_objects);
1678 eina_array_flush(&e->clip_changes);
1680 e->invalidate = EINA_TRUE;
1683 evas_module_clean();
1685 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_POST, NULL);
1693 evas_render_updates_free(Eina_List *updates)
1697 EINA_LIST_FREE(updates, r)
1698 eina_rectangle_free(r);
1702 evas_render_updates(Evas *e)
1704 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1708 if (!e->changed) return NULL;
1709 return evas_render_updates_internal(e, 1, 1);
1713 evas_render(Evas *e)
1715 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1719 if (!e->changed) return;
1720 evas_render_updates_internal(e, 0, 1);
1724 evas_norender(Evas *e)
1726 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1730 // if (!e->changed) return;
1731 evas_render_updates_internal(e, 0, 0);
1735 evas_render_idle_flush(Evas *e)
1737 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1741 evas_fonts_zero_presure(e);
1743 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1744 (e->engine.data.output))
1745 e->engine.func->output_idle_flush(e->engine.data.output);
1747 eina_array_flush(&e->active_objects);
1748 eina_array_flush(&e->render_objects);
1749 eina_array_flush(&e->restack_objects);
1750 eina_array_flush(&e->delete_objects);
1751 eina_array_flush(&e->obscuring_objects);
1752 eina_array_flush(&e->temporary_objects);
1753 eina_array_flush(&e->clip_changes);
1755 e->invalidate = EINA_TRUE;
1765 _evas_render_dump_map_surfaces(Evas_Object *obj)
1767 if ((obj->cur.map) && obj->cur.map->surface)
1769 obj->layer->evas->engine.func->image_map_surface_free
1770 (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1771 obj->cur.map->surface = NULL;
1774 if (obj->smart.smart)
1778 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1779 _evas_render_dump_map_surfaces(obj2);
1784 evas_render_dump(Evas *e)
1788 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1792 EINA_INLIST_FOREACH(e->layers, lay)
1796 EINA_INLIST_FOREACH(lay->objects, obj)
1798 if ((obj->type) && (!strcmp(obj->type, "image")))
1799 evas_object_inform_call_image_unloaded(obj);
1800 _evas_render_dump_map_surfaces(obj);
1803 if ((e->engine.func) && (e->engine.func->output_dump) &&
1804 (e->engine.data.output))
1805 e->engine.func->output_dump(e->engine.data.output);
1809 evas_render_invalidate(Evas *e)
1811 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1815 eina_array_clean(&e->active_objects);
1816 eina_array_clean(&e->render_objects);
1818 eina_array_flush(&e->restack_objects);
1819 eina_array_flush(&e->delete_objects);
1821 e->invalidate = EINA_TRUE;
1825 evas_render_object_recalc(Evas_Object *obj)
1827 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1831 if ((!obj->changed) && (obj->delete_me < 2))
1835 e = obj->layer->evas;
1836 if ((!e) || (e->cleanup)) return;
1837 eina_array_push(&e->pending_objects, obj);
1838 obj->changed = EINA_TRUE;
1842 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/