diff --git a/legacy/ecore/ChangeLog b/legacy/ecore/ChangeLog index 5a7572561b..d9f5d9b39c 100644 --- a/legacy/ecore/ChangeLog +++ b/legacy/ecore/ChangeLog @@ -989,3 +989,9 @@ 2012-10-05 Cedric Bail * Properly reschedule call to curl. + +2012-10-05 Eduardo Lima (Etrunko) + + * Wayland SHM now features a mechanism to synchronize rendering with + the compositor, removing tearing effect in animations when using that + engine. diff --git a/legacy/ecore/NEWS b/legacy/ecore/NEWS index 708ed8fa48..f08395dfe0 100644 --- a/legacy/ecore/NEWS +++ b/legacy/ecore/NEWS @@ -15,6 +15,10 @@ Additions: * ecore_imf: - ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN. - ECORE_IMF_PREEDIT_TYPE_SUB4~7 style. + * ecore_evas: + - Wayland SHM engine now features a mechanism to synchronize rendering with + the compositor, removing the tearing effect in animations when using that + engine. Fixes: * ecore_con_url: diff --git a/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h b/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h index be9032795f..664748cdc8 100644 --- a/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h +++ b/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h @@ -456,6 +456,9 @@ void _ecore_evas_wl_common_iconified_set(Ecore_Evas *ee, int iconify); void _ecore_evas_wl_common_maximized_set(Ecore_Evas *ee, int max); void _ecore_evas_wl_common_fullscreen_set(Ecore_Evas *ee, int full); void _ecore_evas_wl_common_ignore_events_set(Ecore_Evas *ee, int ignore); +int _ecore_evas_wl_common_pre_render(Ecore_Evas *ee); +int _ecore_evas_wl_common_render_updates(Ecore_Evas *ee); +void _ecore_evas_wl_common_post_render(Ecore_Evas *ee); int _ecore_evas_wl_common_render(Ecore_Evas *ee); void _ecore_evas_wl_common_screen_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h); void _ecore_evas_wl_common_screen_dpi_get(const Ecore_Evas *ee, int *xdpi, int *ydpi); diff --git a/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_common.c b/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_common.c index 748e022362..257fd6e11f 100644 --- a/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_common.c +++ b/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_common.c @@ -565,6 +565,57 @@ _ecore_evas_wl_common_ignore_events_set(Ecore_Evas *ee, int ignore) /* NB: Hmmm, may need to pass this to ecore_wl_window in the future */ } +int +_ecore_evas_wl_common_pre_render(Ecore_Evas *ee) +{ + int rend = 0; + Eina_List *ll = NULL; + Ecore_Evas *ee2 = NULL; + + if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); + + 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); + } + + return rend; +} + +int +_ecore_evas_wl_common_render_updates(Ecore_Evas *ee) +{ + int rend = 0; + Eina_List *updates = NULL; + + if ((updates = evas_render_updates(ee->evas))) + { + Eina_List *l = NULL; + Eina_Rectangle *r; + + EINA_LIST_FOREACH(updates, l, r) + ecore_wl_window_damage(ee->engine.wl.win, + r->x, r->y, r->w, r->h); + + ecore_wl_flush(); + + evas_render_updates_free(updates); + rend = 1; + } + + return rend; +} + +void +_ecore_evas_wl_common_post_render(Ecore_Evas *ee) +{ + _ecore_evas_idle_timeout_update(ee); + if (ee->func.fn_post_render) ee->func.fn_post_render(ee); +} + int _ecore_evas_wl_common_render(Ecore_Evas *ee) { @@ -572,40 +623,15 @@ _ecore_evas_wl_common_render(Ecore_Evas *ee) if (!ee) return 0; if (!ee->visible) - evas_norender(ee->evas); - else { - Eina_List *ll = NULL, *updates = NULL; - Ecore_Evas *ee2 = NULL; - - if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); - - 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); - } - - if ((updates = evas_render_updates(ee->evas))) - { - Eina_List *l = NULL; - Eina_Rectangle *r; - - EINA_LIST_FOREACH(updates, l, r) - ecore_wl_window_damage(ee->engine.wl.win, - r->x, r->y, r->w, r->h); - - ecore_wl_flush(); - - evas_render_updates_free(updates); - _ecore_evas_idle_timeout_update(ee); - rend = 1; - } - - if (ee->func.fn_post_render) ee->func.fn_post_render(ee); + evas_norender(ee->evas); + return 0; } + + rend = _ecore_evas_wl_common_pre_render(ee); + rend |= _ecore_evas_wl_common_render_updates(ee); + _ecore_evas_wl_common_post_render(ee); + return rend; } diff --git a/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_shm.c b/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_shm.c index da98b32ecd..d2cf1b8640 100644 --- a/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_shm.c +++ b/legacy/ecore/src/lib/ecore_evas/ecore_evas_wayland_shm.c @@ -37,11 +37,21 @@ static void _ecore_evas_wl_show(Ecore_Evas *ee); static void _ecore_evas_wl_hide(Ecore_Evas *ee); static void _ecore_evas_wl_alpha_set(Ecore_Evas *ee, int alpha); static void _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent); +static int _ecore_evas_wl_render(Ecore_Evas *ee); + +/* SHM Only */ static void _ecore_evas_wl_shm_pool_free(Ecore_Evas *ee); static void _ecore_evas_wl_shm_pool_create(Ecore_Evas *ee, size_t size); static void _ecore_evas_wl_buffer_free(Ecore_Evas *ee); static void _ecore_evas_wl_buffer_new(Ecore_Evas *ee, int w, int h); +/* Frame listener */ +static void _ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback, uint32_t time); +static const struct wl_callback_listener frame_listener = +{ + _ecore_evas_wl_frame_complete, +}; + static Ecore_Evas_Engine_Func _ecore_wl_engine_func = { _ecore_evas_wl_free, @@ -97,7 +107,7 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func = NULL, // modal set NULL, // demand attention set NULL, // focus skip set - _ecore_evas_wl_common_render, + _ecore_evas_wl_render, _ecore_evas_wl_common_screen_geometry_get, _ecore_evas_wl_common_screen_dpi_get }; @@ -476,6 +486,63 @@ _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent) } } +static void +_ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback, uint32_t time __UNUSED__) +{ + Ecore_Evas *ee = data; + Ecore_Wl_Window *win = NULL; + + if (!ee) return; + if (!(win = ee->engine.wl.win)) return; + + win->frame_callback = NULL; + win->frame_pending = EINA_FALSE; + wl_callback_destroy(callback); + + if (win->surface) + { + win->frame_callback = wl_surface_frame(win->surface); + wl_callback_add_listener(win->frame_callback, &frame_listener, ee); + } +} + +static int +_ecore_evas_wl_render(Ecore_Evas *ee) +{ + int rend = 0; + Ecore_Wl_Window *win = NULL; + + if (!ee) return 0; + if (!ee->visible) + { + evas_norender(ee->evas); + return 0; + } + + if (!(win = ee->engine.wl.win)) return 0; + + rend = _ecore_evas_wl_common_pre_render(ee); + if (!(win->frame_pending)) + { + /* FIXME - ideally have an evas_changed_get to return the value + * of evas->changed to avoid creating this callback and + * destroying it again + */ + + if (!win->frame_callback) + { + win->frame_callback = wl_surface_frame(win->surface); + wl_callback_add_listener(win->frame_callback, &frame_listener, ee); + } + + rend |= _ecore_evas_wl_common_render_updates(ee); + if (rend) + win->frame_pending = EINA_TRUE; + } + _ecore_evas_wl_common_post_render(ee); + return rend; +} + static void _ecore_evas_wl_shm_pool_free(Ecore_Evas *ee) { diff --git a/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h b/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h index 02f3c1a6ce..8cd0f9d75a 100644 --- a/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h +++ b/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h @@ -198,6 +198,8 @@ struct _Ecore_Wl_Window Ecore_Wl_Input *pointer_device; Ecore_Wl_Input *keyboard_device; + Eina_Bool frame_pending; + struct wl_callback *frame_callback; /* FIXME: Ideally we should record the cursor name for this window * so we can compare and avoid unnecessary cursor set calls to wayland */