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