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

Reply via email to