Page MenuHomePhabricator

Evas Async And E Comp
Updated 2,147 Days AgoPublic

This page was created to organize the ideas regarding new Evas async render and its implications in E Composite Manager module.

Evas Async

  • a single Render Thread shared by all canvas (provides ordering amongst different canvas, in case they are inter-dependent).
  • opt-in for people using evas_render_async()
  • evas_render_async() calls evas_render_updates_internal(..., do_async=EINA_TRUE), that calls engines with do_async=EINA_TRUE parameter to create Command Queue for the Render Thread;
  • evas_render_updates_internal() will ensure each frame has one command in the queue to execute evas_render_pipe_wakeup() that wakes up Main Thread using evas_async_events_put(data, 0, NULL, evas_render_async_wakeup);
  • while one canvas is rendering, further calls to evas_render_async() will return EINA_FALSE, meaning it's already render. Nothing else is done: prev and cur are not touched.
  • evas_render_wakeup() will run in the Main Thread and mark as "not rendering anymore", executing output_redraws_next_update_push(), output_flush() and output_redraws_clear() from engine as well as emitting events EVAS_CALLBACK_RENDER_POST, EVAS_CALLBACK_RENDER_FLUSH_PRE and EVAS_CALLBACK_RENDER_FLUSH_POST.
  • References:
    • RGBA_Image*:
      • Main Thread references RGBA_Image* using evas_cache_image_ref(), for all source and destination (includes the Evas* owned screen/window buffer).
      • Main Thread unreferences RGBA_Image* after evas_async_events_put(image->image, 0, NULL, _drop_cache_ref); from the Render Thread. Can't unref from thread as Evas_Cache_Image is not thread safe.
    • Evas_Glyph_Array*: introduced with Evas Async to enable threads to use the array without damaging each other.
      • Main Thread references Evas_Glyph_Array* using evas_common_font_glyphs_ref() for all font_draw() engine function.
      • Render Thread unreferences Evas_Glyph_Array* using evas_common_font_glyphs_unref(). It is thread safe and has a lock.
  • Render Thread gets the command queue composed of //only basic render information** and executes these commands (no RGBA_Draw_Context, just color, clipper region, source and destination regions...)
  • Proxy and Maps are rendered in the Main Thread before commands are queued. TODO: in theory they could be moved to the Render Thread as well
  • Synchronization: these will wait until canvas ends rendering by using evas_render_rendering_wait()
    • evas_sync()
    • evas_object_image_data_set()
    • evas_object_image_data_get(o, for_writing=EINA_TRUE)
    • evas_object_image_native_surface_set()

      Main Thread..: Canvas 1: evas_render_async(c1, cb1) .->cb1 | .-----------------' | | Render Thread: `->#'

      Main Thread..: Canvas 1: evas_render_async(c1, cb1) .->cb1 .->cb2 Canvas 2: | evas_render_async(c2, cb2) | | | | .----------------------' | | --|-. .-----------------------' | | | | Render Thread: ->#' `->###' (never interleaves c1 and c2 drawings!)

Ecore Evas Async

  • Just used by ecore_evas_x (software, not GL)
  • Controlled by ee->can_async_render
  • resize, shape, alpha, transparent, damage and rotation are flagged and delayed if can_async_render
  • After render, Main Thread _ecore_evas_x_render_updates() will be called, that calls _render_updates_process() and will apply resize, shape, alpha, transparent, damage and rotation

Possible Bugs:

  • No special handling for ecore_evas_manual_render and friends. E Composite Manager Module is not using this ATM.
  • No special handling for ecore_evas_software_x11_direct_resize_set() and friends. E Composite Manager Module is not using this ATM.
  • No special handling for sub ecore evas, block reads:

    EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2) { if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); if (ee2->engine.func->fn_render) rend |= ee2->engine.func->fn_render(ee2); if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); }
  • fn_post_render() for sub-ecore_evas could be out of place here, if fn_render() is asynchronous:
    • This does not happen now as there is no sub-ecore_evas of type software-x11, only buffer, that is always synchronous.
    • Maybe move fn_post_render() to EVAS_CALLBACK_RENDER_POST?
    • E Composite Manager Module does not call ecore_evas_callback_post_render_set()

E Composite Manager Module

Reported Bugs:

  • second screen gets corrupted drawings mainly after resize
    • external processes (terminology and elementary_test). TODO: does it happens with non-EFL applications?'
    • seems to be E17 border to cause the problem.
  • Render Queue gets stuck: no further clarifications. TODO: using sw or gl? what's the backtrace?


  • Raster thinks that software_x11 windows used by E17 are being used before they are ready
    • Gustavo thinks this is impossible as Evas output_redraws_next_update_push() and output_flush(), then _ecore_evas_x_render_updates()/_render_updates_process() are just called to notify X of damages on the main thread afterwards.

Composite Manager Work Flow

  • E_EVENT_BORDER_RESIZE does nothing.
  • ECORE_X_EVENT_WINDOW_CONFIGURE calls _e_mod_comp_win_configure() if size changes.
    • _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, damage=0); with new size, that adds an update and calls _e_mod_comp_win_render_queue(cw)
    • _e_mod_comp_win_render_queue(cw) will reschedule an Ecore_Job to _e_mod_comp_cb_update(data); that calls _e_mod_comp_win_update() to every updated window and this does a massive amount of stuff, including getting pixmap with ecore_x_composite_name_window_pixmap_get()
    • _e_mod_comp_win_geometry_update(cw) just move the shadow object.

TODO: clarify _e_mod_comp_win_update()

Problem should be that comp gets the ecore_x_composite_name_window_pixmap_get() before E17 painted its border. Flow:

  1. user resize window and generates ECORE_X_EVENT_WINDOW_CONFIGURE
  2. _e_border_eval() happens and resize its bd->bg_ecore_evas, bd->bg_evas and bd->bg_object (edje)
  3. _ecore_evas_idle_enter() is calls evas_render_async() for border. It used to wait until border renders.'
  4. _e_mod_comp_win_configure() is called
  5. _e_mod_comp_win_render_queue() is called
  6. _e_mod_comp_cb_update() is called and uses ecore_x_composite_name_window_pixmap_get() to get the resulting pixmap. But border did not rendered yet!'

If this turns to be true, the bug is in comp assuming that the border is ready whenever the internal window (app) changes its size. Before it would work because we were a single process. If border/decorations were provided by another process (as in Gnome/KDE), the bug would happen as well.

The correct approach would be to wait until border is fully painted and damage events are generated.

Imported from
1 barbieri 2013-01-08 12:08:15
2 barbieri 2013-01-08 12:56:47
3 barbieri 2013-01-08 13:00:30

Last Author
Last Edited
Sep 5 2013, 2:04 PM