On Fri, 20 Dec 2013 15:25:01 -0200 Iván Briano <[email protected]> said:

> The current async render is sending each render command to the thread,
> and here it seems you want a thread to do the whole render.
> That wasn't very clear, let's try again.
> 
> Are you planning on messing with the object's render functions so they can
> be called from a thread? As opposed as what we have now, where they are
> called from the main loop, they in turn call the engine functions and these
> will check the do_async flag to decide if they draw in place or if they send a
> command to the render thread.

first i'm just building some basic structure here, so nothing is set in stone
right now.

i would LIKE parallelize SOME bits of the pipeline before rendering - but not
actually make them async. eg have 2, 4, 8 threads etc. walk over objects in
parallel generating small lists of  update rects as we do now in serial and
then merge them back into parents to finally figure out our update regions.
this basically involves a fully parallelized tree walk, BUT it needs to handle
the "graph" nature of evas where things outside your tree (smart object) could
affect things inside of it (eg clippers).

i really am not sure how to do this other than first walk the tree (and then
branch out with the graph) and figure out what is dependant and in independent
and then throw it at N threads. for now i suspect this will be way too expensive
and the gain will be less than the cost, but i have it marked to have a try at
at some point. i won't know the result until i've tried.

the other possible solution here is still walk tree like now BUT put off into
async thread. in THIS case we can't reset yet. it means ALL operations to that
canvas after evas_render have to block and wait for this to finish, unless it's
sync rendering OR the caller wanted an update list - then we have to generate
update list first before returning.

i'm not fond of going through every evas api call that can affect the canvas or
a child of it and putting in a "if we're doing an async op in the bg on the
canvas itself - then block and wait", so for now it's on the idea list, and i
will structure code to make it easy to shuffle in later. i'm pondering at the
moment how i would have to change the render pre/post methods of objects to
handle this. i know already i need to create new pre/post methods per object to
make this possible, but for now at least i likely am going to have to keep the
object tree walk inline, generate update rects, then walk the tree AGAIN
generating prepare commands, draw commands etc. per rect.

the other thing i want to do is not just have a single render thread but have
multiple other worker threads too so. right now the infra is a single bg
thread. i want to be able to throw 2, 3, 4, 6, 8+ threads at a problem, IF it
can be done. so the above walk and generate update rects AND commands might be
possible to do with more than 1 thread to speed it up.

another one of those ways to parallelize is to break up rendering into more
stages. stage 1 hands off to stage 2, stage 2 off to stage 3, stage 3 off to
stage 4 etc. any stage 4 has to  wait for previous stage 4's but a stage 3 can
work in parallel to a stage 4 etc. etc. - we already have a primitive version
of this - stage 1 and 2. 1 is mainloop, 2 is the async render thread.

an example of the above is in the software renderer, do pre-rendering of font
glyphs we know we will need (or very likely need) and literally have a pool of
2, 4 or 8 threads and throw every glyph we have at these to pre-render prior to
the text renderer needing them. another is scalecache. pre-prepare all
"expensive" scaled data in several worker threads (can be shared with the font
thread pool). anything smooth scaled is so costly that N threads == N times
faster. we can also BEGIN image loads/decodes here in threads (when not
already cached) - admittedly cserve should negate much of the benefit of
this by ensuring all data is already there long before this point, so for
now it's a theoretical talking point, but unlikely to actually get
implemented or have practical value. when preparation pool is done it hands off
rendering to the composition thread.

for opengl this can be split differently. for gl we still need to render glyphs
BUT we also upload them to textures. the same for images - we can upload images
to textures prior to handing off to the next stage which is triangulation (the
evas gl common pipeline stuff). triangulation can hand off to an actual dumb
"draw the triangles" thread that just takes a queue of triangles + states and
dumps to the gpu... which hands off to the swapbuffers thread...

the questions here are how do i make some shared infra that engines have in
common first. this code is to explore that. reality is that gl will be hard
from the simple point that gl contexts are limited. a context costs a lot of
memory (with mesa they cost between 10-40mb of ram for a single context
depending on your version of mesa - it's a memory hog to have a gl context,
though it should not be. they shouldn't consume more than the memory needed to
store the gl state at any point - they could balloon out to store command
queues when needed, but then should trim back down again).

