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