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)
195 RD(" [--- PHASE 1 DIRECT\n");
196 for (i = 0; i < render_objects->count; i++)
200 obj = eina_array_data_get(render_objects, i);
201 RD(" OBJ [%p] changed %i\n", obj, obj->changed);
204 evas_object_clip_recalc(obj);
205 obj->func->render_pre(obj);
206 if (obj->pre_render_done)
208 RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
210 evas_object_smart_members_get_direct(obj),
211 obj->cur.map, obj->cur.usemap,
212 obj->prev.map, obj->prev.usemap,
213 _evas_render_has_map(obj),
214 _evas_render_had_map(obj));
215 if ((obj->smart.smart) &&
216 (_evas_render_has_map(obj)))
218 RD(" has map + smart\n");
219 _evas_render_prev_cur_clip_cache_add(e, obj);
222 else if (_evas_render_had_map(obj))
224 RD(" no pre-render done\n");
225 _evas_render_prev_cur_clip_cache_add(e, obj);
230 if (obj->smart.smart)
232 // obj->func->render_pre(obj);
234 else if (obj->rect_del)
237 _evas_render_cur_clip_cache_del(e, obj);
245 _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
246 Eina_Array *active_objects,
247 Eina_Array *restack_objects,
248 Eina_Array *delete_objects,
249 Eina_Array *render_objects,
250 int restack, int map,
257 Eina_Bool clean_them = EINA_FALSE;
265 #ifndef EVAS_FRAME_QUEUING
266 /* because of clip objects - delete 2 cycles later */
267 if (obj->delete_me == 2)
269 if (obj->delete_me == evas_common_frameq_get_frameq_sz() + 2)
271 eina_array_push(delete_objects, obj);
272 else if (obj->delete_me != 0) obj->delete_me++;
273 /* If the object will be removed, we should not cache anything during this run. */
274 if (obj->delete_me != 0) clean_them = EINA_TRUE;
276 /* build active object list */
277 evas_object_clip_recalc(obj);
278 is_active = evas_object_is_active(obj);
279 obj->is_active = is_active;
282 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);
283 if ((is_active) || (obj->delete_me != 0))
284 eina_array_push(active_objects, obj);
290 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);
294 map = _evas_render_has_map(obj);
295 hmap = _evas_render_had_map(obj);
297 if ((restack) && (!map))
301 eina_array_push(&e->pending_objects, obj);
305 clean_them = EINA_TRUE;
318 evas_object_clip_recalc(obj);
319 if ((obj->restack) &&
320 (is_active) && (!obj->clip.clipees) &&
321 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
322 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
324 eina_array_push(render_objects, obj);
325 _evas_render_prev_cur_clip_cache_add(e, obj);
328 else if ((is_active) && (!obj->clip.clipees) &&
329 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
330 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
332 eina_array_push(render_objects, obj);
333 _evas_render_prev_cur_clip_cache_add(e, obj);
339 else if (_evas_render_had_map(obj))
342 RD(" had map - restack objs\n");
343 // eina_array_push(restack_objects, obj);
344 _evas_render_prev_cur_clip_cache_add(e, obj);
351 if ((obj->cur.map) && (obj->cur.usemap)) map = 1;
361 /* handle normal rendering. this object knows how to handle maps */
364 if (obj->smart.smart)
367 RD(" changed + smart - render ok\n");
368 eina_array_push(render_objects, obj);
370 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
372 _evas_render_phase1_object_process(e, obj2,
388 if ((is_active) && (!obj->clip.clipees) &&
389 _evas_render_is_relevant(obj))
392 RD(" relevant + active\n");
394 eina_array_push(restack_objects, obj);
397 eina_array_push(render_objects, obj);
404 RD(" skip - not smart, not active or clippees or not relevant\n");
410 RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n",
411 evas_object_is_visible(obj),
412 obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart, obj->cur.cache.clip.a,
413 evas_object_was_visible(obj));
414 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
415 (_evas_render_can_render(obj) ||
416 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
418 if (obj->smart.smart)
421 RD(" smart + visible/was visible + not clip\n");
422 eina_array_push(render_objects, obj);
425 (evas_object_smart_members_get_direct(obj), obj2)
427 _evas_render_phase1_object_process(e, obj2,
442 if (evas_object_is_opaque(obj) &&
443 evas_object_is_visible(obj))
446 RD(" opaque + visible\n");
447 eina_array_push(render_objects, obj);
450 else if (evas_object_is_visible(obj))
454 eina_array_push(render_objects, obj);
465 else if (obj->smart.smart)
468 RD(" smart + mot visible/was visible\n");
469 eina_array_push(render_objects, obj);
472 (evas_object_smart_members_get_direct(obj), obj2)
474 _evas_render_phase1_object_process(e, obj2,
489 if (!is_active) obj->restack = 0;
496 _evas_render_phase1_process(Evas *e,
497 Eina_Array *active_objects,
498 Eina_Array *restack_objects,
499 Eina_Array *delete_objects,
500 Eina_Array *render_objects,
504 Eina_Bool clean_them = EINA_FALSE;
506 RD(" [--- PHASE 1\n");
507 EINA_INLIST_FOREACH(e->layers, lay)
511 EINA_INLIST_FOREACH(lay->objects, obj)
513 clean_them |= _evas_render_phase1_object_process
514 (e, obj, active_objects, restack_objects, delete_objects,
515 render_objects, 0, 0, redraw_all
527 _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
531 for (i = 0; i < pending_objects->count; ++i)
534 int is_active, ok = 0;
536 obj = eina_array_data_get(pending_objects, i);
538 if (!obj->layer) goto clean_stuff;
540 evas_object_clip_recalc(obj);
541 is_active = evas_object_is_active(obj);
543 if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
550 if (obj->is_active == is_active)
554 if (obj->smart.smart)
556 if (obj->render_pre || obj->rect_del) ok = 1;
559 if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
560 (_evas_render_can_render(obj) ||
561 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
563 if (!(obj->render_pre || obj->rect_del)) ok = 1;
566 if (is_active && (!obj->clip.clipees) &&
567 (_evas_render_can_render(obj) ||
568 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
570 if (obj->render_pre || obj->rect_del) ok = 1;
575 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
576 (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
577 && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
579 if (obj->rect_del || obj->smart.smart) ok = 1;
587 eina_array_clean(&e->active_objects);
588 eina_array_clean(&e->render_objects);
589 eina_array_clean(&e->restack_objects);
590 eina_array_clean(&e->delete_objects);
598 pending_change(void *data, void *gdata __UNUSED__)
603 if (obj->delete_me) return EINA_FALSE;
604 if (obj->pre_render_done)
606 RD(" OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
607 obj->pre_render_done = 0;
608 //// FIXME: this wipes out changes
611 return obj->changed ? EINA_TRUE : EINA_FALSE;
615 evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
616 int off_x, int off_y, int mapped
624 Eina_Bool clean_them = EINA_FALSE;
626 evas_object_clip_recalc(obj);
628 RD(" { evas_render_mapped(%p, %p, %p, %p, %i, %i, %i, %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
631 if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
632 (obj->cur.have_clipees))
639 else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
640 (_evas_render_can_render(obj))))
648 // set render_pre - for child objs that may not have gotten it.
649 obj->pre_render_done = 1;
651 if (_evas_render_has_map(obj))
653 const Evas_Map_Point *p, *p_end;
654 RGBA_Map_Point pts[4], *pt;
656 int changed = 0, rendered = 0;
658 clean_them = EINA_TRUE;
660 sw = obj->cur.geometry.w;
661 sh = obj->cur.geometry.h;
663 RD(" mapped obj: %ix%i\n", sw, sh);
664 if ((sw <= 0) || (sh <= 0))
671 pts[0].px = obj->cur.map->persp.px << FP;
672 pts[0].py = obj->cur.map->persp.py << FP;
673 pts[0].foc = obj->cur.map->persp.foc << FP;
674 pts[0].z0 = obj->cur.map->persp.z0 << FP;
676 p = obj->cur.map->points;
679 for (; p < p_end; p++, pt++)
681 pt->x = (p->x + off_x) << FP;
682 pt->y = (p->y + off_y) << FP;
683 pt->z = (p->z) << FP;
684 pt->x3 = p->px << FP;
685 pt->y3 = p->py << FP;
688 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
691 if (obj->cur.map->surface)
693 if ((obj->cur.map->surface_w != sw) ||
694 (obj->cur.map->surface_h != sh))
697 RD(" new surf: %ix%i\n", sw, sh);
698 obj->layer->evas->engine.func->image_map_surface_free
699 (e->engine.data.output, obj->cur.map->surface);
700 obj->cur.map->surface = NULL;
703 if (!obj->cur.map->surface)
705 obj->cur.map->surface_w = sw;
706 obj->cur.map->surface_h = sh;
708 obj->cur.map->surface =
709 obj->layer->evas->engine.func->image_map_surface_new
710 (e->engine.data.output, obj->cur.map->surface_w,
711 obj->cur.map->surface_h,
712 obj->cur.map->alpha);
714 RD(" fisrt surf: %ix%i\n", sw, sh);
717 if (obj->smart.smart)
721 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
723 if (!evas_object_is_visible(obj2) &&
724 !evas_object_was_visible(obj2))
747 // clear surface before re-render
748 if ((changed) && (obj->cur.map->surface))
753 RD(" children redraw\n");
754 // FIXME: calculate "changes" within map surface and only clear
755 // and re-render those
756 if (obj->cur.map->alpha)
758 ctx = e->engine.func->context_new(e->engine.data.output);
759 e->engine.func->context_color_set
760 (e->engine.data.output, ctx, 0, 0, 0, 0);
761 e->engine.func->context_render_op_set
762 (e->engine.data.output, ctx, EVAS_RENDER_COPY);
763 e->engine.func->rectangle_draw(e->engine.data.output,
765 obj->cur.map->surface,
767 obj->cur.map->surface_w,
768 obj->cur.map->surface_h);
769 e->engine.func->context_free(e->engine.data.output, ctx);
771 ctx = e->engine.func->context_new(e->engine.data.output);
772 off_x2 = -obj->cur.geometry.x;
773 off_y2 = -obj->cur.geometry.y;
774 if (obj->smart.smart)
777 (evas_object_smart_members_get_direct(obj), obj2)
779 clean_them |= evas_render_mapped(e, obj2, ctx,
780 obj->cur.map->surface,
790 int x = 0, y = 0, w = 0, h = 0;
792 w = obj->cur.map->surface_w;
793 h = obj->cur.map->surface_h;
794 RECTS_CLIP_TO_RECT(x, y, w, h,
795 obj->cur.geometry.x + off_x2,
796 obj->cur.geometry.y + off_y2,
798 obj->cur.geometry.h);
799 e->engine.func->context_clip_set(e->engine.data.output,
801 obj->func->render(obj, e->engine.data.output, ctx,
802 obj->cur.map->surface, off_x2, off_y2);
804 e->engine.func->context_free(e->engine.data.output, ctx);
813 obj->cur.map->surface = e->engine.func->image_dirty_region
814 (e->engine.data.output, obj->cur.map->surface,
815 0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
817 e->engine.func->context_clip_unset(e->engine.data.output,
818 e->engine.data.context);
819 if (obj->cur.map->surface)
821 if (obj->smart.smart)
823 if (obj->cur.clipper)
828 obj->cur.cache.clip.dirty = 1;
829 tobj = obj->cur.map_parent;
830 obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
831 evas_object_clip_recalc(obj);
832 obj->cur.map_parent = tobj;
833 x = obj->cur.cache.clip.x;
834 y = obj->cur.cache.clip.y;
835 w = obj->cur.cache.clip.w;
836 h = obj->cur.cache.clip.h;
837 e->engine.func->context_clip_set(e->engine.data.output,
838 e->engine.data.context,
839 x + off_x, y + off_y, w, h);
844 if (obj->cur.clipper)
848 evas_object_clip_recalc(obj);
849 x = obj->cur.cache.clip.x;
850 y = obj->cur.cache.clip.y;
851 w = obj->cur.cache.clip.w;
852 h = obj->cur.cache.clip.h;
853 RECTS_CLIP_TO_RECT(x, y, w, h,
854 obj->cur.clipper->cur.cache.clip.x + off_x,
855 obj->cur.clipper->cur.cache.clip.y + off_y,
856 obj->cur.clipper->cur.cache.clip.w,
857 obj->cur.clipper->cur.cache.clip.h);
858 e->engine.func->context_clip_set(e->engine.data.output,
859 e->engine.data.context,
860 x + off_x, y + off_y, w, h);
864 if (obj->cur.cache.clip.visible)
865 obj->layer->evas->engine.func->image_map4_draw
866 (e->engine.data.output, e->engine.data.context, surface,
867 obj->cur.map->surface, pts, obj->cur.map->smooth, 0);
868 // FIXME: needs to cache these maps and
869 // keep them only rendering updates
870 // obj->layer->evas->engine.func->image_map_surface_free
871 // (e->engine.data.output, obj->cur.map->surface);
872 // obj->cur.map->surface = NULL;
879 RD(" draw child of mapped obj\n");
880 ctx = e->engine.func->context_new(e->engine.data.output);
881 if (obj->smart.smart)
884 (evas_object_smart_members_get_direct(obj), obj2)
886 clean_them |= evas_render_mapped(e, obj2, ctx,
900 RD(" clip: %i %i %ix%i [%i %i %ix%i]\n",
901 obj->cur.cache.clip.x + off_x,
902 obj->cur.cache.clip.y + off_y,
903 obj->cur.cache.clip.w,
904 obj->cur.cache.clip.h,
905 obj->cur.geometry.x + off_x,
906 obj->cur.geometry.y + off_y,
908 obj->cur.geometry.h);
909 e->engine.func->context_clip_set(e->engine.data.output,
911 obj->cur.cache.clip.x + off_x,
912 obj->cur.cache.clip.y + off_y,
913 obj->cur.cache.clip.w,
914 obj->cur.cache.clip.h);
921 obj->func->render(obj, e->engine.data.output, ctx,
922 surface, off_x, off_y);
924 obj->layer->evas->engine.func->context_color_set(e->engine.data.output,
927 obj->layer->evas->engine.func->rectangle_draw(e->engine.data.output,
933 e->engine.func->context_free(e->engine.data.output, ctx);
938 RD(" draw normal obj\n");
939 obj->func->render(obj, e->engine.data.output, context, surface,
950 evas_render_updates_internal(Evas *e,
951 unsigned char make_updates,
952 unsigned char do_draw)
954 Eina_List *updates = NULL;
957 Eina_Bool clean_them = EINA_FALSE;
966 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
969 if (!e->changed) return NULL;
971 evas_call_smarts_calculate(e);
973 RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
975 /* Check if the modified object mean recalculating every thing */
977 _evas_render_check_pending_objects(&e->pending_objects, e);
979 /* phase 1. add extra updates for changed objects */
980 if (e->invalidate || e->render_objects.count <= 0)
981 clean_them = _evas_render_phase1_process(e,
988 _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
989 &e->delete_objects, &e->render_objects);
991 /* phase 2. force updates for restacks */
992 for (i = 0; i < e->restack_objects.count; ++i)
996 obj = eina_array_data_get(&e->restack_objects, i);
997 obj->func->render_pre(obj);
998 _evas_render_prev_cur_clip_cache_add(e, obj);
1000 eina_array_clean(&e->restack_objects);
1001 /* phase 3. add exposes */
1002 EINA_LIST_FREE(e->damages, r)
1004 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1005 r->x, r->y, r->w, r->h);
1006 eina_rectangle_free(r);
1008 /* phase 4. output & viewport changes */
1009 if (e->viewport.changed)
1011 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1013 e->output.w, e->output.h);
1015 if (e->output.changed)
1017 e->engine.func->output_resize(e->engine.data.output,
1018 e->output.w, e->output.h);
1019 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1021 e->output.w, e->output.h);
1023 if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1025 ERR("viewport size != output size!");
1029 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1031 e->output.w, e->output.h);
1033 /* phase 5. add obscures */
1034 EINA_LIST_FOREACH(e->obscures, ll, r)
1036 e->engine.func->output_redraws_rect_del(e->engine.data.output,
1037 r->x, r->y, r->w, r->h);
1039 /* build obscure objects list of active objects that obscure */
1040 for (i = 0; i < e->active_objects.count; ++i)
1044 obj = eina_array_data_get(&e->active_objects, i);
1045 if (UNLIKELY((evas_object_is_opaque(obj) ||
1046 ((obj->func->has_opaque_rect) &&
1047 (obj->func->has_opaque_rect(obj)))) &&
1048 evas_object_is_visible(obj) &&
1049 (!obj->clip.clipees) &&
1050 (obj->cur.visible) &&
1051 (!obj->delete_me) &&
1052 (obj->cur.cache.clip.visible) &&
1053 (!obj->smart.smart)))
1054 /* obscuring_objects = eina_list_append(obscuring_objects, obj); */
1055 eina_array_push(&e->obscuring_objects, obj);
1057 /* save this list */
1058 /* obscuring_objects_orig = obscuring_objects; */
1059 /* obscuring_objects = NULL; */
1060 /* phase 6. go thru each update rect and render objects in it*/
1063 unsigned int offset = 0;
1065 alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1066 e->engine.data.context);
1069 e->engine.func->output_redraws_next_update_get
1070 (e->engine.data.output,
1072 &cx, &cy, &cw, &ch)))
1076 RD(" [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1079 Eina_Rectangle *rect;
1081 NEW_RECT(rect, ux, uy, uw, uh);
1083 updates = eina_list_append(updates, rect);
1088 /* build obscuring objects list (in order from bottom to top) */
1089 for (i = 0; i < e->obscuring_objects.count; ++i)
1093 obj = (Evas_Object *)eina_array_data_get
1094 (&e->obscuring_objects, i);
1095 if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1097 eina_array_push(&e->temporary_objects, obj);
1099 /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1102 if (evas_object_is_opaque(obj))
1103 e->engine.func->context_cutout_add
1104 (e->engine.data.output,
1105 e->engine.data.context,
1106 obj->cur.cache.clip.x + off_x,
1107 obj->cur.cache.clip.y + off_y,
1108 obj->cur.cache.clip.w,
1109 obj->cur.cache.clip.h);
1112 if (obj->func->get_opaque_rect)
1114 Evas_Coord obx, oby, obw, obh;
1116 obj->func->get_opaque_rect
1117 (obj, &obx, &oby, &obw, &obh);
1118 if ((obw > 0) && (obh > 0))
1123 (obx, oby, obw, obh,
1124 obj->cur.cache.clip.x + off_x,
1125 obj->cur.cache.clip.y + off_y,
1126 obj->cur.cache.clip.w,
1127 obj->cur.cache.clip.h);
1128 e->engine.func->context_cutout_add
1129 (e->engine.data.output,
1130 e->engine.data.context,
1141 e->engine.func->context_clip_set(e->engine.data.output,
1142 e->engine.data.context,
1144 e->engine.func->context_color_set(e->engine.data.output,
1145 e->engine.data.context,
1147 e->engine.func->context_multiplier_unset
1148 (e->engine.data.output, e->engine.data.context);
1149 e->engine.func->context_render_op_set(e->engine.data.output,
1150 e->engine.data.context,
1152 e->engine.func->rectangle_draw(e->engine.data.output,
1153 e->engine.data.context,
1156 e->engine.func->context_cutout_clear(e->engine.data.output,
1157 e->engine.data.context);
1158 e->engine.func->context_clip_unset(e->engine.data.output,
1159 e->engine.data.context);
1161 /* render all object that intersect with rect */
1162 for (i = 0; i < e->active_objects.count; ++i)
1166 obj = eina_array_data_get(&e->active_objects, i);
1168 /* if it's in our outpout rect and it doesn't clip anything */
1169 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);
1170 if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1171 (obj->smart.smart)) &&
1172 (!obj->clip.clipees) &&
1173 (obj->cur.visible) &&
1174 (!obj->delete_me) &&
1175 (obj->cur.cache.clip.visible) &&
1176 // (!obj->smart.smart) &&
1177 ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1181 RD(" DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1182 if ((e->temporary_objects.count > offset) &&
1183 (eina_array_data_get(&e->temporary_objects, offset) == obj))
1185 x = cx; y = cy; w = cw; h = ch;
1186 if (obj->cur.clipper)
1188 if (_evas_render_has_map(obj))
1190 evas_object_clip_recalc(obj);
1192 /* hmmmm clip seems to kill eweather in elm-test
1193 printf("clip: %4i %4i %4ix%4i to %4i %4i %4ix%4i\n",
1195 obj->cur.cache.clip.x + off_x,
1196 obj->cur.cache.clip.y + off_y,
1197 obj->cur.cache.clip.w,
1198 obj->cur.cache.clip.h);
1200 RECTS_CLIP_TO_RECT(x, y, w, h,
1201 obj->cur.cache.clip.x + off_x,
1202 obj->cur.cache.clip.y + off_y,
1203 obj->cur.cache.clip.w,
1204 obj->cur.cache.clip.h);
1206 if (((w > 0) && (h > 0)) || (obj->smart.smart))
1208 if (!obj->smart.smart)
1210 RECTS_CLIP_TO_RECT(x, y, w, h,
1211 obj->cur.cache.clip.x + off_x,
1212 obj->cur.cache.clip.y + off_y,
1213 obj->cur.cache.clip.w,
1214 obj->cur.cache.clip.h);
1216 if (obj->cur.clipper)
1217 e->engine.func->context_clip_set(e->engine.data.output,
1218 e->engine.data.context,
1221 e->engine.func->context_clip_unset(e->engine.data.output,
1222 e->engine.data.context);
1223 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1224 for (j = offset; j < e->temporary_objects.count; ++j)
1228 obj2 = (Evas_Object *) eina_array_data_get(&e->temporary_objects, j);
1229 if (evas_object_is_opaque(obj2))
1230 e->engine.func->context_cutout_add(e->engine.data.output,
1231 e->engine.data.context,
1232 obj2->cur.cache.clip.x + off_x,
1233 obj2->cur.cache.clip.y + off_y,
1234 obj2->cur.cache.clip.w,
1235 obj2->cur.cache.clip.h);
1238 if (obj2->func->get_opaque_rect)
1240 Evas_Coord obx, oby, obw, obh;
1242 obj2->func->get_opaque_rect
1243 (obj2, &obx, &oby, &obw, &obh);
1244 if ((obw > 0) && (obh > 0))
1248 RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1249 obj2->cur.cache.clip.x + off_x,
1250 obj2->cur.cache.clip.y + off_y,
1251 obj2->cur.cache.clip.w,
1252 obj2->cur.cache.clip.h);
1253 e->engine.func->context_cutout_add(e->engine.data.output,
1254 e->engine.data.context,
1262 e->engine.func->context_clip_set(e->engine.data.output,
1263 e->engine.data.context,
1265 clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1266 surface, off_x, off_y, 0
1271 e->engine.func->context_cutout_clear(e->engine.data.output,
1272 e->engine.data.context);
1276 /* punch rect out */
1277 e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1280 /* free obscuring objects list */
1281 eina_array_clean(&e->temporary_objects);
1287 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1288 e->engine.func->output_flush(e->engine.data.output);
1289 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1293 e->engine.func->output_redraws_clear(e->engine.data.output);
1294 /* and do a post render pass */
1295 for (i = 0; i < e->active_objects.count; ++i)
1299 obj = eina_array_data_get(&e->active_objects, i);
1300 obj->pre_render_done = 0;
1301 RD(" OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1302 if ((obj->changed) && (do_draw))
1304 RD(" OBJ [%p] post... func1\n", obj);
1305 obj->func->render_post(obj);
1309 else if ((obj->cur.map != obj->prev.map) ||
1310 (obj->cur.usemap != obj->prev.usemap))
1312 RD(" OBJ [%p] post... func2\n", obj);
1313 obj->func->render_post(obj);
1317 /* moved to other pre-process phase 1
1318 if (obj->delete_me == 2)
1320 delete_objects = eina_list_append(delete_objects, obj);
1322 else if (obj->delete_me != 0) obj->delete_me++;
1325 /* free our obscuring object list */
1326 eina_array_clean(&e->obscuring_objects);
1328 /* If some object are still marked as changed, do not remove
1329 them from the pending list. */
1330 eina_array_remove(&e->pending_objects, pending_change, NULL);
1332 /* delete all objects flagged for deletion now */
1333 for (i = 0; i < e->delete_objects.count; ++i)
1337 obj = eina_array_data_get(&e->delete_objects, i);
1338 evas_object_free(obj, 1);
1340 eina_array_clean(&e->delete_objects);
1343 e->viewport.changed = 0;
1344 e->output.changed = 0;
1347 for (i = 0; i < e->render_objects.count; ++i)
1351 obj = eina_array_data_get(&e->render_objects, i);
1352 obj->pre_render_done = 0;
1355 /* If their are some object to restack or some object to delete,
1356 * it's useless to keep the render object list around. */
1359 eina_array_clean(&e->active_objects);
1360 eina_array_clean(&e->render_objects);
1361 eina_array_clean(&e->restack_objects);
1362 eina_array_clean(&e->delete_objects);
1363 eina_array_clean(&e->obscuring_objects);
1367 evas_module_clean();
1375 * Free the rectangles returned by evas_render_updates().
1377 * @param updates The list of updated rectangles of the canvas.
1379 * This function removes the region from the render updates list. It
1380 * makes the region doesn't be render updated anymore.
1382 * @ingroup Evas_Canvas
1385 evas_render_updates_free(Eina_List *updates)
1389 EINA_LIST_FREE(updates, r)
1390 eina_rectangle_free(r);
1394 * Force immediate renderization of the given canvas.
1396 * @param e The given canvas pointer.
1397 * @return A newly allocated list of updated rectangles of the canvas.
1398 * Free this list with evas_render_updates_free().
1400 * This function forces an immediate renderization update of the given
1403 * @ingroup Evas_Canvas
1406 evas_render_updates(Evas *e)
1408 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1412 #ifdef EVAS_FRAME_QUEUING
1413 evas_common_frameq_flush_ready ();
1416 if (!e->changed) return NULL;
1417 return evas_render_updates_internal(e, 1, 1);
1421 * Force renderization of the given canvas.
1423 * @param e The given canvas pointer.
1425 * @ingroup Evas_Canvas
1428 evas_render(Evas *e)
1430 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1434 #ifdef EVAS_FRAME_QUEUING
1435 evas_common_frameq_flush_ready ();
1438 if (!e->changed) return;
1439 evas_render_updates_internal(e, 0, 1);
1443 * Update the canvas internal objects but not triggering immediate
1446 * @param e The given canvas pointer.
1448 * This function updates the canvas internal objects not triggering
1449 * renderization. To force renderization function evas_render() should
1454 * @ingroup Evas_Canvas
1457 evas_norender(Evas *e)
1459 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1463 // if (!e->changed) return;
1464 evas_render_updates_internal(e, 0, 0);
1468 * Make the canvas discard internally cached data used for rendering.
1470 * @param e The given canvas pointer.
1472 * This function flushes the arrays of delete, active and render objects.
1473 * Other things it may also discard are: shared memory segments,
1474 * temporary scratch buffers, cached data to avoid re-compute of that data etc.
1476 * @ingroup Evas_Canvas
1479 evas_render_idle_flush(Evas *e)
1481 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1485 evas_fonts_zero_presure(e);
1487 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1488 (e->engine.data.output))
1489 e->engine.func->output_idle_flush(e->engine.data.output);
1491 eina_array_flush(&e->delete_objects);
1492 eina_array_flush(&e->active_objects);
1493 eina_array_flush(&e->restack_objects);
1494 eina_array_flush(&e->render_objects);
1495 eina_array_flush(&e->clip_changes);
1503 #ifdef EVAS_FRAME_QUEUING
1504 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1508 evas_common_frameq_flush ();
1515 * Make the canvas discard as much data as possible used by the engine at
1518 * @param e The given canvas pointer.
1520 * This function will unload images, delete textures and much more, where
1521 * possible. You may also want to call evas_render_idle_flush() immediately
1522 * prior to this to perhaps discard a little more, though evas_render_dump()
1523 * should implicitly delete most of what evas_render_idle_flush() might
1526 * @ingroup Evas_Canvas
1529 _evas_render_dump_map_surfaces(Evas_Object *obj)
1531 if ((obj->cur.map) && obj->cur.map->surface)
1533 obj->layer->evas->engine.func->image_map_surface_free
1534 (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1535 obj->cur.map->surface = NULL;
1538 if (obj->smart.smart)
1542 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1543 _evas_render_dump_map_surfaces(obj2);
1548 evas_render_dump(Evas *e)
1552 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1556 EINA_INLIST_FOREACH(e->layers, lay)
1560 EINA_INLIST_FOREACH(lay->objects, obj)
1561 _evas_render_dump_map_surfaces(obj);
1563 if ((e->engine.func) && (e->engine.func->output_dump) &&
1564 (e->engine.data.output))
1565 e->engine.func->output_dump(e->engine.data.output);
1569 evas_render_invalidate(Evas *e)
1571 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1575 eina_array_clean(&e->active_objects);
1576 eina_array_clean(&e->render_objects);
1578 eina_array_flush(&e->restack_objects);
1579 eina_array_flush(&e->delete_objects);
1585 evas_render_object_recalc(Evas_Object *obj)
1587 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1591 #ifndef EVAS_FRAME_QUEUING
1592 if ((!obj->changed) && (obj->delete_me < 2))
1594 if ((!obj->changed))
1599 e = obj->layer->evas;
1600 if ((!e) || (e->cleanup)) return;
1601 #ifdef EVAS_FRAME_QUEUING
1602 if (obj->delete_me >= evas_common_frameq_get_frameq_sz() + 2) return;
1604 eina_array_push(&e->pending_objects, obj);