so having multiple contexts is not a fantastic idea. the other problem is that
a context can ONLY be bound to a single thread at any time. that presents a
problem - we either have a single context and a single render thread for doing
actual gl stuff (texture uploads, draws, swaps), OR we spend the memory on
multiple, but then we hit another issue... 2 contexts are not allowed to share
the same dest buffers/surfaces. : ( (even if unused). so gl presents a whole
bunch of gotchas. reality is that i likely can split out triangulation that
hands off to the gl context thread that does everything else (texture uploads,
switching of state, drawarrays of triangles and swapbuffers).

> On Fri, Dec 20, 2013 at 11:46 AM, Ulisses Furquim <[email protected]> wrote:
> > Hi Raster,
> >
> > I see where you're heading... let's see the outcome. :-) I have a
> > question below inline.
> >
> >
> > On Fri, Dec 20, 2013 at 8:44 AM, Carsten Haitzler <[email protected]>
> > wrote:
> >>
> >> raster pushed a commit to branch master.
> >>
> >> http://git.enlightenment.org/core/efl.git/commit/?id=cb841b56af11bbf787b36b3aaf6c6e69f1e1490f
> >>
> >> commit cb841b56af11bbf787b36b3aaf6c6e69f1e1490f
> >> Author: Carsten Haitzler (Rasterman) <[email protected]>
> >> Date:   Fri Dec 20 19:45:17 2013 +0900
> >>
> >>     evas render2 - more work on basics
> >> ---
> >>  src/lib/evas/canvas/evas_render.c  |  15 +-
> >>  src/lib/evas/canvas/evas_render2.c | 459 ++++++++++++++++++++
> >> +---------------- 2 files changed, 263 insertions(+), 211 deletions(-)
> >>
> >> diff --git a/src/lib/evas/canvas/evas_render.c
> >> b/src/lib/evas/canvas/evas_render.c index 6dab39c..a6b5768 100644
> >> --- a/src/lib/evas/canvas/evas_render.c
> >> +++ b/src/lib/evas/canvas/evas_render.c
> >> @@ -10,15 +10,12 @@
> >>  #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);
> >> +// symbols of funcs from evas_render2 which is a next-gen replacement of
> >> +// the current evas render code. see evas_render2.c for more.
> >> +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
> >> diff --git a/src/lib/evas/canvas/evas_render2.c
> >> b/src/lib/evas/canvas/evas_render2.c index ce95b02..f853473 100644
> >> --- a/src/lib/evas/canvas/evas_render2.c
> >> +++ b/src/lib/evas/canvas/evas_render2.c
> >> @@ -40,49 +40,193 @@ 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); +static void _evas_render2_updates_clean
> >> (Evas_Public_Data *e); +static void _evas_render2_stage_last(Eo *eo_e,
> >> Eina_Bool make_updates); +static void
> >> _evas_render2_stage_generate_object_updates(Evas_Public_Data *e); +static
> >> void _evas_render2_stage_explicit_updates(Evas_Public_Data *e); +static
> >> void _evas_render2_stage_main_render_prepare(Evas_Public_Data *e); +static
> >> void _evas_render2_stage_render_do(Evas_Public_Data *e); +static void
> >> _evas_render2_stage_reset(Evas_Public_Data *e); +static void
> >> _evas_render2_stage_object_cleanup(Evas_Public_Data *e); +static void
> >> _evas_render2_th_render(void *data); +static void _evas_render2_end(Eo
> >> *eo_e);
> >>
> >>  // global data (for rendering only)
> >>  
> >> //////////////////////////////////////////////////////////////////////////////
> >>  static Eina_List *_rendering = NULL;
> >>
> >> +// actual helper/internal functions
> >>  
> >> //////////////////////////////////////////////////////////////////////////////
> >> +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;
> >>
> >> -///////////////////////////////////////////////////////////////////////
> >> -// BEGIN RENDERING (in mainloop)
> >> -///////////////////////////////////////////////////////////////////////
> >> -Eina_Bool
> >> -_evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
> >> -                    Eina_Bool do_draw, Eina_Bool do_async)
> >> +   while (eina_cow_gc(cow))
> >> +     {
> >> +        if (max < 1) continue;
> >> +        i++;
> >> +        if (i > max) break;
> >> +     }
> >> +}
> >> +
> >> +static void
> >> +_evas_render2_cow_all_gc(int max)
> >>  {
> >> -   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
> >> -   Eina_Rectangle *r;
> >> -   Eina_List *l;
> >> +   // 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 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!");
> >> +   if (!_rendering) return;
> >> +   eo_e = eina_list_data_get(eina_list_last(_rendering));
> >> +   _evas_render2_wait(eo_e);
> >> +}
> >>
> >> -   // 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);
> >> +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());
> >> +}
> >>
> >> +static void
> >> +_evas_render2_updates_clean(Evas_Public_Data *e)
> >> +{
> >> +   Update *u;
> >> +
> >> +   // clean out updates and tmp surfaces we were holding/tracking
> >> +   EINA_LIST_FREE(e->render.updates, u)
> >> +     {
> >> +        //evas_cache_image_drop(u->surface);
> >> +        free(u);
> >> +     }
> >> +}
> >> +
> >> +static void
> >> +_evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
> >> +{
> >> +   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CLASS);
> >> +
> >>     // XXX:
> >> -   // XXX: process all objects figuring out update regions
> >> +   // XXX: actually update screen from mainloop here if needed - eg
> >> software
> >> +   // XXX: engine needs to xshmputimage here - engine func does this
> >>     // XXX:
> >> +
> >> +   // if we did do rendering flush output to target and call callbacks
> >> +   if (e->render.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 ((1) || (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);
> >> +   // if we don't want to keep updates after this
> >> +   if (!make_updates) _evas_render2_updates_clean(e);
> >> +   // clean out modules we don't need anymore
> >> +   evas_module_clean();
> >> +}
> >> +
> >> +static void
> >> +_evas_render2_object_basic_process(Evas_Public_Data *e,
> >> +                                   Evas_Object_Protected_Data *obj)
> >> +{
> >> +   printf("_evas_render2_object_basic_process %p %p\n", e, obj);
> >> +}
> >> +
> >> +static void
> >> +_evas_render2_object_process(Evas_Public_Data *e,
> >> +                             Evas_Object_Protected_Data *obj)
> >> +{
> >> +   // process object OR walk through child objects if smart and process
> >> those
> >> +   Evas_Object_Protected_Data *obj2;
> >> +
> >> +   // XXX: this needs to become parallel, BUT we need new object methods
> >> to
> >> +   // call to make that possible as the current ones work on a single
> >> global
> >> +   // engine handle and single orderted redraw queue.
> >> +   if (obj->smart.smart)
> >> +     {
> >> +        EINA_INLIST_FOREACH
> >> +        (evas_object_smart_members_get_direct(obj->object), obj2)
> >> +          _evas_render2_object_process(e, obj2);
> >> +     }
> >> +   else _evas_render2_object_basic_process(e, obj);
> >> +}
> >> +
> >> +static void
> >> +_evas_render2_stage_generate_object_updates(Evas_Public_Data *e)
> >> +{
> >> +   Evas_Layer *lay;
> >> +
> >> +   // XXX: should time this
> >> +   EINA_INLIST_FOREACH(e->layers, lay)
> >> +     {
> >> +        Evas_Object_Protected_Data *obj;
> >>
> >> +        EINA_INLIST_FOREACH(lay->objects, obj)
> >> +          _evas_render2_object_process(e, obj);
> >> +     }
> >> +}
> >> +
> >> +static void
> >> +_evas_render2_stage_explicit_updates(Evas_Public_Data *e)
> >> +{
> >> +   Eina_Rectangle *r;
> >> +   Eina_List *l;
> >> +
> >> +   // XXX: should time this
> >>     // if the output size changed, add a full redraw
> >>     if ((e->output.changed) || (e->framespace.changed))
> >>       {
> >> @@ -104,87 +248,111 @@ _evas_render2_begin(Eo *eo_e, Eina_Bool
> >> make_updates, 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: 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);
> >> -          }
> >> -     }
> >> +static void
> >> +_evas_render2_stage_main_render_prepare(Evas_Public_Data *e)
> >> +{
> >> +   // XXX:
> >> +   // XXX: do any preparation work here that is needed for the render
> >> +   // XXX: threads to do their work, but can't be done in a thread. this
> >> +   // XXX: also includes doing the pose render and clear of change flag
> >> +   // XXX:
> >> +   printf("_evas_render2_stage_main_render_prepare %p\n", e);
> >> +}
> >>
> >> -   // reset flags sinc rendering is processed now
> >> +static void
> >> +_evas_render2_stage_render_do(Evas_Public_Data *e)
> >> +{
> >> +   // XXX:
> >> +   // XXX: actually render now (either in thread or in mainloop)
> >> +   // XXX:
> >> +   printf("_evas_render2_stage_render_do %p\n", e);
> >> +}
> >> +
> >> +static void
> >> +_evas_render2_stage_reset(Evas_Public_Data *e)
> >> +{
> >> +   // cleanup canvas state after a render
> >>     e->changed = EINA_FALSE;
> >>     e->viewport.changed = EINA_FALSE;
> >>     e->output.changed = EINA_FALSE;
> >>     e->framespace.changed = EINA_FALSE;
> >>     e->invalidate = EINA_FALSE;
> >> +}
> >>
> >> +static void
> >> +_evas_render2_stage_object_cleanup(Evas_Public_Data *e)
> >> +{
> >> +   // cleanup objects no longer needed now they have been scanned
> >>     // XXX:
> >>     // XXX: delete objects no longer needed here
> >>     // XXX:
> >> +   printf("_evas_render2_stage_object_cleanup %p\n", e);
> >> +}
> >>
> >> -   // if we are not going to be async then do post render here
> >> -   if (!do_async)
> >> +static void
> >> +_evas_render2_th_render(void *data)
> >> +{
> >> +   Evas_Public_Data *e = data;
> >> +   printf("th rend %p\n", e);
> >> +   _evas_render2_stage_render_do(e);
> >> +}
> >> +
> >> +// major functions (called from evas_render.c)
> >> +//////////////////////////////////////////////////////////////////////////////
> >> +
> >> +///////////////////////////////////////////////////////////////////////
> >> +// 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);
> >> +
> >> +   // 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);
> >> +   // begin out actual rendering bits
> >> +   _evas_render2_stage_generate_object_updates(e);
> >> +   _evas_render2_stage_explicit_updates(e);
> >> +   // we are actually asked to draw not just go through the motions for gc
> >> +   if (do_draw)
> >>       {
> >> -        // 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)
> >> +        // now go through any preparation that needs doing in the mainloop
> >> +        _evas_render2_stage_main_render_prepare(e);
> >> +        // send off rendering to primary thread renderer
> >> +        if (do_async)
> >>            {
> >> -             Update *u;
> >> -
> >> -             EINA_LIST_FREE(e->render.updates, u)
> >> -               {
> >> -                  //evas_cache_image_drop(u->surface);
> >> -                  free(u);
> >> -               }
> >> +             // 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);
> >> +             // queue the render thread command
> >> +             evas_thread_cmd_enqueue(_evas_render2_th_render, e);
> >> +             // flush the thread queue and call wakeup_send in the thread
> >> +             evas_thread_queue_flush(_evas_render2_wakeup_send, eo_e);
> >>            }
> >> +        // or if not async, do rendering inline now
> >> +        else _evas_render2_stage_render_do(e);
> >>       }
> >> +   // reset flags since rendering is processed now
> >> +   _evas_render2_stage_reset(e);
> >> +   // clean/delete/gc objects here
> >> +   _evas_render2_stage_object_cleanup(e);
> >
> > Don't we need to do these last 2 calls only if !do_async? And if
> > do_async then in your wake up function in the mainloop you reset flags
> > and cleanup objects?
> >
> > -- Ulisses
> >
> >> +   // if we are not going to be async then do last render stage here
> >> +   if (!do_async) _evas_render2_stage_last(eo_e, make_updates);
> >> +   if (!do_draw) _evas_render2_updates_clean(e);
> >>     return EINA_TRUE;
> >>  }
> >>
> >> @@ -197,50 +365,7 @@ _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();
> >> +   _evas_render2_stage_last(eo_e, EINA_TRUE);
> >>     // release canvas object ref
> >>     eo_unref(eo_e);
> >>  }
> >> @@ -302,73 +427,3 @@ _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());
> >> -}
> >>
> >> --
> >>
> >>
> >
> > ------------------------------------------------------------------------------
> > Rapidly troubleshoot problems before they affect your business. Most IT
> > organizations don't have a clear picture of how application performance
> > affects their revenue. With AppDynamics, you get 100% visibility into your
> > Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics
> > Pro!
> > http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
> > _______________________________________________ enlightenment-devel mailing
> > list [email protected]
> > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
> 
> ------------------------------------------------------------------------------
> Rapidly troubleshoot problems before they affect your business. Most IT 
> organizations don't have a clear picture of how application performance 
> affects their revenue. With AppDynamics, you get 100% visibility into your 
> Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
> http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
> _______________________________________________
> enlightenment-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
> 


-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
The Rasterman (Carsten Haitzler)    [email protected]


------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to