forked from enlightenment/efl
Wayland_SHM: Add listener to frame callback
This is the method necessary to synchronize Wayland and Evas rendering, similar to vblank sync that is used in X11. This solves the Wayland SHM render issues (tearing effect) without the need to add double buffering to the engine. In a near future, the SHM implementation will feature double (or triple) buffering and this syncrhonization mechanism will be changed to be optional. Patch based on the work started by Robert Bradford on ticket #1280 http://trac.enlightenment.org/e/ticket/1280 Signed-off-by: Eduardo Lima (Etrunko) <eduardo.lima@intel.com> SVN revision: 77580
This commit is contained in:
parent
352926829e
commit
8a014153d4
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue