summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-12-19 22:49:16 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-12-19 22:49:43 +0900
commiteed4526003ad63c2a0bb8b9d574cdcd35c680a06 (patch)
tree6ac9f9f84fa35d65f9d9ce4fa43f6a78945599cc /src
parent8937708e4363b16c8b26f9a8d7526d162ac94547 (diff)
first steps to rewriting evas render... a long path.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Evas.am1
-rw-r--r--src/lib/evas/canvas/evas_render.c212
-rw-r--r--src/lib/evas/canvas/evas_render2.c374
3 files changed, 517 insertions, 70 deletions
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index bb80008340..41372e6e9e 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -75,6 +75,7 @@ lib/evas/canvas/evas_object_grid.c \
75lib/evas/canvas/evas_font_dir.c \ 75lib/evas/canvas/evas_font_dir.c \
76lib/evas/canvas/evas_rectangle.c \ 76lib/evas/canvas/evas_rectangle.c \
77lib/evas/canvas/evas_render.c \ 77lib/evas/canvas/evas_render.c \
78lib/evas/canvas/evas_render2.c \
78lib/evas/canvas/evas_smart.c \ 79lib/evas/canvas/evas_smart.c \
79lib/evas/canvas/evas_stack.c \ 80lib/evas/canvas/evas_stack.c \
80lib/evas/canvas/evas_async_events.c \ 81lib/evas/canvas/evas_async_events.c \
diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c
index d33cd42421..7d3491a444 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -10,6 +10,17 @@
10#include <sys/time.h> 10#include <sys/time.h>
11#endif 11#endif
12 12
13Eina_Bool
14_evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
15 Eina_Bool do_draw, Eina_Bool do_async);
16void
17_evas_render2_idle_flush(Eo *eo_e);
18void
19_evas_render2_dump(Eo *eo_e);
20void
21_evas_render2_wait(Eo *eo_e);
22
23
13/* debug rendering 24/* debug rendering
14 * NOTE: Define REND_DBG 1 in evas_private.h to enable debugging. Don't define 25 * NOTE: Define REND_DBG 1 in evas_private.h to enable debugging. Don't define
15 * it here since the flag is used on other places too. */ 26 * it here since the flag is used on other places too. */
@@ -2279,9 +2290,18 @@ _canvas_render_async(Eo *eo_e, void *_pd, va_list *list)
2279{ 2290{
2280 Eina_Bool *ret = va_arg(*list, Eina_Bool *); 2291 Eina_Bool *ret = va_arg(*list, Eina_Bool *);
2281 Evas_Public_Data *e = _pd; 2292 Evas_Public_Data *e = _pd;
2293 static int render_2 = -1;
2282 2294
2283 *ret = evas_render_updates_internal(eo_e, 1, 1, evas_render_pipe_wakeup, 2295 if (render_2 == -1)
2284 e, EINA_TRUE); 2296 {
2297 if (getenv("EVAS_RENDER2")) render_2 = 1;
2298 else render_2 = 0;
2299 }
2300 if (render_2)
2301 *ret = _evas_render2_begin(eo_e, EINA_TRUE, EINA_TRUE, EINA_TRUE);
2302 else
2303 *ret = evas_render_updates_internal(eo_e, 1, 1, evas_render_pipe_wakeup,
2304 e, EINA_TRUE);
2285} 2305}
2286 2306
2287EAPI Eina_List * 2307EAPI Eina_List *
@@ -2302,10 +2322,24 @@ evas_render_updates_internal_wait(Evas *eo_e,
2302{ 2322{
2303 Eina_List *ret = NULL; 2323 Eina_List *ret = NULL;
2304 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS); 2324 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
2325 static int render_2 = -1;
2305 2326
2306 if (!evas_render_updates_internal(eo_e, make_updates, do_draw, NULL, 2327 if (render_2 == -1)
2307 NULL, EINA_FALSE)) 2328 {
2308 return NULL; 2329 if (getenv("EVAS_RENDER2")) render_2 = 1;
2330 else render_2 = 0;
2331 }
2332 if (render_2)
2333 {
2334 if (!_evas_render2_begin(eo_e, make_updates, do_draw, EINA_FALSE))
2335 return NULL;
2336 }
2337 else
2338 {
2339 if (!evas_render_updates_internal(eo_e, make_updates, do_draw, NULL,
2340 NULL, EINA_FALSE))
2341 return NULL;
2342 }
2309 2343
2310 ret = e->render.updates; 2344 ret = e->render.updates;
2311 e->render.updates = NULL; 2345 e->render.updates = NULL;
@@ -2374,26 +2408,40 @@ evas_render_idle_flush(Evas *eo_e)
2374void 2408void
2375_canvas_render_idle_flush(Eo *eo_e, void *_pd, va_list *list EINA_UNUSED) 2409_canvas_render_idle_flush(Eo *eo_e, void *_pd, va_list *list EINA_UNUSED)
2376{ 2410{
2377 Evas_Public_Data *e = _pd; 2411 static int render_2 = -1;
2378
2379 evas_render_rendering_wait(e);
2380
2381 evas_fonts_zero_pressure(eo_e);
2382
2383 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
2384 (e->engine.data.output))
2385 e->engine.func->output_idle_flush(e->engine.data.output);
2386 2412
2387 OBJS_ARRAY_FLUSH(&e->active_objects); 2413 if (render_2 == -1)
2388 OBJS_ARRAY_FLUSH(&e->render_objects); 2414 {
2389 OBJS_ARRAY_FLUSH(&e->restack_objects); 2415 if (getenv("EVAS_RENDER2")) render_2 = 1;
2390 OBJS_ARRAY_FLUSH(&e->delete_objects); 2416 else render_2 = 0;
2391 OBJS_ARRAY_FLUSH(&e->obscuring_objects); 2417 }
2392 OBJS_ARRAY_FLUSH(&e->temporary_objects); 2418 if (render_2)
2393 eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL); 2419 {
2394 eina_array_clean(&e->clip_changes); 2420 _evas_render2_idle_flush(eo_e);
2395 2421 }
2396 e->invalidate = EINA_TRUE; 2422 else
2423 {
2424 Evas_Public_Data *e = _pd;
2425
2426 evas_render_rendering_wait(e);
2427
2428 evas_fonts_zero_pressure(eo_e);
2429
2430 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
2431 (e->engine.data.output))
2432 e->engine.func->output_idle_flush(e->engine.data.output);
2433
2434 OBJS_ARRAY_FLUSH(&e->active_objects);
2435 OBJS_ARRAY_FLUSH(&e->render_objects);
2436 OBJS_ARRAY_FLUSH(&e->restack_objects);
2437 OBJS_ARRAY_FLUSH(&e->delete_objects);
2438 OBJS_ARRAY_FLUSH(&e->obscuring_objects);
2439 OBJS_ARRAY_FLUSH(&e->temporary_objects);
2440 eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL);
2441 eina_array_clean(&e->clip_changes);
2442
2443 e->invalidate = EINA_TRUE;
2444 }
2397} 2445}
2398 2446
2399EAPI void 2447EAPI void
@@ -2406,7 +2454,17 @@ void
2406_canvas_sync(Eo *eo_e, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED) 2454_canvas_sync(Eo *eo_e, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
2407{ 2455{
2408 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS); 2456 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
2409 evas_render_rendering_wait(e); 2457 static int render_2 = -1;
2458
2459 if (render_2 == -1)
2460 {
2461 if (getenv("EVAS_RENDER2")) render_2 = 1;
2462 else render_2 = 0;
2463 }
2464 if (render_2)
2465 _evas_render2_wait(eo_e);
2466 else
2467 evas_render_rendering_wait(e);
2410} 2468}
2411 2469
2412void 2470void
@@ -2444,66 +2502,80 @@ void
2444_canvas_render_dump(Eo *eo_e EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED) 2502_canvas_render_dump(Eo *eo_e EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
2445{ 2503{
2446 Evas_Public_Data *e = _pd; 2504 Evas_Public_Data *e = _pd;
2447 Evas_Layer *lay; 2505 static int render_2 = -1;
2448 2506
2449 evas_all_sync(); 2507 if (render_2 == -1)
2450 evas_cache_async_freeze();
2451
2452 EINA_INLIST_FOREACH(e->layers, lay)
2453 { 2508 {
2454 Evas_Object_Protected_Data *obj; 2509 if (getenv("EVAS_RENDER2")) render_2 = 1;
2455 2510 else render_2 = 0;
2456 EINA_INLIST_FOREACH(lay->objects, obj) 2511 }
2512 if (render_2)
2513 {
2514 _evas_render2_dump(eo_e);
2515 }
2516 else
2517 {
2518 Evas_Layer *lay;
2519
2520 evas_all_sync();
2521 evas_cache_async_freeze();
2522
2523 EINA_INLIST_FOREACH(e->layers, lay)
2457 { 2524 {
2458 if (obj->proxy) 2525 Evas_Object_Protected_Data *obj;
2526
2527 EINA_INLIST_FOREACH(lay->objects, obj)
2459 { 2528 {
2460 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write) 2529 if (obj->proxy)
2461 { 2530 {
2462 if (proxy_write->surface) 2531 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
2463 { 2532 {
2464 e->engine.func->image_map_surface_free(e->engine.data.output, 2533 if (proxy_write->surface)
2465 proxy_write->surface); 2534 {
2466 proxy_write->surface = NULL; 2535 e->engine.func->image_map_surface_free(e->engine.data.output,
2536 proxy_write->surface);
2537 proxy_write->surface = NULL;
2538 }
2467 } 2539 }
2540 EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write);
2468 } 2541 }
2469 EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write); 2542 if ((obj->type) && (!strcmp(obj->type, "image")))
2543 evas_object_inform_call_image_unloaded(obj->object);
2544 _evas_render_dump_map_surfaces(obj->object);
2470 } 2545 }
2471 if ((obj->type) && (!strcmp(obj->type, "image")))
2472 evas_object_inform_call_image_unloaded(obj->object);
2473 _evas_render_dump_map_surfaces(obj->object);
2474 } 2546 }
2475 } 2547 if ((e->engine.func) && (e->engine.func->output_dump) &&
2476 if ((e->engine.func) && (e->engine.func->output_dump) && 2548 (e->engine.data.output))
2477 (e->engine.data.output)) 2549 e->engine.func->output_dump(e->engine.data.output);
2478 e->engine.func->output_dump(e->engine.data.output);
2479 2550
2480#define GC_ALL(Cow) \ 2551#define GC_ALL(Cow) \
2481 while (eina_cow_gc(Cow)) 2552 while (eina_cow_gc(Cow))
2482 2553
2483 GC_ALL(evas_object_proxy_cow); 2554 GC_ALL(evas_object_proxy_cow);
2484 GC_ALL(evas_object_map_cow); 2555 GC_ALL(evas_object_map_cow);
2485 GC_ALL(evas_object_image_pixels_cow); 2556 GC_ALL(evas_object_image_pixels_cow);
2486 GC_ALL(evas_object_image_load_opts_cow); 2557 GC_ALL(evas_object_image_load_opts_cow);
2487 GC_ALL(evas_object_image_state_cow); 2558 GC_ALL(evas_object_image_state_cow);
2488 2559
2489 evas_fonts_zero_pressure(eo_e); 2560 evas_fonts_zero_pressure(eo_e);
2490 2561
2491 if ((e->engine.func) && (e->engine.func->output_idle_flush) && 2562 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
2492 (e->engine.data.output)) 2563 (e->engine.data.output))
2493 e->engine.func->output_idle_flush(e->engine.data.output); 2564 e->engine.func->output_idle_flush(e->engine.data.output);
2494 2565
2495 OBJS_ARRAY_FLUSH(&e->active_objects); 2566 OBJS_ARRAY_FLUSH(&e->active_objects);
2496 OBJS_ARRAY_FLUSH(&e->render_objects); 2567 OBJS_ARRAY_FLUSH(&e->render_objects);
2497 OBJS_ARRAY_FLUSH(&e->restack_objects); 2568 OBJS_ARRAY_FLUSH(&e->restack_objects);
2498 OBJS_ARRAY_FLUSH(&e->delete_objects); 2569 OBJS_ARRAY_FLUSH(&e->delete_objects);
2499 OBJS_ARRAY_FLUSH(&e->obscuring_objects); 2570 OBJS_ARRAY_FLUSH(&e->obscuring_objects);
2500 OBJS_ARRAY_FLUSH(&e->temporary_objects); 2571 OBJS_ARRAY_FLUSH(&e->temporary_objects);
2501 eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL); 2572 eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL);
2502 eina_array_clean(&e->clip_changes); 2573 eina_array_clean(&e->clip_changes);
2503 2574
2504 e->invalidate = EINA_TRUE; 2575 e->invalidate = EINA_TRUE;
2505 2576
2506 evas_cache_async_thaw(); 2577 evas_cache_async_thaw();
2578 }
2507} 2579}
2508 2580
2509void 2581void
diff --git a/src/lib/evas/canvas/evas_render2.c b/src/lib/evas/canvas/evas_render2.c
new file mode 100644
index 0000000000..1e56ccc803
--- /dev/null
+++ b/src/lib/evas/canvas/evas_render2.c
@@ -0,0 +1,374 @@
1#include "evas_common_private.h"
2#include "evas_private.h"
3#include <math.h>
4#include <assert.h>
5#ifdef EVAS_CSERVE2
6#include "evas_cs2_private.h"
7#endif
8
9#ifdef EVAS_RENDER_DEBUG_TIMING
10#include <sys/time.h>
11#endif
12
13//////////////////////////////////////////////////////////////////////////////
14// this is the start of a rewrite of the evas rendering infra. first port of
15// call is to just make it work and still support async rendering with no
16// optimizations at all. once it WORKS properly start adding back
17// optimizations one at a time very carefully until it is equivalent to where
18// evas render was before, THEN... we can consider switching it on by default
19// but until then it's off unless you set:
20//
21// export EVAS_RENDER2=1
22//
23// at runtime.
24//////////////////////////////////////////////////////////////////////////////
25
26// data types
27//////////////////////////////////////////////////////////////////////////////
28typedef struct Update Update;
29
30struct _Update
31{
32 Eina_Rectangle area;
33 void *surface;
34};
35
36// funcs
37//////////////////////////////////////////////////////////////////////////////
38Eina_Bool _evas_render2_begin(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_draw, Eina_Bool do_async);
39void _evas_render2_idle_flush(Eo *eo_e);
40void _evas_render2_dump(Eo *eo_e);
41void _evas_render2_wait(Eo *eo_e);
42
43static void _evas_render2_end(Eo *eo_e);
44
45static void _evas_render2_cow_gc(Eina_Cow *cow, int max);
46static void _evas_render2_cow_all_gc(int max);
47static void _evas_render2_all_sync(void);
48static void _evas_render2_wakeup_cb(void *target, Evas_Callback_Type type, void *event_info);
49static void _evas_render2_wakeup_send(void *data);
50static void _evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info);
51
52// global data (for rendering only)
53//////////////////////////////////////////////////////////////////////////////
54static Eina_List *_rendering = NULL;
55
56//////////////////////////////////////////////////////////////////////////////
57
58///////////////////////////////////////////////////////////////////////
59// BEGIN RENDERING (in mainloop)
60///////////////////////////////////////////////////////////////////////
61Eina_Bool
62_evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
63 Eina_Bool do_draw, Eina_Bool do_async)
64{
65 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
66 Eina_Rectangle *r;
67 Eina_List *l;
68
69 // if nothing changed at all since last render - skip this frame
70 if (!e->changed) return EINA_FALSE;
71 // we are still rendering while being asked to render - skip this frame
72 if (e->rendering && do_async) return EINA_FALSE;
73 // check viewport size is same as output - not allowed to differ
74 if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
75 ERR("viewport size != output size!");
76
77 // call canvas callbacks saying we are in the pre-render state
78 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_PRE, NULL);
79 // we have to calculate smare objects before render so do that here
80 evas_call_smarts_calculate(eo_e);
81
82 // if the output size changed, add a full redraw
83 if ((e->output.changed) || (e->framespace.changed))
84 {
85 e->engine.func->output_resize(e->engine.data.output,
86 e->output.w, e->output.h);
87 e->engine.func->output_redraws_rect_add(e->engine.data.output, 0, 0,
88 e->output.w, e->output.h);
89 }
90 // if there are explicit update regions - add them
91 EINA_LIST_FREE(e->damages, r)
92 {
93 // if we didnt just do a full redraw if output changed
94 if ((!e->output.changed) && (!e->framespace.changed))
95 e->engine.func->output_redraws_rect_add(e->engine.data.output,
96 r->x, r->y, r->w, r->h);
97 eina_rectangle_free(r);
98 }
99 // remove obscures from rendering - we keep them around
100 EINA_LIST_FOREACH(e->obscures, l, r)
101 e->engine.func->output_redraws_rect_del(e->engine.data.output,
102 r->x, r->y, r->w, r->h);
103
104 // we are actually asked to draw not just go through the motions for gc
105 if (do_draw)
106 {
107 // XXX:
108 // XXX: process all objects figuring out update regions
109 // XXX:
110
111 // XXX:
112 // XXX: RENDER HERE!
113 if (do_async)
114 {
115 // XXX: send off render commands
116 }
117 else
118 {
119 // XXX: do render that is sent of above right here
120 }
121 // XXX:
122
123 // if we are async...
124 if (do_async)
125 {
126 // ref the canvas so it stays while threads wortk
127 eo_ref(eo_e);
128 // track hanvas in list of things going in the background
129 e->rendering = EINA_TRUE;
130 _rendering = eina_list_append(_rendering, eo_e);
131 // flush the thread queue
132 evas_thread_queue_flush
133 ((Evas_Thread_Command_Cb)_evas_render2_wakeup_send, eo_e);
134 }
135 // if not async but we had actual update regions drawn
136 else if (e->render.updates)
137 {
138 // call output flush and callbacks around it
139 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE,
140 NULL);
141 e->engine.func->output_flush(e->engine.data.output,
142 EVAS_RENDER_MODE_SYNC);
143 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST,
144 NULL);
145 }
146 }
147
148 // reset flags sinc rendering is processed now
149 e->changed = EINA_FALSE;
150 e->viewport.changed = EINA_FALSE;
151 e->output.changed = EINA_FALSE;
152 e->framespace.changed = EINA_FALSE;
153 e->invalidate = EINA_FALSE;
154
155 // XXX:
156 // XXX: delete objects no longer needed here
157 // XXX:
158
159 // if we are not going to be async then do post render here
160 if (!do_async)
161 {
162 // clear our previous rendering stuff from the engine
163 e->engine.func->output_redraws_clear(e->engine.data.output);
164 // call the post render callback with info if appropriate
165 if (e->render.updates)
166 {
167 Evas_Event_Render_Post post;
168
169 post.updated_area = e->render.updates;
170 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
171 }
172 else
173 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
174 // clean out modules we don't need anymore
175 evas_module_clean();
176 // clean out updates and tmp surfaces we were holding/tracking
177 if (!make_updates)
178 {
179 Update *u;
180
181 EINA_LIST_FREE(e->render.updates, u)
182 {
183 //evas_cache_image_drop(u->surface);
184 free(u);
185 }
186 }
187 }
188 return EINA_TRUE;
189}
190
191///////////////////////////////////////////////////////////////////////
192// END RENDERING (in mainloop)
193///////////////////////////////////////////////////////////////////////
194static void
195_evas_render2_end(Eo *eo_e)
196{
197 // this is actually called if rendering was async and is done. this is
198 // run in the mainloop where rendering began and may handle any cleanup
199 // or pixel upload if needed here
200 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
201 Eina_Bool have_updates = EINA_FALSE;
202 Update *u;
203
204 // XXX:
205 // XXX: actually update screen from mainloop here if needed - eg software
206 // engine needs to xshmputimage here
207 // XXX:
208
209 // clean out updates and tmp surfaces we were holding/tracking
210 if (e->render.updates)
211 {
212 have_updates = EINA_TRUE;
213 EINA_LIST_FREE(e->render.updates, u)
214 {
215 //evas_cache_image_drop(u->surface);
216 free(u);
217 }
218 }
219 // if we did do rendering flush output to target and call callbacks
220 if (have_updates)
221 {
222 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
223 e->engine.func->output_flush(e->engine.data.output,
224 EVAS_RENDER_MODE_ASYNC_END);
225 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
226 }
227 // clear our previous rendering stuff from the engine
228 e->engine.func->output_redraws_clear(e->engine.data.output);
229 // stop tracking canvas as being async rendered
230 _rendering = eina_list_remove(_rendering, eo_e);
231 e->rendering = EINA_FALSE;
232 // call the post render callback with info if appropriate
233 if (e->render.updates)
234 {
235 Evas_Event_Render_Post post;
236
237 post.updated_area = e->render.updates;
238 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
239 }
240 else
241 _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
242 // clean out modules we don't need anymore
243 evas_module_clean();
244 // release canvas object ref
245 eo_unref(eo_e);
246}
247
248///////////////////////////////////////////////////////////////////////
249// IDLE FLUSH (in mainloop)
250///////////////////////////////////////////////////////////////////////
251void
252_evas_render2_idle_flush(Eo *eo_e)
253{
254 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
255
256 // wait for rendering to finish so we don't mess up shared resources
257 _evas_render2_wait(eo_e);
258 // clean fonts
259 evas_fonts_zero_pressure(eo_e);
260 // call engine idle flush call
261 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
262 (e->engine.data.output))
263 e->engine.func->output_idle_flush(e->engine.data.output);
264 // mark as invalidated
265 e->invalidate = EINA_TRUE;
266 // garbage collect up to 500 cow segments from our cow types
267 // not e that we should probably expose a call to do this outside of evas
268 // so ecore evas can call it in an idler
269 _evas_render2_cow_all_gc(500);
270}
271
272///////////////////////////////////////////////////////////////////////
273// DUMP DATA (in mainloop)
274///////////////////////////////////////////////////////////////////////
275void
276_evas_render2_dump(Eo *eo_e)
277{
278 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
279
280 // freeze core cache system async work
281 evas_cache_async_freeze();
282 // wait for all canvases to render as they may share data we are dumping
283 _evas_render2_all_sync();
284 // go through idle flush first
285 _evas_render2_idle_flush(eo_e);
286 // also now tell engine to dump too
287 if ((e->engine.func) && (e->engine.func->output_dump) &&
288 (e->engine.data.output))
289 e->engine.func->output_dump(e->engine.data.output);
290 // clean up all cow sections no matter how many
291 _evas_render2_cow_all_gc(0);
292 // unfreeze core cache system
293 evas_cache_async_thaw();
294}
295
296///////////////////////////////////////////////////////////////////////
297// WAIT ON CANVAS RENDER (if async, in mainloop)
298///////////////////////////////////////////////////////////////////////
299void
300_evas_render2_wait(Eo *eo_e)
301{
302 Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
303 while (e->rendering) evas_async_events_process_blocking();
304}
305
306
307
308
309// helpers
310//////////////////////////////////////////////////////////////////////////////
311
312static void
313_evas_render2_cow_gc(Eina_Cow *cow, int max)
314{
315 // gc a single cow type up to max iter or if max <= 0, all of them
316 int i = 0;
317
318 while (eina_cow_gc(cow))
319 {
320 if (max < 1) continue;
321 i++;
322 if (i > max) break;
323 }
324}
325
326static void
327_evas_render2_cow_all_gc(int max)
328{
329 // gc all known cow types
330 _evas_render2_cow_gc(evas_object_proxy_cow, max);
331 _evas_render2_cow_gc(evas_object_map_cow, max);
332 _evas_render2_cow_gc(evas_object_image_pixels_cow, max);
333 _evas_render2_cow_gc(evas_object_image_load_opts_cow, max);
334 _evas_render2_cow_gc(evas_object_image_state_cow, max);
335}
336
337static void
338_evas_render2_all_sync(void)
339{
340 // wait for ALL canvases to stop rendering
341 Eo *eo_e;
342
343 if (!_rendering) return;
344 eo_e = eina_list_data_get(eina_list_last(_rendering));
345 _evas_render2_wait(eo_e);
346}
347
348static void
349_evas_render2_wakeup_cb(void *target, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
350{
351 // in mainloop run the rendering end handler
352 Eo *eo_e = target;
353
354 _evas_render2_end(eo_e);
355}
356
357static void
358_evas_render2_wakeup_send(void *data)
359{
360 // pass an event to the mainloop async event handler in evas so mainloop
361 // runs wakeup_cb and not in any thread
362 evas_async_events_put(data, 0, NULL, _evas_render2_wakeup_cb);
363}
364
365static void
366_evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
367{
368 int freeze_num = 0, i;
369
370 eo_do(eo_e, eo_event_freeze_get(&freeze_num));
371 for (i = 0; i < freeze_num; i++) eo_do(eo_e, eo_event_thaw());
372 evas_event_callback_call(eo_e, type, event_info);
373 for (i = 0; i < freeze_num; i++) eo_do(eo_e, eo_event_freeze());
374}