Handle wayland frame commits with no surface damage better

Previously we immediately kicked back the frame callback when a client
sent a surface frame without damage.  This let clients that use frames
for timing proceed, but they generally just send another frame right
away and spin in this way until they reach their intended render time.

Now we use animators so the frame callbacks will be limited to the
animator tick source's frequency.

ref T5850
This commit is contained in:
Derek Foreman 2017-08-31 14:41:07 -05:00
parent 0880d1795d
commit 42d3e30f5c
2 changed files with 47 additions and 4 deletions

View File

@ -2126,6 +2126,44 @@ _e_comp_wl_subsurface_commit_to_cache(E_Client *ec)
sdata->cached.has_data = EINA_TRUE;
}
static Eina_Bool
_cb_early_frame_animator(void *data EINA_UNUSED)
{
E_Client *ec;
ec = data;
if (ec->comp_data->early_frame == 1)
e_pixmap_image_clear(ec->pixmap, 1);
/* If some client does a surface frame and never follows with
* a render, it's just an idiot, so stop trying to help it with
* timing.
*/
if (ec->comp_data->early_frame++ > 15)
{
ec->comp_data->early_frame_animator = NULL;
ec->comp_data->early_frame = 0;
return EINA_FALSE;
}
return EINA_TRUE;
}
static void
_e_comp_wl_surface_early_frame(E_Client *ec)
{
if (e_comp_object_damage_exists(ec->frame))
{
ecore_animator_del(ec->comp_data->early_frame_animator);
ec->comp_data->early_frame_animator = NULL;
ec->comp_data->early_frame = 0;
return;
}
if (ec->on_post_updates) return;
ec->comp_data->early_frame = 1;
if (ec->comp_data->early_frame_animator) return;
ec->comp_data->early_frame_animator = ecore_animator_add(_cb_early_frame_animator, ec);
}
static void
_e_comp_wl_subsurface_commit_from_cache(E_Client *ec)
{
@ -2138,8 +2176,7 @@ _e_comp_wl_subsurface_commit_from_cache(E_Client *ec)
DBG("Subsurface Commit from Cache");
_e_comp_wl_surface_state_commit(ec, &sdata->cached);
if (!e_comp_object_damage_exists(ec->frame))
e_pixmap_image_clear(ec->pixmap, 1);
_e_comp_wl_surface_early_frame(ec);
}
static void
@ -2495,6 +2532,10 @@ _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
/* make sure this is a wayland client */
if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
ecore_animator_del(ec->comp_data->early_frame_animator);
ec->comp_data->early_frame_animator = NULL;
ec->comp_data->early_frame = 0;
if (ec == e_comp_wl->wl.client_ec)
e_comp_wl->wl.client_ec = NULL;
e_comp_wl_extension_pointer_unconstrain(ec);
@ -3028,8 +3069,7 @@ EINTERN Eina_Bool
e_comp_wl_surface_commit(E_Client *ec)
{
_e_comp_wl_surface_state_commit(ec, &ec->comp_data->pending);
if (!e_comp_object_damage_exists(ec->frame))
e_pixmap_image_clear(ec->pixmap, 1);
_e_comp_wl_surface_early_frame(ec);
e_comp_wl_extension_pointer_constraints_commit(ec);
return EINA_TRUE;

View File

@ -358,6 +358,9 @@ struct _E_Comp_Wl_Client_Data
E_Comp_X_Client_Data *xwayland_data;
#endif
Ecore_Animator *early_frame_animator;
int early_frame;
Eina_Bool mapped : 1;
Eina_Bool evas_init : 1;
Eina_Bool cursor : 1;