forked from enlightenment/efl
ecore: Add new way to register animators
Summary: We have back-ends that can generate their own tick sources, but ecore_animator_add()/ecore_animator_timeline_add() gives no indication which backend the animator is running on. This means that all animators have to cause all currently in use backends to tick. For example, if under wayland 4 application windows are open, all 4 windows will create ticks when any animator is present. These new animator APIs that take an evas object allow us to figure out out the backend and only cause the appropriate one to tick. Depends on D7040 Reviewers: devilhorns Reviewed By: devilhorns Subscribers: devilhorns, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D7041
This commit is contained in:
parent
448c7ca2ce
commit
4dc1e8273d
|
@ -391,4 +391,9 @@ EAPI void *ecore_job_del(Ecore_Job *obj);
|
|||
* @}
|
||||
*/
|
||||
|
||||
#ifdef EFL_BETA_API_SUPPORT
|
||||
EAPI Ecore_Animator *ecore_evas_animator_timeline_add(void *evo, double runtime, Ecore_Timeline_Cb func, const void *data);
|
||||
EAPI Ecore_Animator *ecore_evas_animator_add(void *evo, Ecore_Task_Cb func, const void *data);
|
||||
#endif /* EFL_BETA_API_SUPPORT */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "ecore_private.h"
|
||||
|
||||
static int _ecore_anim_log_dom = -1;
|
||||
static Eina_Bool _ee_animators_setup = EINA_FALSE;
|
||||
|
||||
#ifdef ERR
|
||||
# undef ERR
|
||||
|
@ -98,6 +99,8 @@ static Eina_Bool tick_skip = EINA_FALSE;
|
|||
extern volatile int exit_signal_received;
|
||||
#endif
|
||||
|
||||
static Ecore_Evas_Object_Animator_Interface _anim_iface;
|
||||
|
||||
static void
|
||||
_tick_send(signed char val)
|
||||
{
|
||||
|
@ -815,6 +818,8 @@ ecore_animator_del(Ecore_Animator *animator)
|
|||
if (!animator) return NULL;
|
||||
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
||||
|
||||
if (animator->ee) return _anim_iface.del(animator);
|
||||
|
||||
if (animator->delete_me)
|
||||
{
|
||||
data = animator->data;
|
||||
|
@ -855,28 +860,36 @@ EAPI void
|
|||
ecore_animator_freeze(Ecore_Animator *animator)
|
||||
{
|
||||
EINA_MAIN_LOOP_CHECK_RETURN;
|
||||
if (!animator) return ;
|
||||
if (animator->delete_me) return ;
|
||||
if (!animator->suspended)
|
||||
if (!animator) return;
|
||||
if (animator->delete_me) return;
|
||||
if (animator->suspended) return;
|
||||
|
||||
if (animator->ee)
|
||||
{
|
||||
animator->suspended = EINA_TRUE;
|
||||
animators_suspended++;
|
||||
if (!_have_animators()) _end_tick();
|
||||
_anim_iface.freeze(animator);
|
||||
return;
|
||||
}
|
||||
animator->suspended = EINA_TRUE;
|
||||
animators_suspended++;
|
||||
if (!_have_animators()) _end_tick();
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_animator_thaw(Ecore_Animator *animator)
|
||||
{
|
||||
EINA_MAIN_LOOP_CHECK_RETURN;
|
||||
if (!animator) return ;
|
||||
if (!animator) return;
|
||||
if (animator->delete_me) return;
|
||||
if (animator->suspended)
|
||||
if (!animator->suspended) return;
|
||||
|
||||
if (animator->ee)
|
||||
{
|
||||
animator->suspended = EINA_FALSE;
|
||||
animators_suspended--;
|
||||
if (_have_animators()) _begin_tick();
|
||||
_anim_iface.thaw(animator);
|
||||
return;
|
||||
}
|
||||
animator->suspended = EINA_FALSE;
|
||||
animators_suspended--;
|
||||
if (_have_animators()) _begin_tick();
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -1030,3 +1043,36 @@ _ecore_animator_init(void)
|
|||
EINA_LOG_ERR("Ecore was unable to create a log domain.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ecore_evas_object_animator_init(Ecore_Evas_Object_Animator_Interface *iface)
|
||||
{
|
||||
_anim_iface = *iface;
|
||||
_ee_animators_setup = EINA_TRUE;
|
||||
}
|
||||
|
||||
Ecore_Animator *
|
||||
ecore_evas_animator_timeline_add(void *evo, double runtime, Ecore_Timeline_Cb func, const void *data)
|
||||
{
|
||||
Ecore_Animator *anim = NULL;
|
||||
|
||||
if (_ee_animators_setup)
|
||||
anim = _anim_iface.timeline_add(evo, runtime, func, data);
|
||||
|
||||
if (anim) return anim;
|
||||
|
||||
return ecore_animator_timeline_add(runtime, func, data);
|
||||
}
|
||||
|
||||
Ecore_Animator *
|
||||
ecore_evas_animator_add(void *evo, Ecore_Task_Cb func, const void *data)
|
||||
{
|
||||
Ecore_Animator *anim = NULL;
|
||||
|
||||
if (_ee_animators_setup)
|
||||
anim = _anim_iface.add(evo, func, data);
|
||||
|
||||
if (anim) return anim;
|
||||
|
||||
return ecore_animator_add(func, data);
|
||||
}
|
||||
|
|
|
@ -220,11 +220,24 @@ struct _Ecore_Animator
|
|||
Ecore_Timeline_Cb run_func;
|
||||
void *run_data;
|
||||
|
||||
void *ee;
|
||||
|
||||
Eina_Bool delete_me : 1;
|
||||
Eina_Bool suspended : 1;
|
||||
Eina_Bool just_added : 1;
|
||||
};
|
||||
|
||||
typedef struct _Ecore_Evas_Object_Animator_Interface
|
||||
{
|
||||
Ecore_Animator *(*timeline_add)(void *obj, double runtime, Ecore_Timeline_Cb func, const void *data);
|
||||
Ecore_Animator *(*add)(void *obj, Ecore_Task_Cb func, const void *data);
|
||||
void (*freeze)(Ecore_Animator *animator);
|
||||
void (*thaw)(Ecore_Animator *animator);
|
||||
void *(*del)(Ecore_Animator *animator);
|
||||
} Ecore_Evas_Object_Animator_Interface;
|
||||
|
||||
EAPI void ecore_evas_object_animator_init(Ecore_Evas_Object_Animator_Interface *iface);
|
||||
|
||||
#define EVAS_FRAME_QUEUING 1 /* for test */
|
||||
|
||||
#define READBUFSIZ 65536
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#define EFL_INTERNAL_UNSTABLE
|
||||
#include "interfaces/efl_common_internal.h"
|
||||
|
||||
#include "ecore_private.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
@ -71,6 +73,14 @@ static const Efl_Event_Description *_event_description_get(Efl_Pointer_Action ac
|
|||
//RENDER_SYNC
|
||||
static int _ecore_evas_render_sync = 1;
|
||||
|
||||
static void _ecore_evas_animator_flush(Ecore_Evas *ee);
|
||||
|
||||
static Ecore_Animator *_ecore_evas_animator_timeline_add(void *evo, double runtime, Ecore_Timeline_Cb func, const void *data);
|
||||
static Ecore_Animator *_ecore_evas_animator_add(void *evo, Ecore_Task_Cb func, const void *data);
|
||||
static void _ecore_evas_animator_freeze(Ecore_Animator *animator);
|
||||
static void _ecore_evas_animator_thaw(Ecore_Animator *animator);
|
||||
static void *_ecore_evas_animator_del(Ecore_Animator *animator);
|
||||
|
||||
static void
|
||||
_ecore_evas_focus_out_dispatch(Ecore_Evas *ee, Efl_Input_Device *seat)
|
||||
{
|
||||
|
@ -215,6 +225,9 @@ _ecore_evas_idle_enter(void *data EINA_UNUSED)
|
|||
}
|
||||
EINA_INLIST_FOREACH(ecore_evases, ee)
|
||||
{
|
||||
if (ee->ee_anim.deleted)
|
||||
_ecore_evas_animator_flush(ee);
|
||||
|
||||
if (ee->draw_block) continue;
|
||||
|
||||
if (ee->manual_render)
|
||||
|
@ -588,6 +601,8 @@ ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine)
|
|||
EAPI int
|
||||
ecore_evas_init(void)
|
||||
{
|
||||
Ecore_Evas_Object_Animator_Interface iface;
|
||||
|
||||
if (++_ecore_evas_init_count != 1)
|
||||
return _ecore_evas_init_count;
|
||||
|
||||
|
@ -629,6 +644,14 @@ ecore_evas_init(void)
|
|||
_ecore_evas_app_comp_sync = EINA_FALSE;
|
||||
else if (getenv("ECORE_EVAS_COMP_SYNC"))
|
||||
_ecore_evas_app_comp_sync = EINA_TRUE;
|
||||
|
||||
iface.add = _ecore_evas_animator_add;
|
||||
iface.timeline_add = _ecore_evas_animator_timeline_add;
|
||||
iface.freeze = _ecore_evas_animator_freeze;
|
||||
iface.thaw = _ecore_evas_animator_thaw;
|
||||
iface.del = _ecore_evas_animator_del;
|
||||
ecore_evas_object_animator_init(&iface);
|
||||
|
||||
return _ecore_evas_init_count;
|
||||
|
||||
shutdown_ecore:
|
||||
|
@ -3041,6 +3064,54 @@ _ecore_evas_fps_debug_rendertime_add(double t)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_evas_animator_detach(Ecore_Animator *a)
|
||||
{
|
||||
Ecore_Evas *ee;
|
||||
Eina_Inlist *tmp;
|
||||
|
||||
if (a->delete_me) return;
|
||||
|
||||
tmp = EINA_INLIST_GET(a);
|
||||
|
||||
ee = a->ee;
|
||||
if (a->suspended)
|
||||
ee->ee_anim.suspended = eina_inlist_remove(ee->ee_anim.suspended, EINA_INLIST_GET(a));
|
||||
else if ((!tmp->next) && (!tmp->prev) && (EINA_INLIST_GET(a) != ee->ee_anim.active))
|
||||
return;
|
||||
else
|
||||
ee->ee_anim.active = eina_inlist_remove(ee->ee_anim.active, EINA_INLIST_GET(a));
|
||||
|
||||
a->suspended = EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_evas_animators_do(Ecore_Evas *ee)
|
||||
{
|
||||
ee->ee_anim.run_list = ee->ee_anim.active;
|
||||
ee->ee_anim.active = NULL;
|
||||
|
||||
while (ee->ee_anim.run_list)
|
||||
{
|
||||
Ecore_Animator *animator;
|
||||
|
||||
animator = EINA_INLIST_CONTAINER_GET(ee->ee_anim.run_list, Ecore_Animator);
|
||||
ee->ee_anim.run_list = eina_inlist_remove(ee->ee_anim.run_list, EINA_INLIST_GET(animator));
|
||||
|
||||
if (!_ecore_call_task_cb(animator->func, animator->data) || animator->delete_me)
|
||||
{
|
||||
if (animator->delete_me) continue;
|
||||
|
||||
animator->delete_me = EINA_TRUE;
|
||||
ee->ee_anim.deleted = eina_inlist_append(ee->ee_anim.deleted, EINA_INLIST_GET(animator));
|
||||
}
|
||||
else
|
||||
{
|
||||
ee->ee_anim.active = eina_inlist_append(ee->ee_anim.active, EINA_INLIST_GET(animator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_animator_tick(Ecore_Evas *ee, Eina_Rectangle *viewport, double loop_time)
|
||||
{
|
||||
|
@ -3062,6 +3133,8 @@ ecore_evas_animator_tick(Ecore_Evas *ee, Eina_Rectangle *viewport, double loop_t
|
|||
ee->animator_ran = EINA_TRUE;
|
||||
efl_event_callback_call(ee->evas, EFL_EVENT_ANIMATOR_TICK, &a);
|
||||
|
||||
if (ee->ee_anim.active)
|
||||
_ecore_evas_animators_do(ee);
|
||||
// FIXME: We do not support partial animator in the subcanvas
|
||||
EINA_LIST_FOREACH(ee->sub_ecore_evas, l, subee)
|
||||
{
|
||||
|
@ -5193,3 +5266,150 @@ ecore_evas_done(Ecore_Evas *ee, Eina_Bool single_window)
|
|||
if (single_window)
|
||||
evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
|
||||
}
|
||||
|
||||
static Ecore_Animator *
|
||||
_ecore_evas_animator_add(void *evo, Ecore_Task_Cb func, const void *data)
|
||||
{
|
||||
Ecore_Evas *ee;
|
||||
Ecore_Animator *animator;
|
||||
|
||||
if (EINA_UNLIKELY(!eina_main_loop_is()))
|
||||
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
||||
|
||||
if (!func)
|
||||
{
|
||||
ERR("callback function must be set up for an Ecore_Animator object.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(evo));
|
||||
if (!ee) return NULL;
|
||||
|
||||
/* If we don't have back-end specific ticks, fallback to old animators */
|
||||
if (!ee->engine.func->fn_animator_register) return NULL;
|
||||
|
||||
animator = calloc(1, sizeof(Ecore_Animator));
|
||||
if (!animator) return NULL;
|
||||
|
||||
animator->func = func;
|
||||
animator->data = (void *)data;
|
||||
animator->ee = ee;
|
||||
ee->ee_anim.active = eina_inlist_append(ee->ee_anim.active, EINA_INLIST_GET(animator));
|
||||
_ticking_start(ee);
|
||||
|
||||
return animator;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ecore_evas_animator_run(void *data)
|
||||
{
|
||||
Ecore_Animator *animator = data;
|
||||
double pos = 0.0, t;
|
||||
Eina_Bool run_ret;
|
||||
|
||||
t = ecore_loop_time_get();
|
||||
if (animator->run > 0.0)
|
||||
{
|
||||
pos = (t - animator->start) / animator->run;
|
||||
if (pos > 1.0) pos = 1.0;
|
||||
else if (pos < 0.0)
|
||||
pos = 0.0;
|
||||
}
|
||||
run_ret = animator->run_func(animator->run_data, pos);
|
||||
if (eina_dbl_exact(pos, 1.0)) run_ret = EINA_FALSE;
|
||||
return run_ret;
|
||||
}
|
||||
|
||||
static Ecore_Animator *
|
||||
_ecore_evas_animator_timeline_add(void *evo,
|
||||
double runtime,
|
||||
Ecore_Timeline_Cb func,
|
||||
const void *data)
|
||||
{
|
||||
Ecore_Animator *animator;
|
||||
|
||||
if (runtime <= 0.0) runtime = 0.0;
|
||||
|
||||
animator = _ecore_evas_animator_add(evo, _ecore_evas_animator_run, NULL);
|
||||
if (!animator) return NULL;
|
||||
|
||||
animator->data = animator;
|
||||
animator->run_func = func;
|
||||
animator->run_data = (void *)data;
|
||||
animator->start = ecore_loop_time_get();
|
||||
animator->run = runtime;
|
||||
|
||||
return animator;
|
||||
}
|
||||
|
||||
static void *
|
||||
_ecore_evas_animator_del(Ecore_Animator *in)
|
||||
{
|
||||
Ecore_Animator *animator = in;
|
||||
Ecore_Evas *ee;
|
||||
void *data = NULL;
|
||||
|
||||
if (animator->delete_me)
|
||||
return animator->data;
|
||||
ee = animator->ee;
|
||||
|
||||
_ecore_evas_animator_detach(animator);
|
||||
|
||||
ee->ee_anim.deleted = eina_inlist_append(ee->ee_anim.deleted, EINA_INLIST_GET(animator));
|
||||
animator->delete_me = EINA_TRUE;
|
||||
|
||||
if (animator->run_func)
|
||||
data = animator->run_data;
|
||||
else
|
||||
data = animator->data;
|
||||
|
||||
_ticking_stop(ee);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_evas_animator_flush(Ecore_Evas *ee)
|
||||
{
|
||||
Ecore_Animator *l;
|
||||
|
||||
EINA_INLIST_FREE(ee->ee_anim.deleted, l)
|
||||
{
|
||||
ee->ee_anim.deleted = eina_inlist_remove(ee->ee_anim.deleted, EINA_INLIST_GET(l));
|
||||
free(l);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_evas_animator_freeze(Ecore_Animator *in)
|
||||
{
|
||||
Ecore_Animator *animator = in;
|
||||
Ecore_Evas *ee;
|
||||
|
||||
ee = animator->ee;
|
||||
_ecore_evas_animator_detach(animator);
|
||||
|
||||
ee->ee_anim.suspended = eina_inlist_append(ee->ee_anim.suspended, EINA_INLIST_GET(animator));
|
||||
|
||||
animator->suspended = EINA_TRUE;
|
||||
_ticking_stop(ee);
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_evas_animator_thaw(Ecore_Animator *in)
|
||||
{
|
||||
Ecore_Animator *animator = in;
|
||||
Ecore_Evas *ee;
|
||||
|
||||
EINA_MAIN_LOOP_CHECK_RETURN;
|
||||
if (!animator) return;
|
||||
if (animator->delete_me) return;
|
||||
if (!animator->suspended) return;
|
||||
|
||||
ee = animator->ee;
|
||||
ee->ee_anim.suspended = eina_inlist_remove(ee->ee_anim.suspended,
|
||||
EINA_INLIST_GET(animator));
|
||||
animator->suspended = EINA_FALSE;
|
||||
ee->ee_anim.active = eina_inlist_append(ee->ee_anim.active,
|
||||
EINA_INLIST_GET(animator));
|
||||
_ticking_start(ee);
|
||||
}
|
||||
|
|
|
@ -332,6 +332,13 @@ struct _Ecore_Evas
|
|||
Ecore_Animator *anim;
|
||||
unsigned int animator_count;
|
||||
|
||||
struct {
|
||||
Eina_Inlist *active;
|
||||
Eina_Inlist *deleted;
|
||||
Eina_Inlist *suspended;
|
||||
Eina_Inlist *run_list;
|
||||
} ee_anim;
|
||||
|
||||
struct {
|
||||
unsigned char avoid_damage;
|
||||
unsigned char resize_shape : 1;
|
||||
|
|
Loading…
Reference in New Issue