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