1 #include "evas_common.h"
2 #include "evas_private.h"
9 static FILE *dbf = NULL;
12 rend_dbg(const char *txt)
19 dbf = fopen("EVAS-RENDER-DEBUG.log", "w");
28 char __tmpbuf[4096]; \
30 snprintf(__tmpbuf, sizeof(__tmpbuf), ##args); \
35 char __tmpbuf[4096]; int __tmpi; \
36 for (__tmpi = 0; __tmpi < xxxx; __tmpi++) \
37 __tmpbuf[__tmpi] = ' '; \
38 __tmpbuf[__tmpi] = 0; \
47 evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char do_draw);
50 * Add a damage rectangle.
52 * @param e The given canvas pointer.
53 * @param x The rectangle's left position.
54 * @param y The rectangle's top position.
55 * @param w The rectangle's width.
56 * @param h The rectangle's height.
58 * This is the function by which one tells evas that a part of the
59 * canvas has to be repainted.
61 * @ingroup Evas_Canvas
64 evas_damage_rectangle_add(Evas *e, int x, int y, int w, int h)
68 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
71 NEW_RECT(r, x, y, w, h);
73 e->damages = eina_list_append(e->damages, r);
78 * Add an obscured region.
80 * @param e The given canvas pointer.
81 * @param x The rectangle's left position.
82 * @param y The rectangle's top position
83 * @param w The rectangle's width.
84 * @param h The rectangle's height.
86 * This is the function by which one tells evas that a part of the
87 * canvas has not to be repainted. To make this region one that have
88 * to be repainted, call the function evas_obscured_clear().
90 * @see evas_obscured_clear().
92 * @ingroup Evas_Canvas
95 evas_obscured_rectangle_add(Evas *e, int x, int y, int w, int h)
99 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
102 NEW_RECT(r, x, y, w, h);
104 e->obscures = eina_list_append(e->obscures, r);
108 * Remove all obscured region rectangles from the canvas.
110 * @param e The given canvas pointer.
112 * This function removes all the rectangles from the obscured list of
113 * the canvas. It takes obscured areas added with
114 * evas_obscured_rectangle_add() and makes it a region that have to be
117 * @ingroup Evas_Canvas
120 evas_obscured_clear(Evas *e)
124 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
127 EINA_LIST_FREE(e->obscures, r)
129 eina_rectangle_free(r);
134 _evas_render_has_map(Evas_Object *obj)
136 return ((!((obj->func->can_map) && (obj->func->can_map(obj)))) &&
137 ((obj->cur.map) && (obj->cur.usemap)));
138 // return ((obj->cur.map) && (obj->cur.usemap));
142 _evas_render_had_map(Evas_Object *obj)
144 return ((obj->prev.map) && (obj->prev.usemap));
145 // return ((!obj->cur.map) && (obj->prev.usemap));
149 _evas_render_is_relevant(Evas_Object *obj)
151 return ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
152 (evas_object_was_visible(obj) && (!obj->prev.have_clipees)));
156 _evas_render_can_render(Evas_Object *obj)
158 return (evas_object_is_visible(obj) && (!obj->cur.have_clipees));
162 _evas_render_prev_cur_clip_cache_add(Evas *e, Evas_Object *obj)
164 e->engine.func->output_redraws_rect_add(e->engine.data.output,
165 obj->prev.cache.clip.x,
166 obj->prev.cache.clip.y,
167 obj->prev.cache.clip.w,
168 obj->prev.cache.clip.h);
169 e->engine.func->output_redraws_rect_add(e->engine.data.output,
170 obj->cur.cache.clip.x,
171 obj->cur.cache.clip.y,
172 obj->cur.cache.clip.w,
173 obj->cur.cache.clip.h);
177 _evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
179 e->engine.func->output_redraws_rect_del(e->engine.data.output,
180 obj->cur.cache.clip.x,
181 obj->cur.cache.clip.y,
182 obj->cur.cache.clip.w,
183 obj->cur.cache.clip.h);
187 _evas_render_phase1_direct(Evas *e,
188 Eina_Array *active_objects __UNUSED__,
189 Eina_Array *restack_objects __UNUSED__,
190 Eina_Array *delete_objects __UNUSED__,
191 Eina_Array *render_objects)
197 RD(" [--- PHASE 1 DIRECT\n");
198 for (i = 0; i < render_objects->count; i++)
202 obj = eina_array_data_get(render_objects, i);
203 RD(" OBJ [%p] changed %i\n", obj, obj->changed);
206 /* Flag need redraw on proxy too */
207 evas_object_clip_recalc(obj);
208 obj->func->render_pre(obj);
209 if (obj->proxy.proxies)
211 obj->proxy.redraw = 1;
212 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
213 proxy->func->render_pre(proxy);
215 if (obj->pre_render_done)
217 RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
219 evas_object_smart_members_get_direct(obj),
220 obj->cur.map, obj->cur.usemap,
221 obj->prev.map, obj->prev.usemap,
222 _evas_render_has_map(obj),
223 _evas_render_had_map(obj));
224 if ((obj->smart.smart) &&
225 (_evas_render_has_map(obj)))
227 RD(" has map + smart\n");
228 _evas_render_prev_cur_clip_cache_add(e, obj);
231 else if (_evas_render_had_map(obj))
233 RD(" no pre-render done\n");
234 _evas_render_prev_cur_clip_cache_add(e, obj);
239 if (obj->smart.smart)
241 // obj->func->render_pre(obj);
243 else if (obj->rect_del)
246 _evas_render_cur_clip_cache_del(e, obj);
254 _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
255 Eina_Array *active_objects,
256 Eina_Array *restack_objects,
257 Eina_Array *delete_objects,
258 Eina_Array *render_objects,
259 int restack, int map,
266 Eina_Bool clean_them = EINA_FALSE;
274 #ifndef EVAS_FRAME_QUEUING
275 /* because of clip objects - delete 2 cycles later */
276 if (obj->delete_me == 2)
278 if (obj->delete_me == evas_common_frameq_get_frameq_sz() + 2)
280 eina_array_push(delete_objects, obj);
281 else if (obj->delete_me != 0) obj->delete_me++;
282 /* If the object will be removed, we should not cache anything during this run. */
283 if (obj->delete_me != 0) clean_them = EINA_TRUE;
285 /* build active object list */
286 evas_object_clip_recalc(obj);
287 is_active = evas_object_is_active(obj);
288 obj->is_active = is_active;
291 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);
292 if ((is_active) || (obj->delete_me != 0))
293 eina_array_push(active_objects, obj);
299 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);
303 map = _evas_render_has_map(obj);
304 hmap = _evas_render_had_map(obj);
306 if ((restack) && (!map))
310 eina_array_push(&e->pending_objects, obj);
314 clean_them = EINA_TRUE;
327 evas_object_clip_recalc(obj);
328 if ((obj->restack) &&
329 (is_active) && (!obj->clip.clipees) &&
330 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
331 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
333 eina_array_push(render_objects, obj);
334 _evas_render_prev_cur_clip_cache_add(e, obj);
337 else if ((is_active) && (!obj->clip.clipees) &&
338 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
339 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
341 eina_array_push(render_objects, obj);
342 _evas_render_prev_cur_clip_cache_add(e, obj);
348 else if (_evas_render_had_map(obj))
351 RD(" had map - restack objs\n");
352 // eina_array_push(restack_objects, obj);
353 _evas_render_prev_cur_clip_cache_add(e, obj);
360 if ((obj->cur.map) && (obj->cur.usemap)) map = 1;
370 /* handle normal rendering. this object knows how to handle maps */
373 if (obj->smart.smart)
376 RD(" changed + smart - render ok\n");
377 eina_array_push(render_objects, obj);
379 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
381 _evas_render_phase1_object_process(e, obj2,
397 if ((is_active) && (!obj->clip.clipees) &&
398 _evas_render_is_relevant(obj))
401 RD(" relevant + active\n");
403 eina_array_push(restack_objects, obj);
406 eina_array_push(render_objects, obj);
413 RD(" skip - not smart, not active or clippees or not relevant\n");
419 RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n",
420 evas_object_is_visible(obj),
421 obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart, obj->cur.cache.clip.a,
422 evas_object_was_visible(obj));
423 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
424 (_evas_render_can_render(obj) ||
425 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
427 if (obj->smart.smart)
430 RD(" smart + visible/was visible + not clip\n");
431 eina_array_push(render_objects, obj);
434 (evas_object_smart_members_get_direct(obj), obj2)
436 _evas_render_phase1_object_process(e, obj2,
451 if (evas_object_is_opaque(obj) &&
452 evas_object_is_visible(obj))
455 RD(" opaque + visible\n");
456 eina_array_push(render_objects, obj);
459 else if (evas_object_is_visible(obj))
463 eina_array_push(render_objects, obj);
474 else if (obj->smart.smart)
477 RD(" smart + mot visible/was visible\n");
478 eina_array_push(render_objects, obj);
481 (evas_object_smart_members_get_direct(obj), obj2)
483 _evas_render_phase1_object_process(e, obj2,
498 if (!is_active) obj->restack = 0;
505 _evas_render_phase1_process(Evas *e,
506 Eina_Array *active_objects,
507 Eina_Array *restack_objects,
508 Eina_Array *delete_objects,
509 Eina_Array *render_objects,
513 Eina_Bool clean_them = EINA_FALSE;
515 RD(" [--- PHASE 1\n");
516 EINA_INLIST_FOREACH(e->layers, lay)
520 EINA_INLIST_FOREACH(lay->objects, obj)
522 clean_them |= _evas_render_phase1_object_process
523 (e, obj, active_objects, restack_objects, delete_objects,
524 render_objects, 0, 0, redraw_all
536 _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
540 for (i = 0; i < pending_objects->count; ++i)
543 int is_active, ok = 0;
545 obj = eina_array_data_get(pending_objects, i);
547 if (!obj->layer) goto clean_stuff;
549 evas_object_clip_recalc(obj);
550 is_active = evas_object_is_active(obj);
552 if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
559 if (obj->is_active == is_active)
563 if (obj->smart.smart)
565 if (obj->render_pre || obj->rect_del) ok = 1;
568 if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
569 (_evas_render_can_render(obj) ||
570 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
572 if (!(obj->render_pre || obj->rect_del)) ok = 1;
575 if (is_active && (!obj->clip.clipees) &&
576 (_evas_render_can_render(obj) ||
577 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
579 if (obj->render_pre || obj->rect_del) ok = 1;
584 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
585 (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
586 && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
588 if (obj->rect_del || obj->smart.smart) ok = 1;
596 eina_array_clean(&e->active_objects);
597 eina_array_clean(&e->render_objects);
598 eina_array_clean(&e->restack_objects);
599 eina_array_clean(&e->delete_objects);
607 pending_change(void *data, void *gdata __UNUSED__)
612 if (obj->delete_me) return EINA_FALSE;
613 if (obj->pre_render_done)
615 RD(" OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
616 obj->pre_render_done = 0;
617 //// FIXME: this wipes out changes
619 obj->changed_move_only = 0;
620 obj->changed_nomove = 0;
621 obj->changed_move = 0;
623 return obj->changed ? EINA_TRUE : EINA_FALSE;
627 unchange(Evas_Object *obj)
631 if (!obj->changed) return;
633 obj->changed_move_only = 0;
634 obj->changed_nomove = 0;
635 obj->changed_move = 0;
636 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
643 chlist(Evas_Object *obj, int i)
649 if (!obj->changed) return 0;
650 for (j = 0; j < i; j++) printf(" ");
651 printf("ch2 %p %s %i [%i %i %ix%i] v %i/%i [r%i] %p\n", obj,
653 obj->changed_move_only,
662 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
665 ret |= chlist(obj2, i + 1);
671 evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
672 int off_x, int off_y, int mapped
680 Eina_Bool clean_them = EINA_FALSE;
682 evas_object_clip_recalc(obj);
684 RD(" { evas_render_mapped(%p, %p, %p, %p, %i, %i, %i, %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
687 if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
688 (obj->cur.have_clipees))
695 else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
696 (_evas_render_can_render(obj))))
704 // set render_pre - for child objs that may not have gotten it.
705 obj->pre_render_done = 1;
707 if (_evas_render_has_map(obj))
709 const Evas_Map_Point *p, *p_end;
710 RGBA_Map_Point pts[4], *pt;
712 int changed = 0, rendered = 0;
714 clean_them = EINA_TRUE;
716 sw = obj->cur.geometry.w;
717 sh = obj->cur.geometry.h;
719 RD(" mapped obj: %ix%i\n", sw, sh);
720 if ((sw <= 0) || (sh <= 0))
727 pts[0].px = obj->cur.map->persp.px << FP;
728 pts[0].py = obj->cur.map->persp.py << FP;
729 pts[0].foc = obj->cur.map->persp.foc << FP;
730 pts[0].z0 = obj->cur.map->persp.z0 << FP;
732 p = obj->cur.map->points;
735 for (; p < p_end; p++, pt++)
737 pt->x = (p->x + (double)off_x) * FP1;
738 pt->y = (p->y + (double)off_y) * FP1;
739 pt->z = (p->z) * FP1;
745 if (pt->u < 0) pt->u = 0;
746 else if (pt->u > (sw * FP1)) pt->u = (sw * FP1);
747 if (pt->v < 0) pt->v = 0;
748 else if (pt->v > (sh * FP1)) pt->v = (sh * FP1);
749 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
752 if (obj->cur.map->surface)
754 if ((obj->cur.map->surface_w != sw) ||
755 (obj->cur.map->surface_h != sh))
758 RD(" new surf: %ix%i\n", sw, sh);
759 obj->layer->evas->engine.func->image_map_surface_free
760 (e->engine.data.output, obj->cur.map->surface);
761 obj->cur.map->surface = NULL;
764 if (!obj->cur.map->surface)
766 obj->cur.map->surface_w = sw;
767 obj->cur.map->surface_h = sh;
769 obj->cur.map->surface =
770 obj->layer->evas->engine.func->image_map_surface_new
771 (e->engine.data.output, obj->cur.map->surface_w,
772 obj->cur.map->surface_h,
773 obj->cur.map->alpha);
775 RD(" fisrt surf: %ix%i\n", sw, sh);
778 if (obj->smart.smart)
782 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
784 if (!evas_object_is_visible(obj2) &&
785 !evas_object_was_visible(obj2))
788 obj2->changed_move_only = 0;
789 obj2->changed_nomove = 0;
790 obj2->changed_move = 0;
798 obj2->changed_move_only = 0;
799 obj2->changed_nomove = 0;
800 obj2->changed_move = 0;
806 obj->changed_move_only = 0;
807 obj->changed_nomove = 0;
808 obj->changed_move = 0;
816 obj->changed_move_only = 0;
817 obj->changed_nomove = 0;
818 obj->changed_move = 0;
822 // clear surface before re-render
823 if ((changed) && (obj->cur.map->surface))
828 RD(" children redraw\n");
829 // FIXME: calculate "changes" within map surface and only clear
830 // and re-render those
831 if (obj->cur.map->alpha)
833 ctx = e->engine.func->context_new(e->engine.data.output);
834 e->engine.func->context_color_set
835 (e->engine.data.output, ctx, 0, 0, 0, 0);
836 e->engine.func->context_render_op_set
837 (e->engine.data.output, ctx, EVAS_RENDER_COPY);
838 e->engine.func->rectangle_draw(e->engine.data.output,
840 obj->cur.map->surface,
842 obj->cur.map->surface_w,
843 obj->cur.map->surface_h);
844 e->engine.func->context_free(e->engine.data.output, ctx);
846 ctx = e->engine.func->context_new(e->engine.data.output);
847 off_x2 = -obj->cur.geometry.x;
848 off_y2 = -obj->cur.geometry.y;
849 if (obj->smart.smart)
852 (evas_object_smart_members_get_direct(obj), obj2)
854 clean_them |= evas_render_mapped(e, obj2, ctx,
855 obj->cur.map->surface,
865 int x = 0, y = 0, w = 0, h = 0;
867 w = obj->cur.map->surface_w;
868 h = obj->cur.map->surface_h;
869 RECTS_CLIP_TO_RECT(x, y, w, h,
870 obj->cur.geometry.x + off_x2,
871 obj->cur.geometry.y + off_y2,
873 obj->cur.geometry.h);
874 e->engine.func->context_clip_set(e->engine.data.output,
876 obj->func->render(obj, e->engine.data.output, ctx,
877 obj->cur.map->surface, off_x2, off_y2);
879 e->engine.func->context_free(e->engine.data.output, ctx);
888 obj->cur.map->surface = e->engine.func->image_dirty_region
889 (e->engine.data.output, obj->cur.map->surface,
890 0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
892 e->engine.func->context_clip_unset(e->engine.data.output,
893 e->engine.data.context);
894 if (obj->cur.map->surface)
896 if (obj->smart.smart)
898 if (obj->cur.clipper)
903 obj->cur.cache.clip.dirty = 1;
904 tobj = obj->cur.map_parent;
905 obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
906 evas_object_clip_recalc(obj);
907 obj->cur.map_parent = tobj;
908 x = obj->cur.cache.clip.x;
909 y = obj->cur.cache.clip.y;
910 w = obj->cur.cache.clip.w;
911 h = obj->cur.cache.clip.h;
912 e->engine.func->context_clip_set(e->engine.data.output,
913 e->engine.data.context,
914 x + off_x, y + off_y, w, h);
919 if (obj->cur.clipper)
923 evas_object_clip_recalc(obj);
924 x = obj->cur.cache.clip.x;
925 y = obj->cur.cache.clip.y;
926 w = obj->cur.cache.clip.w;
927 h = obj->cur.cache.clip.h;
928 RECTS_CLIP_TO_RECT(x, y, w, h,
929 obj->cur.clipper->cur.cache.clip.x,
930 obj->cur.clipper->cur.cache.clip.y,
931 obj->cur.clipper->cur.cache.clip.w,
932 obj->cur.clipper->cur.cache.clip.h);
933 e->engine.func->context_clip_set(e->engine.data.output,
934 e->engine.data.context,
935 x + off_x, y + off_y, w, h);
939 if (obj->cur.cache.clip.visible)
940 obj->layer->evas->engine.func->image_map4_draw
941 (e->engine.data.output, e->engine.data.context, surface,
942 obj->cur.map->surface, pts, obj->cur.map->smooth, 0);
943 // FIXME: needs to cache these maps and
944 // keep them only rendering updates
945 // obj->layer->evas->engine.func->image_map_surface_free
946 // (e->engine.data.output, obj->cur.map->surface);
947 // obj->cur.map->surface = NULL;
954 RD(" draw child of mapped obj\n");
955 ctx = e->engine.func->context_new(e->engine.data.output);
956 if (obj->smart.smart)
959 (evas_object_smart_members_get_direct(obj), obj2)
961 clean_them |= evas_render_mapped(e, obj2, ctx,
975 RD(" clip: %i %i %ix%i [%i %i %ix%i]\n",
976 obj->cur.cache.clip.x + off_x,
977 obj->cur.cache.clip.y + off_y,
978 obj->cur.cache.clip.w,
979 obj->cur.cache.clip.h,
980 obj->cur.geometry.x + off_x,
981 obj->cur.geometry.y + off_y,
983 obj->cur.geometry.h);
984 e->engine.func->context_clip_set(e->engine.data.output,
986 obj->cur.cache.clip.x + off_x,
987 obj->cur.cache.clip.y + off_y,
988 obj->cur.cache.clip.w,
989 obj->cur.cache.clip.h);
996 obj->func->render(obj, e->engine.data.output, ctx,
997 surface, off_x, off_y);
999 obj->layer->evas->engine.func->context_color_set(e->engine.data.output,
1002 obj->layer->evas->engine.func->rectangle_draw(e->engine.data.output,
1008 e->engine.func->context_free(e->engine.data.output, ctx);
1013 RD(" draw normal obj\n");
1014 obj->func->render(obj, e->engine.data.output, context, surface,
1025 evas_render_updates_internal(Evas *e,
1026 unsigned char make_updates,
1027 unsigned char do_draw)
1029 Eina_List *updates = NULL;
1032 Eina_Bool clean_them = EINA_FALSE;
1041 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1044 if (!e->changed) return NULL;
1046 evas_call_smarts_calculate(e);
1048 RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
1050 /* Check if the modified object mean recalculating every thing */
1052 _evas_render_check_pending_objects(&e->pending_objects, e);
1054 /* phase 1. add extra updates for changed objects */
1055 if (e->invalidate || e->render_objects.count <= 0)
1056 clean_them = _evas_render_phase1_process(e,
1058 &e->restack_objects,
1063 _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
1064 &e->delete_objects, &e->render_objects);
1066 /* phase 2. force updates for restacks */
1067 for (i = 0; i < e->restack_objects.count; ++i)
1071 obj = eina_array_data_get(&e->restack_objects, i);
1072 obj->func->render_pre(obj);
1073 _evas_render_prev_cur_clip_cache_add(e, obj);
1075 eina_array_clean(&e->restack_objects);
1076 /* phase 3. add exposes */
1077 EINA_LIST_FREE(e->damages, r)
1079 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1080 r->x, r->y, r->w, r->h);
1081 eina_rectangle_free(r);
1083 /* phase 4. output & viewport changes */
1084 if (e->viewport.changed)
1086 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1088 e->output.w, e->output.h);
1090 if (e->output.changed)
1092 e->engine.func->output_resize(e->engine.data.output,
1093 e->output.w, e->output.h);
1094 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1096 e->output.w, e->output.h);
1098 if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1100 ERR("viewport size != output size!");
1104 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1106 e->output.w, e->output.h);
1108 /* phase 5. add obscures */
1109 EINA_LIST_FOREACH(e->obscures, ll, r)
1111 e->engine.func->output_redraws_rect_del(e->engine.data.output,
1112 r->x, r->y, r->w, r->h);
1114 /* build obscure objects list of active objects that obscure */
1115 for (i = 0; i < e->active_objects.count; ++i)
1119 obj = eina_array_data_get(&e->active_objects, i);
1120 if (UNLIKELY((evas_object_is_opaque(obj) ||
1121 ((obj->func->has_opaque_rect) &&
1122 (obj->func->has_opaque_rect(obj)))) &&
1123 evas_object_is_visible(obj) &&
1124 (!obj->clip.clipees) &&
1125 (obj->cur.visible) &&
1126 (!obj->delete_me) &&
1127 (obj->cur.cache.clip.visible) &&
1128 (!obj->smart.smart)))
1129 /* obscuring_objects = eina_list_append(obscuring_objects, obj); */
1130 eina_array_push(&e->obscuring_objects, obj);
1132 /* save this list */
1133 /* obscuring_objects_orig = obscuring_objects; */
1134 /* obscuring_objects = NULL; */
1135 /* phase 6. go thru each update rect and render objects in it*/
1138 unsigned int offset = 0;
1140 alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1141 e->engine.data.context);
1144 e->engine.func->output_redraws_next_update_get
1145 (e->engine.data.output,
1147 &cx, &cy, &cw, &ch)))
1151 RD(" [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1154 Eina_Rectangle *rect;
1156 NEW_RECT(rect, ux, uy, uw, uh);
1158 updates = eina_list_append(updates, rect);
1163 /* build obscuring objects list (in order from bottom to top) */
1164 for (i = 0; i < e->obscuring_objects.count; ++i)
1168 obj = (Evas_Object *)eina_array_data_get
1169 (&e->obscuring_objects, i);
1170 if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1172 eina_array_push(&e->temporary_objects, obj);
1174 /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1177 if (evas_object_is_opaque(obj))
1178 e->engine.func->context_cutout_add
1179 (e->engine.data.output,
1180 e->engine.data.context,
1181 obj->cur.cache.clip.x + off_x,
1182 obj->cur.cache.clip.y + off_y,
1183 obj->cur.cache.clip.w,
1184 obj->cur.cache.clip.h);
1187 if (obj->func->get_opaque_rect)
1189 Evas_Coord obx, oby, obw, obh;
1191 obj->func->get_opaque_rect
1192 (obj, &obx, &oby, &obw, &obh);
1193 if ((obw > 0) && (obh > 0))
1198 (obx, oby, obw, obh,
1199 obj->cur.cache.clip.x + off_x,
1200 obj->cur.cache.clip.y + off_y,
1201 obj->cur.cache.clip.w,
1202 obj->cur.cache.clip.h);
1203 e->engine.func->context_cutout_add
1204 (e->engine.data.output,
1205 e->engine.data.context,
1216 e->engine.func->context_clip_set(e->engine.data.output,
1217 e->engine.data.context,
1219 e->engine.func->context_color_set(e->engine.data.output,
1220 e->engine.data.context,
1222 e->engine.func->context_multiplier_unset
1223 (e->engine.data.output, e->engine.data.context);
1224 e->engine.func->context_render_op_set(e->engine.data.output,
1225 e->engine.data.context,
1227 e->engine.func->rectangle_draw(e->engine.data.output,
1228 e->engine.data.context,
1231 e->engine.func->context_cutout_clear(e->engine.data.output,
1232 e->engine.data.context);
1233 e->engine.func->context_clip_unset(e->engine.data.output,
1234 e->engine.data.context);
1236 /* render all object that intersect with rect */
1237 for (i = 0; i < e->active_objects.count; ++i)
1241 obj = eina_array_data_get(&e->active_objects, i);
1243 /* if it's in our outpout rect and it doesn't clip anything */
1244 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);
1245 if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1246 (obj->smart.smart)) &&
1247 (!obj->clip.clipees) &&
1248 (obj->cur.visible) &&
1249 (!obj->delete_me) &&
1250 (obj->cur.cache.clip.visible) &&
1251 // (!obj->smart.smart) &&
1252 ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1256 RD(" DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1257 if ((e->temporary_objects.count > offset) &&
1258 (eina_array_data_get(&e->temporary_objects, offset) == obj))
1260 x = cx; y = cy; w = cw; h = ch;
1261 if (obj->cur.clipper)
1263 if (_evas_render_has_map(obj))
1265 evas_object_clip_recalc(obj);
1267 /* hmmmm clip seems to kill eweather in elm-test
1268 printf("clip: %4i %4i %4ix%4i to %4i %4i %4ix%4i\n",
1270 obj->cur.cache.clip.x + off_x,
1271 obj->cur.cache.clip.y + off_y,
1272 obj->cur.cache.clip.w,
1273 obj->cur.cache.clip.h);
1275 RECTS_CLIP_TO_RECT(x, y, w, h,
1276 obj->cur.cache.clip.x + off_x,
1277 obj->cur.cache.clip.y + off_y,
1278 obj->cur.cache.clip.w,
1279 obj->cur.cache.clip.h);
1281 if (((w > 0) && (h > 0)) || (obj->smart.smart))
1283 if (!obj->smart.smart)
1285 RECTS_CLIP_TO_RECT(x, y, w, h,
1286 obj->cur.cache.clip.x + off_x,
1287 obj->cur.cache.clip.y + off_y,
1288 obj->cur.cache.clip.w,
1289 obj->cur.cache.clip.h);
1291 if (obj->cur.clipper)
1292 e->engine.func->context_clip_set(e->engine.data.output,
1293 e->engine.data.context,
1296 e->engine.func->context_clip_unset(e->engine.data.output,
1297 e->engine.data.context);
1298 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1299 for (j = offset; j < e->temporary_objects.count; ++j)
1303 obj2 = (Evas_Object *) eina_array_data_get(&e->temporary_objects, j);
1304 if (evas_object_is_opaque(obj2))
1305 e->engine.func->context_cutout_add(e->engine.data.output,
1306 e->engine.data.context,
1307 obj2->cur.cache.clip.x + off_x,
1308 obj2->cur.cache.clip.y + off_y,
1309 obj2->cur.cache.clip.w,
1310 obj2->cur.cache.clip.h);
1313 if (obj2->func->get_opaque_rect)
1315 Evas_Coord obx, oby, obw, obh;
1317 obj2->func->get_opaque_rect
1318 (obj2, &obx, &oby, &obw, &obh);
1319 if ((obw > 0) && (obh > 0))
1323 RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1324 obj2->cur.cache.clip.x + off_x,
1325 obj2->cur.cache.clip.y + off_y,
1326 obj2->cur.cache.clip.w,
1327 obj2->cur.cache.clip.h);
1328 e->engine.func->context_cutout_add(e->engine.data.output,
1329 e->engine.data.context,
1337 e->engine.func->context_clip_set(e->engine.data.output,
1338 e->engine.data.context,
1340 clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1341 surface, off_x, off_y, 0
1346 e->engine.func->context_cutout_clear(e->engine.data.output,
1347 e->engine.data.context);
1351 /* punch rect out */
1352 e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1355 /* free obscuring objects list */
1356 eina_array_clean(&e->temporary_objects);
1362 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1363 e->engine.func->output_flush(e->engine.data.output);
1364 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1368 e->engine.func->output_redraws_clear(e->engine.data.output);
1369 /* and do a post render pass */
1370 for (i = 0; i < e->active_objects.count; ++i)
1374 obj = eina_array_data_get(&e->active_objects, i);
1375 obj->pre_render_done = 0;
1376 RD(" OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1377 if ((obj->changed) && (do_draw))
1379 RD(" OBJ [%p] post... func1\n", obj);
1380 obj->func->render_post(obj);
1383 obj->changed_move_only = 0;
1384 obj->changed_nomove = 0;
1385 obj->changed_move = 0;
1387 else if ((obj->cur.map != obj->prev.map) ||
1388 (obj->cur.usemap != obj->prev.usemap))
1390 RD(" OBJ [%p] post... func2\n", obj);
1391 obj->func->render_post(obj);
1394 obj->changed_move_only = 0;
1395 obj->changed_nomove = 0;
1396 obj->changed_move = 0;
1398 /* moved to other pre-process phase 1
1399 if (obj->delete_me == 2)
1401 delete_objects = eina_list_append(delete_objects, obj);
1403 else if (obj->delete_me != 0) obj->delete_me++;
1406 /* free our obscuring object list */
1407 eina_array_clean(&e->obscuring_objects);
1409 /* If some object are still marked as changed, do not remove
1410 them from the pending list. */
1411 eina_array_remove(&e->pending_objects, pending_change, NULL);
1413 /* delete all objects flagged for deletion now */
1414 for (i = 0; i < e->delete_objects.count; ++i)
1418 obj = eina_array_data_get(&e->delete_objects, i);
1419 evas_object_free(obj, 1);
1421 eina_array_clean(&e->delete_objects);
1424 e->viewport.changed = 0;
1425 e->output.changed = 0;
1428 for (i = 0; i < e->render_objects.count; ++i)
1432 obj = eina_array_data_get(&e->render_objects, i);
1433 obj->pre_render_done = 0;
1436 /* If their are some object to restack or some object to delete,
1437 * it's useless to keep the render object list around. */
1440 eina_array_clean(&e->active_objects);
1441 eina_array_clean(&e->render_objects);
1442 eina_array_clean(&e->restack_objects);
1443 eina_array_clean(&e->delete_objects);
1444 eina_array_clean(&e->obscuring_objects);
1448 evas_module_clean();
1456 * Free the rectangles returned by evas_render_updates().
1458 * @param updates The list of updated rectangles of the canvas.
1460 * This function removes the region from the render updates list. It
1461 * makes the region doesn't be render updated anymore.
1463 * @ingroup Evas_Canvas
1466 evas_render_updates_free(Eina_List *updates)
1470 EINA_LIST_FREE(updates, r)
1471 eina_rectangle_free(r);
1475 * Force immediate renderization of the given canvas.
1477 * @param e The given canvas pointer.
1478 * @return A newly allocated list of updated rectangles of the canvas.
1479 * Free this list with evas_render_updates_free().
1481 * This function forces an immediate renderization update of the given
1484 * @ingroup Evas_Canvas
1487 evas_render_updates(Evas *e)
1489 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1493 #ifdef EVAS_FRAME_QUEUING
1494 evas_common_frameq_flush_ready ();
1497 if (!e->changed) return NULL;
1498 return evas_render_updates_internal(e, 1, 1);
1502 * Force renderization of the given canvas.
1504 * @param e The given canvas pointer.
1506 * @ingroup Evas_Canvas
1509 evas_render(Evas *e)
1511 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1515 #ifdef EVAS_FRAME_QUEUING
1516 evas_common_frameq_flush_ready ();
1519 if (!e->changed) return;
1520 evas_render_updates_internal(e, 0, 1);
1524 * Update the canvas internal objects but not triggering immediate
1527 * @param e The given canvas pointer.
1529 * This function updates the canvas internal objects not triggering
1530 * renderization. To force renderization function evas_render() should
1535 * @ingroup Evas_Canvas
1538 evas_norender(Evas *e)
1540 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1544 // if (!e->changed) return;
1545 evas_render_updates_internal(e, 0, 0);
1549 * Make the canvas discard internally cached data used for rendering.
1551 * @param e The given canvas pointer.
1553 * This function flushes the arrays of delete, active and render objects.
1554 * Other things it may also discard are: shared memory segments,
1555 * temporary scratch buffers, cached data to avoid re-compute of that data etc.
1557 * @ingroup Evas_Canvas
1560 evas_render_idle_flush(Evas *e)
1562 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1566 evas_fonts_zero_presure(e);
1568 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1569 (e->engine.data.output))
1570 e->engine.func->output_idle_flush(e->engine.data.output);
1572 eina_array_flush(&e->delete_objects);
1573 eina_array_flush(&e->active_objects);
1574 eina_array_flush(&e->restack_objects);
1575 eina_array_flush(&e->render_objects);
1576 eina_array_flush(&e->clip_changes);
1584 #ifdef EVAS_FRAME_QUEUING
1585 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1589 evas_common_frameq_flush ();
1596 * Make the canvas discard as much data as possible used by the engine at
1599 * @param e The given canvas pointer.
1601 * This function will unload images, delete textures and much more, where
1602 * possible. You may also want to call evas_render_idle_flush() immediately
1603 * prior to this to perhaps discard a little more, though evas_render_dump()
1604 * should implicitly delete most of what evas_render_idle_flush() might
1607 * @ingroup Evas_Canvas
1610 _evas_render_dump_map_surfaces(Evas_Object *obj)
1612 if ((obj->cur.map) && obj->cur.map->surface)
1614 obj->layer->evas->engine.func->image_map_surface_free
1615 (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1616 obj->cur.map->surface = NULL;
1619 if (obj->smart.smart)
1623 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1624 _evas_render_dump_map_surfaces(obj2);
1629 evas_render_dump(Evas *e)
1633 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1637 EINA_INLIST_FOREACH(e->layers, lay)
1641 EINA_INLIST_FOREACH(lay->objects, obj)
1643 if ((obj->type) && (!strcmp(obj->type, "image")))
1644 evas_object_inform_call_image_unloaded(obj);
1645 _evas_render_dump_map_surfaces(obj);
1648 if ((e->engine.func) && (e->engine.func->output_dump) &&
1649 (e->engine.data.output))
1650 e->engine.func->output_dump(e->engine.data.output);
1654 evas_render_invalidate(Evas *e)
1656 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1660 eina_array_clean(&e->active_objects);
1661 eina_array_clean(&e->render_objects);
1663 eina_array_flush(&e->restack_objects);
1664 eina_array_flush(&e->delete_objects);
1670 evas_render_object_recalc(Evas_Object *obj)
1672 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1676 #ifndef EVAS_FRAME_QUEUING
1677 if ((!obj->changed) && (obj->delete_me < 2))
1679 if ((!obj->changed))
1684 e = obj->layer->evas;
1685 if ((!e) || (e->cleanup)) return;
1686 #ifdef EVAS_FRAME_QUEUING
1687 if (obj->delete_me >= evas_common_frameq_get_frameq_sz() + 2) return;
1689 eina_array_push(&e->pending_objects, obj);
1695 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/