1 #include "evas_common.h"
2 #include "evas_private.h"
6 /* #define REND_DGB 1 */
7 /* #define STDOUT_DBG 1 */
10 static FILE *dbf = NULL;
13 rend_dbg(const char *txt)
20 dbf = fopen("EVAS-RENDER-DEBUG.log", "w");
29 char __tmpbuf[4096]; \
31 snprintf(__tmpbuf, sizeof(__tmpbuf), ##args); \
36 char __tmpbuf[4096]; int __tmpi; \
37 for (__tmpi = 0; __tmpi < xxxx; __tmpi++) \
38 __tmpbuf[__tmpi] = ' '; \
39 __tmpbuf[__tmpi] = 0; \
48 evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char do_draw);
51 evas_damage_rectangle_add(Evas *e, int x, int y, int w, int h)
55 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
58 NEW_RECT(r, x, y, w, h);
60 e->damages = eina_list_append(e->damages, r);
61 e->changed = EINA_TRUE;
65 evas_obscured_rectangle_add(Evas *e, int x, int y, int w, int h)
69 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
72 NEW_RECT(r, x, y, w, h);
74 e->obscures = eina_list_append(e->obscures, r);
78 evas_obscured_clear(Evas *e)
82 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
85 EINA_LIST_FREE(e->obscures, r)
87 eina_rectangle_free(r);
92 _evas_render_has_map(Evas_Object *obj)
94 return ((!((obj->func->can_map) && (obj->func->can_map(obj)))) &&
95 ((obj->cur.map) && (obj->cur.usemap)));
96 // return ((obj->cur.map) && (obj->cur.usemap));
100 _evas_render_had_map(Evas_Object *obj)
102 return ((obj->prev.map) && (obj->prev.usemap));
103 // return ((!obj->cur.map) && (obj->prev.usemap));
107 _evas_render_is_relevant(Evas_Object *obj)
109 return ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
110 (evas_object_was_visible(obj) && (!obj->prev.have_clipees)));
114 _evas_render_can_render(Evas_Object *obj)
116 return (evas_object_is_visible(obj) && (!obj->cur.have_clipees));
120 _evas_render_prev_cur_clip_cache_add(Evas *e, Evas_Object *obj)
122 e->engine.func->output_redraws_rect_add(e->engine.data.output,
123 obj->prev.cache.clip.x,
124 obj->prev.cache.clip.y,
125 obj->prev.cache.clip.w,
126 obj->prev.cache.clip.h);
127 e->engine.func->output_redraws_rect_add(e->engine.data.output,
128 obj->cur.cache.clip.x,
129 obj->cur.cache.clip.y,
130 obj->cur.cache.clip.w,
131 obj->cur.cache.clip.h);
135 _evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
137 Evas_Coord x, y, w, h;
139 x = obj->cur.cache.clip.x;
140 y = obj->cur.cache.clip.y;
141 w = obj->cur.cache.clip.w;
142 h = obj->cur.cache.clip.h;
143 if (obj->cur.clipper)
145 RECTS_CLIP_TO_RECT(x, y, w, h,
146 obj->cur.clipper->cur.cache.clip.x,
147 obj->cur.clipper->cur.cache.clip.y,
148 obj->cur.clipper->cur.cache.clip.w,
149 obj->cur.clipper->cur.cache.clip.h);
151 e->engine.func->output_redraws_rect_del(e->engine.data.output,
156 _evas_render_phase1_direct(Evas *e,
157 Eina_Array *active_objects,
158 Eina_Array *restack_objects __UNUSED__,
159 Eina_Array *delete_objects __UNUSED__,
160 Eina_Array *render_objects)
166 RD(" [--- PHASE 1 DIRECT\n");
167 for (i = 0; i < active_objects->count; i++)
171 obj = eina_array_data_get(active_objects, i);
174 /* Flag need redraw on proxy too */
175 evas_object_clip_recalc(obj);
176 if (obj->proxy.proxies)
178 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
179 proxy->proxy.redraw = EINA_TRUE;
183 for (i = 0; i < render_objects->count; i++)
187 obj = eina_array_data_get(render_objects, i);
188 RD(" OBJ [%p] changed %i\n", obj, obj->changed);
191 /* Flag need redraw on proxy too */
192 evas_object_clip_recalc(obj);
193 obj->func->render_pre(obj);
194 if (obj->proxy.proxies)
196 obj->proxy.redraw = EINA_TRUE;
197 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
199 proxy->func->render_pre(proxy);
200 _evas_render_prev_cur_clip_cache_add(e, proxy);
203 else if (obj->proxy.redraw)
204 _evas_render_prev_cur_clip_cache_add(e, obj);
206 RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
208 evas_object_smart_members_get_direct(obj),
209 obj->cur.map, obj->cur.usemap,
210 obj->prev.map, obj->prev.usemap,
211 _evas_render_has_map(obj),
212 _evas_render_had_map(obj));
213 if ((obj->smart.smart) &&
214 (_evas_render_has_map(obj)))
216 RD(" has map + smart\n");
217 _evas_render_prev_cur_clip_cache_add(e, obj);
222 if (obj->smart.smart)
224 // obj->func->render_pre(obj);
226 else if ((obj->rect_del) ||
227 (evas_object_is_opaque(obj) && evas_object_is_visible(obj)))
230 _evas_render_cur_clip_cache_del(e, obj);
238 _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
239 Eina_Array *active_objects,
240 Eina_Array *restack_objects,
241 Eina_Array *delete_objects,
242 Eina_Array *render_objects,
250 Eina_Bool clean_them = EINA_FALSE;
255 obj->rect_del = EINA_FALSE;
256 obj->render_pre = EINA_FALSE;
258 #ifndef EVAS_FRAME_QUEUING
259 /* because of clip objects - delete 2 cycles later */
260 if (obj->delete_me == 2)
262 if (obj->delete_me == evas_common_frameq_get_frameq_sz() + 2)
264 eina_array_push(delete_objects, obj);
265 else if (obj->delete_me != 0) obj->delete_me++;
266 /* If the object will be removed, we should not cache anything during this run. */
267 if (obj->delete_me != 0) clean_them = EINA_TRUE;
269 /* build active object list */
270 evas_object_clip_recalc(obj);
271 is_active = evas_object_is_active(obj);
272 obj->is_active = is_active;
275 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);
276 if ((is_active) || (obj->delete_me != 0))
277 eina_array_push(active_objects, obj);
283 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);
287 map = _evas_render_has_map(obj);
288 hmap = _evas_render_had_map(obj);
290 if ((restack) && (!map))
294 eina_array_push(&e->pending_objects, obj);
295 obj->changed = EINA_TRUE;
297 obj->restack = EINA_TRUE;
298 clean_them = EINA_TRUE;
307 if (map != hmap) *redraw_all = 1;
308 evas_object_clip_recalc(obj);
310 if ((is_active) && (!obj->clip.clipees) &&
311 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
312 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
314 eina_array_push(render_objects, obj);
315 _evas_render_prev_cur_clip_cache_add(e, obj);
316 obj->render_pre = EINA_TRUE;
324 RD(" had map - restack objs\n");
325 // eina_array_push(restack_objects, obj);
326 _evas_render_prev_cur_clip_cache_add(e, obj);
333 if ((obj->cur.map) && (obj->cur.usemap)) map = EINA_TRUE;
343 /* handle normal rendering. this object knows how to handle maps */
346 if (obj->smart.smart)
349 RD(" changed + smart - render ok\n");
350 eina_array_push(render_objects, obj);
351 obj->render_pre = EINA_TRUE;
352 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
354 _evas_render_phase1_object_process(e, obj2,
369 if ((is_active) && (!obj->clip.clipees) &&
370 _evas_render_is_relevant(obj))
373 RD(" relevant + active\n");
375 eina_array_push(restack_objects, obj);
378 eina_array_push(render_objects, obj);
379 obj->render_pre = EINA_TRUE;
385 RD(" skip - not smart, not active or clippees or not relevant\n");
391 RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n",
392 evas_object_is_visible(obj),
393 obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart, obj->cur.cache.clip.a,
394 evas_object_was_visible(obj));
395 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
396 (_evas_render_can_render(obj) ||
397 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
399 if (obj->smart.smart)
402 RD(" smart + visible/was visible + not clip\n");
403 eina_array_push(render_objects, obj);
404 obj->render_pre = EINA_TRUE;
406 (evas_object_smart_members_get_direct(obj), obj2)
408 _evas_render_phase1_object_process(e, obj2,
423 if (evas_object_is_opaque(obj) &&
424 evas_object_is_visible(obj))
427 RD(" opaque + visible\n");
428 eina_array_push(render_objects, obj);
429 obj->rect_del = EINA_TRUE;
431 else if (evas_object_is_visible(obj))
435 eina_array_push(render_objects, obj);
436 obj->render_pre = EINA_TRUE;
446 else if (obj->smart.smart)
449 RD(" smart + mot visible/was visible\n");
450 eina_array_push(render_objects, obj);
453 (evas_object_smart_members_get_direct(obj), obj2)
455 _evas_render_phase1_object_process(e, obj2,
470 if (!is_active) obj->restack = EINA_FALSE;
477 _evas_render_phase1_process(Evas *e,
478 Eina_Array *active_objects,
479 Eina_Array *restack_objects,
480 Eina_Array *delete_objects,
481 Eina_Array *render_objects,
485 Eina_Bool clean_them = EINA_FALSE;
487 RD(" [--- PHASE 1\n");
488 EINA_INLIST_FOREACH(e->layers, lay)
492 EINA_INLIST_FOREACH(lay->objects, obj)
494 clean_them |= _evas_render_phase1_object_process
495 (e, obj, active_objects, restack_objects, delete_objects,
496 render_objects, 0, redraw_all
508 _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
512 for (i = 0; i < pending_objects->count; ++i)
514 Evas_Object *obj, *parent;
516 Eina_Bool ok = EINA_FALSE;
517 obj = eina_array_data_get(pending_objects, i);
518 if (!obj->layer) goto clean_stuff;
520 parent = evas_object_smart_parent_get(obj);
521 if (parent && _evas_render_has_map(parent))
524 evas_object_clip_recalc(obj);
525 is_active = evas_object_is_active(obj);
527 if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
534 if (obj->is_active == is_active)
538 if (obj->smart.smart)
540 if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
543 if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
544 (_evas_render_can_render(obj) ||
545 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
547 if (!(obj->render_pre || obj->rect_del))
551 if (is_active && (!obj->clip.clipees) &&
552 (_evas_render_can_render(obj) ||
553 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
555 if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
560 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
561 (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
562 && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
564 if (obj->rect_del || obj->smart.smart) ok = EINA_TRUE;
572 eina_array_clean(&e->active_objects);
573 eina_array_clean(&e->render_objects);
574 eina_array_clean(&e->restack_objects);
575 eina_array_clean(&e->delete_objects);
576 e->invalidate = EINA_TRUE;
583 pending_change(void *data, void *gdata __UNUSED__)
588 if (obj->delete_me) return EINA_FALSE;
589 if (obj->pre_render_done)
591 RD(" OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
592 obj->pre_render_done = EINA_FALSE;
593 evas_object_change_reset(obj);
595 return obj->changed ? EINA_TRUE : EINA_FALSE;
599 _evas_render_can_use_overlay(Evas *e, Evas_Object *obj)
603 Eina_List *alphas = NULL;
604 Eina_List *opaques = NULL;
605 Evas_Object *video_parent = NULL;
607 Evas_Coord xc1, yc1, xc2, yc2;
611 video_parent = _evas_object_image_video_parent_get(obj);
613 /* Check if any one is the stack make this object mapped */
615 while (tmp && !_evas_render_has_map(tmp))
616 tmp = tmp->smart.parent;
618 if (tmp && _evas_render_has_map(tmp)) return EINA_FALSE; /* we are mapped, we can't be an overlay */
620 if (!evas_object_is_visible(obj)) return EINA_FALSE; /* no need to update the overlay if it's not visible */
622 /* If any recoloring of the surface is needed, n overlay to */
623 if ((obj->cur.cache.clip.r != 255) ||
624 (obj->cur.cache.clip.g != 255) ||
625 (obj->cur.cache.clip.b != 255) ||
626 (obj->cur.cache.clip.a != 255))
629 /* Check presence of transparent object on top of the video object */
630 EINA_RECTANGLE_SET(&zone,
631 obj->cur.cache.clip.x,
632 obj->cur.cache.clip.y,
633 obj->cur.cache.clip.w,
634 obj->cur.cache.clip.h);
636 for (i = e->active_objects.count - 1; i > 0; i--)
639 Eina_Rectangle *match;
640 Evas_Object *current;
642 int xm1, ym1, xm2, ym2;
644 current = eina_array_data_get(&e->active_objects, i);
646 /* Did we find the video object in the stack ? */
647 if (current == video_parent || current == obj)
650 EINA_RECTANGLE_SET(&self,
651 current->cur.cache.clip.x,
652 current->cur.cache.clip.y,
653 current->cur.cache.clip.w,
654 current->cur.cache.clip.h);
656 /* This doesn't cover the area of the video object, so don't bother with that object */
657 if (!eina_rectangles_intersect(&zone, &self))
660 xc1 = current->cur.cache.clip.x;
661 yc1 = current->cur.cache.clip.y;
662 xc2 = current->cur.cache.clip.x + current->cur.cache.clip.w;
663 yc2 = current->cur.cache.clip.y + current->cur.cache.clip.h;
665 if (evas_object_is_visible(current) &&
666 (!current->clip.clipees) &&
667 (current->cur.visible) &&
668 (!current->delete_me) &&
669 (current->cur.cache.clip.visible) &&
670 (!current->smart.smart))
672 Eina_Bool included = EINA_FALSE;
674 if (evas_object_is_opaque(current) ||
675 ((current->func->has_opaque_rect) &&
676 (current->func->has_opaque_rect(current))))
678 /* The object is opaque */
680 /* Check if the opaque object is inside another opaque object */
681 EINA_LIST_FOREACH(opaques, l, match)
685 xm2 = match->x + match->w;
686 ym2 = match->y + match->h;
688 /* Both object are included */
689 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
691 included = EINA_TRUE;
696 /* Not included yet */
702 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
703 current->cur.cache.clip.w, current->cur.cache.clip.h);
705 opaques = eina_list_append(opaques, r);
710 /* Remove all the transparent object that are covered by the new opaque object */
711 EINA_LIST_FOREACH_SAFE(alphas, l, ln, match)
715 xm2 = match->x + match->w;
716 ym2 = match->y + match->h;
718 if (xm1 >= r->x && ym1 >= r->y && xm2 <= xn2 && ym2 <= yn2)
720 /* The new rectangle is over some transparent object,
721 so remove the transparent object */
722 alphas = eina_list_remove_list(alphas, l);
729 /* The object has some transparency */
731 /* Check if the transparent object is inside any other transparent object */
732 EINA_LIST_FOREACH(alphas, l, match)
736 xm2 = match->x + match->w;
737 ym2 = match->y + match->h;
739 /* Both object are included */
740 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
742 included = EINA_TRUE;
747 /* If not check if it is inside any opaque one */
750 EINA_LIST_FOREACH(opaques, l, match)
754 xm2 = match->x + match->w;
755 ym2 = match->y + match->h;
757 /* Both object are included */
758 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
760 included = EINA_TRUE;
766 /* No inclusion at all, so add it */
769 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
770 current->cur.cache.clip.w, current->cur.cache.clip.h);
772 alphas = eina_list_append(alphas, r);
778 /* If there is any pending transparent object, then no overlay */
779 nooverlay = !!eina_list_count(alphas);
781 EINA_LIST_FREE(alphas, r)
782 eina_rectangle_free(r);
783 EINA_LIST_FREE(opaques, r)
784 eina_rectangle_free(r);
793 evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
794 int off_x, int off_y, int mapped,
795 int ecx, int ecy, int ecw, int ech
803 Eina_Bool clean_them = EINA_FALSE;
805 evas_object_clip_recalc(obj);
807 RD(" { evas_render_mapped(%p, %p, %p, %p, %i, %i, %i, %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
810 if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
811 (obj->cur.have_clipees))
818 else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
819 (_evas_render_can_render(obj))))
827 // set render_pre - for child objs that may not have gotten it.
828 obj->pre_render_done = EINA_TRUE;
829 RD(" Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map,
830 obj->func->can_map ? obj->func->can_map(obj): -1,
831 obj->cur.map, obj->cur.usemap,
832 _evas_render_has_map(obj));
833 if (_evas_render_has_map(obj))
835 const Evas_Map_Point *p, *p_end;
836 RGBA_Map_Point pts[4], *pt;
838 Eina_Bool changed = EINA_FALSE, rendered = EINA_FALSE;
840 clean_them = EINA_TRUE;
842 sw = obj->cur.geometry.w;
843 sh = obj->cur.geometry.h;
845 RD(" mapped obj: %ix%i\n", sw, sh);
846 if ((sw <= 0) || (sh <= 0))
853 pts[0].px = obj->cur.map->persp.px << FP;
854 pts[0].py = obj->cur.map->persp.py << FP;
855 pts[0].foc = obj->cur.map->persp.foc << FP;
856 pts[0].z0 = obj->cur.map->persp.z0 << FP;
858 p = obj->cur.map->points;
859 p_end = p + obj->cur.map->count;
861 for (; p < p_end; p++, pt++)
863 pt->x = (lround(p->x) + off_x) * FP1;
864 pt->y = (lround(p->y) + off_y) * FP1;
865 pt->z = (lround(p->z) ) * FP1;
869 pt->u = lround(p->u) * FP1;
870 pt->v = lround(p->v) * FP1;
871 if (pt->u < 0) pt->u = 0;
872 else if (pt->u > (sw * FP1)) pt->u = (sw * FP1);
873 if (pt->v < 0) pt->v = 0;
874 else if (pt->v > (sh * FP1)) pt->v = (sh * FP1);
875 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
877 /* Copy last for software engine */
878 if (obj->cur.map->count & 0x1)
880 pts[obj->cur.map->count] = pts[obj->cur.map->count - 1];
884 if (obj->cur.map->surface)
886 if ((obj->cur.map->surface_w != sw) ||
887 (obj->cur.map->surface_h != sh))
890 RD(" new surf: %ix%i\n", sw, sh);
891 obj->layer->evas->engine.func->image_map_surface_free
892 (e->engine.data.output, obj->cur.map->surface);
893 obj->cur.map->surface = NULL;
896 if (!obj->cur.map->surface)
898 obj->cur.map->surface_w = sw;
899 obj->cur.map->surface_h = sh;
901 obj->cur.map->surface =
902 obj->layer->evas->engine.func->image_map_surface_new
903 (e->engine.data.output, obj->cur.map->surface_w,
904 obj->cur.map->surface_h,
905 obj->cur.map->alpha);
907 RD(" fisrt surf: %ix%i\n", sw, sh);
910 if (obj->smart.smart)
914 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), o2)
916 if (!evas_object_is_visible(o2) &&
917 !evas_object_was_visible(o2))
919 evas_object_change_reset(o2);
925 evas_object_change_reset(o2);
929 if (obj->changed_color) changed = EINA_TRUE;
930 evas_object_change_reset(obj);
932 else if (obj->changed)
934 if (((obj->changed_pchange) && (obj->changed_map)) ||
935 (obj->changed_color))
937 evas_object_change_reset(obj);
940 // clear surface before re-render
941 if ((changed) && (obj->cur.map->surface))
946 RD(" children redraw\n");
947 // FIXME: calculate "changes" within map surface and only clear
948 // and re-render those
949 if (obj->cur.map->alpha)
951 ctx = e->engine.func->context_new(e->engine.data.output);
952 e->engine.func->context_color_set
953 (e->engine.data.output, ctx, 0, 0, 0, 0);
954 e->engine.func->context_render_op_set
955 (e->engine.data.output, ctx, EVAS_RENDER_COPY);
956 e->engine.func->rectangle_draw(e->engine.data.output,
958 obj->cur.map->surface,
960 obj->cur.map->surface_w,
961 obj->cur.map->surface_h);
962 e->engine.func->context_free(e->engine.data.output, ctx);
964 ctx = e->engine.func->context_new(e->engine.data.output);
965 off_x2 = -obj->cur.geometry.x;
966 off_y2 = -obj->cur.geometry.y;
967 if (obj->smart.smart)
970 (evas_object_smart_members_get_direct(obj), obj2)
972 clean_them |= evas_render_mapped(e, obj2, ctx,
973 obj->cur.map->surface,
984 int x = 0, y = 0, w = 0, h = 0;
986 w = obj->cur.map->surface_w;
987 h = obj->cur.map->surface_h;
988 RECTS_CLIP_TO_RECT(x, y, w, h,
989 obj->cur.geometry.x + off_x2,
990 obj->cur.geometry.y + off_y2,
992 obj->cur.geometry.h);
994 e->engine.func->context_clip_set(e->engine.data.output,
996 obj->func->render(obj, e->engine.data.output, ctx,
997 obj->cur.map->surface, off_x2, off_y2);
999 e->engine.func->context_free(e->engine.data.output, ctx);
1000 rendered = EINA_TRUE;
1008 obj->cur.map->surface = e->engine.func->image_dirty_region
1009 (e->engine.data.output, obj->cur.map->surface,
1010 0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
1012 e->engine.func->context_clip_unset(e->engine.data.output,
1013 e->engine.data.context);
1014 if (obj->cur.map->surface)
1016 if (obj->smart.smart)
1018 if (obj->cur.clipper)
1023 obj->cur.cache.clip.dirty = EINA_TRUE;
1024 tobj = obj->cur.map_parent;
1025 obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
1026 evas_object_clip_recalc(obj);
1027 obj->cur.map_parent = tobj;
1028 x = obj->cur.cache.clip.x;
1029 y = obj->cur.cache.clip.y;
1030 w = obj->cur.cache.clip.w;
1031 h = obj->cur.cache.clip.h;
1032 RECTS_CLIP_TO_RECT(x, y, w, h,
1033 obj->cur.clipper->cur.cache.clip.x,
1034 obj->cur.clipper->cur.cache.clip.y,
1035 obj->cur.clipper->cur.cache.clip.w,
1036 obj->cur.clipper->cur.cache.clip.h);
1037 e->engine.func->context_clip_set(e->engine.data.output,
1038 e->engine.data.context,
1039 x + off_x, y + off_y, w, h);
1044 if (obj->cur.clipper)
1048 evas_object_clip_recalc(obj);
1049 x = obj->cur.cache.clip.x;
1050 y = obj->cur.cache.clip.y;
1051 w = obj->cur.cache.clip.w;
1052 h = obj->cur.cache.clip.h;
1053 RECTS_CLIP_TO_RECT(x, y, w, h,
1054 obj->cur.clipper->cur.cache.clip.x,
1055 obj->cur.clipper->cur.cache.clip.y,
1056 obj->cur.clipper->cur.cache.clip.w,
1057 obj->cur.clipper->cur.cache.clip.h);
1058 e->engine.func->context_clip_set(e->engine.data.output,
1059 e->engine.data.context,
1060 x + off_x, y + off_y, w, h);
1064 // if (surface == e->engine.data.output)
1065 e->engine.func->context_clip_clip(e->engine.data.output,
1066 e->engine.data.context,
1067 ecx, ecy, ecw, ech);
1068 if (obj->cur.cache.clip.visible)
1070 obj->layer->evas->engine.func->context_multiplier_unset
1071 (e->engine.data.output, e->engine.data.context);
1072 obj->layer->evas->engine.func->image_map_draw
1073 (e->engine.data.output, e->engine.data.context, surface,
1074 obj->cur.map->surface, obj->cur.map->count, pts,
1075 obj->cur.map->smooth, 0);
1077 // FIXME: needs to cache these maps and
1078 // keep them only rendering updates
1079 // obj->layer->evas->engine.func->image_map_surface_free
1080 // (e->engine.data.output, obj->cur.map->surface);
1081 // obj->cur.map->surface = NULL;
1088 RD(" draw child of mapped obj\n");
1089 ctx = e->engine.func->context_new(e->engine.data.output);
1090 if (obj->smart.smart)
1093 (evas_object_smart_members_get_direct(obj), obj2)
1095 clean_them |= evas_render_mapped(e, obj2, ctx,
1113 x = obj->cur.cache.clip.x + off_x;
1114 y = obj->cur.cache.clip.y + off_y;
1115 w = obj->cur.cache.clip.w;
1116 h = obj->cur.cache.clip.h;
1118 if (obj->cur.clipper)
1120 if (_evas_render_has_map(obj))
1121 evas_object_clip_recalc(obj);
1123 RD(" clipper: %i %i %ix%i\n",
1124 obj->cur.clipper->cur.cache.clip.x + off_x,
1125 obj->cur.clipper->cur.cache.clip.y + off_y,
1126 obj->cur.clipper->cur.cache.clip.w,
1127 obj->cur.clipper->cur.cache.clip.h);
1129 RECTS_CLIP_TO_RECT(x, y, w, h,
1130 obj->cur.clipper->cur.cache.clip.x + off_x,
1131 obj->cur.clipper->cur.cache.clip.y + off_y,
1132 obj->cur.clipper->cur.cache.clip.w,
1133 obj->cur.clipper->cur.cache.clip.h);
1136 RD(" clip: %i %i %ix%i [%i %i %ix%i]\n",
1137 obj->cur.cache.clip.x + off_x,
1138 obj->cur.cache.clip.y + off_y,
1139 obj->cur.cache.clip.w,
1140 obj->cur.cache.clip.h,
1141 obj->cur.geometry.x + off_x,
1142 obj->cur.geometry.y + off_y,
1143 obj->cur.geometry.w,
1144 obj->cur.geometry.h);
1145 e->engine.func->context_clip_set(e->engine.data.output,
1153 obj->func->render(obj, e->engine.data.output, ctx,
1154 surface, off_x, off_y);
1156 obj->layer->evas->engine.func->context_color_set(e->engine.data.output,
1159 obj->layer->evas->engine.func->rectangle_draw(e->engine.data.output,
1165 e->engine.func->context_free(e->engine.data.output, ctx);
1169 if (obj->cur.clipper)
1173 if (_evas_render_has_map(obj))
1174 evas_object_clip_recalc(obj);
1175 x = obj->cur.cache.clip.x;
1176 y = obj->cur.cache.clip.y;
1177 w = obj->cur.cache.clip.w;
1178 h = obj->cur.cache.clip.h;
1179 RECTS_CLIP_TO_RECT(x, y, w, h,
1180 obj->cur.clipper->cur.cache.clip.x,
1181 obj->cur.clipper->cur.cache.clip.y,
1182 obj->cur.clipper->cur.cache.clip.w,
1183 obj->cur.clipper->cur.cache.clip.h);
1184 e->engine.func->context_clip_set(e->engine.data.output,
1185 e->engine.data.context,
1186 x + off_x, y + off_y, w, h);
1187 e->engine.func->context_clip_clip(e->engine.data.output,
1188 e->engine.data.context,
1189 ecx, ecy, ecw, ech);
1193 RD(" draw normal obj\n");
1194 obj->func->render(obj, e->engine.data.output, context, surface,
1197 if (obj->changed_map) clean_them = EINA_TRUE;
1206 _evas_render_cutout_add(Evas *e, Evas_Object *obj, int off_x, int off_y)
1208 if (evas_object_is_opaque(obj))
1210 Evas_Coord cox, coy, cow, coh;
1212 cox = obj->cur.cache.clip.x;
1213 coy = obj->cur.cache.clip.y;
1214 cow = obj->cur.cache.clip.w;
1215 coh = obj->cur.cache.clip.h;
1216 if ((obj->cur.map) && (obj->cur.usemap))
1221 while (oo->cur.clipper)
1223 if ((oo->cur.clipper->cur.map_parent
1224 != oo->cur.map_parent) &&
1225 (!((oo->cur.map) && (oo->cur.usemap))))
1227 RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
1231 oo->cur.geometry.h);
1232 oo = oo->cur.clipper;
1235 e->engine.func->context_cutout_add
1236 (e->engine.data.output, e->engine.data.context,
1237 cox + off_x, coy + off_y, cow, coh);
1241 if (obj->func->get_opaque_rect)
1243 Evas_Coord obx, oby, obw, obh;
1245 obj->func->get_opaque_rect(obj, &obx, &oby, &obw, &obh);
1246 if ((obw > 0) && (obh > 0))
1250 RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1251 obj->cur.cache.clip.x + off_x,
1252 obj->cur.cache.clip.y + off_y,
1253 obj->cur.cache.clip.w,
1254 obj->cur.cache.clip.h);
1255 e->engine.func->context_cutout_add
1256 (e->engine.data.output, e->engine.data.context,
1257 obx, oby, obw, obh);
1264 evas_render_updates_internal(Evas *e,
1265 unsigned char make_updates,
1266 unsigned char do_draw)
1269 Eina_List *updates = NULL;
1272 Eina_Bool clean_them = EINA_FALSE;
1279 Eina_Bool haveup = 0;
1281 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1284 if (!e->changed) return NULL;
1286 evas_call_smarts_calculate(e);
1288 RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
1290 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_PRE, NULL);
1292 /* Check if the modified object mean recalculating every thing */
1294 _evas_render_check_pending_objects(&e->pending_objects, e);
1296 /* phase 1. add extra updates for changed objects */
1297 if (e->invalidate || e->render_objects.count <= 0)
1298 clean_them = _evas_render_phase1_process(e,
1300 &e->restack_objects,
1305 /* phase 1.5. check if the video should be inlined or stay in their overlay */
1306 alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1307 e->engine.data.context);
1309 EINA_LIST_FOREACH(e->video_objects, ll, obj)
1311 /* we need the surface to be transparent to display the underlying overlay */
1312 if (alpha && _evas_render_can_use_overlay(e, obj))
1313 _evas_object_image_video_overlay_show(obj);
1315 _evas_object_image_video_overlay_hide(obj);
1319 /* phase 1.8. pre render for proxy */
1320 _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
1321 &e->delete_objects, &e->render_objects);
1323 /* phase 2. force updates for restacks */
1324 for (i = 0; i < e->restack_objects.count; ++i)
1326 obj = eina_array_data_get(&e->restack_objects, i);
1327 obj->func->render_pre(obj);
1328 _evas_render_prev_cur_clip_cache_add(e, obj);
1330 eina_array_clean(&e->restack_objects);
1332 /* phase 3. add exposes */
1333 EINA_LIST_FREE(e->damages, r)
1335 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1336 r->x, r->y, r->w, r->h);
1337 eina_rectangle_free(r);
1340 /* phase 4. framespace, output & viewport changes */
1341 if (e->framespace.changed)
1345 fx = e->viewport.x - e->framespace.x;
1346 fy = e->viewport.y - e->framespace.y;
1347 fw = e->viewport.w + e->framespace.w;
1348 fh = e->viewport.h + e->framespace.h;
1349 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1353 if (e->viewport.changed)
1355 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1357 e->output.w, e->output.h);
1359 if (e->output.changed)
1361 e->engine.func->output_resize(e->engine.data.output,
1362 e->output.w, e->output.h);
1363 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1365 e->output.w, e->output.h);
1367 if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1369 ERR("viewport size != output size!");
1373 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1375 e->output.w, e->output.h);
1378 /* phase 5. add obscures */
1379 EINA_LIST_FOREACH(e->obscures, ll, r)
1381 e->engine.func->output_redraws_rect_del(e->engine.data.output,
1382 r->x, r->y, r->w, r->h);
1384 /* build obscure objects list of active objects that obscure */
1385 for (i = 0; i < e->active_objects.count; ++i)
1387 obj = eina_array_data_get(&e->active_objects, i);
1388 if (UNLIKELY((evas_object_is_opaque(obj) ||
1389 ((obj->func->has_opaque_rect) &&
1390 (obj->func->has_opaque_rect(obj)))) &&
1391 evas_object_is_visible(obj) &&
1392 (!obj->clip.clipees) &&
1393 (obj->cur.visible) &&
1394 (!obj->delete_me) &&
1395 (obj->cur.cache.clip.visible) &&
1396 (!obj->smart.smart)))
1397 /* obscuring_objects = eina_list_append(obscuring_objects, obj); */
1398 eina_array_push(&e->obscuring_objects, obj);
1401 /* save this list */
1402 /* obscuring_objects_orig = obscuring_objects; */
1403 /* obscuring_objects = NULL; */
1404 /* phase 6. go thru each update rect and render objects in it*/
1407 unsigned int offset = 0;
1410 e->engine.func->output_redraws_next_update_get
1411 (e->engine.data.output,
1413 &cx, &cy, &cw, &ch)))
1417 RD(" [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1420 Eina_Rectangle *rect;
1422 NEW_RECT(rect, ux, uy, uw, uh);
1424 updates = eina_list_append(updates, rect);
1429 /* build obscuring objects list (in order from bottom to top) */
1432 e->engine.func->context_clip_set(e->engine.data.output,
1433 e->engine.data.context,
1434 ux + off_x, uy + off_y, uw, uh);
1436 for (i = 0; i < e->obscuring_objects.count; ++i)
1438 obj = (Evas_Object *)eina_array_data_get
1439 (&e->obscuring_objects, i);
1440 if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1442 eina_array_push(&e->temporary_objects, obj);
1444 /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1446 _evas_render_cutout_add(e, obj, off_x, off_y);
1451 e->engine.func->context_color_set(e->engine.data.output,
1452 e->engine.data.context,
1454 e->engine.func->context_multiplier_unset
1455 (e->engine.data.output, e->engine.data.context);
1456 e->engine.func->context_render_op_set(e->engine.data.output,
1457 e->engine.data.context,
1459 e->engine.func->rectangle_draw(e->engine.data.output,
1460 e->engine.data.context,
1463 e->engine.func->context_cutout_clear(e->engine.data.output,
1464 e->engine.data.context);
1465 e->engine.func->context_clip_unset(e->engine.data.output,
1466 e->engine.data.context);
1468 /* render all object that intersect with rect */
1469 for (i = 0; i < e->active_objects.count; ++i)
1471 obj = eina_array_data_get(&e->active_objects, i);
1473 /* if it's in our outpout rect and it doesn't clip anything */
1474 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);
1475 if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1476 (obj->smart.smart)) &&
1477 (!obj->clip.clipees) &&
1478 (obj->cur.visible) &&
1479 (!obj->delete_me) &&
1480 (obj->cur.cache.clip.visible) &&
1481 // (!obj->smart.smart) &&
1482 ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1486 RD(" DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1487 if ((e->temporary_objects.count > offset) &&
1488 (eina_array_data_get(&e->temporary_objects, offset) == obj))
1490 x = cx; y = cy; w = cw; h = ch;
1491 if (((w > 0) && (h > 0)) || (obj->smart.smart))
1493 if (!obj->smart.smart)
1495 RECTS_CLIP_TO_RECT(x, y, w, h,
1496 obj->cur.cache.clip.x + off_x,
1497 obj->cur.cache.clip.y + off_y,
1498 obj->cur.cache.clip.w,
1499 obj->cur.cache.clip.h);
1502 e->engine.func->context_mask_set(e->engine.data.output,
1503 e->engine.data.context,
1504 obj->cur.mask->func->engine_data_get(obj->cur.mask),
1505 obj->cur.mask->cur.geometry.x + off_x,
1506 obj->cur.mask->cur.geometry.y + off_y,
1507 obj->cur.mask->cur.geometry.w,
1508 obj->cur.mask->cur.geometry.h);
1510 e->engine.func->context_mask_unset(e->engine.data.output,
1511 e->engine.data.context);
1512 e->engine.func->context_clip_set(e->engine.data.output,
1513 e->engine.data.context,
1515 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1516 for (j = offset; j < e->temporary_objects.count; ++j)
1520 obj2 = (Evas_Object *)eina_array_data_get
1521 (&e->temporary_objects, j);
1522 _evas_render_cutout_add(e, obj2, off_x, off_y);
1525 clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1526 surface, off_x, off_y, 0,
1533 e->engine.func->context_cutout_clear(e->engine.data.output,
1534 e->engine.data.context);
1538 /* punch rect out */
1539 e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1542 /* free obscuring objects list */
1543 eina_array_clean(&e->temporary_objects);
1549 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1550 e->engine.func->output_flush(e->engine.data.output);
1551 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1555 e->engine.func->output_redraws_clear(e->engine.data.output);
1556 /* and do a post render pass */
1557 for (i = 0; i < e->active_objects.count; ++i)
1559 obj = eina_array_data_get(&e->active_objects, i);
1560 obj->pre_render_done = EINA_FALSE;
1561 RD(" OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1562 if ((obj->changed) && (do_draw))
1564 RD(" OBJ [%p] post... func1\n", obj);
1565 obj->func->render_post(obj);
1566 obj->restack = EINA_FALSE;
1567 evas_object_change_reset(obj);
1569 else if (clean_them)
1571 RD(" OBJ [%p] post... func2\n", obj);
1572 obj->func->render_post(obj);
1573 obj->restack = EINA_FALSE;
1574 evas_object_change_reset(obj);
1576 /* moved to other pre-process phase 1
1577 if (obj->delete_me == 2)
1579 delete_objects = eina_list_append(delete_objects, obj);
1581 else if (obj->delete_me != 0) obj->delete_me++;
1584 /* free our obscuring object list */
1585 eina_array_clean(&e->obscuring_objects);
1587 /* If some object are still marked as changed, do not remove
1588 them from the pending list. */
1589 eina_array_remove(&e->pending_objects, pending_change, NULL);
1591 for (i = 0; i < e->render_objects.count; ++i)
1593 obj = eina_array_data_get(&e->render_objects, i);
1594 obj->pre_render_done = EINA_FALSE;
1597 /* delete all objects flagged for deletion now */
1598 for (i = 0; i < e->delete_objects.count; ++i)
1600 obj = eina_array_data_get(&e->delete_objects, i);
1601 evas_object_free(obj, 1);
1603 eina_array_clean(&e->delete_objects);
1605 e->changed = EINA_FALSE;
1606 e->viewport.changed = EINA_FALSE;
1607 e->output.changed = EINA_FALSE;
1608 e->framespace.changed = EINA_FALSE;
1609 e->invalidate = EINA_FALSE;
1611 // always clean... lots of mem waste!
1612 /* If their are some object to restack or some object to delete,
1613 * it's useless to keep the render object list around. */
1616 eina_array_clean(&e->active_objects);
1617 eina_array_clean(&e->render_objects);
1618 eina_array_clean(&e->restack_objects);
1619 eina_array_clean(&e->temporary_objects);
1620 eina_array_clean(&e->clip_changes);
1621 /* we should flush here and have a mempool system for this
1622 eina_array_flush(&e->active_objects);
1623 eina_array_flush(&e->render_objects);
1624 eina_array_flush(&e->restack_objects);
1625 eina_array_flush(&e->delete_objects);
1626 eina_array_flush(&e->obscuring_objects);
1627 eina_array_flush(&e->temporary_objects);
1628 eina_array_flush(&e->clip_changes);
1630 e->invalidate = EINA_TRUE;
1633 evas_module_clean();
1635 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_POST, NULL);
1643 evas_render_updates_free(Eina_List *updates)
1647 EINA_LIST_FREE(updates, r)
1648 eina_rectangle_free(r);
1652 evas_render_updates(Evas *e)
1654 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1658 #ifdef EVAS_FRAME_QUEUING
1659 evas_common_frameq_flush_ready ();
1662 if (!e->changed) return NULL;
1663 return evas_render_updates_internal(e, 1, 1);
1667 evas_render(Evas *e)
1669 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1673 #ifdef EVAS_FRAME_QUEUING
1674 evas_common_frameq_flush_ready ();
1677 if (!e->changed) return;
1678 evas_render_updates_internal(e, 0, 1);
1682 evas_norender(Evas *e)
1684 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1688 // if (!e->changed) return;
1689 evas_render_updates_internal(e, 0, 0);
1693 evas_render_idle_flush(Evas *e)
1695 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1699 evas_fonts_zero_presure(e);
1701 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1702 (e->engine.data.output))
1703 e->engine.func->output_idle_flush(e->engine.data.output);
1705 eina_array_flush(&e->active_objects);
1706 eina_array_flush(&e->render_objects);
1707 eina_array_flush(&e->restack_objects);
1708 eina_array_flush(&e->delete_objects);
1709 eina_array_flush(&e->obscuring_objects);
1710 eina_array_flush(&e->temporary_objects);
1711 eina_array_flush(&e->clip_changes);
1713 e->invalidate = EINA_TRUE;
1719 #ifdef EVAS_FRAME_QUEUING
1720 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1724 evas_common_frameq_flush();
1731 _evas_render_dump_map_surfaces(Evas_Object *obj)
1733 if ((obj->cur.map) && obj->cur.map->surface)
1735 obj->layer->evas->engine.func->image_map_surface_free
1736 (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1737 obj->cur.map->surface = NULL;
1740 if (obj->smart.smart)
1744 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1745 _evas_render_dump_map_surfaces(obj2);
1750 evas_render_dump(Evas *e)
1754 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1758 EINA_INLIST_FOREACH(e->layers, lay)
1762 EINA_INLIST_FOREACH(lay->objects, obj)
1764 if ((obj->type) && (!strcmp(obj->type, "image")))
1765 evas_object_inform_call_image_unloaded(obj);
1766 _evas_render_dump_map_surfaces(obj);
1769 if ((e->engine.func) && (e->engine.func->output_dump) &&
1770 (e->engine.data.output))
1771 e->engine.func->output_dump(e->engine.data.output);
1775 evas_render_invalidate(Evas *e)
1777 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1781 eina_array_clean(&e->active_objects);
1782 eina_array_clean(&e->render_objects);
1784 eina_array_flush(&e->restack_objects);
1785 eina_array_flush(&e->delete_objects);
1787 e->invalidate = EINA_TRUE;
1791 evas_render_object_recalc(Evas_Object *obj)
1793 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1797 #ifndef EVAS_FRAME_QUEUING
1798 if ((!obj->changed) && (obj->delete_me < 2))
1800 if ((!obj->changed))
1805 e = obj->layer->evas;
1806 if ((!e) || (e->cleanup)) return;
1807 #ifdef EVAS_FRAME_QUEUING
1808 if (obj->delete_me >= evas_common_frameq_get_frameq_sz() + 2) return;
1810 eina_array_push(&e->pending_objects, obj);
1811 obj->changed = EINA_TRUE;
1815 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/