sync with private
[profile/ivi/evas.git] / src / lib / canvas / evas_render.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3 #include <math.h>
4 #ifdef EVAS_CSERVE2
5 #include "evas_cs2_private.h"
6 #endif
7
8 // debug rendering
9 /* #define REND_DGB 1 */
10 /* #define STDOUT_DBG 1 */
11
12 #ifdef REND_DGB
13 static FILE *dbf = NULL;
14
15 static void
16 rend_dbg(const char *txt)
17 {
18    if (!dbf)
19      {
20 #ifdef STDOUT_DBG
21         dbf = stdout;
22 #else
23         dbf = fopen("EVAS-RENDER-DEBUG.log", "w");
24 #endif
25         if (!dbf) return;
26      }
27    fputs(txt, dbf);
28    fflush(dbf);
29 }
30 #define RD(args...) \
31    { \
32       char __tmpbuf[4096]; \
33       \
34       snprintf(__tmpbuf, sizeof(__tmpbuf), ##args); \
35       rend_dbg(__tmpbuf); \
36    }
37 #define RDI(xxxx) \
38    { \
39       char __tmpbuf[4096]; int __tmpi; \
40       for (__tmpi = 0; __tmpi < xxxx; __tmpi++) \
41         __tmpbuf[__tmpi] = ' '; \
42       __tmpbuf[__tmpi] = 0; \
43       rend_dbg(__tmpbuf); \
44    }
45 #else
46 #define RD(args...)
47 #define RDI(x)
48 #endif
49
50 static Eina_List *
51 evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char do_draw);
52
53 EAPI void
54 evas_damage_rectangle_add(Evas *e, int x, int y, int w, int h)
55 {
56    Eina_Rectangle *r;
57
58    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
59    return;
60    MAGIC_CHECK_END();
61    NEW_RECT(r, x, y, w, h);
62    if (!r) return;
63    e->damages = eina_list_append(e->damages, r);
64    e->changed = EINA_TRUE;
65 }
66
67 EAPI void
68 evas_obscured_rectangle_add(Evas *e, int x, int y, int w, int h)
69 {
70    Eina_Rectangle *r;
71
72    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
73    return;
74    MAGIC_CHECK_END();
75    NEW_RECT(r, x, y, w, h);
76    if (!r) return;
77    e->obscures = eina_list_append(e->obscures, r);
78 }
79
80 EAPI void
81 evas_obscured_clear(Evas *e)
82 {
83    Eina_Rectangle *r;
84
85    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
86    return;
87    MAGIC_CHECK_END();
88    EINA_LIST_FREE(e->obscures, r)
89      {
90         eina_rectangle_free(r);
91      }
92 }
93
94 static Eina_Bool
95 _evas_render_had_map(Evas_Object *obj)
96 {
97    return ((obj->prev.map) && (obj->prev.usemap));
98    //   return ((!obj->cur.map) && (obj->prev.usemap));
99 }
100
101 static Eina_Bool
102 _evas_render_is_relevant(Evas_Object *obj)
103 {
104    return ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
105            (evas_object_was_visible(obj) && (!obj->prev.have_clipees)));
106 }
107
108 static Eina_Bool
109 _evas_render_can_render(Evas_Object *obj)
110 {
111    return (evas_object_is_visible(obj) && (!obj->cur.have_clipees));
112 }
113
114 static void
115 _evas_render_prev_cur_clip_cache_add(Evas *e, Evas_Object *obj)
116 {
117    e->engine.func->output_redraws_rect_add(e->engine.data.output,
118                                            obj->prev.cache.clip.x,
119                                            obj->prev.cache.clip.y,
120                                            obj->prev.cache.clip.w,
121                                            obj->prev.cache.clip.h);
122    e->engine.func->output_redraws_rect_add(e->engine.data.output,
123                                            obj->cur.cache.clip.x,
124                                            obj->cur.cache.clip.y,
125                                            obj->cur.cache.clip.w,
126                                            obj->cur.cache.clip.h);
127 }
128
129 static void
130 _evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
131 {
132    Evas_Coord x, y, w, h;
133
134    x = obj->cur.cache.clip.x;
135    y = obj->cur.cache.clip.y;
136    w = obj->cur.cache.clip.w;
137    h = obj->cur.cache.clip.h;
138    if (obj->cur.clipper)
139      {
140         RECTS_CLIP_TO_RECT(x, y, w, h,
141                            obj->cur.clipper->cur.cache.clip.x,
142                            obj->cur.clipper->cur.cache.clip.y,
143                            obj->cur.clipper->cur.cache.clip.w,
144                            obj->cur.clipper->cur.cache.clip.h);
145      }
146    e->engine.func->output_redraws_rect_del(e->engine.data.output,
147                                            x, y, w, h);
148 }
149
150 static void
151 _evas_render_phase1_direct(Evas *e,
152                            Eina_Array *active_objects,
153                            Eina_Array *restack_objects __UNUSED__,
154                            Eina_Array *delete_objects __UNUSED__,
155                            Eina_Array *render_objects)
156 {
157    unsigned int i;
158    Eina_List *l;
159    Evas_Object *proxy;
160
161    RD("  [--- PHASE 1 DIRECT\n");
162    for (i = 0; i < active_objects->count; i++)
163      {
164         Evas_Object *obj;
165
166         obj = eina_array_data_get(active_objects, i);
167         if (obj->changed)
168           {
169              /* Flag need redraw on proxy too */
170              evas_object_clip_recalc(obj);
171              EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
172                proxy->proxy.redraw = EINA_TRUE;
173           }
174      }
175    for (i = 0; i < render_objects->count; i++)
176      {
177         Evas_Object *obj;
178
179         obj = eina_array_data_get(render_objects, i);
180         RD("    OBJ [%p] changed %i\n", obj, obj->changed);
181         if (obj->changed)
182           {
183              /* Flag need redraw on proxy too */
184              evas_object_clip_recalc(obj);
185              obj->func->render_pre(obj);
186              if (obj->proxy.redraw)
187                _evas_render_prev_cur_clip_cache_add(e, obj);
188              if (obj->proxy.proxies)
189                {
190                   obj->proxy.redraw = EINA_TRUE;
191                   EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
192                     {
193                        proxy->func->render_pre(proxy);
194                        _evas_render_prev_cur_clip_cache_add(e, proxy);
195                     }
196                }
197
198              RD("      pre-render-done smart:%p|%p  [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
199                 obj->smart.smart,
200                 evas_object_smart_members_get_direct(obj),
201                 obj->cur.map, obj->cur.usemap,
202                 obj->prev.map, obj->prev.usemap,
203                 _evas_render_has_map(obj),
204                 _evas_render_had_map(obj));
205              if ((obj->smart.smart) &&
206                  (_evas_render_has_map(obj)))
207                {
208                   RD("      has map + smart\n");
209                   _evas_render_prev_cur_clip_cache_add(e, obj);
210                }
211           }
212         else
213           {
214              if (obj->smart.smart)
215                {
216                   //                  obj->func->render_pre(obj);
217                }
218              else if ((obj->rect_del) ||
219                       (evas_object_is_opaque(obj) && evas_object_is_visible(obj)))
220                {
221                   RD("    rect del\n");
222                   _evas_render_cur_clip_cache_del(e, obj);
223                }
224           }
225      }
226    RD("  ---]\n");
227 }
228
229 static Eina_Bool
230 _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
231                                    Eina_Array *active_objects,
232                                    Eina_Array *restack_objects,
233                                    Eina_Array *delete_objects,
234                                    Eina_Array *render_objects,
235                                    int restack,
236                                    int *redraw_all,
237                                    Eina_Bool mapped_parent
238 #ifdef REND_DGB
239                                    , int level
240 #endif
241                                   )
242 {
243    Eina_Bool clean_them = EINA_FALSE;
244    Evas_Object *obj2;
245    int is_active;
246    Eina_Bool map, hmap;
247
248    //Need pre render for the children of mapped object.
249    //But only when they have changed.
250    if (mapped_parent && (!obj->changed)) return EINA_FALSE;
251
252    obj->rect_del = EINA_FALSE;
253    obj->render_pre = EINA_FALSE;
254
255    if (obj->delete_me == 2)
256      eina_array_push(delete_objects, obj);
257    else if (obj->delete_me != 0) obj->delete_me++;
258    /* If the object will be removed, we should not cache anything during this run. */
259    if (obj->delete_me != 0) clean_them = EINA_TRUE;
260
261    /* build active object list */
262    evas_object_clip_recalc(obj);
263    is_active = evas_object_is_active(obj);
264    obj->is_active = is_active;
265
266    RDI(level);
267    RD("    [--- PROCESS [%p] '%s' active = %i, del = %i | %i %i %ix%i\n", obj, obj->type, is_active, obj->delete_me, obj->cur.geometry.x, obj->cur.geometry.y, obj->cur.geometry.w, obj->cur.geometry.h);
268
269    if ((!mapped_parent) && ((is_active) || (obj->delete_me != 0)))
270      eina_array_push(active_objects, obj);
271
272 #ifdef REND_DGB
273    if (!is_active)
274      {
275         RDI(level);
276         RD("     [%p] vis: %i, cache.clip.vis: %i cache.clip.a: %i [%p]\n", obj, obj->cur.visible, obj->cur.cache.clip.visible, obj->cur.cache.clip.a, obj->func->is_visible);
277      }
278 #endif
279
280    map = _evas_render_has_map(obj);
281    hmap = _evas_render_had_map(obj);
282
283    if ((restack) && (!map))
284      {
285         if (!obj->changed)
286           {
287              eina_array_push(&e->pending_objects, obj);
288              obj->changed = EINA_TRUE;
289           }
290         obj->restack = EINA_TRUE;
291         clean_them = EINA_TRUE;
292      }
293
294    if (map)
295      {
296         RDI(level);
297         RD("      obj mapped\n");
298         if (obj->changed)
299           {
300              if (map != hmap) *redraw_all = 1;
301
302              if ((is_active) && (!obj->clip.clipees) &&
303                  ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
304                   (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
305                {
306                   eina_array_push(render_objects, obj);
307                   _evas_render_prev_cur_clip_cache_add(e, obj);
308                   obj->render_pre = EINA_TRUE;
309
310                   if (obj->smart.smart)
311                     {
312                        EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
313                          {
314                             _evas_render_phase1_object_process(e, obj2,
315                                                                active_objects,
316                                                                restack_objects,
317                                                                delete_objects,
318                                                                render_objects,
319                                                                obj->restack,
320                                                                redraw_all,
321                                                                EINA_TRUE
322 #ifdef REND_DGB
323                                                                , level + 1
324 #endif
325                                                               );
326                          }
327                     }
328                }
329           }
330         return clean_them;
331      }
332    else if (hmap)
333      {
334         RDI(level);
335         RD("      had map - restack objs\n");
336         //        eina_array_push(restack_objects, obj);
337         _evas_render_prev_cur_clip_cache_add(e, obj);
338         if (obj->changed)
339           {
340              if (!map)
341                {
342                   if ((obj->cur.map) && (obj->cur.usemap)) map = EINA_TRUE;
343                }
344              if (map != hmap)
345                {
346                   *redraw_all = 1;
347                }
348           }
349      }
350
351    /* handle normal rendering. this object knows how to handle maps */
352    if (obj->changed)
353      {
354         if (obj->smart.smart)
355           {
356              RDI(level);
357              RD("      changed + smart - render ok\n");
358              eina_array_push(render_objects, obj);
359              obj->render_pre = EINA_TRUE;
360              EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj),
361                                  obj2)
362                {
363                   _evas_render_phase1_object_process(e, obj2,
364                                                      active_objects,
365                                                      restack_objects,
366                                                      delete_objects,
367                                                      render_objects,
368                                                      obj->restack,
369                                                      redraw_all,
370                                                      mapped_parent
371 #ifdef REND_DGB
372                                                      , level + 1
373 #endif
374                                                     );
375                }
376           }
377         else
378           {
379              if ((is_active) && (!obj->clip.clipees) &&
380                  _evas_render_is_relevant(obj))
381                {
382                   RDI(level);
383                   RD("      relevant + active\n");
384                   if (obj->restack)
385                     eina_array_push(restack_objects, obj);
386                   else
387                     {
388                        eina_array_push(render_objects, obj);
389                        obj->render_pre = EINA_TRUE;
390                     }
391                }
392              else
393                {
394                   RDI(level);
395                   RD("      skip - not smart, not active or clippees or not relevant\n");
396                }
397           }
398      }
399    else
400      {
401         RD("      not changed... [%i] -> (%i %i %p %i) [%i]\n",
402            evas_object_is_visible(obj),
403            obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart,
404            obj->cur.cache.clip.a, evas_object_was_visible(obj));
405
406         if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
407             (_evas_render_can_render(obj) ||
408              (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
409           {
410              if (obj->smart.smart)
411                {
412                   RDI(level);
413                   RD("      smart + visible/was visible + not clip\n");
414                   eina_array_push(render_objects, obj);
415                   obj->render_pre = EINA_TRUE;
416                   EINA_INLIST_FOREACH
417                      (evas_object_smart_members_get_direct(obj), obj2)
418                        {
419                           _evas_render_phase1_object_process(e, obj2,
420                                                              active_objects,
421                                                              restack_objects,
422                                                              delete_objects,
423                                                              render_objects,
424                                                              restack,
425                                                              redraw_all,
426                                                              mapped_parent
427 #ifdef REND_DGB
428                                                              , level + 1
429 #endif
430                                                             );
431                        }
432                }
433              else
434                {
435                   if (evas_object_is_opaque(obj) &&
436                       evas_object_is_visible(obj))
437                     {
438                        RDI(level);
439                        RD("      opaque + visible\n");
440                        eina_array_push(render_objects, obj);
441                        obj->rect_del = EINA_TRUE;
442                     }
443                   else if (evas_object_is_visible(obj))
444                     {
445                        RDI(level);
446                        RD("      visible\n");
447                        eina_array_push(render_objects, obj);
448                        obj->render_pre = EINA_TRUE;
449                     }
450                   else
451                     {
452                        RDI(level);
453                        RD("      skip\n");
454                     }
455                }
456           }
457  /*       else if (obj->smart.smart)
458           {
459              RDI(level);
460              RD("      smart + mot visible/was visible\n");
461              eina_array_push(render_objects, obj);
462              obj->render_pre = 1;
463              EINA_INLIST_FOREACH (evas_object_smart_members_get_direct(obj),
464                                   obj2)
465                {
466                   _evas_render_phase1_object_process(e, obj2,
467                                                      active_objects,
468                                                      restack_objects,
469                                                      delete_objects,
470                                                      render_objects,
471                                                      restack,
472                                                      redraw_all
473 #ifdef REND_DGB
474                                                      , level + 1
475 #endif
476                                                     );
477                }
478           }
479 */
480      }
481    if (!is_active) obj->restack = EINA_FALSE;
482    RDI(level);
483    RD("    ---]\n");
484    return clean_them;
485 }
486
487 static Eina_Bool
488 _evas_render_phase1_process(Evas *e,
489                             Eina_Array *active_objects,
490                             Eina_Array *restack_objects,
491                             Eina_Array *delete_objects,
492                             Eina_Array *render_objects,
493                             int *redraw_all)
494 {
495    Evas_Layer *lay;
496    Eina_Bool clean_them = EINA_FALSE;
497
498    RD("  [--- PHASE 1\n");
499    EINA_INLIST_FOREACH(e->layers, lay)
500      {
501         Evas_Object *obj;
502
503         EINA_INLIST_FOREACH(lay->objects, obj)
504           {
505              clean_them |= _evas_render_phase1_object_process
506                 (e, obj, active_objects, restack_objects, delete_objects,
507                  render_objects, 0, redraw_all, EINA_FALSE
508 #ifdef REND_DGB
509                  , 1
510 #endif
511                 );
512           }
513      }
514    RD("  ---]\n");
515    return clean_them;
516 }
517
518 static void
519 _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
520 {
521    unsigned int i;
522
523    for (i = 0; i < pending_objects->count; ++i)
524      {
525         Evas_Object *obj;
526         int is_active;
527         Eina_Bool ok = EINA_FALSE;
528         obj = eina_array_data_get(pending_objects, i);
529         if (!obj->layer) goto clean_stuff;
530
531        //If the children are in active objects, They should be cleaned up.
532        if (obj->changed_map && _evas_render_has_map(obj))
533          goto clean_stuff;
534
535         evas_object_clip_recalc(obj);
536         is_active = evas_object_is_active(obj);
537
538         if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
539             (!obj->rect_del))
540           {
541              ok = EINA_TRUE;
542              goto clean_stuff;
543           }
544
545         if (obj->is_active == is_active)
546           {
547              if (obj->changed)
548                {
549                   if (obj->smart.smart)
550                     {
551                        if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
552                     }
553                   else
554                     if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
555                         (_evas_render_can_render(obj) ||
556                          (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
557                       {
558                          if (!(obj->render_pre || obj->rect_del))
559                            ok = EINA_TRUE;
560                       }
561                     else
562                       if (is_active && (!obj->clip.clipees) &&
563                           (_evas_render_can_render(obj) ||
564                            (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
565                         {
566                            if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
567                         }
568                }
569              else
570                {
571                   if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
572                       (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
573                       && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
574                     {
575                        if (obj->rect_del || obj->smart.smart) ok = EINA_TRUE;
576                     }
577                }
578           }
579
580 clean_stuff:
581         if (!ok)
582           {
583              eina_array_clean(&e->active_objects);
584              eina_array_clean(&e->render_objects);
585              eina_array_clean(&e->restack_objects);
586              eina_array_clean(&e->delete_objects);
587              e->invalidate = EINA_TRUE;
588              return ;
589           }
590      }
591 }
592
593 Eina_Bool
594 pending_change(void *data, void *gdata __UNUSED__)
595 {
596    Evas_Object *obj;
597
598    obj = data;
599    if (obj->delete_me) return EINA_FALSE;
600    if (obj->pre_render_done)
601      {
602         RD("  OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
603         obj->pre_render_done = EINA_FALSE;
604         evas_object_change_reset(obj);
605      }
606    return obj->changed ? EINA_TRUE : EINA_FALSE;
607 }
608
609 static Eina_Bool
610 _evas_render_can_use_overlay(Evas *e, Evas_Object *obj)
611 {
612    Eina_Rectangle *r;
613    Evas_Object *tmp;
614    Eina_List *alphas = NULL;
615    Eina_List *opaques = NULL;
616    Evas_Object *video_parent = NULL;
617    Eina_Rectangle zone;
618    Evas_Coord xc1, yc1, xc2, yc2;
619    unsigned int i;
620    Eina_Bool nooverlay;
621
622    video_parent = _evas_object_image_video_parent_get(obj);
623
624    /* Check if any one is the stack make this object mapped */
625    tmp = obj;
626    while (tmp && !_evas_render_has_map(tmp))
627      tmp = tmp->smart.parent;
628
629    if (tmp && _evas_render_has_map(tmp)) return EINA_FALSE; /* we are mapped, we can't be an overlay */
630
631    if (!evas_object_is_visible(obj)) return EINA_FALSE; /* no need to update the overlay if it's not visible */
632
633    /* If any recoloring of the surface is needed, n overlay to */
634    if ((obj->cur.cache.clip.r != 255) ||
635        (obj->cur.cache.clip.g != 255) ||
636        (obj->cur.cache.clip.b != 255) ||
637        (obj->cur.cache.clip.a != 255))
638      return EINA_FALSE;
639
640    /* Check presence of transparent object on top of the video object */
641    EINA_RECTANGLE_SET(&zone,
642                       obj->cur.cache.clip.x,
643                       obj->cur.cache.clip.y,
644                       obj->cur.cache.clip.w,
645                       obj->cur.cache.clip.h);
646
647    for (i = e->active_objects.count - 1; i > 0; i--)
648      {
649         Eina_Rectangle self;
650         Eina_Rectangle *match;
651         Evas_Object *current;
652         Eina_List *l;
653         int xm1, ym1, xm2, ym2;
654
655         current = eina_array_data_get(&e->active_objects, i);
656
657         /* Did we find the video object in the stack ? */
658         if (current == video_parent || current == obj)
659           break;
660
661         EINA_RECTANGLE_SET(&self,
662                            current->cur.cache.clip.x,
663                            current->cur.cache.clip.y,
664                            current->cur.cache.clip.w,
665                            current->cur.cache.clip.h);
666
667         /* This doesn't cover the area of the video object, so don't bother with that object */
668         if (!eina_rectangles_intersect(&zone, &self))
669           continue;
670
671         xc1 = current->cur.cache.clip.x;
672         yc1 = current->cur.cache.clip.y;
673         xc2 = current->cur.cache.clip.x + current->cur.cache.clip.w;
674         yc2 = current->cur.cache.clip.y + current->cur.cache.clip.h;
675
676         if (evas_object_is_visible(current) &&
677             (!current->clip.clipees) &&
678             (current->cur.visible) &&
679             (!current->delete_me) &&
680             (current->cur.cache.clip.visible) &&
681             (!current->smart.smart))
682           {
683              Eina_Bool included = EINA_FALSE;
684
685              if (evas_object_is_opaque(current) ||
686                  ((current->func->has_opaque_rect) &&
687                   (current->func->has_opaque_rect(current))))
688                {
689                   /* The object is opaque */
690
691                   /* Check if the opaque object is inside another opaque object */
692                   EINA_LIST_FOREACH(opaques, l, match)
693                     {
694                        xm1 = match->x;
695                        ym1 = match->y;
696                        xm2 = match->x + match->w;
697                        ym2 = match->y + match->h;
698
699                        /* Both object are included */
700                        if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
701                          {
702                             included = EINA_TRUE;
703                             break;
704                          }
705                     }
706
707                   /* Not included yet */
708                   if (!included)
709                     {
710                        Eina_List *ln;
711                        Evas_Coord xn2, yn2;
712
713                        r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
714                                               current->cur.cache.clip.w, current->cur.cache.clip.h);
715
716                        opaques = eina_list_append(opaques, r);
717
718                        xn2 = r->x + r->w;
719                        yn2 = r->y + r->h;
720
721                        /* Remove all the transparent object that are covered by the new opaque object */
722                        EINA_LIST_FOREACH_SAFE(alphas, l, ln, match)
723                          {
724                             xm1 = match->x;
725                             ym1 = match->y;
726                             xm2 = match->x + match->w;
727                             ym2 = match->y + match->h;
728
729                             if (xm1 >= r->x && ym1 >= r->y && xm2 <= xn2 && ym2 <= yn2)
730                               {
731                                  /* The new rectangle is over some transparent object,
732                                     so remove the transparent object */
733                                  alphas = eina_list_remove_list(alphas, l);
734                               }
735                          }
736                     }
737                }
738              else
739                {
740                   /* The object has some transparency */
741
742                   /* Check if the transparent object is inside any other transparent object */
743                   EINA_LIST_FOREACH(alphas, l, match)
744                     {
745                        xm1 = match->x;
746                        ym1 = match->y;
747                        xm2 = match->x + match->w;
748                        ym2 = match->y + match->h;
749
750                        /* Both object are included */
751                        if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
752                          {
753                             included = EINA_TRUE;
754                             break;
755                          }
756                     }
757
758                   /* If not check if it is inside any opaque one */
759                   if (!included)
760                     {
761                        EINA_LIST_FOREACH(opaques, l, match)
762                          {
763                             xm1 = match->x;
764                             ym1 = match->y;
765                             xm2 = match->x + match->w;
766                             ym2 = match->y + match->h;
767
768                             /* Both object are included */
769                             if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
770                               {
771                                  included = EINA_TRUE;
772                                  break;
773                               }
774                          }
775                     }
776
777                   /* No inclusion at all, so add it */
778                   if (!included)
779                     {
780                        r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
781                                               current->cur.cache.clip.w, current->cur.cache.clip.h);
782
783                        alphas = eina_list_append(alphas, r);
784                     }
785                }
786           }
787      }
788
789    /* If there is any pending transparent object, then no overlay */
790    nooverlay = !!eina_list_count(alphas);
791
792    EINA_LIST_FREE(alphas, r)
793      eina_rectangle_free(r);
794    EINA_LIST_FREE(opaques, r)
795      eina_rectangle_free(r);
796
797    if (nooverlay)
798      return EINA_FALSE;
799
800    return EINA_TRUE;
801 }
802
803 Eina_Bool
804 evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
805                    int off_x, int off_y, int mapped,
806                    int ecx, int ecy, int ecw, int ech
807 #ifdef REND_DGB
808                    , int level
809 #endif
810                   )
811 {
812    void *ctx;
813    Evas_Object *obj2;
814    Eina_Bool clean_them = EINA_FALSE;
815
816    evas_object_clip_recalc(obj);
817
818    RDI(level);
819    RD("      { evas_render_mapped(%p, %p,   %p, %p,   %i, %i,   %i,   %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
820    if (mapped)
821      {
822         if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
823             (obj->cur.have_clipees))
824           {
825              RDI(level);
826              RD("      }\n");
827              return clean_them;
828           }
829      }
830    else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
831                 (_evas_render_can_render(obj))))
832              ))
833      {
834         RDI(level);
835         RD("      }\n");
836         return clean_them;
837      }
838
839    // set render_pre - for child objs that may not have gotten it.
840    obj->pre_render_done = EINA_TRUE;
841    RD("          Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map,
842       obj->func->can_map ? obj->func->can_map(obj): -1,
843       obj->cur.map, obj->cur.usemap,
844       _evas_render_has_map(obj));
845    if (_evas_render_has_map(obj))
846      {
847         int sw, sh;
848         Eina_Bool changed = EINA_FALSE, rendered = EINA_FALSE;
849
850         clean_them = EINA_TRUE;
851
852         sw = obj->cur.geometry.w;
853         sh = obj->cur.geometry.h;
854         RDI(level);
855         RD("        mapped obj: %ix%i\n", sw, sh);
856         if ((sw <= 0) || (sh <= 0))
857           {
858              RDI(level);
859              RD("      }\n");
860              return clean_them;
861           }
862         evas_object_map_update(obj, off_x, off_y, sw, sh, sw, sh);
863
864         if (obj->cur.map->surface)
865           {
866              if ((obj->cur.map->surface_w != sw) ||
867                  (obj->cur.map->surface_h != sh))
868                {
869                   RDI(level);
870                   RD("        new surf: %ix%i\n", sw, sh);
871                   obj->layer->evas->engine.func->image_map_surface_free
872                      (e->engine.data.output, obj->cur.map->surface);
873                   obj->cur.map->surface = NULL;
874                }
875           }
876         if (!obj->cur.map->surface)
877           {
878              obj->cur.map->surface_w = sw;
879              obj->cur.map->surface_h = sh;
880
881              obj->cur.map->surface =
882                 obj->layer->evas->engine.func->image_map_surface_new
883                 (e->engine.data.output, obj->cur.map->surface_w,
884                  obj->cur.map->surface_h,
885                  obj->cur.map->alpha);
886              RDI(level);
887              RD("        fisrt surf: %ix%i\n", sw, sh);
888              changed = EINA_TRUE;
889           }
890         if (obj->smart.smart)
891           {
892              Evas_Object *o2;
893
894              EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), o2)
895                {
896                   if (!evas_object_is_visible(o2) &&
897                       !evas_object_was_visible(o2))
898                     {
899                        evas_object_change_reset(o2);
900                        continue;
901                     }
902                   if (o2->changed)
903                     {
904                        changed = EINA_TRUE;
905                        evas_object_change_reset(o2);
906                        break;
907                     }
908                }
909              if (obj->changed_color) changed = EINA_TRUE;
910              evas_object_change_reset(obj);
911           }
912         else if (obj->changed)
913           {
914              if (((obj->changed_pchange) && (obj->changed_map)) ||
915                  (obj->changed_color))
916                changed = EINA_TRUE;
917              evas_object_change_reset(obj);
918           }
919
920         /* mark the old map as invalid, so later we don't reuse it as a
921          * cache. */
922         if (changed && obj->prev.map)
923            obj->prev.valid_map = EINA_FALSE;
924
925         // clear surface before re-render
926         if ((changed) && (obj->cur.map->surface))
927           {
928              int off_x2, off_y2;
929
930              RDI(level);
931              RD("        children redraw\n");
932              // FIXME: calculate "changes" within map surface and only clear
933              // and re-render those
934              if (obj->cur.map->alpha)
935                {
936                   ctx = e->engine.func->context_new(e->engine.data.output);
937                   e->engine.func->context_color_set
938                      (e->engine.data.output, ctx, 0, 0, 0, 0);
939                   e->engine.func->context_render_op_set
940                      (e->engine.data.output, ctx, EVAS_RENDER_COPY);
941                   e->engine.func->rectangle_draw(e->engine.data.output,
942                                                  ctx,
943                                                  obj->cur.map->surface,
944                                                  0, 0,
945                                                  obj->cur.map->surface_w,
946                                                  obj->cur.map->surface_h);
947                   e->engine.func->context_free(e->engine.data.output, ctx);
948                }
949              ctx = e->engine.func->context_new(e->engine.data.output);
950              off_x2 = -obj->cur.geometry.x;
951              off_y2 = -obj->cur.geometry.y;
952              if (obj->smart.smart)
953                {
954                   EINA_INLIST_FOREACH
955                      (evas_object_smart_members_get_direct(obj), obj2)
956                        {
957                           clean_them |= evas_render_mapped(e, obj2, ctx,
958                                                            obj->cur.map->surface,
959                                                            off_x2, off_y2, 1,
960                                                            ecx, ecy, ecw, ech
961 #ifdef REND_DGB
962                                                            , level + 1
963 #endif
964                                                           );
965                        }
966                }
967              else
968                {
969                   int x = 0, y = 0, w = 0, h = 0;
970
971                   w = obj->cur.map->surface_w;
972                   h = obj->cur.map->surface_h;
973                   RECTS_CLIP_TO_RECT(x, y, w, h,
974                                      obj->cur.geometry.x + off_x2,
975                                      obj->cur.geometry.y + off_y2,
976                                      obj->cur.geometry.w,
977                                      obj->cur.geometry.h);
978
979                   e->engine.func->context_clip_set(e->engine.data.output,
980                                                    ctx, x, y, w, h);
981                   obj->func->render(obj, e->engine.data.output, ctx,
982                                     obj->cur.map->surface, off_x2, off_y2);
983                }
984              e->engine.func->context_free(e->engine.data.output, ctx);
985              rendered = EINA_TRUE;
986           }
987
988         RDI(level);
989         RD("        draw map\n");
990
991         if (rendered)
992           {
993              obj->cur.map->surface = e->engine.func->image_dirty_region
994                 (e->engine.data.output, obj->cur.map->surface,
995                  0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
996              obj->cur.valid_map = EINA_TRUE;
997           }
998         e->engine.func->context_clip_unset(e->engine.data.output,
999                                            context);
1000         if (obj->cur.map->surface)
1001           {
1002              if (obj->smart.smart)
1003                {
1004                   if (obj->cur.clipper)
1005                     {
1006                        int x, y, w, h;
1007                        Evas_Object *tobj;
1008
1009                        obj->cur.cache.clip.dirty = EINA_TRUE;
1010                        tobj = obj->cur.map_parent;
1011                        obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
1012                        evas_object_clip_recalc(obj);
1013                        obj->cur.map_parent = tobj;
1014                        x = obj->cur.cache.clip.x;
1015                        y = obj->cur.cache.clip.y;
1016                        w = obj->cur.cache.clip.w;
1017                        h = obj->cur.cache.clip.h;
1018                        RECTS_CLIP_TO_RECT(x, y, w, h,
1019                                           obj->cur.clipper->cur.cache.clip.x,
1020                                           obj->cur.clipper->cur.cache.clip.y,
1021                                           obj->cur.clipper->cur.cache.clip.w,
1022                                           obj->cur.clipper->cur.cache.clip.h);
1023                        e->engine.func->context_clip_set(e->engine.data.output,
1024                                                         context,
1025                                                         x + off_x, y + off_y, w, h);
1026                     }
1027                }
1028              else
1029                {
1030                   if (obj->cur.clipper)
1031                     {
1032                        int x, y, w, h;
1033
1034                        evas_object_clip_recalc(obj);
1035                        x = obj->cur.cache.clip.x;
1036                        y = obj->cur.cache.clip.y;
1037                        w = obj->cur.cache.clip.w;
1038                        h = obj->cur.cache.clip.h;
1039                        RECTS_CLIP_TO_RECT(x, y, w, h,
1040                                           obj->cur.clipper->cur.cache.clip.x,
1041                                           obj->cur.clipper->cur.cache.clip.y,
1042                                           obj->cur.clipper->cur.cache.clip.w,
1043                                           obj->cur.clipper->cur.cache.clip.h);
1044                        e->engine.func->context_clip_set(e->engine.data.output,
1045                                                         context,
1046                                                         x + off_x, y + off_y, w, h);
1047                     }
1048                }
1049           }
1050 //        if (surface == e->engine.data.output)
1051           e->engine.func->context_clip_clip(e->engine.data.output,
1052                                             context,
1053                                             ecx, ecy, ecw, ech);
1054         if (obj->cur.cache.clip.visible)
1055           {
1056              obj->layer->evas->engine.func->context_multiplier_unset
1057                (e->engine.data.output, context);
1058              obj->layer->evas->engine.func->image_map_draw
1059                (e->engine.data.output, context, surface,
1060                    obj->cur.map->surface, obj->spans,
1061                    obj->cur.map->smooth, 0);
1062           }
1063         // FIXME: needs to cache these maps and
1064         // keep them only rendering updates
1065         //        obj->layer->evas->engine.func->image_map_surface_free
1066         //          (e->engine.data.output, obj->cur.map->surface);
1067         //        obj->cur.map->surface = NULL;
1068      }
1069    else
1070      {
1071         if (0 && obj->cur.cached_surface)
1072           fprintf(stderr, "We should cache '%s' [%i, %i, %i, %i]\n",
1073                   evas_object_type_get(obj),
1074                   obj->cur.bounding_box.x, obj->cur.bounding_box.x,
1075                   obj->cur.bounding_box.w, obj->cur.bounding_box.h);
1076         if (mapped)
1077           {
1078              RDI(level);
1079              RD("        draw child of mapped obj\n");
1080              ctx = e->engine.func->context_new(e->engine.data.output);
1081              if (obj->smart.smart)
1082                {
1083                   EINA_INLIST_FOREACH
1084                      (evas_object_smart_members_get_direct(obj), obj2)
1085                        {
1086                           clean_them |= evas_render_mapped(e, obj2, ctx,
1087                                                            surface,
1088                                                            off_x, off_y, 1,
1089                                                            ecx, ecy, ecw, ech
1090 #ifdef REND_DGB
1091                                                            , level + 1
1092 #endif
1093                                                           );
1094                        }
1095                }
1096              else
1097                {
1098                   RDI(level);
1099
1100                   if (obj->cur.clipper)
1101                     {
1102                        RD("        clip: %i %i %ix%i [%i %i %ix%i]\n",
1103                           obj->cur.cache.clip.x + off_x,
1104                           obj->cur.cache.clip.y + off_y,
1105                           obj->cur.cache.clip.w,
1106                           obj->cur.cache.clip.h,
1107                           obj->cur.geometry.x + off_x,
1108                           obj->cur.geometry.y + off_y,
1109                           obj->cur.geometry.w,
1110                           obj->cur.geometry.h);
1111
1112                        RD("        clipper: %i %i %ix%i\n",
1113                           obj->cur.clipper->cur.cache.clip.x + off_x,
1114                           obj->cur.clipper->cur.cache.clip.y + off_y,
1115                           obj->cur.clipper->cur.cache.clip.w,
1116                           obj->cur.clipper->cur.cache.clip.h);
1117
1118                        int x, y, w, h;
1119
1120                        if (_evas_render_has_map(obj))
1121                          evas_object_clip_recalc(obj);
1122
1123                        x = obj->cur.cache.clip.x + off_x;
1124                        y = obj->cur.cache.clip.y + off_y;
1125                        w = obj->cur.cache.clip.w;
1126                        h = obj->cur.cache.clip.h;
1127
1128                        RECTS_CLIP_TO_RECT(x, y, w, h,
1129                                           obj->cur.clipper->cur.cache.clip.x + off_x,
1130                                           obj->cur.clipper->cur.cache.clip.y + off_y,
1131                                           obj->cur.clipper->cur.cache.clip.w,
1132                                           obj->cur.clipper->cur.cache.clip.h);
1133
1134                        e->engine.func->context_clip_set(e->engine.data.output,
1135                                                         ctx, x, y, w, h);
1136                     }
1137                   obj->func->render(obj, e->engine.data.output, ctx,
1138                                     surface, off_x, off_y);
1139                }
1140              e->engine.func->context_free(e->engine.data.output, ctx);
1141           }
1142         else
1143           {
1144              if (obj->cur.clipper)
1145                {
1146                   int x, y, w, h;
1147
1148                   if (_evas_render_has_map(obj))
1149                     evas_object_clip_recalc(obj);
1150                   x = obj->cur.cache.clip.x;
1151                   y = obj->cur.cache.clip.y;
1152                   w = obj->cur.cache.clip.w;
1153                   h = obj->cur.cache.clip.h;
1154                   RECTS_CLIP_TO_RECT(x, y, w, h,
1155                                      obj->cur.clipper->cur.cache.clip.x,
1156                                      obj->cur.clipper->cur.cache.clip.y,
1157                                      obj->cur.clipper->cur.cache.clip.w,
1158                                      obj->cur.clipper->cur.cache.clip.h);
1159                   e->engine.func->context_clip_set(e->engine.data.output,
1160                                                    context,
1161                                                    x + off_x, y + off_y, w, h);
1162                   e->engine.func->context_clip_clip(e->engine.data.output,
1163                                                     context,
1164                                                     ecx, ecy, ecw, ech);
1165                }
1166
1167              RDI(level);
1168              RD("        draw normal obj\n");
1169              obj->func->render(obj, e->engine.data.output, context, surface,
1170                                off_x, off_y);
1171           }
1172         if (obj->changed_map) clean_them = EINA_TRUE;
1173      }
1174    RDI(level);
1175    RD("      }\n");
1176
1177    return clean_them;
1178 }
1179
1180 static void
1181 _evas_render_cutout_add(Evas *e, Evas_Object *obj, int off_x, int off_y)
1182 {
1183    if (evas_object_is_opaque(obj))
1184      {
1185         Evas_Coord cox, coy, cow, coh;
1186
1187         cox = obj->cur.cache.clip.x;
1188         coy = obj->cur.cache.clip.y;
1189         cow = obj->cur.cache.clip.w;
1190         coh = obj->cur.cache.clip.h;
1191         if ((obj->cur.map) && (obj->cur.usemap))
1192           {
1193              Evas_Object *oo;
1194
1195              oo = obj;
1196              while (oo->cur.clipper)
1197                {
1198                   if ((oo->cur.clipper->cur.map_parent
1199                        != oo->cur.map_parent) &&
1200                       (!((oo->cur.map) && (oo->cur.usemap))))
1201                     break;
1202                   RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
1203                                      oo->cur.geometry.x,
1204                                      oo->cur.geometry.y,
1205                                      oo->cur.geometry.w,
1206                                      oo->cur.geometry.h);
1207                   oo = oo->cur.clipper;
1208                }
1209           }
1210         e->engine.func->context_cutout_add
1211           (e->engine.data.output, e->engine.data.context,
1212               cox + off_x, coy + off_y, cow, coh);
1213      }
1214    else
1215      {
1216         if (obj->func->get_opaque_rect)
1217           {
1218              Evas_Coord obx, oby, obw, obh;
1219
1220              obj->func->get_opaque_rect(obj, &obx, &oby, &obw, &obh);
1221              if ((obw > 0) && (obh > 0))
1222                {
1223                   obx += off_x;
1224                   oby += off_y;
1225                   RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1226                                      obj->cur.cache.clip.x + off_x,
1227                                      obj->cur.cache.clip.y + off_y,
1228                                      obj->cur.cache.clip.w,
1229                                      obj->cur.cache.clip.h);
1230                   e->engine.func->context_cutout_add
1231                     (e->engine.data.output, e->engine.data.context,
1232                         obx, oby, obw, obh);
1233                }
1234           }
1235      }
1236 }
1237
1238 static Eina_List *
1239 evas_render_updates_internal(Evas *e,
1240                              unsigned char make_updates,
1241                              unsigned char do_draw)
1242 {
1243    Evas_Object *obj;
1244    Eina_List *updates = NULL;
1245    Eina_List *ll;
1246    void *surface;
1247    Eina_Bool clean_them = EINA_FALSE;
1248    Eina_Bool alpha;
1249    Eina_Rectangle *r;
1250    int ux, uy, uw, uh;
1251    int cx, cy, cw, ch;
1252    unsigned int i, j;
1253    int redraw_all = 0;
1254    Eina_Bool haveup = 0;
1255
1256    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1257    return NULL;
1258    MAGIC_CHECK_END();
1259    if (!e->changed) return NULL;
1260
1261 #ifdef EVAS_CSERVE2
1262    if (evas_cserve2_use_get())
1263       evas_cserve2_dispatch();
1264 #endif
1265    evas_call_smarts_calculate(e);
1266
1267    RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
1268
1269    evas_event_callback_call(e, EVAS_CALLBACK_RENDER_PRE, NULL);
1270
1271    /* Check if the modified object mean recalculating every thing */
1272    if (!e->invalidate)
1273      _evas_render_check_pending_objects(&e->pending_objects, e);
1274
1275    /* phase 1. add extra updates for changed objects */
1276    if (e->invalidate || e->render_objects.count <= 0)
1277      clean_them = _evas_render_phase1_process(e,
1278                                               &e->active_objects,
1279                                               &e->restack_objects,
1280                                               &e->delete_objects,
1281                                               &e->render_objects,
1282                                               &redraw_all);
1283
1284    /* phase 1.5. check if the video should be inlined or stay in their overlay */
1285    alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1286                                             e->engine.data.context);
1287
1288    EINA_LIST_FOREACH(e->video_objects, ll, obj)
1289      {
1290         /* we need the surface to be transparent to display the underlying overlay */
1291         if (alpha && _evas_render_can_use_overlay(e, obj))
1292           _evas_object_image_video_overlay_show(obj);
1293         else
1294           _evas_object_image_video_overlay_hide(obj);
1295      }
1296    /* phase 1.8. pre render for proxy */
1297    _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
1298                               &e->delete_objects, &e->render_objects);
1299
1300    /* phase 2. force updates for restacks */
1301    for (i = 0; i < e->restack_objects.count; ++i)
1302      {
1303         obj = eina_array_data_get(&e->restack_objects, i);
1304         obj->func->render_pre(obj);
1305         _evas_render_prev_cur_clip_cache_add(e, obj);
1306      }
1307    eina_array_clean(&e->restack_objects);
1308
1309    /* phase 3. add exposes */
1310    EINA_LIST_FREE(e->damages, r)
1311      {
1312         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1313                                                 r->x, r->y, r->w, r->h);
1314         eina_rectangle_free(r);
1315      }
1316
1317    /* phase 4. framespace, output & viewport changes */
1318    if (e->viewport.changed)
1319      {
1320         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1321                                                 0, 0,
1322                                                 e->output.w, e->output.h);
1323      }
1324    if (e->output.changed)
1325      {
1326         e->engine.func->output_resize(e->engine.data.output,
1327                                       e->output.w, e->output.h);
1328         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1329                                                 0, 0,
1330                                                 e->output.w, e->output.h);
1331      }
1332    if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1333      {
1334         ERR("viewport size != output size!");
1335      }
1336
1337    if (e->framespace.changed)
1338      {
1339         int fx, fy, fw, fh;
1340
1341         fx = e->viewport.x - e->framespace.x;
1342         fy = e->viewport.y - e->framespace.y;
1343         fw = e->viewport.w + e->framespace.w;
1344         fh = e->viewport.h + e->framespace.h;
1345         if (fx < 0) fx = 0;
1346         if (fy < 0) fy = 0;
1347         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1348                                                 fx, fy, fw, fh);
1349      }
1350
1351    /* phase 4.5: check if object is not in framespace. if not, we need to clip 
1352     * it to the 'master' clip.
1353     * 
1354     * NB: This is for the wayland engine(s). If we do not do this, then 
1355     * objects will draw outside the viewport and potentially onto the frame 
1356     * itself */
1357    if (!strncmp(e->engine.module->definition->name, "wayland", 7))
1358      {
1359         Eina_Rectangle clip_rect;
1360
1361         /* see if the master clip has been added yet, if not, then create */
1362         if (!e->framespace.clip)
1363           {
1364              e->framespace.clip = evas_object_rectangle_add(e);
1365              evas_object_color_set(e->framespace.clip, 255, 255, 255, 255);
1366              evas_object_move(e->framespace.clip,
1367                               e->framespace.x, e->framespace.y);
1368              evas_object_resize(e->framespace.clip,
1369                                 e->viewport.w - e->framespace.w, 
1370                                 e->viewport.h - e->framespace.h);
1371              evas_object_show(e->framespace.clip);
1372           }
1373         else
1374           {
1375              /* master clip is already present. check for size changes in the 
1376               * viewport, and update master clip size if needed */
1377              if ((e->viewport.changed) || (e->output.changed))
1378                {
1379                   evas_object_resize(e->framespace.clip,
1380                                      e->viewport.w - e->framespace.w,
1381                                      e->viewport.h - e->framespace.h);
1382                }
1383           }
1384
1385         EINA_RECTANGLE_SET(&clip_rect,
1386                            e->framespace.clip->cur.geometry.x,
1387                            e->framespace.clip->cur.geometry.y,
1388                            e->framespace.clip->cur.geometry.w,
1389                            e->framespace.clip->cur.geometry.h)
1390
1391         /* With the master clip all setup, we need to loop the objects on this 
1392          * canvas and determine if the object is in the viewport space. If it 
1393          * is in the viewport space (and not in framespace), then we need to 
1394          * clip the object to the master clip so that it does not draw on top 
1395          * of the frame (eg: elm 3d test) */
1396         for (i = 0; i < e->render_objects.count; ++i)
1397           {
1398              Eina_Rectangle obj_rect;
1399              Evas_Object *pclip;
1400
1401              obj = eina_array_data_get(&e->render_objects, i);
1402              if (evas_object_is_frame_object_get(obj))
1403                continue;
1404
1405              EINA_RECTANGLE_SET(&obj_rect,
1406                                 obj->cur.geometry.x, obj->cur.geometry.y,
1407                                 obj->cur.geometry.w, obj->cur.geometry.h);
1408
1409              /* if the object does not intersect our clip rect, ignore it */
1410              if (!eina_rectangles_intersect(&clip_rect, &obj_rect))
1411                continue;
1412
1413              if (!(pclip = evas_object_clip_get(obj)))
1414                {
1415                   /* clip this object so it does not draw on the window frame */
1416                   evas_object_clip_set(obj, e->framespace.clip);
1417                }
1418           }
1419      }
1420
1421    if (redraw_all)
1422      {
1423         e->engine.func->output_redraws_rect_add(e->engine.data.output, 0, 0,
1424                                                 e->output.w, e->output.h);
1425      }
1426
1427    /* phase 5. add obscures */
1428    EINA_LIST_FOREACH(e->obscures, ll, r)
1429      {
1430         e->engine.func->output_redraws_rect_del(e->engine.data.output,
1431                                                 r->x, r->y, r->w, r->h);
1432      }
1433    /* build obscure objects list of active objects that obscure */
1434    for (i = 0; i < e->active_objects.count; ++i)
1435      {
1436         obj = eina_array_data_get(&e->active_objects, i);
1437         if (UNLIKELY((evas_object_is_opaque(obj) ||
1438                       ((obj->func->has_opaque_rect) &&
1439                        (obj->func->has_opaque_rect(obj)))) &&
1440                      evas_object_is_visible(obj) &&
1441                      (!obj->clip.clipees) &&
1442                      (obj->cur.visible) &&
1443                      (!obj->delete_me) &&
1444                      (obj->cur.cache.clip.visible) &&
1445                      (!obj->smart.smart)))
1446           /*      obscuring_objects = eina_list_append(obscuring_objects, obj); */
1447           eina_array_push(&e->obscuring_objects, obj);
1448      }
1449
1450    /* save this list */
1451    /*    obscuring_objects_orig = obscuring_objects; */
1452    /*    obscuring_objects = NULL; */
1453    /* phase 6. go thru each update rect and render objects in it*/
1454    if (do_draw)
1455      {
1456         unsigned int offset = 0;
1457
1458         while ((surface =
1459                 e->engine.func->output_redraws_next_update_get
1460                 (e->engine.data.output,
1461                  &ux, &uy, &uw, &uh,
1462                  &cx, &cy, &cw, &ch)))
1463           {
1464              int off_x, off_y;
1465
1466              RD("  [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1467              if (make_updates)
1468                {
1469                   Eina_Rectangle *rect;
1470
1471                   NEW_RECT(rect, ux, uy, uw, uh);
1472                   if (rect)
1473                     updates = eina_list_append(updates, rect);
1474                }
1475              haveup = EINA_TRUE;
1476              off_x = cx - ux;
1477              off_y = cy - uy;
1478              /* build obscuring objects list (in order from bottom to top) */
1479              if (alpha)
1480                {
1481                   e->engine.func->context_clip_set(e->engine.data.output,
1482                                                    e->engine.data.context,
1483                                                    ux + off_x, uy + off_y, uw, uh);
1484                }
1485              for (i = 0; i < e->obscuring_objects.count; ++i)
1486                {
1487                   obj = (Evas_Object *)eina_array_data_get
1488                      (&e->obscuring_objects, i);
1489                   if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1490                     {
1491                        eina_array_push(&e->temporary_objects, obj);
1492
1493                        /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1494                        if (alpha)
1495                          _evas_render_cutout_add(e, obj, off_x, off_y);
1496                     }
1497                }
1498              if (alpha)
1499                {
1500                   e->engine.func->context_color_set(e->engine.data.output,
1501                                                     e->engine.data.context,
1502                                                     0, 0, 0, 0);
1503                   e->engine.func->context_multiplier_unset
1504                      (e->engine.data.output, e->engine.data.context);
1505                   e->engine.func->context_render_op_set(e->engine.data.output,
1506                                                         e->engine.data.context,
1507                                                         EVAS_RENDER_COPY);
1508                   e->engine.func->rectangle_draw(e->engine.data.output,
1509                                                  e->engine.data.context,
1510                                                  surface,
1511                                                  cx, cy, cw, ch);
1512                   e->engine.func->context_cutout_clear(e->engine.data.output,
1513                                                        e->engine.data.context);
1514                   e->engine.func->context_clip_unset(e->engine.data.output,
1515                                                      e->engine.data.context);
1516                }
1517
1518              /* render all object that intersect with rect */
1519              for (i = 0; i < e->active_objects.count; ++i)
1520                {
1521                   obj = eina_array_data_get(&e->active_objects, i);
1522
1523                   /* if it's in our outpout rect and it doesn't clip anything */
1524                   RD("    OBJ: [%p] '%s' %i %i %ix%i\n", obj, obj->type, obj->cur.geometry.x, obj->cur.geometry.y, obj->cur.geometry.w, obj->cur.geometry.h);
1525                   if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1526                        (obj->smart.smart)) &&
1527                       (!obj->clip.clipees) &&
1528                       (obj->cur.visible) &&
1529                       (!obj->delete_me) &&
1530                       (obj->cur.cache.clip.visible) &&
1531 //                    (!obj->smart.smart) &&
1532                       ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1533                     {
1534                        int x, y, w, h;
1535
1536                        RD("      DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1537                        if ((e->temporary_objects.count > offset) &&
1538                            (eina_array_data_get(&e->temporary_objects, offset) == obj))
1539                          offset++;
1540                        x = cx; y = cy; w = cw; h = ch;
1541                        if (((w > 0) && (h > 0)) || (obj->smart.smart))
1542                          {
1543                             if (!obj->smart.smart)
1544                               {
1545                                  RECTS_CLIP_TO_RECT(x, y, w, h,
1546                                                     obj->cur.cache.clip.x + off_x,
1547                                                     obj->cur.cache.clip.y + off_y,
1548                                                     obj->cur.cache.clip.w,
1549                                                     obj->cur.cache.clip.h);
1550                               }
1551                             if (obj->cur.mask)
1552                               e->engine.func->context_mask_set(e->engine.data.output,
1553                                                                e->engine.data.context,
1554                                                                obj->cur.mask->func->engine_data_get(obj->cur.mask),
1555                                                                obj->cur.mask->cur.geometry.x + off_x,
1556                                                                obj->cur.mask->cur.geometry.y + off_y,
1557                                                                obj->cur.mask->cur.geometry.w,
1558                                                                obj->cur.mask->cur.geometry.h);
1559                             else
1560                               e->engine.func->context_mask_unset(e->engine.data.output,
1561                                                                  e->engine.data.context);
1562                             e->engine.func->context_clip_set(e->engine.data.output,
1563                                                              e->engine.data.context,
1564                                                              x, y, w, h);
1565 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1566                             for (j = offset; j < e->temporary_objects.count; ++j)
1567                               {
1568                                  Evas_Object *obj2;
1569
1570                                  obj2 = (Evas_Object *)eina_array_data_get
1571                                    (&e->temporary_objects, j);
1572                                  _evas_render_cutout_add(e, obj2, off_x, off_y);
1573                               }
1574 #endif
1575                             clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1576                                                              surface, off_x, off_y, 0,
1577                                                              cx, cy, cw, ch
1578 #ifdef REND_DGB
1579                                                              , 1
1580 #endif
1581                                                             );
1582
1583                             e->engine.func->context_cutout_clear(e->engine.data.output,
1584                                                                  e->engine.data.context);
1585                          }
1586                     }
1587                }
1588              /* punch rect out */
1589              e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1590                                                              surface,
1591                                                              ux, uy, uw, uh);
1592              /* free obscuring objects list */
1593              eina_array_clean(&e->temporary_objects);
1594              RD("  ---]\n");
1595           }
1596         /* flush redraws */
1597         if (haveup)
1598           {
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);
1602           }
1603      }
1604    /* clear redraws */
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)
1608      {
1609         obj = eina_array_data_get(&e->active_objects, i);
1610         obj->pre_render_done = EINA_FALSE;
1611         RD("    OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1612         if ((obj->changed) && (do_draw))
1613           {
1614              RD("    OBJ [%p] post... func1\n", obj);
1615              obj->func->render_post(obj);
1616              obj->restack = EINA_FALSE;
1617              evas_object_change_reset(obj);
1618           }
1619         else if (clean_them)
1620           {
1621              RD("    OBJ [%p] post... func2\n", obj);
1622              obj->func->render_post(obj);
1623              obj->restack = EINA_FALSE;
1624              evas_object_change_reset(obj);
1625           }
1626         /* moved to other pre-process phase 1
1627            if (obj->delete_me == 2)
1628            {
1629            delete_objects = eina_list_append(delete_objects, obj);
1630            }
1631            else if (obj->delete_me != 0) obj->delete_me++;
1632          */
1633      }
1634    /* free our obscuring object list */
1635    eina_array_clean(&e->obscuring_objects);
1636
1637    /* If some object are still marked as changed, do not remove
1638       them from the pending list. */
1639    eina_array_remove(&e->pending_objects, pending_change, NULL);
1640
1641    for (i = 0; i < e->render_objects.count; ++i)
1642      {
1643         obj = eina_array_data_get(&e->render_objects, i);
1644         obj->pre_render_done = EINA_FALSE;
1645      }
1646
1647    /* delete all objects flagged for deletion now */
1648    for (i = 0; i < e->delete_objects.count; ++i)
1649      {
1650         obj = eina_array_data_get(&e->delete_objects, i);
1651         evas_object_free(obj, 1);
1652      }
1653    eina_array_clean(&e->delete_objects);
1654
1655    e->changed = EINA_FALSE;
1656    e->viewport.changed = EINA_FALSE;
1657    e->output.changed = EINA_FALSE;
1658    e->framespace.changed = EINA_FALSE;
1659    e->invalidate = EINA_FALSE;
1660
1661    // always clean... lots of mem waste!
1662    /* If their are some object to restack or some object to delete,
1663     * it's useless to keep the render object list around. */
1664    if (clean_them)
1665      {
1666         eina_array_clean(&e->active_objects);
1667         eina_array_clean(&e->render_objects);
1668         eina_array_clean(&e->restack_objects);
1669         eina_array_clean(&e->temporary_objects);
1670         eina_array_clean(&e->clip_changes);
1671 /* we should flush here and have a mempool system for this        
1672         eina_array_flush(&e->active_objects);
1673         eina_array_flush(&e->render_objects);
1674         eina_array_flush(&e->restack_objects);
1675         eina_array_flush(&e->delete_objects);
1676         eina_array_flush(&e->obscuring_objects);
1677         eina_array_flush(&e->temporary_objects);
1678         eina_array_flush(&e->clip_changes);
1679  */
1680         e->invalidate = EINA_TRUE;
1681      }
1682
1683    evas_module_clean();
1684
1685    evas_event_callback_call(e, EVAS_CALLBACK_RENDER_POST, NULL);
1686
1687    RD("---]\n");
1688
1689    return updates;
1690 }
1691
1692 EAPI void
1693 evas_render_updates_free(Eina_List *updates)
1694 {
1695    Eina_Rectangle *r;
1696
1697    EINA_LIST_FREE(updates, r)
1698       eina_rectangle_free(r);
1699 }
1700
1701 EAPI Eina_List *
1702 evas_render_updates(Evas *e)
1703 {
1704    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1705    return NULL;
1706    MAGIC_CHECK_END();
1707
1708    if (!e->changed) return NULL;
1709    return evas_render_updates_internal(e, 1, 1);
1710 }
1711
1712 EAPI void
1713 evas_render(Evas *e)
1714 {
1715    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1716    return;
1717    MAGIC_CHECK_END();
1718
1719    if (!e->changed) return;
1720    evas_render_updates_internal(e, 0, 1);
1721 }
1722
1723 EAPI void
1724 evas_norender(Evas *e)
1725 {
1726    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1727    return;
1728    MAGIC_CHECK_END();
1729
1730    //   if (!e->changed) return;
1731    evas_render_updates_internal(e, 0, 0);
1732 }
1733
1734 EAPI void
1735 evas_render_idle_flush(Evas *e)
1736 {
1737    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1738    return;
1739    MAGIC_CHECK_END();
1740
1741    evas_fonts_zero_presure(e);
1742
1743    if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1744        (e->engine.data.output))
1745      e->engine.func->output_idle_flush(e->engine.data.output);
1746
1747    eina_array_flush(&e->active_objects);
1748    eina_array_flush(&e->render_objects);
1749    eina_array_flush(&e->restack_objects);
1750    eina_array_flush(&e->delete_objects);
1751    eina_array_flush(&e->obscuring_objects);
1752    eina_array_flush(&e->temporary_objects);
1753    eina_array_flush(&e->clip_changes);
1754
1755    e->invalidate = EINA_TRUE;
1756 }
1757
1758 EAPI void
1759 evas_sync(Evas *e)
1760 {
1761   (void) e;
1762 }
1763
1764 static void
1765 _evas_render_dump_map_surfaces(Evas_Object *obj)
1766 {
1767    if ((obj->cur.map) && obj->cur.map->surface)
1768      {
1769         obj->layer->evas->engine.func->image_map_surface_free
1770            (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1771         obj->cur.map->surface = NULL;
1772      }
1773
1774    if (obj->smart.smart)
1775      {
1776         Evas_Object *obj2;
1777
1778         EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1779            _evas_render_dump_map_surfaces(obj2);
1780      }
1781 }
1782
1783 EAPI void
1784 evas_render_dump(Evas *e)
1785 {
1786    Evas_Layer *lay;
1787
1788    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1789    return;
1790    MAGIC_CHECK_END();
1791
1792    EINA_INLIST_FOREACH(e->layers, lay)
1793      {
1794         Evas_Object *obj;
1795
1796         EINA_INLIST_FOREACH(lay->objects, obj)
1797           {
1798              if ((obj->type) && (!strcmp(obj->type, "image")))
1799                evas_object_inform_call_image_unloaded(obj);
1800              _evas_render_dump_map_surfaces(obj);
1801           }
1802      }
1803    if ((e->engine.func) && (e->engine.func->output_dump) &&
1804        (e->engine.data.output))
1805      e->engine.func->output_dump(e->engine.data.output);
1806 }
1807
1808 void
1809 evas_render_invalidate(Evas *e)
1810 {
1811    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1812    return;
1813    MAGIC_CHECK_END();
1814
1815    eina_array_clean(&e->active_objects);
1816    eina_array_clean(&e->render_objects);
1817
1818    eina_array_flush(&e->restack_objects);
1819    eina_array_flush(&e->delete_objects);
1820
1821    e->invalidate = EINA_TRUE;
1822 }
1823
1824 void
1825 evas_render_object_recalc(Evas_Object *obj)
1826 {
1827    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1828    return;
1829    MAGIC_CHECK_END();
1830
1831    if ((!obj->changed) && (obj->delete_me < 2))
1832      {
1833        Evas *e;
1834
1835        e = obj->layer->evas;
1836        if ((!e) || (e->cleanup)) return;
1837        eina_array_push(&e->pending_objects, obj);
1838        obj->changed = EINA_TRUE;
1839      }
1840 }
1841
1842 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/