forked from enlightenment/efl
first steps to rewriting evas render... a long path.
This commit is contained in:
parent
8937708e43
commit
eed4526003
|
@ -75,6 +75,7 @@ lib/evas/canvas/evas_object_grid.c \
|
|||
lib/evas/canvas/evas_font_dir.c \
|
||||
lib/evas/canvas/evas_rectangle.c \
|
||||
lib/evas/canvas/evas_render.c \
|
||||
lib/evas/canvas/evas_render2.c \
|
||||
lib/evas/canvas/evas_smart.c \
|
||||
lib/evas/canvas/evas_stack.c \
|
||||
lib/evas/canvas/evas_async_events.c \
|
||||
|
|
|
@ -10,6 +10,17 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
Eina_Bool
|
||||
_evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
|
||||
Eina_Bool do_draw, Eina_Bool do_async);
|
||||
void
|
||||
_evas_render2_idle_flush(Eo *eo_e);
|
||||
void
|
||||
_evas_render2_dump(Eo *eo_e);
|
||||
void
|
||||
_evas_render2_wait(Eo *eo_e);
|
||||
|
||||
|
||||
/* debug rendering
|
||||
* NOTE: Define REND_DBG 1 in evas_private.h to enable debugging. Don't define
|
||||
* 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)
|
|||
{
|
||||
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
|
||||
Evas_Public_Data *e = _pd;
|
||||
static int render_2 = -1;
|
||||
|
||||
*ret = evas_render_updates_internal(eo_e, 1, 1, evas_render_pipe_wakeup,
|
||||
e, EINA_TRUE);
|
||||
if (render_2 == -1)
|
||||
{
|
||||
if (getenv("EVAS_RENDER2")) render_2 = 1;
|
||||
else render_2 = 0;
|
||||
}
|
||||
if (render_2)
|
||||
*ret = _evas_render2_begin(eo_e, EINA_TRUE, EINA_TRUE, EINA_TRUE);
|
||||
else
|
||||
*ret = evas_render_updates_internal(eo_e, 1, 1, evas_render_pipe_wakeup,
|
||||
e, EINA_TRUE);
|
||||
}
|
||||
|
||||
EAPI Eina_List *
|
||||
|
@ -2302,10 +2322,24 @@ evas_render_updates_internal_wait(Evas *eo_e,
|
|||
{
|
||||
Eina_List *ret = NULL;
|
||||
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
static int render_2 = -1;
|
||||
|
||||
if (!evas_render_updates_internal(eo_e, make_updates, do_draw, NULL,
|
||||
NULL, EINA_FALSE))
|
||||
return NULL;
|
||||
if (render_2 == -1)
|
||||
{
|
||||
if (getenv("EVAS_RENDER2")) render_2 = 1;
|
||||
else render_2 = 0;
|
||||
}
|
||||
if (render_2)
|
||||
{
|
||||
if (!_evas_render2_begin(eo_e, make_updates, do_draw, EINA_FALSE))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!evas_render_updates_internal(eo_e, make_updates, do_draw, NULL,
|
||||
NULL, EINA_FALSE))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = e->render.updates;
|
||||
e->render.updates = NULL;
|
||||
|
@ -2374,26 +2408,40 @@ evas_render_idle_flush(Evas *eo_e)
|
|||
void
|
||||
_canvas_render_idle_flush(Eo *eo_e, void *_pd, va_list *list EINA_UNUSED)
|
||||
{
|
||||
Evas_Public_Data *e = _pd;
|
||||
static int render_2 = -1;
|
||||
|
||||
evas_render_rendering_wait(e);
|
||||
|
||||
evas_fonts_zero_pressure(eo_e);
|
||||
if (render_2 == -1)
|
||||
{
|
||||
if (getenv("EVAS_RENDER2")) render_2 = 1;
|
||||
else render_2 = 0;
|
||||
}
|
||||
if (render_2)
|
||||
{
|
||||
_evas_render2_idle_flush(eo_e);
|
||||
}
|
||||
else
|
||||
{
|
||||
Evas_Public_Data *e = _pd;
|
||||
|
||||
if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_idle_flush(e->engine.data.output);
|
||||
|
||||
OBJS_ARRAY_FLUSH(&e->active_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->render_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->restack_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->delete_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->obscuring_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->temporary_objects);
|
||||
eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL);
|
||||
eina_array_clean(&e->clip_changes);
|
||||
|
||||
e->invalidate = EINA_TRUE;
|
||||
evas_render_rendering_wait(e);
|
||||
|
||||
evas_fonts_zero_pressure(eo_e);
|
||||
|
||||
if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_idle_flush(e->engine.data.output);
|
||||
|
||||
OBJS_ARRAY_FLUSH(&e->active_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->render_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->restack_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->delete_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->obscuring_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->temporary_objects);
|
||||
eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL);
|
||||
eina_array_clean(&e->clip_changes);
|
||||
|
||||
e->invalidate = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -2406,7 +2454,17 @@ void
|
|||
_canvas_sync(Eo *eo_e, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
evas_render_rendering_wait(e);
|
||||
static int render_2 = -1;
|
||||
|
||||
if (render_2 == -1)
|
||||
{
|
||||
if (getenv("EVAS_RENDER2")) render_2 = 1;
|
||||
else render_2 = 0;
|
||||
}
|
||||
if (render_2)
|
||||
_evas_render2_wait(eo_e);
|
||||
else
|
||||
evas_render_rendering_wait(e);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2444,66 +2502,80 @@ void
|
|||
_canvas_render_dump(Eo *eo_e EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
|
||||
{
|
||||
Evas_Public_Data *e = _pd;
|
||||
Evas_Layer *lay;
|
||||
static int render_2 = -1;
|
||||
|
||||
evas_all_sync();
|
||||
evas_cache_async_freeze();
|
||||
|
||||
EINA_INLIST_FOREACH(e->layers, lay)
|
||||
if (render_2 == -1)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj;
|
||||
|
||||
EINA_INLIST_FOREACH(lay->objects, obj)
|
||||
{
|
||||
if (obj->proxy)
|
||||
{
|
||||
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
|
||||
{
|
||||
if (proxy_write->surface)
|
||||
{
|
||||
e->engine.func->image_map_surface_free(e->engine.data.output,
|
||||
proxy_write->surface);
|
||||
proxy_write->surface = NULL;
|
||||
}
|
||||
}
|
||||
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write);
|
||||
}
|
||||
if ((obj->type) && (!strcmp(obj->type, "image")))
|
||||
evas_object_inform_call_image_unloaded(obj->object);
|
||||
_evas_render_dump_map_surfaces(obj->object);
|
||||
}
|
||||
if (getenv("EVAS_RENDER2")) render_2 = 1;
|
||||
else render_2 = 0;
|
||||
}
|
||||
if ((e->engine.func) && (e->engine.func->output_dump) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_dump(e->engine.data.output);
|
||||
if (render_2)
|
||||
{
|
||||
_evas_render2_dump(eo_e);
|
||||
}
|
||||
else
|
||||
{
|
||||
Evas_Layer *lay;
|
||||
|
||||
evas_all_sync();
|
||||
evas_cache_async_freeze();
|
||||
|
||||
EINA_INLIST_FOREACH(e->layers, lay)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj;
|
||||
|
||||
EINA_INLIST_FOREACH(lay->objects, obj)
|
||||
{
|
||||
if (obj->proxy)
|
||||
{
|
||||
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
|
||||
{
|
||||
if (proxy_write->surface)
|
||||
{
|
||||
e->engine.func->image_map_surface_free(e->engine.data.output,
|
||||
proxy_write->surface);
|
||||
proxy_write->surface = NULL;
|
||||
}
|
||||
}
|
||||
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write);
|
||||
}
|
||||
if ((obj->type) && (!strcmp(obj->type, "image")))
|
||||
evas_object_inform_call_image_unloaded(obj->object);
|
||||
_evas_render_dump_map_surfaces(obj->object);
|
||||
}
|
||||
}
|
||||
if ((e->engine.func) && (e->engine.func->output_dump) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_dump(e->engine.data.output);
|
||||
|
||||
#define GC_ALL(Cow) \
|
||||
#define GC_ALL(Cow) \
|
||||
while (eina_cow_gc(Cow))
|
||||
|
||||
GC_ALL(evas_object_proxy_cow);
|
||||
GC_ALL(evas_object_map_cow);
|
||||
GC_ALL(evas_object_image_pixels_cow);
|
||||
GC_ALL(evas_object_image_load_opts_cow);
|
||||
GC_ALL(evas_object_image_state_cow);
|
||||
GC_ALL(evas_object_proxy_cow);
|
||||
GC_ALL(evas_object_map_cow);
|
||||
GC_ALL(evas_object_image_pixels_cow);
|
||||
GC_ALL(evas_object_image_load_opts_cow);
|
||||
GC_ALL(evas_object_image_state_cow);
|
||||
|
||||
evas_fonts_zero_pressure(eo_e);
|
||||
|
||||
evas_fonts_zero_pressure(eo_e);
|
||||
if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_idle_flush(e->engine.data.output);
|
||||
|
||||
if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_idle_flush(e->engine.data.output);
|
||||
|
||||
OBJS_ARRAY_FLUSH(&e->active_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->render_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->restack_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->delete_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->obscuring_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->temporary_objects);
|
||||
eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL);
|
||||
eina_array_clean(&e->clip_changes);
|
||||
|
||||
e->invalidate = EINA_TRUE;
|
||||
|
||||
evas_cache_async_thaw();
|
||||
OBJS_ARRAY_FLUSH(&e->active_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->render_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->restack_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->delete_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->obscuring_objects);
|
||||
OBJS_ARRAY_FLUSH(&e->temporary_objects);
|
||||
eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL);
|
||||
eina_array_clean(&e->clip_changes);
|
||||
|
||||
e->invalidate = EINA_TRUE;
|
||||
|
||||
evas_cache_async_thaw();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -0,0 +1,374 @@
|
|||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#ifdef EVAS_CSERVE2
|
||||
#include "evas_cs2_private.h"
|
||||
#endif
|
||||
|
||||
#ifdef EVAS_RENDER_DEBUG_TIMING
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// this is the start of a rewrite of the evas rendering infra. first port of
|
||||
// call is to just make it work and still support async rendering with no
|
||||
// optimizations at all. once it WORKS properly start adding back
|
||||
// optimizations one at a time very carefully until it is equivalent to where
|
||||
// evas render was before, THEN... we can consider switching it on by default
|
||||
// but until then it's off unless you set:
|
||||
//
|
||||
// export EVAS_RENDER2=1
|
||||
//
|
||||
// at runtime.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// data types
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct Update Update;
|
||||
|
||||
struct _Update
|
||||
{
|
||||
Eina_Rectangle area;
|
||||
void *surface;
|
||||
};
|
||||
|
||||
// funcs
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
Eina_Bool _evas_render2_begin(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_draw, Eina_Bool do_async);
|
||||
void _evas_render2_idle_flush(Eo *eo_e);
|
||||
void _evas_render2_dump(Eo *eo_e);
|
||||
void _evas_render2_wait(Eo *eo_e);
|
||||
|
||||
static void _evas_render2_end(Eo *eo_e);
|
||||
|
||||
static void _evas_render2_cow_gc(Eina_Cow *cow, int max);
|
||||
static void _evas_render2_cow_all_gc(int max);
|
||||
static void _evas_render2_all_sync(void);
|
||||
static void _evas_render2_wakeup_cb(void *target, Evas_Callback_Type type, void *event_info);
|
||||
static void _evas_render2_wakeup_send(void *data);
|
||||
static void _evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info);
|
||||
|
||||
// global data (for rendering only)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
static Eina_List *_rendering = NULL;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// BEGIN RENDERING (in mainloop)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
Eina_Bool
|
||||
_evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
|
||||
Eina_Bool do_draw, Eina_Bool do_async)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
Eina_Rectangle *r;
|
||||
Eina_List *l;
|
||||
|
||||
// if nothing changed at all since last render - skip this frame
|
||||
if (!e->changed) return EINA_FALSE;
|
||||
// we are still rendering while being asked to render - skip this frame
|
||||
if (e->rendering && do_async) return EINA_FALSE;
|
||||
// check viewport size is same as output - not allowed to differ
|
||||
if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
|
||||
ERR("viewport size != output size!");
|
||||
|
||||
// call canvas callbacks saying we are in the pre-render state
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_PRE, NULL);
|
||||
// we have to calculate smare objects before render so do that here
|
||||
evas_call_smarts_calculate(eo_e);
|
||||
|
||||
// if the output size changed, add a full redraw
|
||||
if ((e->output.changed) || (e->framespace.changed))
|
||||
{
|
||||
e->engine.func->output_resize(e->engine.data.output,
|
||||
e->output.w, e->output.h);
|
||||
e->engine.func->output_redraws_rect_add(e->engine.data.output, 0, 0,
|
||||
e->output.w, e->output.h);
|
||||
}
|
||||
// if there are explicit update regions - add them
|
||||
EINA_LIST_FREE(e->damages, r)
|
||||
{
|
||||
// if we didnt just do a full redraw if output changed
|
||||
if ((!e->output.changed) && (!e->framespace.changed))
|
||||
e->engine.func->output_redraws_rect_add(e->engine.data.output,
|
||||
r->x, r->y, r->w, r->h);
|
||||
eina_rectangle_free(r);
|
||||
}
|
||||
// remove obscures from rendering - we keep them around
|
||||
EINA_LIST_FOREACH(e->obscures, l, r)
|
||||
e->engine.func->output_redraws_rect_del(e->engine.data.output,
|
||||
r->x, r->y, r->w, r->h);
|
||||
|
||||
// we are actually asked to draw not just go through the motions for gc
|
||||
if (do_draw)
|
||||
{
|
||||
// XXX:
|
||||
// XXX: process all objects figuring out update regions
|
||||
// XXX:
|
||||
|
||||
// XXX:
|
||||
// XXX: RENDER HERE!
|
||||
if (do_async)
|
||||
{
|
||||
// XXX: send off render commands
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: do render that is sent of above right here
|
||||
}
|
||||
// XXX:
|
||||
|
||||
// if we are async...
|
||||
if (do_async)
|
||||
{
|
||||
// ref the canvas so it stays while threads wortk
|
||||
eo_ref(eo_e);
|
||||
// track hanvas in list of things going in the background
|
||||
e->rendering = EINA_TRUE;
|
||||
_rendering = eina_list_append(_rendering, eo_e);
|
||||
// flush the thread queue
|
||||
evas_thread_queue_flush
|
||||
((Evas_Thread_Command_Cb)_evas_render2_wakeup_send, eo_e);
|
||||
}
|
||||
// if not async but we had actual update regions drawn
|
||||
else if (e->render.updates)
|
||||
{
|
||||
// call output flush and callbacks around it
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE,
|
||||
NULL);
|
||||
e->engine.func->output_flush(e->engine.data.output,
|
||||
EVAS_RENDER_MODE_SYNC);
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// reset flags sinc rendering is processed now
|
||||
e->changed = EINA_FALSE;
|
||||
e->viewport.changed = EINA_FALSE;
|
||||
e->output.changed = EINA_FALSE;
|
||||
e->framespace.changed = EINA_FALSE;
|
||||
e->invalidate = EINA_FALSE;
|
||||
|
||||
// XXX:
|
||||
// XXX: delete objects no longer needed here
|
||||
// XXX:
|
||||
|
||||
// if we are not going to be async then do post render here
|
||||
if (!do_async)
|
||||
{
|
||||
// clear our previous rendering stuff from the engine
|
||||
e->engine.func->output_redraws_clear(e->engine.data.output);
|
||||
// call the post render callback with info if appropriate
|
||||
if (e->render.updates)
|
||||
{
|
||||
Evas_Event_Render_Post post;
|
||||
|
||||
post.updated_area = e->render.updates;
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
|
||||
}
|
||||
else
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
|
||||
// clean out modules we don't need anymore
|
||||
evas_module_clean();
|
||||
// clean out updates and tmp surfaces we were holding/tracking
|
||||
if (!make_updates)
|
||||
{
|
||||
Update *u;
|
||||
|
||||
EINA_LIST_FREE(e->render.updates, u)
|
||||
{
|
||||
//evas_cache_image_drop(u->surface);
|
||||
free(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// END RENDERING (in mainloop)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
static void
|
||||
_evas_render2_end(Eo *eo_e)
|
||||
{
|
||||
// this is actually called if rendering was async and is done. this is
|
||||
// run in the mainloop where rendering began and may handle any cleanup
|
||||
// or pixel upload if needed here
|
||||
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
Eina_Bool have_updates = EINA_FALSE;
|
||||
Update *u;
|
||||
|
||||
// XXX:
|
||||
// XXX: actually update screen from mainloop here if needed - eg software
|
||||
// engine needs to xshmputimage here
|
||||
// XXX:
|
||||
|
||||
// clean out updates and tmp surfaces we were holding/tracking
|
||||
if (e->render.updates)
|
||||
{
|
||||
have_updates = EINA_TRUE;
|
||||
EINA_LIST_FREE(e->render.updates, u)
|
||||
{
|
||||
//evas_cache_image_drop(u->surface);
|
||||
free(u);
|
||||
}
|
||||
}
|
||||
// if we did do rendering flush output to target and call callbacks
|
||||
if (have_updates)
|
||||
{
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
|
||||
e->engine.func->output_flush(e->engine.data.output,
|
||||
EVAS_RENDER_MODE_ASYNC_END);
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
|
||||
}
|
||||
// clear our previous rendering stuff from the engine
|
||||
e->engine.func->output_redraws_clear(e->engine.data.output);
|
||||
// stop tracking canvas as being async rendered
|
||||
_rendering = eina_list_remove(_rendering, eo_e);
|
||||
e->rendering = EINA_FALSE;
|
||||
// call the post render callback with info if appropriate
|
||||
if (e->render.updates)
|
||||
{
|
||||
Evas_Event_Render_Post post;
|
||||
|
||||
post.updated_area = e->render.updates;
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
|
||||
}
|
||||
else
|
||||
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
|
||||
// clean out modules we don't need anymore
|
||||
evas_module_clean();
|
||||
// release canvas object ref
|
||||
eo_unref(eo_e);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// IDLE FLUSH (in mainloop)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
_evas_render2_idle_flush(Eo *eo_e)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
|
||||
// wait for rendering to finish so we don't mess up shared resources
|
||||
_evas_render2_wait(eo_e);
|
||||
// clean fonts
|
||||
evas_fonts_zero_pressure(eo_e);
|
||||
// call engine idle flush call
|
||||
if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_idle_flush(e->engine.data.output);
|
||||
// mark as invalidated
|
||||
e->invalidate = EINA_TRUE;
|
||||
// garbage collect up to 500 cow segments from our cow types
|
||||
// not e that we should probably expose a call to do this outside of evas
|
||||
// so ecore evas can call it in an idler
|
||||
_evas_render2_cow_all_gc(500);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// DUMP DATA (in mainloop)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
_evas_render2_dump(Eo *eo_e)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
|
||||
// freeze core cache system async work
|
||||
evas_cache_async_freeze();
|
||||
// wait for all canvases to render as they may share data we are dumping
|
||||
_evas_render2_all_sync();
|
||||
// go through idle flush first
|
||||
_evas_render2_idle_flush(eo_e);
|
||||
// also now tell engine to dump too
|
||||
if ((e->engine.func) && (e->engine.func->output_dump) &&
|
||||
(e->engine.data.output))
|
||||
e->engine.func->output_dump(e->engine.data.output);
|
||||
// clean up all cow sections no matter how many
|
||||
_evas_render2_cow_all_gc(0);
|
||||
// unfreeze core cache system
|
||||
evas_cache_async_thaw();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// WAIT ON CANVAS RENDER (if async, in mainloop)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
_evas_render2_wait(Eo *eo_e)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
while (e->rendering) evas_async_events_process_blocking();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// helpers
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
_evas_render2_cow_gc(Eina_Cow *cow, int max)
|
||||
{
|
||||
// gc a single cow type up to max iter or if max <= 0, all of them
|
||||
int i = 0;
|
||||
|
||||
while (eina_cow_gc(cow))
|
||||
{
|
||||
if (max < 1) continue;
|
||||
i++;
|
||||
if (i > max) break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_render2_cow_all_gc(int max)
|
||||
{
|
||||
// gc all known cow types
|
||||
_evas_render2_cow_gc(evas_object_proxy_cow, max);
|
||||
_evas_render2_cow_gc(evas_object_map_cow, max);
|
||||
_evas_render2_cow_gc(evas_object_image_pixels_cow, max);
|
||||
_evas_render2_cow_gc(evas_object_image_load_opts_cow, max);
|
||||
_evas_render2_cow_gc(evas_object_image_state_cow, max);
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_render2_all_sync(void)
|
||||
{
|
||||
// wait for ALL canvases to stop rendering
|
||||
Eo *eo_e;
|
||||
|
||||
if (!_rendering) return;
|
||||
eo_e = eina_list_data_get(eina_list_last(_rendering));
|
||||
_evas_render2_wait(eo_e);
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_render2_wakeup_cb(void *target, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
// in mainloop run the rendering end handler
|
||||
Eo *eo_e = target;
|
||||
|
||||
_evas_render2_end(eo_e);
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_render2_wakeup_send(void *data)
|
||||
{
|
||||
// pass an event to the mainloop async event handler in evas so mainloop
|
||||
// runs wakeup_cb and not in any thread
|
||||
evas_async_events_put(data, 0, NULL, _evas_render2_wakeup_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
|
||||
{
|
||||
int freeze_num = 0, i;
|
||||
|
||||
eo_do(eo_e, eo_event_freeze_get(&freeze_num));
|
||||
for (i = 0; i < freeze_num; i++) eo_do(eo_e, eo_event_thaw());
|
||||
evas_event_callback_call(eo_e, type, event_info);
|
||||
for (i = 0; i < freeze_num; i++) eo_do(eo_e, eo_event_freeze());
|
||||
}
|
Loading…
Reference in New Issue