0a1f938bed71b57532b2a8adf2706a3f284e2f04
[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    RDI(level);
818    RD("      { evas_render_mapped(%p, %p,   %p, %p,   %i, %i,   %i,   %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
819    if (mapped)
820      {
821         if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
822             (obj->cur.have_clipees))
823           {
824              RDI(level);
825              RD("      }\n");
826              return clean_them;
827           }
828      }
829    else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
830                 (_evas_render_can_render(obj))))
831              ))
832      {
833         RDI(level);
834         RD("      }\n");
835         return clean_them;
836      }
837
838    // set render_pre - for child objs that may not have gotten it.
839    obj->pre_render_done = EINA_TRUE;
840    RD("          Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map,
841       obj->func->can_map ? obj->func->can_map(obj): -1,
842       obj->cur.map, obj->cur.usemap,
843       _evas_render_has_map(obj));
844    if (_evas_render_has_map(obj))
845      {
846         int sw, sh;
847         Eina_Bool changed = EINA_FALSE, rendered = EINA_FALSE;
848
849         clean_them = EINA_TRUE;
850
851         sw = obj->cur.geometry.w;
852         sh = obj->cur.geometry.h;
853         RDI(level);
854         RD("        mapped obj: %ix%i\n", sw, sh);
855         if ((sw <= 0) || (sh <= 0))
856           {
857              RDI(level);
858              RD("      }\n");
859              return clean_them;
860           }
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         // clear surface before re-render
921         if ((changed) && (obj->cur.map->surface))
922           {
923              int off_x2, off_y2;
924
925              RDI(level);
926              RD("        children redraw\n");
927              // FIXME: calculate "changes" within map surface and only clear
928              // and re-render those
929              if (obj->cur.map->alpha)
930                {
931                   ctx = e->engine.func->context_new(e->engine.data.output);
932                   e->engine.func->context_color_set
933                      (e->engine.data.output, ctx, 0, 0, 0, 0);
934                   e->engine.func->context_render_op_set
935                      (e->engine.data.output, ctx, EVAS_RENDER_COPY);
936                   e->engine.func->rectangle_draw(e->engine.data.output,
937                                                  ctx,
938                                                  obj->cur.map->surface,
939                                                  0, 0,
940                                                  obj->cur.map->surface_w,
941                                                  obj->cur.map->surface_h);
942                   e->engine.func->context_free(e->engine.data.output, ctx);
943                }
944              ctx = e->engine.func->context_new(e->engine.data.output);
945              off_x2 = -obj->cur.geometry.x;
946              off_y2 = -obj->cur.geometry.y;
947              if (obj->smart.smart)
948                {
949                   EINA_INLIST_FOREACH
950                      (evas_object_smart_members_get_direct(obj), obj2)
951                        {
952                           clean_them |= evas_render_mapped(e, obj2, ctx,
953                                                            obj->cur.map->surface,
954                                                            off_x2, off_y2, 1,
955                                                            ecx, ecy, ecw, ech
956 #ifdef REND_DGB
957                                                            , level + 1
958 #endif
959                                                           );
960                        }
961                }
962              else
963                {
964                   int x = 0, y = 0, w = 0, h = 0;
965
966                   w = obj->cur.map->surface_w;
967                   h = obj->cur.map->surface_h;
968                   RECTS_CLIP_TO_RECT(x, y, w, h,
969                                      obj->cur.geometry.x + off_x2,
970                                      obj->cur.geometry.y + off_y2,
971                                      obj->cur.geometry.w,
972                                      obj->cur.geometry.h);
973
974                   e->engine.func->context_clip_set(e->engine.data.output,
975                                                    ctx, x, y, w, h);
976                   obj->func->render(obj, e->engine.data.output, ctx,
977                                     obj->cur.map->surface, off_x2, off_y2);
978                }
979              e->engine.func->context_free(e->engine.data.output, ctx);
980              rendered = EINA_TRUE;
981           }
982
983         RDI(level);
984         RD("        draw map\n");
985
986         if (rendered)
987           {
988              obj->cur.map->surface = e->engine.func->image_dirty_region
989                 (e->engine.data.output, obj->cur.map->surface,
990                  0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
991           }
992         e->engine.func->context_clip_unset(e->engine.data.output,
993                                            context);
994         if (obj->cur.map->surface)
995           {
996              if (obj->smart.smart)
997                {
998                   if (obj->cur.clipper)
999                     {
1000                        int x, y, w, h;
1001                        Evas_Object *tobj;
1002
1003                        obj->cur.cache.clip.dirty = EINA_TRUE;
1004                        tobj = obj->cur.map_parent;
1005                        obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
1006                        evas_object_clip_recalc(obj);
1007                        obj->cur.map_parent = tobj;
1008                        x = obj->cur.cache.clip.x;
1009                        y = obj->cur.cache.clip.y;
1010                        w = obj->cur.cache.clip.w;
1011                        h = obj->cur.cache.clip.h;
1012                        RECTS_CLIP_TO_RECT(x, y, w, h,
1013                                           obj->cur.clipper->cur.cache.clip.x,
1014                                           obj->cur.clipper->cur.cache.clip.y,
1015                                           obj->cur.clipper->cur.cache.clip.w,
1016                                           obj->cur.clipper->cur.cache.clip.h);
1017                        e->engine.func->context_clip_set(e->engine.data.output,
1018                                                         context,
1019                                                         x + off_x, y + off_y, w, h);
1020                     }
1021                }
1022              else
1023                {
1024                   if (obj->cur.clipper)
1025                     {
1026                        int x, y, w, h;
1027
1028                        evas_object_clip_recalc(obj);
1029                        x = obj->cur.cache.clip.x;
1030                        y = obj->cur.cache.clip.y;
1031                        w = obj->cur.cache.clip.w;
1032                        h = obj->cur.cache.clip.h;
1033                        RECTS_CLIP_TO_RECT(x, y, w, h,
1034                                           obj->cur.clipper->cur.cache.clip.x,
1035                                           obj->cur.clipper->cur.cache.clip.y,
1036                                           obj->cur.clipper->cur.cache.clip.w,
1037                                           obj->cur.clipper->cur.cache.clip.h);
1038                        e->engine.func->context_clip_set(e->engine.data.output,
1039                                                         context,
1040                                                         x + off_x, y + off_y, w, h);
1041                     }
1042                }
1043           }
1044 //        if (surface == e->engine.data.output)
1045           e->engine.func->context_clip_clip(e->engine.data.output,
1046                                             context,
1047                                             ecx, ecy, ecw, ech);
1048         if (obj->cur.cache.clip.visible)
1049           {
1050              obj->layer->evas->engine.func->context_multiplier_unset
1051                (e->engine.data.output, context);
1052              obj->layer->evas->engine.func->image_map_draw
1053                (e->engine.data.output, context, surface,
1054                    obj->cur.map->surface, obj->spans,
1055                    obj->cur.map->smooth, 0);
1056           }
1057         // FIXME: needs to cache these maps and
1058         // keep them only rendering updates
1059         //        obj->layer->evas->engine.func->image_map_surface_free
1060         //          (e->engine.data.output, obj->cur.map->surface);
1061         //        obj->cur.map->surface = NULL;
1062      }
1063    else
1064      {
1065         if (0 && obj->cur.cached_surface)
1066           fprintf(stderr, "We should cache '%s' [%i, %i, %i, %i]\n",
1067                   evas_object_type_get(obj),
1068                   obj->cur.bounding_box.x, obj->cur.bounding_box.x,
1069                   obj->cur.bounding_box.w, obj->cur.bounding_box.h);
1070         if (mapped)
1071           {
1072              RDI(level);
1073              RD("        draw child of mapped obj\n");
1074              ctx = e->engine.func->context_new(e->engine.data.output);
1075              if (obj->smart.smart)
1076                {
1077                   EINA_INLIST_FOREACH
1078                      (evas_object_smart_members_get_direct(obj), obj2)
1079                        {
1080                           clean_them |= evas_render_mapped(e, obj2, ctx,
1081                                                            surface,
1082                                                            off_x, off_y, 1,
1083                                                            ecx, ecy, ecw, ech
1084 #ifdef REND_DGB
1085                                                            , level + 1
1086 #endif
1087                                                           );
1088                        }
1089                }
1090              else
1091                {
1092                   if (!obj->cur.map)
1093                     {
1094                        int x, y, w, h;
1095
1096                        RDI(level);
1097
1098                        x = obj->cur.cache.clip.x + off_x;
1099                        y = obj->cur.cache.clip.y + off_y;
1100                        w = obj->cur.cache.clip.w;
1101                        h = obj->cur.cache.clip.h;
1102
1103                        if (obj->cur.clipper)
1104                          {
1105                             if (_evas_render_has_map(obj))
1106                               evas_object_clip_recalc(obj);
1107
1108                             RD("        clipper: %i %i %ix%i\n",
1109                                obj->cur.clipper->cur.cache.clip.x + off_x,
1110                                obj->cur.clipper->cur.cache.clip.y + off_y,
1111                                obj->cur.clipper->cur.cache.clip.w,
1112                                obj->cur.clipper->cur.cache.clip.h);
1113
1114                             RECTS_CLIP_TO_RECT(x, y, w, h,
1115                                                obj->cur.clipper->cur.cache.clip.x + off_x,
1116                                                obj->cur.clipper->cur.cache.clip.y + off_y,
1117                                                obj->cur.clipper->cur.cache.clip.w,
1118                                                obj->cur.clipper->cur.cache.clip.h);
1119                          }
1120
1121                        RD("        clip: %i %i %ix%i [%i %i %ix%i]\n",
1122                           obj->cur.cache.clip.x + off_x,
1123                           obj->cur.cache.clip.y + off_y,
1124                           obj->cur.cache.clip.w,
1125                           obj->cur.cache.clip.h,
1126                           obj->cur.geometry.x + off_x,
1127                           obj->cur.geometry.y + off_y,
1128                           obj->cur.geometry.w,
1129                           obj->cur.geometry.h);
1130                        e->engine.func->context_clip_set(e->engine.data.output,
1131                                                         ctx, x, y, w, h);
1132                     }
1133                   else
1134                     {
1135                        RDI(level);
1136                        RD("        noclip\n");
1137                     }
1138                   obj->func->render(obj, e->engine.data.output, ctx,
1139                                     surface, off_x, off_y);
1140                   /*
1141                                       obj->layer->evas->engine.func->context_color_set(e->engine.data.output,
1142                                       ctx,
1143                                       0, 30, 0, 30);
1144                                       obj->layer->evas->engine.func->rectangle_draw(e->engine.data.output,
1145                                       ctx,
1146                                       surface,
1147                                       0, 0, 9999, 9999);
1148                    */
1149                }
1150              e->engine.func->context_free(e->engine.data.output, ctx);
1151           }
1152         else
1153           {
1154              if (obj->cur.clipper)
1155                {
1156                   int x, y, w, h;
1157
1158                   if (_evas_render_has_map(obj))
1159                     evas_object_clip_recalc(obj);
1160                   x = obj->cur.cache.clip.x;
1161                   y = obj->cur.cache.clip.y;
1162                   w = obj->cur.cache.clip.w;
1163                   h = obj->cur.cache.clip.h;
1164                   RECTS_CLIP_TO_RECT(x, y, w, h,
1165                                      obj->cur.clipper->cur.cache.clip.x,
1166                                      obj->cur.clipper->cur.cache.clip.y,
1167                                      obj->cur.clipper->cur.cache.clip.w,
1168                                      obj->cur.clipper->cur.cache.clip.h);
1169                   e->engine.func->context_clip_set(e->engine.data.output,
1170                                                    context,
1171                                                    x + off_x, y + off_y, w, h);
1172                   e->engine.func->context_clip_clip(e->engine.data.output,
1173                                                     context,
1174                                                     ecx, ecy, ecw, ech);
1175                }
1176
1177              RDI(level);
1178              RD("        draw normal obj\n");
1179              obj->func->render(obj, e->engine.data.output, context, surface,
1180                                off_x, off_y);
1181           }
1182         if (obj->changed_map) clean_them = EINA_TRUE;
1183      }
1184    RDI(level);
1185    RD("      }\n");
1186
1187    return clean_them;
1188 }
1189
1190 static void
1191 _evas_render_cutout_add(Evas *e, Evas_Object *obj, int off_x, int off_y)
1192 {
1193    if (evas_object_is_opaque(obj))
1194      {
1195         Evas_Coord cox, coy, cow, coh;
1196
1197         cox = obj->cur.cache.clip.x;
1198         coy = obj->cur.cache.clip.y;
1199         cow = obj->cur.cache.clip.w;
1200         coh = obj->cur.cache.clip.h;
1201         if ((obj->cur.map) && (obj->cur.usemap))
1202           {
1203              Evas_Object *oo;
1204
1205              oo = obj;
1206              while (oo->cur.clipper)
1207                {
1208                   if ((oo->cur.clipper->cur.map_parent
1209                        != oo->cur.map_parent) &&
1210                       (!((oo->cur.map) && (oo->cur.usemap))))
1211                     break;
1212                   RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
1213                                      oo->cur.geometry.x,
1214                                      oo->cur.geometry.y,
1215                                      oo->cur.geometry.w,
1216                                      oo->cur.geometry.h);
1217                   oo = oo->cur.clipper;
1218                }
1219           }
1220         e->engine.func->context_cutout_add
1221           (e->engine.data.output, e->engine.data.context,
1222               cox + off_x, coy + off_y, cow, coh);
1223      }
1224    else
1225      {
1226         if (obj->func->get_opaque_rect)
1227           {
1228              Evas_Coord obx, oby, obw, obh;
1229
1230              obj->func->get_opaque_rect(obj, &obx, &oby, &obw, &obh);
1231              if ((obw > 0) && (obh > 0))
1232                {
1233                   obx += off_x;
1234                   oby += off_y;
1235                   RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1236                                      obj->cur.cache.clip.x + off_x,
1237                                      obj->cur.cache.clip.y + off_y,
1238                                      obj->cur.cache.clip.w,
1239                                      obj->cur.cache.clip.h);
1240                   e->engine.func->context_cutout_add
1241                     (e->engine.data.output, e->engine.data.context,
1242                         obx, oby, obw, obh);
1243                }
1244           }
1245      }
1246 }
1247
1248 static Eina_List *
1249 evas_render_updates_internal(Evas *e,
1250                              unsigned char make_updates,
1251                              unsigned char do_draw)
1252 {
1253    Evas_Object *obj;
1254    Eina_List *updates = NULL;
1255    Eina_List *ll;
1256    void *surface;
1257    Eina_Bool clean_them = EINA_FALSE;
1258    Eina_Bool alpha;
1259    Eina_Rectangle *r;
1260    int ux, uy, uw, uh;
1261    int cx, cy, cw, ch;
1262    unsigned int i, j;
1263    int redraw_all = 0;
1264    Eina_Bool haveup = 0;
1265
1266    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1267    return NULL;
1268    MAGIC_CHECK_END();
1269    if (!e->changed) return NULL;
1270
1271 #ifdef EVAS_CSERVE2
1272    if (evas_cserve2_use_get())
1273       evas_cserve2_dispatch();
1274 #endif
1275    evas_call_smarts_calculate(e);
1276
1277    RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
1278
1279    evas_event_callback_call(e, EVAS_CALLBACK_RENDER_PRE, NULL);
1280
1281    /* Check if the modified object mean recalculating every thing */
1282    if (!e->invalidate)
1283      _evas_render_check_pending_objects(&e->pending_objects, e);
1284
1285    /* phase 1. add extra updates for changed objects */
1286    if (e->invalidate || e->render_objects.count <= 0)
1287      clean_them = _evas_render_phase1_process(e,
1288                                               &e->active_objects,
1289                                               &e->restack_objects,
1290                                               &e->delete_objects,
1291                                               &e->render_objects,
1292                                               &redraw_all);
1293
1294    /* phase 1.5. check if the video should be inlined or stay in their overlay */
1295    alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1296                                             e->engine.data.context);
1297
1298    EINA_LIST_FOREACH(e->video_objects, ll, obj)
1299      {
1300         /* we need the surface to be transparent to display the underlying overlay */
1301         if (alpha && _evas_render_can_use_overlay(e, obj))
1302           _evas_object_image_video_overlay_show(obj);
1303         else
1304           _evas_object_image_video_overlay_hide(obj);
1305      }
1306    /* phase 1.8. pre render for proxy */
1307    _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
1308                               &e->delete_objects, &e->render_objects);
1309
1310    /* phase 2. force updates for restacks */
1311    for (i = 0; i < e->restack_objects.count; ++i)
1312      {
1313         obj = eina_array_data_get(&e->restack_objects, i);
1314         obj->func->render_pre(obj);
1315         _evas_render_prev_cur_clip_cache_add(e, obj);
1316      }
1317    eina_array_clean(&e->restack_objects);
1318
1319    /* phase 3. add exposes */
1320    EINA_LIST_FREE(e->damages, r)
1321      {
1322         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1323                                                 r->x, r->y, r->w, r->h);
1324         eina_rectangle_free(r);
1325      }
1326
1327    /* phase 4. framespace, output & viewport changes */
1328    if (e->viewport.changed)
1329      {
1330         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1331                                                 0, 0,
1332                                                 e->output.w, e->output.h);
1333      }
1334    if (e->output.changed)
1335      {
1336         e->engine.func->output_resize(e->engine.data.output,
1337                                       e->output.w, e->output.h);
1338         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1339                                                 0, 0,
1340                                                 e->output.w, e->output.h);
1341      }
1342    if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1343      {
1344         ERR("viewport size != output size!");
1345      }
1346
1347    if (e->framespace.changed)
1348      {
1349         int fx, fy, fw, fh;
1350
1351         fx = e->viewport.x - e->framespace.x;
1352         fy = e->viewport.y - e->framespace.y;
1353         fw = e->viewport.w + e->framespace.w;
1354         fh = e->viewport.h + e->framespace.h;
1355         if (fx < 0) fx = 0;
1356         if (fy < 0) fy = 0;
1357         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1358                                                 fx, fy, fw, fh);
1359      }
1360
1361    /* phase 4.5: check if object is not in framespace. if not, we need to clip 
1362     * it to the 'master' clip.
1363     * 
1364     * NB: This is for the wayland engine(s). If we do not do this, then 
1365     * objects will draw outside the viewport and potentially onto the frame 
1366     * itself */
1367    if (!strncmp(e->engine.module->definition->name, "wayland", 7))
1368      {
1369         Eina_Rectangle clip_rect;
1370
1371         /* see if the master clip has been added yet, if not, then create */
1372         if (!e->framespace.clip)
1373           {
1374              e->framespace.clip = evas_object_rectangle_add(e);
1375              evas_object_color_set(e->framespace.clip, 255, 255, 255, 255);
1376              evas_object_move(e->framespace.clip,
1377                               e->framespace.x, e->framespace.y);
1378              evas_object_resize(e->framespace.clip,
1379                                 e->viewport.w - e->framespace.w, 
1380                                 e->viewport.h - e->framespace.h);
1381              evas_object_show(e->framespace.clip);
1382           }
1383         else
1384           {
1385              /* master clip is already present. check for size changes in the 
1386               * viewport, and update master clip size if needed */
1387              if ((e->viewport.changed) || (e->output.changed))
1388                {
1389                   evas_object_resize(e->framespace.clip,
1390                                      e->viewport.w - e->framespace.w,
1391                                      e->viewport.h - e->framespace.h);
1392                }
1393           }
1394
1395         EINA_RECTANGLE_SET(&clip_rect,
1396                            e->framespace.clip->cur.geometry.x,
1397                            e->framespace.clip->cur.geometry.y,
1398                            e->framespace.clip->cur.geometry.w,
1399                            e->framespace.clip->cur.geometry.h)
1400
1401         /* With the master clip all setup, we need to loop the objects on this 
1402          * canvas and determine if the object is in the viewport space. If it 
1403          * is in the viewport space (and not in framespace), then we need to 
1404          * clip the object to the master clip so that it does not draw on top 
1405          * of the frame (eg: elm 3d test) */
1406         for (i = 0; i < e->render_objects.count; ++i)
1407           {
1408              Eina_Rectangle obj_rect;
1409              Evas_Object *pclip;
1410
1411              obj = eina_array_data_get(&e->render_objects, i);
1412              if (evas_object_is_frame_object_get(obj))
1413                continue;
1414
1415              if (obj->delete_me) continue;
1416
1417              EINA_RECTANGLE_SET(&obj_rect,
1418                                 obj->cur.geometry.x, obj->cur.geometry.y,
1419                                 obj->cur.geometry.w, obj->cur.geometry.h);
1420
1421              /* if the object does not intersect our clip rect, ignore it */
1422              if (!eina_rectangles_intersect(&clip_rect, &obj_rect))
1423                continue;
1424
1425              if (!(pclip = evas_object_clip_get(obj)))
1426                {
1427                   /* clip this object so it does not draw on the window frame */
1428                   evas_object_clip_set(obj, e->framespace.clip);
1429                }
1430           }
1431      }
1432
1433    if (redraw_all)
1434      {
1435         e->engine.func->output_redraws_rect_add(e->engine.data.output, 0, 0,
1436                                                 e->output.w, e->output.h);
1437      }
1438
1439    /* phase 5. add obscures */
1440    EINA_LIST_FOREACH(e->obscures, ll, r)
1441      {
1442         e->engine.func->output_redraws_rect_del(e->engine.data.output,
1443                                                 r->x, r->y, r->w, r->h);
1444      }
1445    /* build obscure objects list of active objects that obscure */
1446    for (i = 0; i < e->active_objects.count; ++i)
1447      {
1448         obj = eina_array_data_get(&e->active_objects, i);
1449         if (UNLIKELY((evas_object_is_opaque(obj) ||
1450                       ((obj->func->has_opaque_rect) &&
1451                        (obj->func->has_opaque_rect(obj)))) &&
1452                      evas_object_is_visible(obj) &&
1453                      (!obj->clip.clipees) &&
1454                      (obj->cur.visible) &&
1455                      (!obj->delete_me) &&
1456                      (obj->cur.cache.clip.visible) &&
1457                      (!obj->smart.smart)))
1458           /*      obscuring_objects = eina_list_append(obscuring_objects, obj); */
1459           eina_array_push(&e->obscuring_objects, obj);
1460      }
1461
1462    /* save this list */
1463    /*    obscuring_objects_orig = obscuring_objects; */
1464    /*    obscuring_objects = NULL; */
1465    /* phase 6. go thru each update rect and render objects in it*/
1466    if (do_draw)
1467      {
1468         unsigned int offset = 0;
1469
1470         while ((surface =
1471                 e->engine.func->output_redraws_next_update_get
1472                 (e->engine.data.output,
1473                  &ux, &uy, &uw, &uh,
1474                  &cx, &cy, &cw, &ch)))
1475           {
1476              int off_x, off_y;
1477
1478              RD("  [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1479              if (make_updates)
1480                {
1481                   Eina_Rectangle *rect;
1482
1483                   NEW_RECT(rect, ux, uy, uw, uh);
1484                   if (rect)
1485                     updates = eina_list_append(updates, rect);
1486                }
1487              haveup = EINA_TRUE;
1488              off_x = cx - ux;
1489              off_y = cy - uy;
1490              /* build obscuring objects list (in order from bottom to top) */
1491              if (alpha)
1492                {
1493                   e->engine.func->context_clip_set(e->engine.data.output,
1494                                                    e->engine.data.context,
1495                                                    ux + off_x, uy + off_y, uw, uh);
1496                }
1497              for (i = 0; i < e->obscuring_objects.count; ++i)
1498                {
1499                   obj = (Evas_Object *)eina_array_data_get
1500                      (&e->obscuring_objects, i);
1501                   if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1502                     {
1503                        eina_array_push(&e->temporary_objects, obj);
1504
1505                        /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1506                        if (alpha)
1507                          _evas_render_cutout_add(e, obj, off_x, off_y);
1508                     }
1509                }
1510              if (alpha)
1511                {
1512                   e->engine.func->context_color_set(e->engine.data.output,
1513                                                     e->engine.data.context,
1514                                                     0, 0, 0, 0);
1515                   e->engine.func->context_multiplier_unset
1516                      (e->engine.data.output, e->engine.data.context);
1517                   e->engine.func->context_render_op_set(e->engine.data.output,
1518                                                         e->engine.data.context,
1519                                                         EVAS_RENDER_COPY);
1520                   e->engine.func->rectangle_draw(e->engine.data.output,
1521                                                  e->engine.data.context,
1522                                                  surface,
1523                                                  cx, cy, cw, ch);
1524                   e->engine.func->context_cutout_clear(e->engine.data.output,
1525                                                        e->engine.data.context);
1526                   e->engine.func->context_clip_unset(e->engine.data.output,
1527                                                      e->engine.data.context);
1528                }
1529
1530              /* render all object that intersect with rect */
1531              for (i = 0; i < e->active_objects.count; ++i)
1532                {
1533                   obj = eina_array_data_get(&e->active_objects, i);
1534
1535                   /* if it's in our outpout rect and it doesn't clip anything */
1536                   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);
1537                   if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1538                        (obj->smart.smart)) &&
1539                       (!obj->clip.clipees) &&
1540                       (obj->cur.visible) &&
1541                       (!obj->delete_me) &&
1542                       (obj->cur.cache.clip.visible) &&
1543 //                    (!obj->smart.smart) &&
1544                       ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1545                     {
1546                        int x, y, w, h;
1547
1548                        RD("      DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1549                        if ((e->temporary_objects.count > offset) &&
1550                            (eina_array_data_get(&e->temporary_objects, offset) == obj))
1551                          offset++;
1552                        x = cx; y = cy; w = cw; h = ch;
1553                        if (((w > 0) && (h > 0)) || (obj->smart.smart))
1554                          {
1555                             if (!obj->smart.smart)
1556                               {
1557                                  RECTS_CLIP_TO_RECT(x, y, w, h,
1558                                                     obj->cur.cache.clip.x + off_x,
1559                                                     obj->cur.cache.clip.y + off_y,
1560                                                     obj->cur.cache.clip.w,
1561                                                     obj->cur.cache.clip.h);
1562                               }
1563                             if (obj->cur.mask)
1564                               e->engine.func->context_mask_set(e->engine.data.output,
1565                                                                e->engine.data.context,
1566                                                                obj->cur.mask->func->engine_data_get(obj->cur.mask),
1567                                                                obj->cur.mask->cur.geometry.x + off_x,
1568                                                                obj->cur.mask->cur.geometry.y + off_y,
1569                                                                obj->cur.mask->cur.geometry.w,
1570                                                                obj->cur.mask->cur.geometry.h);
1571                             else
1572                               e->engine.func->context_mask_unset(e->engine.data.output,
1573                                                                  e->engine.data.context);
1574                             e->engine.func->context_clip_set(e->engine.data.output,
1575                                                              e->engine.data.context,
1576                                                              x, y, w, h);
1577 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1578                             for (j = offset; j < e->temporary_objects.count; ++j)
1579                               {
1580                                  Evas_Object *obj2;
1581
1582                                  obj2 = (Evas_Object *)eina_array_data_get
1583                                    (&e->temporary_objects, j);
1584                                  _evas_render_cutout_add(e, obj2, off_x, off_y);
1585                               }
1586 #endif
1587                             clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1588                                                              surface, off_x, off_y, 0,
1589                                                              cx, cy, cw, ch
1590 #ifdef REND_DGB
1591                                                              , 1
1592 #endif
1593                                                             );
1594                             e->engine.func->context_cutout_clear(e->engine.data.output,
1595                                                                  e->engine.data.context);
1596                          }
1597                     }
1598                }
1599              /* punch rect out */
1600              e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1601                                                              surface,
1602                                                              ux, uy, uw, uh);
1603              /* free obscuring objects list */
1604              eina_array_clean(&e->temporary_objects);
1605              RD("  ---]\n");
1606           }
1607         /* flush redraws */
1608         if (haveup)
1609           {
1610              evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1611              e->engine.func->output_flush(e->engine.data.output);
1612              evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1613           }
1614      }
1615    /* clear redraws */
1616    e->engine.func->output_redraws_clear(e->engine.data.output);
1617    /* and do a post render pass */
1618    for (i = 0; i < e->active_objects.count; ++i)
1619      {
1620         obj = eina_array_data_get(&e->active_objects, i);
1621         obj->pre_render_done = EINA_FALSE;
1622         RD("    OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1623         if ((obj->changed) && (do_draw))
1624           {
1625              RD("    OBJ [%p] post... func1\n", obj);
1626              obj->func->render_post(obj);
1627              obj->restack = EINA_FALSE;
1628              evas_object_change_reset(obj);
1629           }
1630         else if (clean_them)
1631           {
1632              RD("    OBJ [%p] post... func2\n", obj);
1633              obj->func->render_post(obj);
1634              obj->restack = EINA_FALSE;
1635              evas_object_change_reset(obj);
1636           }
1637         /* moved to other pre-process phase 1
1638            if (obj->delete_me == 2)
1639            {
1640            delete_objects = eina_list_append(delete_objects, obj);
1641            }
1642            else if (obj->delete_me != 0) obj->delete_me++;
1643          */
1644      }
1645    /* free our obscuring object list */
1646    eina_array_clean(&e->obscuring_objects);
1647
1648    /* If some object are still marked as changed, do not remove
1649       them from the pending list. */
1650    eina_array_remove(&e->pending_objects, pending_change, NULL);
1651
1652    for (i = 0; i < e->render_objects.count; ++i)
1653      {
1654         obj = eina_array_data_get(&e->render_objects, i);
1655         obj->pre_render_done = EINA_FALSE;
1656      }
1657
1658    /* delete all objects flagged for deletion now */
1659    for (i = 0; i < e->delete_objects.count; ++i)
1660      {
1661         obj = eina_array_data_get(&e->delete_objects, i);
1662         evas_object_free(obj, 1);
1663      }
1664    eina_array_clean(&e->delete_objects);
1665
1666    e->changed = EINA_FALSE;
1667    e->viewport.changed = EINA_FALSE;
1668    e->output.changed = EINA_FALSE;
1669    e->framespace.changed = EINA_FALSE;
1670    e->invalidate = EINA_FALSE;
1671
1672    // always clean... lots of mem waste!
1673    /* If their are some object to restack or some object to delete,
1674     * it's useless to keep the render object list around. */
1675    if (clean_them)
1676      {
1677         eina_array_clean(&e->active_objects);
1678         eina_array_clean(&e->render_objects);
1679         eina_array_clean(&e->restack_objects);
1680         eina_array_clean(&e->temporary_objects);
1681         eina_array_clean(&e->clip_changes);
1682 /* we should flush here and have a mempool system for this        
1683         eina_array_flush(&e->active_objects);
1684         eina_array_flush(&e->render_objects);
1685         eina_array_flush(&e->restack_objects);
1686         eina_array_flush(&e->delete_objects);
1687         eina_array_flush(&e->obscuring_objects);
1688         eina_array_flush(&e->temporary_objects);
1689         eina_array_flush(&e->clip_changes);
1690  */
1691         e->invalidate = EINA_TRUE;
1692      }
1693
1694    evas_module_clean();
1695
1696    evas_event_callback_call(e, EVAS_CALLBACK_RENDER_POST, NULL);
1697
1698    RD("---]\n");
1699
1700    return updates;
1701 }
1702
1703 EAPI void
1704 evas_render_updates_free(Eina_List *updates)
1705 {
1706    Eina_Rectangle *r;
1707
1708    EINA_LIST_FREE(updates, r)
1709       eina_rectangle_free(r);
1710 }
1711
1712 EAPI Eina_List *
1713 evas_render_updates(Evas *e)
1714 {
1715    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1716    return NULL;
1717    MAGIC_CHECK_END();
1718
1719    if (!e->changed) return NULL;
1720    return evas_render_updates_internal(e, 1, 1);
1721 }
1722
1723 EAPI void
1724 evas_render(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, 1);
1732 }
1733
1734 EAPI void
1735 evas_norender(Evas *e)
1736 {
1737    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1738    return;
1739    MAGIC_CHECK_END();
1740
1741    //   if (!e->changed) return;
1742    evas_render_updates_internal(e, 0, 0);
1743 }
1744
1745 EAPI void
1746 evas_render_idle_flush(Evas *e)
1747 {
1748    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1749    return;
1750    MAGIC_CHECK_END();
1751
1752    evas_fonts_zero_presure(e);
1753
1754    if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1755        (e->engine.data.output))
1756      e->engine.func->output_idle_flush(e->engine.data.output);
1757
1758    eina_array_flush(&e->active_objects);
1759    eina_array_flush(&e->render_objects);
1760    eina_array_flush(&e->restack_objects);
1761    eina_array_flush(&e->delete_objects);
1762    eina_array_flush(&e->obscuring_objects);
1763    eina_array_flush(&e->temporary_objects);
1764    eina_array_flush(&e->clip_changes);
1765
1766    e->invalidate = EINA_TRUE;
1767 }
1768
1769 EAPI void
1770 evas_sync(Evas *e)
1771 {
1772   (void) e;
1773 }
1774
1775 static void
1776 _evas_render_dump_map_surfaces(Evas_Object *obj)
1777 {
1778    if ((obj->cur.map) && obj->cur.map->surface)
1779      {
1780         obj->layer->evas->engine.func->image_map_surface_free
1781            (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1782         obj->cur.map->surface = NULL;
1783      }
1784
1785    if (obj->smart.smart)
1786      {
1787         Evas_Object *obj2;
1788
1789         EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1790            _evas_render_dump_map_surfaces(obj2);
1791      }
1792 }
1793
1794 EAPI void
1795 evas_render_dump(Evas *e)
1796 {
1797    Evas_Layer *lay;
1798
1799    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1800    return;
1801    MAGIC_CHECK_END();
1802
1803    EINA_INLIST_FOREACH(e->layers, lay)
1804      {
1805         Evas_Object *obj;
1806
1807         EINA_INLIST_FOREACH(lay->objects, obj)
1808           {
1809              if ((obj->type) && (!strcmp(obj->type, "image")))
1810                evas_object_inform_call_image_unloaded(obj);
1811              _evas_render_dump_map_surfaces(obj);
1812           }
1813      }
1814    if ((e->engine.func) && (e->engine.func->output_dump) &&
1815        (e->engine.data.output))
1816      e->engine.func->output_dump(e->engine.data.output);
1817 }
1818
1819 void
1820 evas_render_invalidate(Evas *e)
1821 {
1822    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1823    return;
1824    MAGIC_CHECK_END();
1825
1826    eina_array_clean(&e->active_objects);
1827    eina_array_clean(&e->render_objects);
1828
1829    eina_array_flush(&e->restack_objects);
1830    eina_array_flush(&e->delete_objects);
1831
1832    e->invalidate = EINA_TRUE;
1833 }
1834
1835 void
1836 evas_render_object_recalc(Evas_Object *obj)
1837 {
1838    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1839    return;
1840    MAGIC_CHECK_END();
1841
1842    if ((!obj->changed) && (obj->delete_me < 2))
1843      {
1844        Evas *e;
1845
1846        e = obj->layer->evas;
1847        if ((!e) || (e->cleanup)) return;
1848        eina_array_push(&e->pending_objects, obj);
1849        obj->changed = EINA_TRUE;
1850      }
1851 }
1852
1853 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/