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