1 #include "evas_common.h"
2 #include "evas_private.h"
5 /* #define REND_DGB 1 */
6 /* #define STDOUT_DBG 1 */
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 evas_damage_rectangle_add(Evas *e, int x, int y, int w, int h)
54 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
57 NEW_RECT(r, x, y, w, h);
59 e->damages = eina_list_append(e->damages, r);
64 evas_obscured_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->obscures = eina_list_append(e->obscures, r);
77 evas_obscured_clear(Evas *e)
81 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
84 EINA_LIST_FREE(e->obscures, r)
86 eina_rectangle_free(r);
91 _evas_render_has_map(Evas_Object *obj)
93 return ((!((obj->func->can_map) && (obj->func->can_map(obj)))) &&
94 ((obj->cur.map) && (obj->cur.usemap)));
95 // return ((obj->cur.map) && (obj->cur.usemap));
99 _evas_render_had_map(Evas_Object *obj)
101 return ((obj->prev.map) && (obj->prev.usemap));
102 // return ((!obj->cur.map) && (obj->prev.usemap));
106 _evas_render_is_relevant(Evas_Object *obj)
108 return ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
109 (evas_object_was_visible(obj) && (!obj->prev.have_clipees)));
113 _evas_render_can_render(Evas_Object *obj)
115 return (evas_object_is_visible(obj) && (!obj->cur.have_clipees));
119 _evas_render_prev_cur_clip_cache_add(Evas *e, Evas_Object *obj)
121 e->engine.func->output_redraws_rect_add(e->engine.data.output,
122 obj->prev.cache.clip.x,
123 obj->prev.cache.clip.y,
124 obj->prev.cache.clip.w,
125 obj->prev.cache.clip.h);
126 e->engine.func->output_redraws_rect_add(e->engine.data.output,
127 obj->cur.cache.clip.x,
128 obj->cur.cache.clip.y,
129 obj->cur.cache.clip.w,
130 obj->cur.cache.clip.h);
134 _evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
136 e->engine.func->output_redraws_rect_del(e->engine.data.output,
137 obj->cur.cache.clip.x,
138 obj->cur.cache.clip.y,
139 obj->cur.cache.clip.w,
140 obj->cur.cache.clip.h);
144 _evas_render_phase1_direct(Evas *e,
145 Eina_Array *active_objects,
146 Eina_Array *restack_objects __UNUSED__,
147 Eina_Array *delete_objects __UNUSED__,
148 Eina_Array *render_objects)
154 RD(" [--- PHASE 1 DIRECT\n");
155 for (i = 0; i < active_objects->count; i++)
159 obj = eina_array_data_get(active_objects, i);
162 /* Flag need redraw on proxy too */
163 evas_object_clip_recalc(obj);
164 if (obj->proxy.proxies)
166 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
167 proxy->proxy.redraw = 1;
171 for (i = 0; i < render_objects->count; i++)
175 obj = eina_array_data_get(render_objects, i);
176 RD(" OBJ [%p] changed %i\n", obj, obj->changed);
179 /* Flag need redraw on proxy too */
180 evas_object_clip_recalc(obj);
181 obj->func->render_pre(obj);
182 if (obj->proxy.proxies)
184 obj->proxy.redraw = 1;
185 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
187 proxy->func->render_pre(proxy);
188 _evas_render_prev_cur_clip_cache_add(e, proxy);
191 else if (obj->proxy.redraw)
193 _evas_render_prev_cur_clip_cache_add(e, obj);
195 if (obj->pre_render_done)
197 RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
199 evas_object_smart_members_get_direct(obj),
200 obj->cur.map, obj->cur.usemap,
201 obj->prev.map, obj->prev.usemap,
202 _evas_render_has_map(obj),
203 _evas_render_had_map(obj));
204 if ((obj->smart.smart) &&
205 (_evas_render_has_map(obj)))
207 RD(" has map + smart\n");
208 _evas_render_prev_cur_clip_cache_add(e, obj);
211 else if (_evas_render_had_map(obj))
213 RD(" no pre-render done\n");
214 _evas_render_prev_cur_clip_cache_add(e, obj);
219 if (obj->smart.smart)
221 // obj->func->render_pre(obj);
223 else if (obj->rect_del)
226 _evas_render_cur_clip_cache_del(e, obj);
234 _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
235 Eina_Array *active_objects,
236 Eina_Array *restack_objects,
237 Eina_Array *delete_objects,
238 Eina_Array *render_objects,
239 int restack, int map,
246 Eina_Bool clean_them = EINA_FALSE;
254 #ifndef EVAS_FRAME_QUEUING
255 /* because of clip objects - delete 2 cycles later */
256 if (obj->delete_me == 2)
258 if (obj->delete_me == evas_common_frameq_get_frameq_sz() + 2)
260 eina_array_push(delete_objects, obj);
261 else if (obj->delete_me != 0) obj->delete_me++;
262 /* If the object will be removed, we should not cache anything during this run. */
263 if (obj->delete_me != 0) clean_them = EINA_TRUE;
265 /* build active object list */
266 evas_object_clip_recalc(obj);
267 is_active = evas_object_is_active(obj);
268 obj->is_active = is_active;
271 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);
272 if ((is_active) || (obj->delete_me != 0))
273 eina_array_push(active_objects, obj);
279 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);
283 map = _evas_render_has_map(obj);
284 hmap = _evas_render_had_map(obj);
286 if ((restack) && (!map))
290 eina_array_push(&e->pending_objects, obj);
294 clean_them = EINA_TRUE;
307 evas_object_clip_recalc(obj);
308 if ((obj->restack) &&
309 (is_active) && (!obj->clip.clipees) &&
310 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
311 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
313 eina_array_push(render_objects, obj);
314 _evas_render_prev_cur_clip_cache_add(e, obj);
317 else if ((is_active) && (!obj->clip.clipees) &&
318 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
319 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
321 eina_array_push(render_objects, obj);
322 _evas_render_prev_cur_clip_cache_add(e, obj);
328 else if (_evas_render_had_map(obj))
331 RD(" had map - restack objs\n");
332 // eina_array_push(restack_objects, obj);
333 _evas_render_prev_cur_clip_cache_add(e, obj);
340 if ((obj->cur.map) && (obj->cur.usemap)) map = 1;
350 /* handle normal rendering. this object knows how to handle maps */
353 if (obj->smart.smart)
356 RD(" changed + smart - render ok\n");
357 eina_array_push(render_objects, obj);
359 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
361 _evas_render_phase1_object_process(e, obj2,
377 if ((is_active) && (!obj->clip.clipees) &&
378 _evas_render_is_relevant(obj))
381 RD(" relevant + active\n");
383 eina_array_push(restack_objects, obj);
386 eina_array_push(render_objects, obj);
393 RD(" skip - not smart, not active or clippees or not relevant\n");
399 RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n",
400 evas_object_is_visible(obj),
401 obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart, obj->cur.cache.clip.a,
402 evas_object_was_visible(obj));
403 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
404 (_evas_render_can_render(obj) ||
405 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
407 if (obj->smart.smart)
410 RD(" smart + visible/was visible + not clip\n");
411 eina_array_push(render_objects, obj);
414 (evas_object_smart_members_get_direct(obj), obj2)
416 _evas_render_phase1_object_process(e, obj2,
431 if (evas_object_is_opaque(obj) &&
432 evas_object_is_visible(obj))
435 RD(" opaque + visible\n");
436 eina_array_push(render_objects, obj);
439 else if (evas_object_is_visible(obj))
443 eina_array_push(render_objects, obj);
454 else if (obj->smart.smart)
457 RD(" smart + mot visible/was visible\n");
458 eina_array_push(render_objects, obj);
461 (evas_object_smart_members_get_direct(obj), obj2)
463 _evas_render_phase1_object_process(e, obj2,
478 if (!is_active) obj->restack = 0;
485 _evas_render_phase1_process(Evas *e,
486 Eina_Array *active_objects,
487 Eina_Array *restack_objects,
488 Eina_Array *delete_objects,
489 Eina_Array *render_objects,
493 Eina_Bool clean_them = EINA_FALSE;
495 RD(" [--- PHASE 1\n");
496 EINA_INLIST_FOREACH(e->layers, lay)
500 EINA_INLIST_FOREACH(lay->objects, obj)
502 clean_them |= _evas_render_phase1_object_process
503 (e, obj, active_objects, restack_objects, delete_objects,
504 render_objects, 0, 0, redraw_all
516 _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
520 for (i = 0; i < pending_objects->count; ++i)
523 int is_active, ok = 0;
525 obj = eina_array_data_get(pending_objects, i);
527 if (!obj->layer) goto clean_stuff;
529 evas_object_clip_recalc(obj);
530 is_active = evas_object_is_active(obj);
532 if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
539 if (obj->is_active == is_active)
543 if (obj->smart.smart)
545 if (obj->render_pre || obj->rect_del) ok = 1;
548 if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
549 (_evas_render_can_render(obj) ||
550 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
552 if (!(obj->render_pre || obj->rect_del)) ok = 1;
555 if (is_active && (!obj->clip.clipees) &&
556 (_evas_render_can_render(obj) ||
557 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
559 if (obj->render_pre || obj->rect_del) ok = 1;
564 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
565 (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
566 && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
568 if (obj->rect_del || obj->smart.smart) ok = 1;
576 eina_array_clean(&e->active_objects);
577 eina_array_clean(&e->render_objects);
578 eina_array_clean(&e->restack_objects);
579 eina_array_clean(&e->delete_objects);
587 pending_change(void *data, void *gdata __UNUSED__)
592 if (obj->delete_me) return EINA_FALSE;
593 if (obj->pre_render_done)
595 RD(" OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
596 obj->pre_render_done = 0;
597 //// FIXME: this wipes out changes
599 obj->changed_move_only = 0;
600 obj->changed_nomove = 0;
601 obj->changed_move = 0;
603 return obj->changed ? EINA_TRUE : EINA_FALSE;
607 unchange(Evas_Object *obj)
611 if (!obj->changed) return;
613 obj->changed_move_only = 0;
614 obj->changed_nomove = 0;
615 obj->changed_move = 0;
616 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
623 chlist(Evas_Object *obj, int i)
629 if (!obj->changed) return 0;
630 for (j = 0; j < i; j++) printf(" ");
631 printf("ch2 %p %s %i [%i %i %ix%i] v %i/%i [r%i] %p\n", obj,
633 obj->changed_move_only,
642 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
645 ret |= chlist(obj2, i + 1);
650 _evas_render_can_use_overlay(Evas *e, Evas_Object *obj)
654 Eina_List *alphas = NULL;
655 Eina_List *opaques = NULL;
656 Evas_Object *video_parent = NULL;
658 Evas_Coord xc1, yc1, xc2, yc2;
662 video_parent = _evas_object_image_video_parent_get(obj);
664 /* Check if any one is the stack make this object mapped */
666 while (tmp && !_evas_render_has_map(tmp))
667 tmp = tmp->smart.parent;
669 if (tmp && _evas_render_has_map(tmp)) return EINA_FALSE; /* we are mapped, we can't be an overlay */
671 if (!evas_object_is_visible(obj)) return EINA_FALSE; /* no need to update the overlay if it's not visible */
673 /* If any recoloring of the surface is needed, n overlay to */
674 if ((obj->cur.cache.clip.r != 255) ||
675 (obj->cur.cache.clip.g != 255) ||
676 (obj->cur.cache.clip.b != 255) ||
677 (obj->cur.cache.clip.a != 255))
680 /* Check presence of transparent object on top of the video object */
681 EINA_RECTANGLE_SET(&zone,
682 obj->cur.cache.clip.x,
683 obj->cur.cache.clip.y,
684 obj->cur.cache.clip.w,
685 obj->cur.cache.clip.h);
687 for (i = e->active_objects.count - 1; i > 0; i--)
690 Eina_Rectangle *match;
691 Evas_Object *current;
693 int xm1, ym1, xm2, ym2;
695 current = eina_array_data_get(&e->active_objects, i);
697 /* Did we find the video object in the stack ? */
698 if (current == video_parent || current == obj)
701 EINA_RECTANGLE_SET(&self,
702 current->cur.cache.clip.x,
703 current->cur.cache.clip.y,
704 current->cur.cache.clip.w,
705 current->cur.cache.clip.h);
707 /* This doesn't cover the area of the video object, so don't bother with that object */
708 if (!eina_rectangles_intersect(&zone, &self))
711 xc1 = current->cur.cache.clip.x;
712 yc1 = current->cur.cache.clip.y;
713 xc2 = current->cur.cache.clip.x + current->cur.cache.clip.w;
714 yc2 = current->cur.cache.clip.y + current->cur.cache.clip.h;
716 if (evas_object_is_visible(current) &&
717 (!current->clip.clipees) &&
718 (current->cur.visible) &&
719 (!current->delete_me) &&
720 (current->cur.cache.clip.visible) &&
721 (!current->smart.smart))
723 Eina_Bool included = EINA_FALSE;
725 if (evas_object_is_opaque(current) ||
726 ((current->func->has_opaque_rect) &&
727 (current->func->has_opaque_rect(current))))
729 /* The object is opaque */
731 /* Check if the opaque object is inside another opaque object */
732 EINA_LIST_FOREACH(opaques, 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 /* Not included yet */
753 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
754 current->cur.cache.clip.w, current->cur.cache.clip.h);
756 opaques = eina_list_append(opaques, r);
761 /* Remove all the transparent object that are covered by the new opaque object */
762 EINA_LIST_FOREACH_SAFE(alphas, l, ln, match)
766 xm2 = match->x + match->w;
767 ym2 = match->y + match->h;
769 if (xm1 >= r->x && ym1 >= r->y && xm2 <= xn2 && ym2 <= yn2)
771 /* The new rectangle is over some transparent object,
772 so remove the transparent object */
773 alphas = eina_list_remove_list(alphas, l);
780 /* The object has some transparency */
782 /* Check if the transparent object is inside any other transparent object */
783 EINA_LIST_FOREACH(alphas, l, match)
787 xm2 = match->x + match->w;
788 ym2 = match->y + match->h;
790 /* Both object are included */
791 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
793 included = EINA_TRUE;
798 /* If not check if it is inside any opaque one */
801 EINA_LIST_FOREACH(opaques, l, match)
805 xm2 = match->x + match->w;
806 ym2 = match->y + match->h;
808 /* Both object are included */
809 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
811 included = EINA_TRUE;
817 /* No inclusion at all, so add it */
820 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
821 current->cur.cache.clip.w, current->cur.cache.clip.h);
823 alphas = eina_list_append(alphas, r);
829 /* If there is any pending transparent object, then no overlay */
830 nooverlay = !!eina_list_count(alphas);
832 EINA_LIST_FREE(alphas, r)
833 eina_rectangle_free(r);
834 EINA_LIST_FREE(opaques, r)
835 eina_rectangle_free(r);
844 evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
845 int off_x, int off_y, int mapped,
846 int ecx, int ecy, int ecw, int ech
854 Eina_Bool clean_them = EINA_FALSE;
856 evas_object_clip_recalc(obj);
858 RD(" { evas_render_mapped(%p, %p, %p, %p, %i, %i, %i, %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
861 if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
862 (obj->cur.have_clipees))
869 else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
870 (_evas_render_can_render(obj))))
878 // set render_pre - for child objs that may not have gotten it.
879 obj->pre_render_done = 1;
880 RD(" Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map,
881 obj->func->can_map ? obj->func->can_map(obj): -1,
882 obj->cur.map, obj->cur.usemap,
883 _evas_render_has_map(obj));
884 if (_evas_render_has_map(obj))
886 const Evas_Map_Point *p, *p_end;
887 RGBA_Map_Point pts[4], *pt;
889 int changed = 0, rendered = 0;
891 clean_them = EINA_TRUE;
893 sw = obj->cur.geometry.w;
894 sh = obj->cur.geometry.h;
896 RD(" mapped obj: %ix%i\n", sw, sh);
897 if ((sw <= 0) || (sh <= 0))
904 pts[0].px = obj->cur.map->persp.px << FP;
905 pts[0].py = obj->cur.map->persp.py << FP;
906 pts[0].foc = obj->cur.map->persp.foc << FP;
907 pts[0].z0 = obj->cur.map->persp.z0 << FP;
909 p = obj->cur.map->points;
910 p_end = p + obj->cur.map->count;
912 for (; p < p_end; p++, pt++)
914 pt->x = (p->x + (double)off_x) * FP1;
915 pt->y = (p->y + (double)off_y) * FP1;
916 pt->z = (p->z) * FP1;
922 if (pt->u < 0) pt->u = 0;
923 else if (pt->u > (sw * FP1)) pt->u = (sw * FP1);
924 if (pt->v < 0) pt->v = 0;
925 else if (pt->v > (sh * FP1)) pt->v = (sh * FP1);
926 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
928 /* Copy last for software engine */
929 if (obj->cur.map->count & 0x1)
931 pts[obj->cur.map->count] = pts[obj->cur.map->count - 1];
935 if (obj->cur.map->surface)
937 if ((obj->cur.map->surface_w != sw) ||
938 (obj->cur.map->surface_h != sh))
941 RD(" new surf: %ix%i\n", sw, sh);
942 obj->layer->evas->engine.func->image_map_surface_free
943 (e->engine.data.output, obj->cur.map->surface);
944 obj->cur.map->surface = NULL;
947 if (!obj->cur.map->surface)
949 obj->cur.map->surface_w = sw;
950 obj->cur.map->surface_h = sh;
952 obj->cur.map->surface =
953 obj->layer->evas->engine.func->image_map_surface_new
954 (e->engine.data.output, obj->cur.map->surface_w,
955 obj->cur.map->surface_h,
956 obj->cur.map->alpha);
958 RD(" fisrt surf: %ix%i\n", sw, sh);
961 if (obj->smart.smart)
965 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), o2)
967 if (!evas_object_is_visible(o2) &&
968 !evas_object_was_visible(o2))
971 o2->changed_move_only = 0;
972 o2->changed_nomove = 0;
973 o2->changed_move = 0;
981 o2->changed_move_only = 0;
982 o2->changed_nomove = 0;
983 o2->changed_move = 0;
989 obj->changed_move_only = 0;
990 obj->changed_nomove = 0;
991 obj->changed_move = 0;
999 obj->changed_move_only = 0;
1000 obj->changed_nomove = 0;
1001 obj->changed_move = 0;
1005 // clear surface before re-render
1006 if ((changed) && (obj->cur.map->surface))
1011 RD(" children redraw\n");
1012 // FIXME: calculate "changes" within map surface and only clear
1013 // and re-render those
1014 if (obj->cur.map->alpha)
1016 ctx = e->engine.func->context_new(e->engine.data.output);
1017 e->engine.func->context_color_set
1018 (e->engine.data.output, ctx, 0, 0, 0, 0);
1019 e->engine.func->context_render_op_set
1020 (e->engine.data.output, ctx, EVAS_RENDER_COPY);
1021 e->engine.func->rectangle_draw(e->engine.data.output,
1023 obj->cur.map->surface,
1025 obj->cur.map->surface_w,
1026 obj->cur.map->surface_h);
1027 e->engine.func->context_free(e->engine.data.output, ctx);
1029 ctx = e->engine.func->context_new(e->engine.data.output);
1030 off_x2 = -obj->cur.geometry.x;
1031 off_y2 = -obj->cur.geometry.y;
1032 if (obj->smart.smart)
1035 (evas_object_smart_members_get_direct(obj), obj2)
1037 clean_them |= evas_render_mapped(e, obj2, ctx,
1038 obj->cur.map->surface,
1049 int x = 0, y = 0, w = 0, h = 0;
1051 w = obj->cur.map->surface_w;
1052 h = obj->cur.map->surface_h;
1053 RECTS_CLIP_TO_RECT(x, y, w, h,
1054 obj->cur.geometry.x + off_x2,
1055 obj->cur.geometry.y + off_y2,
1056 obj->cur.geometry.w,
1057 obj->cur.geometry.h);
1059 e->engine.func->context_clip_set(e->engine.data.output,
1061 obj->func->render(obj, e->engine.data.output, ctx,
1062 obj->cur.map->surface, off_x2, off_y2);
1064 e->engine.func->context_free(e->engine.data.output, ctx);
1073 obj->cur.map->surface = e->engine.func->image_dirty_region
1074 (e->engine.data.output, obj->cur.map->surface,
1075 0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
1077 e->engine.func->context_clip_unset(e->engine.data.output,
1078 e->engine.data.context);
1079 if (obj->cur.map->surface)
1081 if (obj->smart.smart)
1083 if (obj->cur.clipper)
1088 obj->cur.cache.clip.dirty = 1;
1089 tobj = obj->cur.map_parent;
1090 obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
1091 evas_object_clip_recalc(obj);
1092 obj->cur.map_parent = tobj;
1093 x = obj->cur.cache.clip.x;
1094 y = obj->cur.cache.clip.y;
1095 w = obj->cur.cache.clip.w;
1096 h = obj->cur.cache.clip.h;
1097 RECTS_CLIP_TO_RECT(x, y, w, h,
1098 obj->cur.clipper->cur.cache.clip.x,
1099 obj->cur.clipper->cur.cache.clip.y,
1100 obj->cur.clipper->cur.cache.clip.w,
1101 obj->cur.clipper->cur.cache.clip.h);
1102 e->engine.func->context_clip_set(e->engine.data.output,
1103 e->engine.data.context,
1104 x + off_x, y + off_y, w, h);
1109 if (obj->cur.clipper)
1113 evas_object_clip_recalc(obj);
1114 x = obj->cur.cache.clip.x;
1115 y = obj->cur.cache.clip.y;
1116 w = obj->cur.cache.clip.w;
1117 h = obj->cur.cache.clip.h;
1118 RECTS_CLIP_TO_RECT(x, y, w, h,
1119 obj->cur.clipper->cur.cache.clip.x,
1120 obj->cur.clipper->cur.cache.clip.y,
1121 obj->cur.clipper->cur.cache.clip.w,
1122 obj->cur.clipper->cur.cache.clip.h);
1123 e->engine.func->context_clip_set(e->engine.data.output,
1124 e->engine.data.context,
1125 x + off_x, y + off_y, w, h);
1129 if (surface == e->engine.data.output)
1130 e->engine.func->context_clip_clip(e->engine.data.output,
1131 e->engine.data.context,
1132 ecx, ecy, ecw, ech);
1133 if (obj->cur.cache.clip.visible)
1134 obj->layer->evas->engine.func->image_map_draw
1135 (e->engine.data.output, e->engine.data.context, surface,
1136 obj->cur.map->surface, obj->cur.map->count, pts,
1137 obj->cur.map->smooth, 0);
1138 // FIXME: needs to cache these maps and
1139 // keep them only rendering updates
1140 // obj->layer->evas->engine.func->image_map_surface_free
1141 // (e->engine.data.output, obj->cur.map->surface);
1142 // obj->cur.map->surface = NULL;
1149 RD(" draw child of mapped obj\n");
1150 ctx = e->engine.func->context_new(e->engine.data.output);
1151 if (obj->smart.smart)
1154 (evas_object_smart_members_get_direct(obj), obj2)
1156 clean_them |= evas_render_mapped(e, obj2, ctx,
1174 x = obj->cur.cache.clip.x + off_x;
1175 y = obj->cur.cache.clip.y + off_y;
1176 w = obj->cur.cache.clip.w;
1177 h = obj->cur.cache.clip.h;
1179 if (obj->cur.clipper)
1181 if (_evas_render_has_map(obj))
1182 evas_object_clip_recalc(obj);
1184 RD(" clipper: %i %i %ix%i\n",
1185 obj->cur.clipper->cur.cache.clip.x + off_x,
1186 obj->cur.clipper->cur.cache.clip.y + off_y,
1187 obj->cur.clipper->cur.cache.clip.w,
1188 obj->cur.clipper->cur.cache.clip.h);
1190 RECTS_CLIP_TO_RECT(x, y, w, h,
1191 obj->cur.clipper->cur.cache.clip.x + off_x,
1192 obj->cur.clipper->cur.cache.clip.y + off_y,
1193 obj->cur.clipper->cur.cache.clip.w,
1194 obj->cur.clipper->cur.cache.clip.h);
1197 RD(" clip: %i %i %ix%i [%i %i %ix%i]\n",
1198 obj->cur.cache.clip.x + off_x,
1199 obj->cur.cache.clip.y + off_y,
1200 obj->cur.cache.clip.w,
1201 obj->cur.cache.clip.h,
1202 obj->cur.geometry.x + off_x,
1203 obj->cur.geometry.y + off_y,
1204 obj->cur.geometry.w,
1205 obj->cur.geometry.h);
1206 e->engine.func->context_clip_set(e->engine.data.output,
1214 obj->func->render(obj, e->engine.data.output, ctx,
1215 surface, off_x, off_y);
1217 obj->layer->evas->engine.func->context_color_set(e->engine.data.output,
1220 obj->layer->evas->engine.func->rectangle_draw(e->engine.data.output,
1226 e->engine.func->context_free(e->engine.data.output, ctx);
1230 if (obj->cur.clipper)
1234 if (_evas_render_has_map(obj))
1235 evas_object_clip_recalc(obj);
1236 x = obj->cur.cache.clip.x;
1237 y = obj->cur.cache.clip.y;
1238 w = obj->cur.cache.clip.w;
1239 h = obj->cur.cache.clip.h;
1240 RECTS_CLIP_TO_RECT(x, y, w, h,
1241 obj->cur.clipper->cur.cache.clip.x,
1242 obj->cur.clipper->cur.cache.clip.y,
1243 obj->cur.clipper->cur.cache.clip.w,
1244 obj->cur.clipper->cur.cache.clip.h);
1245 e->engine.func->context_clip_set(e->engine.data.output,
1246 e->engine.data.context,
1247 x + off_x, y + off_y, w, h);
1248 e->engine.func->context_clip_clip(e->engine.data.output,
1249 e->engine.data.context,
1250 ecx, ecy, ecw, ech);
1254 RD(" draw normal obj\n");
1255 obj->func->render(obj, e->engine.data.output, context, surface,
1266 evas_render_updates_internal(Evas *e,
1267 unsigned char make_updates,
1268 unsigned char do_draw)
1271 Eina_List *updates = NULL;
1274 Eina_Bool clean_them = EINA_FALSE;
1283 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1286 if (!e->changed) return NULL;
1288 evas_call_smarts_calculate(e);
1290 RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
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 _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
1306 &e->delete_objects, &e->render_objects);
1308 /* phase 1.5. check if the video should be inlined or stay in their overlay */
1309 alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1310 e->engine.data.context);
1312 EINA_LIST_FOREACH(e->video_objects, ll, obj)
1314 /* we need the surface to be transparent to display the underlying overlay */
1315 if (alpha && _evas_render_can_use_overlay(e, obj))
1316 _evas_object_image_video_overlay_show(obj);
1318 _evas_object_image_video_overlay_hide(obj);
1321 /* phase 2. force updates for restacks */
1322 for (i = 0; i < e->restack_objects.count; ++i)
1324 obj = eina_array_data_get(&e->restack_objects, i);
1325 obj->func->render_pre(obj);
1326 _evas_render_prev_cur_clip_cache_add(e, obj);
1328 eina_array_clean(&e->restack_objects);
1329 /* phase 3. add exposes */
1330 EINA_LIST_FREE(e->damages, r)
1332 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1333 r->x, r->y, r->w, r->h);
1334 eina_rectangle_free(r);
1336 /* phase 4. output & viewport changes */
1337 if (e->viewport.changed)
1339 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1341 e->output.w, e->output.h);
1343 if (e->output.changed)
1345 e->engine.func->output_resize(e->engine.data.output,
1346 e->output.w, e->output.h);
1347 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1349 e->output.w, e->output.h);
1351 if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1353 ERR("viewport size != output size!");
1357 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1359 e->output.w, e->output.h);
1361 /* phase 5. add obscures */
1362 EINA_LIST_FOREACH(e->obscures, ll, r)
1364 e->engine.func->output_redraws_rect_del(e->engine.data.output,
1365 r->x, r->y, r->w, r->h);
1367 /* build obscure objects list of active objects that obscure */
1368 for (i = 0; i < e->active_objects.count; ++i)
1370 obj = eina_array_data_get(&e->active_objects, i);
1371 if (UNLIKELY((evas_object_is_opaque(obj) ||
1372 ((obj->func->has_opaque_rect) &&
1373 (obj->func->has_opaque_rect(obj)))) &&
1374 evas_object_is_visible(obj) &&
1375 (!obj->clip.clipees) &&
1376 (obj->cur.visible) &&
1377 (!obj->delete_me) &&
1378 (obj->cur.cache.clip.visible) &&
1379 (!obj->smart.smart)))
1380 /* obscuring_objects = eina_list_append(obscuring_objects, obj); */
1381 eina_array_push(&e->obscuring_objects, obj);
1384 /* save this list */
1385 /* obscuring_objects_orig = obscuring_objects; */
1386 /* obscuring_objects = NULL; */
1387 /* phase 6. go thru each update rect and render objects in it*/
1390 unsigned int offset = 0;
1393 e->engine.func->output_redraws_next_update_get
1394 (e->engine.data.output,
1396 &cx, &cy, &cw, &ch)))
1400 RD(" [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1403 Eina_Rectangle *rect;
1405 NEW_RECT(rect, ux, uy, uw, uh);
1407 updates = eina_list_append(updates, rect);
1412 /* build obscuring objects list (in order from bottom to top) */
1413 for (i = 0; i < e->obscuring_objects.count; ++i)
1415 obj = (Evas_Object *)eina_array_data_get
1416 (&e->obscuring_objects, i);
1417 if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1419 eina_array_push(&e->temporary_objects, obj);
1421 /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1424 if (evas_object_is_opaque(obj))
1425 e->engine.func->context_cutout_add
1426 (e->engine.data.output,
1427 e->engine.data.context,
1428 obj->cur.cache.clip.x + off_x,
1429 obj->cur.cache.clip.y + off_y,
1430 obj->cur.cache.clip.w,
1431 obj->cur.cache.clip.h);
1434 if (obj->func->get_opaque_rect)
1436 Evas_Coord obx, oby, obw, obh;
1438 obj->func->get_opaque_rect
1439 (obj, &obx, &oby, &obw, &obh);
1440 if ((obw > 0) && (obh > 0))
1445 (obx, oby, obw, obh,
1446 obj->cur.cache.clip.x + off_x,
1447 obj->cur.cache.clip.y + off_y,
1448 obj->cur.cache.clip.w,
1449 obj->cur.cache.clip.h);
1450 e->engine.func->context_cutout_add
1451 (e->engine.data.output,
1452 e->engine.data.context,
1463 e->engine.func->context_clip_set(e->engine.data.output,
1464 e->engine.data.context,
1465 ux + off_x, uy + off_y, uw, uh);
1466 e->engine.func->context_color_set(e->engine.data.output,
1467 e->engine.data.context,
1469 e->engine.func->context_multiplier_unset
1470 (e->engine.data.output, e->engine.data.context);
1471 e->engine.func->context_render_op_set(e->engine.data.output,
1472 e->engine.data.context,
1474 e->engine.func->rectangle_draw(e->engine.data.output,
1475 e->engine.data.context,
1478 e->engine.func->context_cutout_clear(e->engine.data.output,
1479 e->engine.data.context);
1480 e->engine.func->context_clip_unset(e->engine.data.output,
1481 e->engine.data.context);
1483 /* render all object that intersect with rect */
1484 for (i = 0; i < e->active_objects.count; ++i)
1486 obj = eina_array_data_get(&e->active_objects, i);
1488 /* if it's in our outpout rect and it doesn't clip anything */
1489 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);
1490 if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1491 (obj->smart.smart)) &&
1492 (!obj->clip.clipees) &&
1493 (obj->cur.visible) &&
1494 (!obj->delete_me) &&
1495 (obj->cur.cache.clip.visible) &&
1496 // (!obj->smart.smart) &&
1497 ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1501 RD(" DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1502 if ((e->temporary_objects.count > offset) &&
1503 (eina_array_data_get(&e->temporary_objects, offset) == obj))
1505 x = cx; y = cy; w = cw; h = ch;
1506 if (((w > 0) && (h > 0)) || (obj->smart.smart))
1508 if (!obj->smart.smart)
1510 RECTS_CLIP_TO_RECT(x, y, w, h,
1511 obj->cur.cache.clip.x + off_x,
1512 obj->cur.cache.clip.y + off_y,
1513 obj->cur.cache.clip.w,
1514 obj->cur.cache.clip.h);
1517 e->engine.func->context_mask_set(e->engine.data.output,
1518 e->engine.data.context,
1519 obj->cur.mask->func->engine_data_get(obj->cur.mask),
1520 obj->cur.mask->cur.geometry.x + off_x,
1521 obj->cur.mask->cur.geometry.y + off_y,
1522 obj->cur.mask->cur.geometry.w,
1523 obj->cur.mask->cur.geometry.h);
1525 e->engine.func->context_mask_unset(e->engine.data.output,
1526 e->engine.data.context);
1527 if (obj->cur.clipper)
1528 e->engine.func->context_clip_set(e->engine.data.output,
1529 e->engine.data.context,
1532 e->engine.func->context_clip_unset(e->engine.data.output,
1533 e->engine.data.context);
1534 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1535 for (j = offset; j < e->temporary_objects.count; ++j)
1539 obj2 = (Evas_Object *) eina_array_data_get(&e->temporary_objects, j);
1540 if (evas_object_is_opaque(obj2))
1541 e->engine.func->context_cutout_add(e->engine.data.output,
1542 e->engine.data.context,
1543 obj2->cur.cache.clip.x + off_x,
1544 obj2->cur.cache.clip.y + off_y,
1545 obj2->cur.cache.clip.w,
1546 obj2->cur.cache.clip.h);
1549 if (obj2->func->get_opaque_rect)
1551 Evas_Coord obx, oby, obw, obh;
1553 obj2->func->get_opaque_rect
1554 (obj2, &obx, &oby, &obw, &obh);
1555 if ((obw > 0) && (obh > 0))
1559 RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1560 obj2->cur.cache.clip.x + off_x,
1561 obj2->cur.cache.clip.y + off_y,
1562 obj2->cur.cache.clip.w,
1563 obj2->cur.cache.clip.h);
1564 e->engine.func->context_cutout_add(e->engine.data.output,
1565 e->engine.data.context,
1573 e->engine.func->context_clip_set(e->engine.data.output,
1574 e->engine.data.context,
1576 clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1577 surface, off_x, off_y, 0,
1583 e->engine.func->context_cutout_clear(e->engine.data.output,
1584 e->engine.data.context);
1588 /* punch rect out */
1589 e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1592 /* free obscuring objects list */
1593 eina_array_clean(&e->temporary_objects);
1599 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1600 e->engine.func->output_flush(e->engine.data.output);
1601 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1605 e->engine.func->output_redraws_clear(e->engine.data.output);
1606 /* and do a post render pass */
1607 for (i = 0; i < e->active_objects.count; ++i)
1609 obj = eina_array_data_get(&e->active_objects, i);
1610 obj->pre_render_done = 0;
1611 RD(" OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1612 if ((obj->changed) && (do_draw))
1614 RD(" OBJ [%p] post... func1\n", obj);
1615 obj->func->render_post(obj);
1618 obj->changed_move_only = 0;
1619 obj->changed_nomove = 0;
1620 obj->changed_move = 0;
1622 else if ((obj->cur.map != obj->prev.map) ||
1623 (obj->cur.usemap != obj->prev.usemap))
1625 RD(" OBJ [%p] post... func2\n", obj);
1626 obj->func->render_post(obj);
1629 obj->changed_move_only = 0;
1630 obj->changed_nomove = 0;
1631 obj->changed_move = 0;
1633 /* moved to other pre-process phase 1
1634 if (obj->delete_me == 2)
1636 delete_objects = eina_list_append(delete_objects, obj);
1638 else if (obj->delete_me != 0) obj->delete_me++;
1641 /* free our obscuring object list */
1642 eina_array_clean(&e->obscuring_objects);
1644 /* If some object are still marked as changed, do not remove
1645 them from the pending list. */
1646 eina_array_remove(&e->pending_objects, pending_change, NULL);
1648 for (i = 0; i < e->render_objects.count; ++i)
1650 obj = eina_array_data_get(&e->render_objects, i);
1651 obj->pre_render_done = 0;
1654 /* delete all objects flagged for deletion now */
1655 for (i = 0; i < e->delete_objects.count; ++i)
1657 obj = eina_array_data_get(&e->delete_objects, i);
1658 evas_object_free(obj, 1);
1660 eina_array_clean(&e->delete_objects);
1663 e->viewport.changed = 0;
1664 e->output.changed = 0;
1667 /* If their are some object to restack or some object to delete,
1668 * it's useless to keep the render object list around. */
1671 eina_array_clean(&e->active_objects);
1672 eina_array_clean(&e->render_objects);
1673 eina_array_clean(&e->restack_objects);
1674 eina_array_clean(&e->delete_objects);
1675 eina_array_clean(&e->obscuring_objects);
1679 evas_module_clean();
1687 evas_render_updates_free(Eina_List *updates)
1691 EINA_LIST_FREE(updates, r)
1692 eina_rectangle_free(r);
1696 evas_render_updates(Evas *e)
1698 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1702 #ifdef EVAS_FRAME_QUEUING
1703 evas_common_frameq_flush_ready ();
1706 if (!e->changed) return NULL;
1707 return evas_render_updates_internal(e, 1, 1);
1711 evas_render(Evas *e)
1713 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1717 #ifdef EVAS_FRAME_QUEUING
1718 evas_common_frameq_flush_ready ();
1721 if (!e->changed) return;
1722 evas_render_updates_internal(e, 0, 1);
1726 evas_norender(Evas *e)
1728 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1732 // if (!e->changed) return;
1733 evas_render_updates_internal(e, 0, 0);
1737 evas_render_idle_flush(Evas *e)
1739 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1743 evas_fonts_zero_presure(e);
1745 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1746 (e->engine.data.output))
1747 e->engine.func->output_idle_flush(e->engine.data.output);
1749 eina_array_flush(&e->delete_objects);
1750 eina_array_flush(&e->active_objects);
1751 eina_array_flush(&e->restack_objects);
1752 eina_array_flush(&e->render_objects);
1753 eina_array_flush(&e->clip_changes);
1761 #ifdef EVAS_FRAME_QUEUING
1762 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1766 evas_common_frameq_flush();
1773 _evas_render_dump_map_surfaces(Evas_Object *obj)
1775 if ((obj->cur.map) && obj->cur.map->surface)
1777 obj->layer->evas->engine.func->image_map_surface_free
1778 (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1779 obj->cur.map->surface = NULL;
1782 if (obj->smart.smart)
1786 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1787 _evas_render_dump_map_surfaces(obj2);
1792 evas_render_dump(Evas *e)
1796 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1800 EINA_INLIST_FOREACH(e->layers, lay)
1804 EINA_INLIST_FOREACH(lay->objects, obj)
1806 if ((obj->type) && (!strcmp(obj->type, "image")))
1807 evas_object_inform_call_image_unloaded(obj);
1808 _evas_render_dump_map_surfaces(obj);
1811 if ((e->engine.func) && (e->engine.func->output_dump) &&
1812 (e->engine.data.output))
1813 e->engine.func->output_dump(e->engine.data.output);
1817 evas_render_invalidate(Evas *e)
1819 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1823 eina_array_clean(&e->active_objects);
1824 eina_array_clean(&e->render_objects);
1826 eina_array_flush(&e->restack_objects);
1827 eina_array_flush(&e->delete_objects);
1833 evas_render_object_recalc(Evas_Object *obj)
1835 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1839 #ifndef EVAS_FRAME_QUEUING
1840 if ((!obj->changed) && (obj->delete_me < 2))
1842 if ((!obj->changed))
1847 e = obj->layer->evas;
1848 if ((!e) || (e->cleanup)) return;
1849 #ifdef EVAS_FRAME_QUEUING
1850 if (obj->delete_me >= evas_common_frameq_get_frameq_sz() + 2) return;
1852 eina_array_push(&e->pending_objects, obj);
1857 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/