453a4fc6faaa924efcf22d651345fbdf401c96d9
[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 /**
50  * Add a damage rectangle.
51  *
52  * @param e The given canvas pointer.
53  * @param x The rectangle's left position.
54  * @param y The rectangle's top position.
55  * @param w The rectangle's width.
56  * @param h The rectangle's height.
57  *
58  * This is the function by which one tells evas that a part of the
59  * canvas has to be repainted.
60  *
61  * @ingroup Evas_Canvas
62  */
63 EAPI void
64 evas_damage_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->damages = eina_list_append(e->damages, r);
74    e->changed = 1;
75 }
76
77 /**
78  * Add an obscured region.
79  *
80  * @param e The given canvas pointer.
81  * @param x The rectangle's left position.
82  * @param y The rectangle's top position
83  * @param w The rectangle's width.
84  * @param h The rectangle's height.
85  *
86  * This is the function by which one tells evas that a part of the
87  * canvas has not to be repainted. To make this region one that have
88  * to be repainted, call the function evas_obscured_clear().
89  *
90  * @see evas_obscured_clear().
91  *
92  * @ingroup Evas_Canvas
93  */
94 EAPI void
95 evas_obscured_rectangle_add(Evas *e, int x, int y, int w, int h)
96 {
97    Eina_Rectangle *r;
98
99    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
100    return;
101    MAGIC_CHECK_END();
102    NEW_RECT(r, x, y, w, h);
103    if (!r) return;
104    e->obscures = eina_list_append(e->obscures, r);
105 }
106
107 /**
108  * Remove all obscured region rectangles from the canvas.
109  *
110  * @param e The given canvas pointer.
111  *
112  * This function removes all the rectangles from the obscured list of
113  * the canvas. It takes obscured areas added with
114  * evas_obscured_rectangle_add() and makes it a region that have to be
115  * repainted.
116  *
117  * @ingroup Evas_Canvas
118  */
119 EAPI void
120 evas_obscured_clear(Evas *e)
121 {
122    Eina_Rectangle *r;
123
124    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
125    return;
126    MAGIC_CHECK_END();
127    EINA_LIST_FREE(e->obscures, r)
128      {
129         eina_rectangle_free(r);
130      }
131 }
132
133 static Eina_Bool
134 _evas_render_has_map(Evas_Object *obj)
135 {
136    return ((!((obj->func->can_map) && (obj->func->can_map(obj)))) &&
137            ((obj->cur.map) && (obj->cur.usemap)));
138 //   return ((obj->cur.map) && (obj->cur.usemap));
139 }
140
141 static Eina_Bool
142 _evas_render_had_map(Evas_Object *obj)
143 {
144    return ((obj->prev.map) && (obj->prev.usemap));
145 //   return ((!obj->cur.map) && (obj->prev.usemap));
146 }
147
148 static Eina_Bool
149 _evas_render_is_relevant(Evas_Object *obj)
150 {
151    return ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
152            (evas_object_was_visible(obj) && (!obj->prev.have_clipees)));
153 }
154
155 static Eina_Bool
156 _evas_render_can_render(Evas_Object *obj)
157 {
158    return (evas_object_is_visible(obj) && (!obj->cur.have_clipees));
159 }
160
161 static void
162 _evas_render_prev_cur_clip_cache_add(Evas *e, Evas_Object *obj)
163 {
164    e->engine.func->output_redraws_rect_add(e->engine.data.output,
165                                            obj->prev.cache.clip.x,
166                                            obj->prev.cache.clip.y,
167                                            obj->prev.cache.clip.w,
168                                            obj->prev.cache.clip.h);
169    e->engine.func->output_redraws_rect_add(e->engine.data.output,
170                                            obj->cur.cache.clip.x,
171                                            obj->cur.cache.clip.y,
172                                            obj->cur.cache.clip.w,
173                                            obj->cur.cache.clip.h);
174 }
175
176 static void
177 _evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
178 {
179    e->engine.func->output_redraws_rect_del(e->engine.data.output,
180                                            obj->cur.cache.clip.x,
181                                            obj->cur.cache.clip.y,
182                                            obj->cur.cache.clip.w,
183                                            obj->cur.cache.clip.h);
184 }
185
186 static void
187 _evas_render_phase1_direct(Evas *e,
188                            Eina_Array *active_objects __UNUSED__,
189                            Eina_Array *restack_objects __UNUSED__,
190                            Eina_Array *delete_objects __UNUSED__,
191                            Eina_Array *render_objects)
192 {
193    unsigned int i;
194
195    RD("  [--- PHASE 1 DIRECT\n");
196    for (i = 0; i < render_objects->count; i++)
197      {
198         Evas_Object *obj;
199
200         obj = eina_array_data_get(render_objects, i);
201         RD("    OBJ [%p] changed %i\n", obj, obj->changed);
202         if (obj->changed)
203           {
204              evas_object_clip_recalc(obj);
205              obj->func->render_pre(obj);
206              if (obj->pre_render_done)
207                {
208                   RD("      pre-render-done smart:%p|%p  [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
209                      obj->smart.smart, 
210                      evas_object_smart_members_get_direct(obj),
211                      obj->cur.map, obj->cur.usemap,
212                      obj->prev.map, obj->prev.usemap,
213                      _evas_render_has_map(obj),
214                      _evas_render_had_map(obj));
215                   if ((obj->smart.smart) && 
216                       (_evas_render_has_map(obj)))
217                     {
218                        RD("      has map + smart\n");
219                        _evas_render_prev_cur_clip_cache_add(e, obj);
220                     }
221                }
222              else if (_evas_render_had_map(obj))
223                {
224                   RD("      no pre-render done\n");
225                   _evas_render_prev_cur_clip_cache_add(e, obj);
226                }
227           }
228         else
229           {
230              if (obj->smart.smart)
231                {
232 //                  obj->func->render_pre(obj);
233                }
234              else if (obj->rect_del)
235                {
236                   RD("    rect del\n");
237                   _evas_render_cur_clip_cache_del(e, obj);
238                }
239           }
240      }
241    RD("  ---]\n");
242 }
243
244 static Eina_Bool
245 _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
246                                    Eina_Array *active_objects,
247                                    Eina_Array *restack_objects,
248                                    Eina_Array *delete_objects,
249                                    Eina_Array *render_objects,
250                                    int restack, int map,
251                                    int *redraw_all
252 #ifdef REND_DGB
253                                    , int level
254 #endif
255                                    )
256 {
257    Eina_Bool clean_them = EINA_FALSE;
258    Evas_Object *obj2;
259    int is_active;
260    Eina_Bool hmap;
261    
262    obj->rect_del = 0;
263    obj->render_pre = 0;
264
265 #ifndef EVAS_FRAME_QUEUING
266    /* because of clip objects - delete 2 cycles later */
267    if (obj->delete_me == 2)
268 #else
269    if (obj->delete_me == evas_common_frameq_get_frameq_sz() + 2)
270 #endif
271         eina_array_push(delete_objects, obj);
272    else if (obj->delete_me != 0) obj->delete_me++;
273    /* If the object will be removed, we should not cache anything during this run. */
274    if (obj->delete_me != 0) clean_them = EINA_TRUE;
275
276    /* build active object list */
277    evas_object_clip_recalc(obj);
278    is_active = evas_object_is_active(obj);
279    obj->is_active = is_active;
280
281    RDI(level);
282    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);
283    if ((is_active) || (obj->delete_me != 0))
284      eina_array_push(active_objects, obj);
285
286 #ifdef REND_DGB
287    if (!is_active)
288      {
289         RDI(level);
290         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);
291      }
292 #endif
293
294    map = _evas_render_has_map(obj);
295    hmap = _evas_render_had_map(obj);
296
297    if ((restack) && (!map))
298      {
299         if (!obj->changed)
300           {
301              eina_array_push(&e->pending_objects, obj);
302              obj->changed = 1;
303           }
304         obj->restack = 1;
305         clean_them = EINA_TRUE;
306      }
307
308    if (map)
309      {
310         RDI(level);
311         RD("      obj mapped\n");
312         if (obj->changed)
313           {
314              if (map != hmap)
315                {
316                   *redraw_all = 1;
317                }
318              evas_object_clip_recalc(obj);
319              if ((obj->restack) &&
320                  (is_active) && (!obj->clip.clipees) &&
321                  ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
322                   (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
323                {
324                   eina_array_push(render_objects, obj);
325                   _evas_render_prev_cur_clip_cache_add(e, obj);
326                   obj->render_pre = 1;
327                }
328              else if ((is_active) && (!obj->clip.clipees) &&
329                       ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
330                        (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
331                {
332                   eina_array_push(render_objects, obj);
333                   _evas_render_prev_cur_clip_cache_add(e, obj);
334                   obj->render_pre = 1;
335                }
336           }
337         return clean_them;
338      }
339    else if (_evas_render_had_map(obj))
340      {
341         RDI(level);
342         RD("      had map - restack objs\n");
343 //        eina_array_push(restack_objects, obj);
344         _evas_render_prev_cur_clip_cache_add(e, obj);
345         if (obj->changed)
346           {
347              if (hmap)
348                {
349                   if (!map)
350                     {
351                        if ((obj->cur.map) && (obj->cur.usemap)) map = 1;
352                     }
353                }
354              if (map != hmap)
355                {
356                   *redraw_all = 1;
357                }
358           }
359      }
360
361    /* handle normal rendering. this object knows how to handle maps */
362    if (obj->changed)
363      {
364         if (obj->smart.smart)
365           {
366              RDI(level);
367              RD("      changed + smart - render ok\n");
368              eina_array_push(render_objects, obj);
369              obj->render_pre = 1;
370              EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
371                {
372                   _evas_render_phase1_object_process(e, obj2,
373                                                      active_objects,
374                                                      restack_objects,
375                                                      delete_objects,
376                                                      render_objects,
377                                                      obj->restack,
378                                                      map,
379                                                      redraw_all
380 #ifdef REND_DGB
381                                                      , level + 1
382 #endif
383                                                      );
384                }
385           }
386         else
387           {
388              if ((is_active) && (!obj->clip.clipees) &&
389                  _evas_render_is_relevant(obj))
390                {
391                   RDI(level);
392                   RD("      relevant + active\n");
393                   if (obj->restack)
394                     eina_array_push(restack_objects, obj);
395                   else
396                     {
397                        eina_array_push(render_objects, obj);
398                        obj->render_pre = 1;
399                     }
400                }
401              else
402                {
403                   RDI(level);
404                   RD("      skip - not smart, not active or clippees or not relevant\n");
405                }
406           }
407      }
408    else
409      {
410         RD("      not changed... [%i] -> (%i %i %p %i) [%i]\n",
411            evas_object_is_visible(obj),
412            obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart, obj->cur.cache.clip.a,
413            evas_object_was_visible(obj));
414         if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
415             (_evas_render_can_render(obj) ||
416              (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
417           {
418              if (obj->smart.smart)
419                {
420                   RDI(level);
421                   RD("      smart + visible/was visible + not clip\n");
422                   eina_array_push(render_objects, obj);
423                   obj->render_pre = 1;
424                   EINA_INLIST_FOREACH
425                     (evas_object_smart_members_get_direct(obj), obj2)
426                     {
427                        _evas_render_phase1_object_process(e, obj2,
428                                                           active_objects,
429                                                           restack_objects,
430                                                           delete_objects,
431                                                           render_objects,
432                                                           restack, map,
433                                                           redraw_all
434 #ifdef REND_DGB
435                                                           , level + 1
436 #endif
437                                                           );
438                     }
439                }
440              else
441                {
442                   if (evas_object_is_opaque(obj) &&
443                       evas_object_is_visible(obj))
444                     {
445                        RDI(level);
446                        RD("      opaque + visible\n");
447                        eina_array_push(render_objects, obj);
448                        obj->rect_del = 1;
449                     }
450                   else if (evas_object_is_visible(obj))
451                     {
452                        RDI(level);
453                        RD("      visible\n");
454                        eina_array_push(render_objects, obj);
455                        obj->render_pre = 1;
456                     }
457                   else
458                     {
459                        RDI(level);
460                        RD("      skip\n");
461                     }
462                }
463           }
464 /*
465         else if (obj->smart.smart)
466           {
467              RDI(level);
468              RD("      smart + mot visible/was visible\n");
469              eina_array_push(render_objects, obj);
470              obj->render_pre = 1;
471              EINA_INLIST_FOREACH
472                (evas_object_smart_members_get_direct(obj), obj2)
473                {
474                   _evas_render_phase1_object_process(e, obj2,
475                                                      active_objects,
476                                                      restack_objects,
477                                                      delete_objects,
478                                                      render_objects,
479                                                      restack, map,
480                                                      redraw_all
481 #ifdef REND_DGB
482                                                      , level + 1
483 #endif
484                                                      );
485                }
486           }
487  */
488      }
489    if (!is_active) obj->restack = 0;
490    RDI(level);
491    RD("    ---]\n");
492    return clean_them;
493 }
494
495 static Eina_Bool
496 _evas_render_phase1_process(Evas *e,
497                             Eina_Array *active_objects,
498                             Eina_Array *restack_objects,
499                             Eina_Array *delete_objects,
500                             Eina_Array *render_objects,
501                             int *redraw_all)
502 {
503    Evas_Layer *lay;
504    Eina_Bool clean_them = EINA_FALSE;
505
506    RD("  [--- PHASE 1\n");
507    EINA_INLIST_FOREACH(e->layers, lay)
508      {
509         Evas_Object *obj;
510
511         EINA_INLIST_FOREACH(lay->objects, obj)
512           {
513              clean_them |= _evas_render_phase1_object_process
514                (e, obj, active_objects, restack_objects, delete_objects,
515                 render_objects, 0, 0, redraw_all
516 #ifdef REND_DGB
517                 , 1
518 #endif
519                 );
520           }
521      }
522    RD("  ---]\n");
523    return clean_them;
524 }
525
526 static void
527 _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
528 {
529    unsigned int i;
530
531    for (i = 0; i < pending_objects->count; ++i)
532      {
533         Evas_Object *obj;
534         int is_active, ok = 0;
535
536         obj = eina_array_data_get(pending_objects, i);
537
538         if (!obj->layer) goto clean_stuff;
539
540         evas_object_clip_recalc(obj);
541         is_active = evas_object_is_active(obj);
542
543         if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
544             (!obj->rect_del))
545           {
546              ok = 1;
547              goto clean_stuff;
548           }
549
550         if (obj->is_active == is_active)
551           {
552              if (obj->changed)
553                {
554                   if (obj->smart.smart)
555                     {
556                        if (obj->render_pre || obj->rect_del) ok = 1;
557                     }
558                   else
559                     if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
560                         (_evas_render_can_render(obj) ||
561                          (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
562                       {
563                          if (!(obj->render_pre || obj->rect_del)) ok = 1;
564                       }
565                   else
566                     if (is_active && (!obj->clip.clipees) &&
567                         (_evas_render_can_render(obj) ||
568                          (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
569                       {
570                          if (obj->render_pre || obj->rect_del) ok = 1;
571                       }
572                }
573              else
574                {
575                   if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
576                       (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
577                       && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
578                     {
579                        if (obj->rect_del || obj->smart.smart) ok = 1;
580                     }
581                }
582           }
583
584      clean_stuff:
585         if (!ok)
586           {
587              eina_array_clean(&e->active_objects);
588              eina_array_clean(&e->render_objects);
589              eina_array_clean(&e->restack_objects);
590              eina_array_clean(&e->delete_objects);
591              e->invalidate = 1;
592              return ;
593           }
594      }
595 }
596
597 Eina_Bool
598 pending_change(void *data, void *gdata __UNUSED__)
599 {
600    Evas_Object *obj;
601
602    obj = data;
603    if (obj->delete_me) return EINA_FALSE;
604    if (obj->pre_render_done)
605      {
606         RD("  OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
607         obj->pre_render_done = 0;
608 //// FIXME: this wipes out changes
609         obj->changed = 0;
610      }
611    return obj->changed ? EINA_TRUE : EINA_FALSE;
612 }
613
614 static Eina_Bool
615 evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
616                    int off_x, int off_y, int mapped
617 #ifdef REND_DGB
618                    , int level
619 #endif
620                    )
621 {
622    void *ctx;
623    Evas_Object *obj2;
624    Eina_Bool clean_them = EINA_FALSE;
625
626    evas_object_clip_recalc(obj);
627    RDI(level);
628    RD("      { evas_render_mapped(%p, %p,   %p, %p,   %i, %i,   %i,   %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
629    if (mapped)
630      {
631         if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
632             (obj->cur.have_clipees))
633           {
634              RDI(level);
635              RD("      }\n");
636              return clean_them;
637           }
638      }
639    else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
640                 (_evas_render_can_render(obj))))
641               ))
642      {
643         RDI(level);
644         RD("      }\n");
645         return clean_them;
646      }
647
648    // set render_pre - for child objs that may not have gotten it.
649    obj->pre_render_done = 1;
650
651    if (_evas_render_has_map(obj))
652      {
653         const Evas_Map_Point *p, *p_end;
654         RGBA_Map_Point pts[4], *pt;
655         int sw, sh;
656         int changed = 0, rendered = 0;
657
658         clean_them = EINA_TRUE;
659
660         sw = obj->cur.geometry.w;
661         sh = obj->cur.geometry.h;
662         RDI(level);
663         RD("        mapped obj: %ix%i\n", sw, sh);
664         if ((sw <= 0) || (sh <= 0))
665           {
666              RDI(level);
667              RD("      }\n");
668              return clean_them;
669           }
670
671         pts[0].px = obj->cur.map->persp.px << FP;
672         pts[0].py = obj->cur.map->persp.py << FP;
673         pts[0].foc = obj->cur.map->persp.foc << FP;
674         pts[0].z0 = obj->cur.map->persp.z0 << FP;
675         
676         p = obj->cur.map->points;
677         p_end = p + 4;
678         pt = pts;
679         for (; p < p_end; p++, pt++)
680           {
681              pt->x = (p->x + off_x) << FP;
682              pt->y = (p->y + off_y) << FP;
683              pt->z = (p->z)         << FP;
684              pt->x3 = p->px << FP;
685              pt->y3 = p->py << FP;
686              pt->u = p->u * FP1;
687              pt->v = p->v * FP1;
688              pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
689           }
690
691         if (obj->cur.map->surface)
692           {
693              if ((obj->cur.map->surface_w != sw) ||
694                  (obj->cur.map->surface_h != sh))
695                {
696                   RDI(level);
697                   RD("        new surf: %ix%i\n", sw, sh);
698                   obj->layer->evas->engine.func->image_map_surface_free
699                     (e->engine.data.output, obj->cur.map->surface);
700                   obj->cur.map->surface = NULL;
701                }
702           }
703         if (!obj->cur.map->surface)
704           {
705              obj->cur.map->surface_w = sw;
706              obj->cur.map->surface_h = sh;
707
708              obj->cur.map->surface =
709                obj->layer->evas->engine.func->image_map_surface_new
710                (e->engine.data.output, obj->cur.map->surface_w,
711                 obj->cur.map->surface_h,
712                 obj->cur.map->alpha);
713              RDI(level);
714              RD("        fisrt surf: %ix%i\n", sw, sh);
715              changed = 1;
716           }
717         if (obj->smart.smart)
718           {
719              Evas_Object *obj2;
720              
721              EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
722                {
723                   if (!evas_object_is_visible(obj2) &&
724                       !evas_object_was_visible(obj2))
725                     {
726                        obj2->changed = 0;
727                        continue;
728                     }
729                   if (obj2->changed)
730                     {
731                        obj2->changed = 0;
732                        changed = 1;
733                        break;
734                     }
735                }
736              obj->changed = 0;
737           }
738         else
739           {
740              if (obj->changed)
741                {
742                   obj->changed = 0;
743                   changed = 1;
744                }
745           }
746
747         // clear surface before re-render
748         if ((changed) && (obj->cur.map->surface))
749           {
750              int off_x2, off_y2;
751              
752              RDI(level);
753              RD("        children redraw\n");
754              // FIXME: calculate "changes" within map surface and only clear
755              // and re-render those
756              if (obj->cur.map->alpha)
757                {
758                   ctx = e->engine.func->context_new(e->engine.data.output);
759                   e->engine.func->context_color_set
760                     (e->engine.data.output, ctx, 0, 0, 0, 0);
761                   e->engine.func->context_render_op_set
762                     (e->engine.data.output, ctx, EVAS_RENDER_COPY);
763                   e->engine.func->rectangle_draw(e->engine.data.output,
764                                                  ctx,
765                                                  obj->cur.map->surface,
766                                                  0, 0,
767                                                  obj->cur.map->surface_w,
768                                                  obj->cur.map->surface_h);
769                   e->engine.func->context_free(e->engine.data.output, ctx);
770                }
771              ctx = e->engine.func->context_new(e->engine.data.output);
772              off_x2 = -obj->cur.geometry.x;
773              off_y2 = -obj->cur.geometry.y;
774              if (obj->smart.smart)
775                {
776                   EINA_INLIST_FOREACH
777                     (evas_object_smart_members_get_direct(obj), obj2)
778                     {
779                        clean_them |= evas_render_mapped(e, obj2, ctx,
780                                                         obj->cur.map->surface,
781                                                         off_x2, off_y2, 1
782 #ifdef REND_DGB
783                                                         , level + 1
784 #endif
785                                                         );
786                     }
787                }
788              else
789                {
790                   int x = 0, y = 0, w = 0, h = 0;
791
792                   w = obj->cur.map->surface_w;
793                   h = obj->cur.map->surface_h;
794                   RECTS_CLIP_TO_RECT(x, y, w, h,
795                                      obj->cur.geometry.x + off_x2,
796                                      obj->cur.geometry.y + off_y2,
797                                      obj->cur.geometry.w,
798                                      obj->cur.geometry.h);
799                   e->engine.func->context_clip_set(e->engine.data.output,
800                                                    ctx, x, y, w, h);
801                   obj->func->render(obj, e->engine.data.output, ctx,
802                                     obj->cur.map->surface, off_x2, off_y2);
803                }
804              e->engine.func->context_free(e->engine.data.output, ctx);
805              rendered = 1;
806           }
807
808         RDI(level);
809         RD("        draw map4\n");
810
811         if (rendered)
812           {
813              obj->cur.map->surface = e->engine.func->image_dirty_region
814                (e->engine.data.output, obj->cur.map->surface,
815                 0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
816           }
817         e->engine.func->context_clip_unset(e->engine.data.output,
818                                            e->engine.data.context);
819         if (obj->cur.map->surface) 
820           {
821              if (obj->smart.smart)
822                {
823                   if (obj->cur.clipper)
824                     {
825                        int x, y, w, h;
826                        Evas_Object *tobj;
827                        
828                        obj->cur.cache.clip.dirty = 1;
829                        tobj = obj->cur.map_parent;
830                        obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
831                        evas_object_clip_recalc(obj);
832                        obj->cur.map_parent = tobj;
833                        x = obj->cur.cache.clip.x;
834                        y = obj->cur.cache.clip.y;
835                        w = obj->cur.cache.clip.w;
836                        h = obj->cur.cache.clip.h;
837                        e->engine.func->context_clip_set(e->engine.data.output,
838                                                         e->engine.data.context,
839                                                         x + off_x, y + off_y, w, h);
840                     }
841                }
842              else
843                {
844                   if (obj->cur.clipper)
845                     {
846                        int x, y, w, h;
847                        
848                        evas_object_clip_recalc(obj);
849                        x = obj->cur.cache.clip.x;
850                        y = obj->cur.cache.clip.y;
851                        w = obj->cur.cache.clip.w;
852                        h = obj->cur.cache.clip.h;
853                        RECTS_CLIP_TO_RECT(x, y, w, h,
854                               obj->cur.clipper->cur.cache.clip.x + off_x,
855                               obj->cur.clipper->cur.cache.clip.y + off_y,
856                               obj->cur.clipper->cur.cache.clip.w,
857                               obj->cur.clipper->cur.cache.clip.h);
858                        e->engine.func->context_clip_set(e->engine.data.output,
859                                                         e->engine.data.context,
860                                                         x + off_x, y + off_y, w, h);
861                     }
862                }
863           }
864         if (obj->cur.cache.clip.visible)
865            obj->layer->evas->engine.func->image_map4_draw
866            (e->engine.data.output, e->engine.data.context, surface,
867             obj->cur.map->surface, pts, obj->cur.map->smooth, 0);
868         // FIXME: needs to cache these maps and
869         // keep them only rendering updates
870 //        obj->layer->evas->engine.func->image_map_surface_free
871 //          (e->engine.data.output, obj->cur.map->surface);
872 //        obj->cur.map->surface = NULL;
873      }
874    else
875      {
876         if (mapped)
877           {
878              RDI(level);
879              RD("        draw child of mapped obj\n");
880              ctx = e->engine.func->context_new(e->engine.data.output);
881              if (obj->smart.smart)
882                {
883                   EINA_INLIST_FOREACH
884                     (evas_object_smart_members_get_direct(obj), obj2)
885                     {
886                        clean_them |= evas_render_mapped(e, obj2, ctx,
887                                                         surface,
888                                                         off_x, off_y, 1
889 #ifdef REND_DGB
890                                                         , level + 1
891 #endif
892                                                         );
893                     }
894                }
895              else
896                {
897                   if (!obj->cur.map)
898                     {
899                        RDI(level);
900                        RD("        clip: %i %i %ix%i [%i %i %ix%i]\n",
901                           obj->cur.cache.clip.x + off_x,
902                           obj->cur.cache.clip.y + off_y, 
903                           obj->cur.cache.clip.w,
904                           obj->cur.cache.clip.h,
905                           obj->cur.geometry.x + off_x,
906                           obj->cur.geometry.y + off_y,
907                           obj->cur.geometry.w,
908                           obj->cur.geometry.h);
909                        e->engine.func->context_clip_set(e->engine.data.output,
910                                                         ctx,
911                                                         obj->cur.cache.clip.x + off_x,
912                                                         obj->cur.cache.clip.y + off_y, 
913                                                         obj->cur.cache.clip.w,
914                                                         obj->cur.cache.clip.h);
915                     }
916                   else
917                     {
918                        RDI(level);
919                        RD("        noclip\n");
920                     }
921                   obj->func->render(obj, e->engine.data.output, ctx,
922                                     surface, off_x, off_y);
923 /*                  
924                   obj->layer->evas->engine.func->context_color_set(e->engine.data.output,
925                                                                    ctx,
926                                                                    0, 30, 0, 30);
927                   obj->layer->evas->engine.func->rectangle_draw(e->engine.data.output,
928                                                                 ctx,
929                                                                 surface,
930                                                                 0, 0, 9999, 9999);
931  */
932                }
933              e->engine.func->context_free(e->engine.data.output, ctx);
934           }
935         else
936           {
937              RDI(level);
938              RD("        draw normal obj\n");
939              obj->func->render(obj, e->engine.data.output, context, surface,
940                                off_x, off_y);
941           }
942      }
943    RDI(level);
944    RD("      }\n");
945
946    return clean_them;
947 }
948
949 static Eina_List *
950 evas_render_updates_internal(Evas *e,
951                              unsigned char make_updates,
952                              unsigned char do_draw)
953 {
954    Eina_List *updates = NULL;
955    Eina_List *ll;
956    void *surface;
957    Eina_Bool clean_them = EINA_FALSE;
958    Eina_Bool alpha;
959    Eina_Rectangle *r;
960    int ux, uy, uw, uh;
961    int cx, cy, cw, ch;
962    unsigned int i, j;
963    int haveup = 0;
964    int redraw_all = 0;
965
966    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
967    return NULL;
968    MAGIC_CHECK_END();
969    if (!e->changed) return NULL;
970
971    evas_call_smarts_calculate(e);
972
973    RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
974
975    /* Check if the modified object mean recalculating every thing */
976    if (!e->invalidate)
977      _evas_render_check_pending_objects(&e->pending_objects, e);
978
979    /* phase 1. add extra updates for changed objects */
980    if (e->invalidate || e->render_objects.count <= 0)
981      clean_them = _evas_render_phase1_process(e, 
982                                               &e->active_objects, 
983                                               &e->restack_objects, 
984                                               &e->delete_objects, 
985                                               &e->render_objects,
986                                               &redraw_all);
987
988    _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
989                               &e->delete_objects, &e->render_objects);
990
991    /* phase 2. force updates for restacks */
992    for (i = 0; i < e->restack_objects.count; ++i)
993      {
994         Evas_Object *obj;
995
996         obj = eina_array_data_get(&e->restack_objects, i);
997         obj->func->render_pre(obj);
998         _evas_render_prev_cur_clip_cache_add(e, obj);
999      }
1000    eina_array_clean(&e->restack_objects);
1001    /* phase 3. add exposes */
1002    EINA_LIST_FREE(e->damages, r)
1003      {
1004         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1005                                                 r->x, r->y, r->w, r->h);
1006         eina_rectangle_free(r);
1007      }
1008    /* phase 4. output & viewport changes */
1009    if (e->viewport.changed)
1010      {
1011         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1012                                                 0, 0,
1013                                                 e->output.w, e->output.h);
1014      }
1015    if (e->output.changed)
1016      {
1017         e->engine.func->output_resize(e->engine.data.output,
1018                                       e->output.w, e->output.h);
1019         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1020                                                 0, 0,
1021                                                 e->output.w, e->output.h);
1022      }
1023    if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1024      {
1025         ERR("viewport size != output size!");
1026      }
1027    if (redraw_all)
1028      {
1029         e->engine.func->output_redraws_rect_add(e->engine.data.output,
1030                                                 0, 0, 
1031                                                 e->output.w, e->output.h);
1032      }
1033    /* phase 5. add obscures */
1034    EINA_LIST_FOREACH(e->obscures, ll, r)
1035      {
1036         e->engine.func->output_redraws_rect_del(e->engine.data.output,
1037                                                r->x, r->y, r->w, r->h);
1038      }
1039    /* build obscure objects list of active objects that obscure */
1040    for (i = 0; i < e->active_objects.count; ++i)
1041      {
1042         Evas_Object *obj;
1043
1044         obj = eina_array_data_get(&e->active_objects, i);
1045         if (UNLIKELY((evas_object_is_opaque(obj) ||
1046                       ((obj->func->has_opaque_rect) &&
1047                        (obj->func->has_opaque_rect(obj)))) &&
1048                      evas_object_is_visible(obj) &&
1049                      (!obj->clip.clipees) &&
1050                      (obj->cur.visible) &&
1051                      (!obj->delete_me) &&
1052                      (obj->cur.cache.clip.visible) &&
1053                      (!obj->smart.smart)))
1054 /*        obscuring_objects = eina_list_append(obscuring_objects, obj); */
1055           eina_array_push(&e->obscuring_objects, obj);
1056      }
1057    /* save this list */
1058 /*    obscuring_objects_orig = obscuring_objects; */
1059 /*    obscuring_objects = NULL; */
1060    /* phase 6. go thru each update rect and render objects in it*/
1061    if (do_draw)
1062      {
1063         unsigned int offset = 0;
1064
1065         alpha = e->engine.func->canvas_alpha_get(e->engine.data.output, 
1066                                                  e->engine.data.context);
1067
1068         while ((surface =
1069                 e->engine.func->output_redraws_next_update_get
1070                 (e->engine.data.output,
1071                     &ux, &uy, &uw, &uh,
1072                     &cx, &cy, &cw, &ch)))
1073           {
1074              int off_x, off_y;
1075
1076              RD("  [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1077              if (make_updates)
1078                {
1079                   Eina_Rectangle *rect;
1080
1081                   NEW_RECT(rect, ux, uy, uw, uh);
1082                   if (rect)
1083                     updates = eina_list_append(updates, rect);
1084                }
1085              haveup = 1;
1086              off_x = cx - ux;
1087              off_y = cy - uy;
1088              /* build obscuring objects list (in order from bottom to top) */
1089              for (i = 0; i < e->obscuring_objects.count; ++i)
1090                {
1091                   Evas_Object *obj;
1092
1093                   obj = (Evas_Object *)eina_array_data_get
1094                      (&e->obscuring_objects, i);
1095                   if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1096                     {
1097                        eina_array_push(&e->temporary_objects, obj);
1098                        
1099                        /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1100                        if (alpha)
1101                          {
1102                             if (evas_object_is_opaque(obj))
1103                                e->engine.func->context_cutout_add
1104                                (e->engine.data.output,
1105                                    e->engine.data.context,
1106                                    obj->cur.cache.clip.x + off_x,
1107                                    obj->cur.cache.clip.y + off_y,
1108                                    obj->cur.cache.clip.w,
1109                                    obj->cur.cache.clip.h);
1110                             else
1111                               {
1112                                  if (obj->func->get_opaque_rect)
1113                                    {
1114                                       Evas_Coord obx, oby, obw, obh;
1115
1116                                       obj->func->get_opaque_rect
1117                                          (obj, &obx, &oby, &obw, &obh);
1118                                       if ((obw > 0) && (obh > 0))
1119                                         {
1120                                            obx += off_x;
1121                                            oby += off_y;
1122                                            RECTS_CLIP_TO_RECT
1123                                               (obx, oby, obw, obh,
1124                                                   obj->cur.cache.clip.x + off_x,
1125                                                   obj->cur.cache.clip.y + off_y,
1126                                                   obj->cur.cache.clip.w,
1127                                                   obj->cur.cache.clip.h);
1128                                            e->engine.func->context_cutout_add
1129                                               (e->engine.data.output,
1130                                                   e->engine.data.context,
1131                                                   obx, oby,
1132                                                   obw, obh);
1133                                         }
1134                                    }
1135                               }
1136                          }
1137                     }
1138                }
1139              if (alpha)
1140                {
1141                   e->engine.func->context_clip_set(e->engine.data.output,
1142                                                    e->engine.data.context,
1143                                                    ux, uy, uw, uh);
1144                   e->engine.func->context_color_set(e->engine.data.output, 
1145                                                     e->engine.data.context, 
1146                                                     0, 0, 0, 0);
1147                   e->engine.func->context_multiplier_unset
1148                      (e->engine.data.output, e->engine.data.context);
1149                   e->engine.func->context_render_op_set(e->engine.data.output, 
1150                                                         e->engine.data.context,
1151                                                         EVAS_RENDER_COPY);
1152                   e->engine.func->rectangle_draw(e->engine.data.output,
1153                                                  e->engine.data.context,
1154                                                  surface,
1155                                                  cx, cy, cw, ch);
1156                   e->engine.func->context_cutout_clear(e->engine.data.output,
1157                                                        e->engine.data.context);
1158                   e->engine.func->context_clip_unset(e->engine.data.output,
1159                                                      e->engine.data.context);
1160                }
1161              /* render all object that intersect with rect */
1162              for (i = 0; i < e->active_objects.count; ++i)
1163                {
1164                   Evas_Object *obj;
1165
1166                   obj = eina_array_data_get(&e->active_objects, i);
1167
1168                   /* if it's in our outpout rect and it doesn't clip anything */
1169                   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);
1170                   if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1171                        (obj->smart.smart)) &&
1172                       (!obj->clip.clipees) &&
1173                       (obj->cur.visible) &&
1174                       (!obj->delete_me) &&
1175                       (obj->cur.cache.clip.visible) &&
1176 //                    (!obj->smart.smart) &&
1177                       ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1178                     {
1179                        int x, y, w, h;
1180
1181                        RD("      DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1182                        if ((e->temporary_objects.count > offset) &&
1183                            (eina_array_data_get(&e->temporary_objects, offset) == obj))
1184                          offset++;
1185                        x = cx; y = cy; w = cw; h = ch;
1186                        if (obj->cur.clipper)
1187                          {
1188                             if (_evas_render_has_map(obj))
1189                               {
1190                                  evas_object_clip_recalc(obj);
1191                               }
1192 /* hmmmm clip seems to kill eweather in elm-test
1193                             printf("clip: %4i %4i %4ix%4i to %4i %4i %4ix%4i\n",
1194                                    x, y, w, h,
1195                                    obj->cur.cache.clip.x + off_x,
1196                                    obj->cur.cache.clip.y + off_y,
1197                                    obj->cur.cache.clip.w,
1198                                    obj->cur.cache.clip.h);
1199  */
1200                             RECTS_CLIP_TO_RECT(x, y, w, h,
1201                                                obj->cur.cache.clip.x + off_x,
1202                                                obj->cur.cache.clip.y + off_y,
1203                                                obj->cur.cache.clip.w,
1204                                                obj->cur.cache.clip.h);
1205                          }
1206                        if (((w > 0) && (h > 0)) || (obj->smart.smart))
1207                          {
1208                             if (!obj->smart.smart)
1209                               {
1210                                  RECTS_CLIP_TO_RECT(x, y, w, h,
1211                                                     obj->cur.cache.clip.x + off_x,
1212                                                     obj->cur.cache.clip.y + off_y,
1213                                                     obj->cur.cache.clip.w,
1214                                                     obj->cur.cache.clip.h);
1215                               }
1216                             if (obj->cur.clipper)
1217                                e->engine.func->context_clip_set(e->engine.data.output,
1218                                                                 e->engine.data.context,
1219                                                                 x, y, w, h);
1220                             else
1221                                e->engine.func->context_clip_unset(e->engine.data.output,
1222                                                                   e->engine.data.context);
1223 #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1224                             for (j = offset; j < e->temporary_objects.count; ++j)
1225                               {
1226                                  Evas_Object *obj2;
1227
1228                                  obj2 = (Evas_Object *) eina_array_data_get(&e->temporary_objects, j);
1229                                  if (evas_object_is_opaque(obj2))
1230                                    e->engine.func->context_cutout_add(e->engine.data.output,
1231                                                                       e->engine.data.context,
1232                                                                       obj2->cur.cache.clip.x + off_x,
1233                                                                       obj2->cur.cache.clip.y + off_y,
1234                                                                       obj2->cur.cache.clip.w,
1235                                                                       obj2->cur.cache.clip.h);
1236                                  else
1237                                    {
1238                                       if (obj2->func->get_opaque_rect)
1239                                         {
1240                                            Evas_Coord obx, oby, obw, obh;
1241
1242                                            obj2->func->get_opaque_rect
1243                                              (obj2, &obx, &oby, &obw, &obh);
1244                                            if ((obw > 0) && (obh > 0))
1245                                              {
1246                                                 obx += off_x;
1247                                                 oby += off_y;
1248                                                 RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1249                                                                    obj2->cur.cache.clip.x + off_x,
1250                                                                    obj2->cur.cache.clip.y + off_y,
1251                                                                    obj2->cur.cache.clip.w,
1252                                                                    obj2->cur.cache.clip.h);
1253                                                 e->engine.func->context_cutout_add(e->engine.data.output,
1254                                                                                    e->engine.data.context,
1255                                                                                    obx, oby,
1256                                                                                    obw, obh);
1257                                              }
1258                                         }
1259                                    }
1260                               }
1261 #endif
1262                             e->engine.func->context_clip_set(e->engine.data.output,
1263                                                              e->engine.data.context,
1264                                                              x, y, w, h);
1265                             clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1266                                                              surface, off_x, off_y, 0
1267 #ifdef REND_DGB
1268                                                              , 1
1269 #endif
1270                                                              );
1271                             e->engine.func->context_cutout_clear(e->engine.data.output,
1272                                                                  e->engine.data.context);
1273                          }
1274                     }
1275                }
1276              /* punch rect out */
1277              e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1278                                                              surface,
1279                                                              ux, uy, uw, uh);
1280              /* free obscuring objects list */
1281              eina_array_clean(&e->temporary_objects);
1282              RD("  ---]\n");
1283           }
1284         /* flush redraws */
1285         if (haveup)
1286           {
1287              evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1288              e->engine.func->output_flush(e->engine.data.output);
1289              evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1290           }
1291      }
1292    /* clear redraws */
1293    e->engine.func->output_redraws_clear(e->engine.data.output);
1294    /* and do a post render pass */
1295    for (i = 0; i < e->active_objects.count; ++i)
1296      {
1297         Evas_Object *obj;
1298
1299         obj = eina_array_data_get(&e->active_objects, i);
1300         obj->pre_render_done = 0;
1301         RD("    OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1302         if ((obj->changed) && (do_draw))
1303           {
1304              RD("    OBJ [%p] post... func1\n", obj);
1305              obj->func->render_post(obj);
1306              obj->restack = 0;
1307              obj->changed = 0;
1308           }
1309         else if ((obj->cur.map != obj->prev.map) ||
1310                  (obj->cur.usemap != obj->prev.usemap))
1311           {
1312              RD("    OBJ [%p] post... func2\n", obj);
1313              obj->func->render_post(obj);
1314              obj->restack = 0;
1315              obj->changed = 0;
1316           }
1317 /* moved to other pre-process phase 1
1318         if (obj->delete_me == 2)
1319           {
1320              delete_objects = eina_list_append(delete_objects, obj);
1321           }
1322         else if (obj->delete_me != 0) obj->delete_me++;
1323  */
1324      }
1325    /* free our obscuring object list */
1326    eina_array_clean(&e->obscuring_objects);
1327
1328    /* If some object are still marked as changed, do not remove
1329       them from the pending list. */
1330    eina_array_remove(&e->pending_objects, pending_change, NULL);
1331
1332    /* delete all objects flagged for deletion now */
1333    for (i = 0; i < e->delete_objects.count; ++i)
1334      {
1335         Evas_Object *obj;
1336
1337         obj = eina_array_data_get(&e->delete_objects, i);
1338         evas_object_free(obj, 1);
1339      }
1340    eina_array_clean(&e->delete_objects);
1341
1342    e->changed = 0;
1343    e->viewport.changed = 0;
1344    e->output.changed = 0;
1345    e->invalidate = 0;
1346
1347    for (i = 0; i < e->render_objects.count; ++i)
1348      {
1349         Evas_Object *obj;
1350
1351         obj = eina_array_data_get(&e->render_objects, i);
1352         obj->pre_render_done = 0;
1353      }
1354
1355    /* If their are some object to restack or some object to delete,
1356     * it's useless to keep the render object list around. */
1357    if (clean_them)
1358      {
1359         eina_array_clean(&e->active_objects);
1360         eina_array_clean(&e->render_objects);
1361         eina_array_clean(&e->restack_objects);
1362         eina_array_clean(&e->delete_objects);
1363         eina_array_clean(&e->obscuring_objects);
1364         e->invalidate = 1;
1365      }
1366
1367    evas_module_clean();
1368
1369    RD("---]\n");
1370
1371    return updates;
1372 }
1373
1374 /**
1375  * Free the rectangles returned by evas_render_updates().
1376  *
1377  * @param updates The list of updated rectangles of the canvas.
1378  *
1379  * This function removes the region from the render updates list. It
1380  * makes the region doesn't be render updated anymore.
1381  *
1382  * @ingroup Evas_Canvas
1383  */
1384 EAPI void
1385 evas_render_updates_free(Eina_List *updates)
1386 {
1387    Eina_Rectangle *r;
1388
1389    EINA_LIST_FREE(updates, r)
1390      eina_rectangle_free(r);
1391 }
1392
1393 /**
1394  * Force immediate renderization of the given canvas.
1395  *
1396  * @param e The given canvas pointer.
1397  * @return A newly allocated list of updated rectangles of the canvas.
1398  *         Free this list with evas_render_updates_free().
1399  *
1400  * This function forces an immediate renderization update of the given
1401  * given canvas.
1402  *
1403  * @ingroup Evas_Canvas
1404  */
1405 EAPI Eina_List *
1406 evas_render_updates(Evas *e)
1407 {
1408    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1409    return NULL;
1410    MAGIC_CHECK_END();
1411
1412 #ifdef EVAS_FRAME_QUEUING
1413    evas_common_frameq_flush_ready ();
1414 #endif
1415
1416    if (!e->changed) return NULL;
1417    return evas_render_updates_internal(e, 1, 1);
1418 }
1419
1420 /**
1421  * Force renderization of the given canvas.
1422  *
1423  * @param e The given canvas pointer.
1424  *
1425  * @ingroup Evas_Canvas
1426  */
1427 EAPI void
1428 evas_render(Evas *e)
1429 {
1430    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1431    return;
1432    MAGIC_CHECK_END();
1433
1434 #ifdef EVAS_FRAME_QUEUING
1435    evas_common_frameq_flush_ready ();
1436 #endif
1437
1438    if (!e->changed) return;
1439    evas_render_updates_internal(e, 0, 1);
1440 }
1441
1442 /**
1443  * Update the canvas internal objects but not triggering immediate
1444  * renderization.
1445  *
1446  * @param e The given canvas pointer.
1447  *
1448  * This function updates the canvas internal objects not triggering
1449  * renderization. To force renderization function evas_render() should
1450  * be used.
1451  *
1452  * @see evas_render.
1453  *
1454  * @ingroup Evas_Canvas
1455  */
1456 EAPI void
1457 evas_norender(Evas *e)
1458 {
1459    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1460    return;
1461    MAGIC_CHECK_END();
1462
1463 //   if (!e->changed) return;
1464    evas_render_updates_internal(e, 0, 0);
1465 }
1466
1467 /**
1468  * Make the canvas discard internally cached data used for rendering.
1469  *
1470  * @param e The given canvas pointer.
1471  *
1472  * This function flushes the arrays of delete, active and render objects.
1473  * Other things it may also discard are: shared memory segments,
1474  * temporary scratch buffers, cached data to avoid re-compute of that data etc.
1475  *
1476  * @ingroup Evas_Canvas
1477  */
1478 EAPI void
1479 evas_render_idle_flush(Evas *e)
1480 {
1481    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1482    return;
1483    MAGIC_CHECK_END();
1484
1485    evas_fonts_zero_presure(e);
1486
1487    if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1488        (e->engine.data.output))
1489      e->engine.func->output_idle_flush(e->engine.data.output);
1490
1491    eina_array_flush(&e->delete_objects);
1492    eina_array_flush(&e->active_objects);
1493    eina_array_flush(&e->restack_objects);
1494    eina_array_flush(&e->render_objects);
1495    eina_array_flush(&e->clip_changes);
1496
1497    e->invalidate = 1;
1498 }
1499
1500 EAPI void
1501 evas_sync(Evas *e)
1502 {
1503 #ifdef EVAS_FRAME_QUEUING
1504    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1505    return;
1506    MAGIC_CHECK_END();
1507
1508    evas_common_frameq_flush ();
1509 #else
1510    (void) e;
1511 #endif
1512 }
1513
1514 /**
1515  * Make the canvas discard as much data as possible used by the engine at
1516  * runtime.
1517  *
1518  * @param e The given canvas pointer.
1519  *
1520  * This function will unload images, delete textures and much more, where
1521  * possible. You may also want to call evas_render_idle_flush() immediately
1522  * prior to this to perhaps discard a little more, though evas_render_dump()
1523  * should implicitly delete most of what evas_render_idle_flush() might
1524  * discard too.
1525  *
1526  * @ingroup Evas_Canvas
1527  */
1528 static void
1529 _evas_render_dump_map_surfaces(Evas_Object *obj)
1530 {
1531    if ((obj->cur.map) && obj->cur.map->surface)
1532      {
1533         obj->layer->evas->engine.func->image_map_surface_free
1534           (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1535         obj->cur.map->surface = NULL;
1536      }
1537
1538    if (obj->smart.smart)
1539      {
1540         Evas_Object *obj2;
1541
1542         EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1543           _evas_render_dump_map_surfaces(obj2);
1544      }
1545 }
1546
1547 EAPI void
1548 evas_render_dump(Evas *e)
1549 {
1550    Evas_Layer *lay;
1551
1552    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1553    return;
1554    MAGIC_CHECK_END();
1555
1556    EINA_INLIST_FOREACH(e->layers, lay)
1557      {
1558         Evas_Object *obj;
1559
1560         EINA_INLIST_FOREACH(lay->objects, obj)
1561           _evas_render_dump_map_surfaces(obj);
1562      }
1563    if ((e->engine.func) && (e->engine.func->output_dump) &&
1564        (e->engine.data.output))
1565      e->engine.func->output_dump(e->engine.data.output);
1566 }
1567
1568 void
1569 evas_render_invalidate(Evas *e)
1570 {
1571    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1572    return;
1573    MAGIC_CHECK_END();
1574
1575    eina_array_clean(&e->active_objects);
1576    eina_array_clean(&e->render_objects);
1577
1578    eina_array_flush(&e->restack_objects);
1579    eina_array_flush(&e->delete_objects);
1580
1581    e->invalidate = 1;
1582 }
1583
1584 void
1585 evas_render_object_recalc(Evas_Object *obj)
1586 {
1587    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1588    return;
1589    MAGIC_CHECK_END();
1590
1591 #ifndef EVAS_FRAME_QUEUING
1592    if ((!obj->changed) && (obj->delete_me < 2))
1593 #else
1594    if ((!obj->changed))
1595 #endif
1596      {
1597         Evas *e;
1598
1599         e = obj->layer->evas;
1600         if ((!e) || (e->cleanup)) return;
1601 #ifdef EVAS_FRAME_QUEUING
1602         if (obj->delete_me >= evas_common_frameq_get_frameq_sz() + 2) return;
1603 #endif
1604         eina_array_push(&e->pending_objects, obj);
1605         obj->changed = 1;
1606      }
1607 }