forked from enlightenment/efl
Add a custom Ecore Aniamtor source and tick ability to be able
to plug in external animator tick sources like vblank interrupts and so on. SVN revision: 59345
This commit is contained in:
parent
909e11f49f
commit
7fbe314439
|
@ -167,3 +167,8 @@
|
|||
* Fixed null pointer dereference in selection notification
|
||||
handling in Ecore_X.
|
||||
|
||||
2011-05-12 Carsten Haitzler (The Rasterman)
|
||||
|
||||
* Add a custom Ecore Aniamtor source and tick ability to be able
|
||||
to plug in external animator tick sources like vblank interrupts
|
||||
and so on.
|
||||
|
|
|
@ -162,6 +162,13 @@ extern "C" {
|
|||
};
|
||||
typedef enum _Ecore_Pos_Map Ecore_Pos_Map;
|
||||
|
||||
enum _Ecore_Animator_Source /* Timing sources for animators */
|
||||
{
|
||||
ECORE_ANIMATOR_SOURCE_TIMER, /**< The default system clock/timer based animator that ticks every "frametime" seconds */
|
||||
ECORE_ANIMATOR_SOURCE_CUSTOM /**< A custom animator trigger that you need to call ecore_animator_trigger() to make it tick */
|
||||
};
|
||||
typedef enum _Ecore_Animator_Source Ecore_Animator_Source;
|
||||
|
||||
typedef struct _Ecore_Exe Ecore_Exe; /**< A handle for spawned processes */
|
||||
typedef struct _Ecore_Timer Ecore_Timer; /**< A handle for timers */
|
||||
typedef struct _Ecore_Idler Ecore_Idler; /**< A handle for idlers */
|
||||
|
@ -582,6 +589,11 @@ extern "C" {
|
|||
EAPI void ecore_animator_frametime_set(double frametime);
|
||||
EAPI double ecore_animator_frametime_get(void);
|
||||
EAPI double ecore_animator_pos_map(double pos, Ecore_Pos_Map map, double v1, double v2);
|
||||
EAPI void ecore_animator_source_set(Ecore_Animator_Source source);
|
||||
EAPI Ecore_Animator_Source ecore_animator_source_get(void);
|
||||
EAPI void ecore_animator_custom_source_tick_begin_callback_set(Ecore_Cb func, const void *data);
|
||||
EAPI void ecore_animator_custom_source_tick_end_callback_set(Ecore_Cb func, const void *data);
|
||||
EAPI void ecore_animator_custom_tick(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
|
|
@ -29,11 +29,110 @@ struct _Ecore_Animator
|
|||
static Eina_Bool _ecore_animator_run(void *data);
|
||||
static Eina_Bool _ecore_animator(void *data);
|
||||
|
||||
static Ecore_Timer *timer = NULL;
|
||||
static int animators_delete_me = 0;
|
||||
static Ecore_Animator *animators = NULL;
|
||||
static double animators_frametime = 1.0 / 30.0;
|
||||
|
||||
static Ecore_Animator_Source src = ECORE_ANIMATOR_SOURCE_TIMER;
|
||||
static Ecore_Timer *timer = NULL;
|
||||
static int ticking = 0;
|
||||
static Ecore_Cb begin_tick_cb = NULL;
|
||||
static const void *begin_tick_data = NULL;
|
||||
static Ecore_Cb end_tick_cb = NULL;
|
||||
static const void *end_tick_data = NULL;
|
||||
|
||||
static void
|
||||
_begin_tick(void)
|
||||
{
|
||||
if (ticking) return;
|
||||
ticking = 1;
|
||||
switch (src)
|
||||
{
|
||||
case ECORE_ANIMATOR_SOURCE_TIMER:
|
||||
if (!timer)
|
||||
{
|
||||
double t_loop = ecore_loop_time_get();
|
||||
double sync_0 = 0.0;
|
||||
double d = -fmod(t_loop - sync_0, animators_frametime);
|
||||
|
||||
timer = ecore_timer_loop_add(animators_frametime,
|
||||
_ecore_animator, NULL);
|
||||
ecore_timer_delay(timer, d);
|
||||
}
|
||||
break;
|
||||
case ECORE_ANIMATOR_SOURCE_CUSTOM:
|
||||
if (begin_tick_cb) begin_tick_cb((void *)begin_tick_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_end_tick(void)
|
||||
{
|
||||
if (!ticking) return;
|
||||
ticking = 0;
|
||||
switch (src)
|
||||
{
|
||||
case ECORE_ANIMATOR_SOURCE_TIMER:
|
||||
if (timer)
|
||||
{
|
||||
ecore_timer_del(timer);
|
||||
timer = NULL;
|
||||
}
|
||||
break;
|
||||
case ECORE_ANIMATOR_SOURCE_CUSTOM:
|
||||
if (end_tick_cb) end_tick_cb((void *)end_tick_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_do_tick(void)
|
||||
{
|
||||
Ecore_Animator *animator;
|
||||
|
||||
EINA_INLIST_FOREACH(animators, animator)
|
||||
{
|
||||
if (!animator->delete_me && !animator->suspended)
|
||||
{
|
||||
if (!animator->func(animator->data))
|
||||
{
|
||||
animator->delete_me = EINA_TRUE;
|
||||
animators_delete_me++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (animators_delete_me)
|
||||
{
|
||||
Ecore_Animator *l;
|
||||
for (l = animators; l;)
|
||||
{
|
||||
animator = l;
|
||||
l = (Ecore_Animator *) EINA_INLIST_GET(l)->next;
|
||||
if (animator->delete_me)
|
||||
{
|
||||
animators = (Ecore_Animator *)
|
||||
eina_inlist_remove(EINA_INLIST_GET(animators),
|
||||
EINA_INLIST_GET(animator));
|
||||
ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE);
|
||||
free(animator);
|
||||
animators_delete_me--;
|
||||
if (animators_delete_me == 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!animators)
|
||||
{
|
||||
_end_tick();
|
||||
return ECORE_CALLBACK_CANCEL;
|
||||
}
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
/**
|
||||
* @addtogroup Ecore_Group Ecore - Main Loop and Job Functions.
|
||||
*
|
||||
|
@ -74,15 +173,7 @@ ecore_animator_add(Ecore_Task_Cb func, const void *data)
|
|||
animator->func = func;
|
||||
animator->data = (void *)data;
|
||||
animators = (Ecore_Animator *)eina_inlist_append(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
|
||||
if (!timer)
|
||||
{
|
||||
double t_loop = ecore_loop_time_get();
|
||||
double sync_0 = 0.0;
|
||||
double d = -fmod(t_loop - sync_0, animators_frametime);
|
||||
|
||||
timer = ecore_timer_loop_add(animators_frametime, _ecore_animator, NULL);
|
||||
ecore_timer_delay(timer, d);
|
||||
}
|
||||
_begin_tick();
|
||||
return animator;
|
||||
}
|
||||
|
||||
|
@ -280,13 +371,8 @@ ecore_animator_frametime_set(double frametime)
|
|||
if (frametime < 0.0) frametime = 0.0;
|
||||
if (animators_frametime == frametime) return;
|
||||
animators_frametime = frametime;
|
||||
if (timer)
|
||||
{
|
||||
ecore_timer_del(timer);
|
||||
timer = NULL;
|
||||
}
|
||||
if (animators)
|
||||
timer = ecore_timer_add(animators_frametime, _ecore_animator, NULL);
|
||||
_end_tick();
|
||||
if (animators) _begin_tick();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -341,14 +427,111 @@ ecore_animator_thaw(Ecore_Animator *animator)
|
|||
animator->suspended = EINA_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source of animator ticks for the mainloop
|
||||
*
|
||||
* @param source The source of animator ticks to use
|
||||
*
|
||||
* This sets the source of animator ticks. When an animator is active the
|
||||
* mainloop will "tick" over frame by frame calling all animators that are
|
||||
* registered until none are. The mainloop will tick at a given rate based
|
||||
* on the animator source. The default source is the system clock timer
|
||||
* source - ECORE_ANIMATOR_SOURCE_TIMER. This source uses the system clock
|
||||
* to tick over every N seconds (specified by ecore_animator_frametime_set(),
|
||||
* with the default being 1/30th of a second unless set otherwise). You can
|
||||
* set a custom tick source by setting the source to
|
||||
* ECORE_ANIMATOR_SOURCE_CUSTOM and then drive it yourself based on some input
|
||||
* tick source (like another application via ipc, some vertical blanking
|
||||
* interrupt etc.) using ecore_animator_custom_source_tick_begin_callback_set()
|
||||
* and ecore_animator_custom_source_tick_end_callback_set() to set the
|
||||
* functions that will be called to start and stop the ticking source, which
|
||||
* when it gets a "tick" should call ecore_animator_custom_tick() to make
|
||||
* the animator "tick" over 1 frame.
|
||||
*/
|
||||
EAPI void
|
||||
ecore_animator_source_set(Ecore_Animator_Source source)
|
||||
{
|
||||
src = source;
|
||||
_end_tick();
|
||||
if (animators) _begin_tick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animator source currently set
|
||||
* @return The current animator source
|
||||
*
|
||||
* This gets the current animator source. See ecore_animator_source_set() for
|
||||
* more information.
|
||||
*/
|
||||
EAPI Ecore_Animator_Source
|
||||
ecore_animator_source_get(void)
|
||||
{
|
||||
return src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function that begins a custom animator tick source
|
||||
*
|
||||
* @param func The function to call when ticking is to begin
|
||||
* @param data The data passed to the tick begin function as its parameter
|
||||
*
|
||||
* The Ecore Animator infrastructure handles tracking if animators are needed
|
||||
* or not and which ones need to be called and when, but when the tick source
|
||||
* is custom, you have to provide a tick source by calling
|
||||
* ecore_animator_custom_tick() to indicate a frame tick happened. In order
|
||||
* to allow the source of ticks to be dynamically enabled or disabled as
|
||||
* needed, the @p func when set is called to enable the tick source to
|
||||
* produce tick events that call ecore_animator_custom_tick(). If @p func
|
||||
* is NULL then no function is called to begin custom ticking.
|
||||
*/
|
||||
EAPI void
|
||||
ecore_animator_custom_source_tick_begin_callback_set(Ecore_Cb func, const void *data)
|
||||
{
|
||||
begin_tick_cb = func;
|
||||
begin_tick_data = data;
|
||||
_end_tick();
|
||||
if (animators) _begin_tick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function that ends a custom animator tick source
|
||||
* @param func The function to call when ticking is to end
|
||||
* @param data The data passed to the tick end function as its parameter
|
||||
*
|
||||
* This function is a matching pair to the function set by
|
||||
* ecore_animator_custom_source_tick_begin_callback_set() and is called
|
||||
* when ticking is to stop. If @p func is NULL then no function will be
|
||||
* called to stop ticking. For more information please see
|
||||
* ecore_animator_custom_source_tick_begin_callback_set().
|
||||
*/
|
||||
EAPI void
|
||||
ecore_animator_custom_source_tick_end_callback_set(Ecore_Cb func, const void *data)
|
||||
{
|
||||
end_tick_cb = func;
|
||||
end_tick_data = data;
|
||||
_end_tick();
|
||||
if (animators) _begin_tick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a custom animator tick
|
||||
*
|
||||
* When animator source is set to ECORE_ANIMATOR_SOURCE_CUSTOM, then calling
|
||||
* this function triggers a run of all animators currently registered with
|
||||
* Ecore as this indicates a "frame tick" happened. This will do nothing
|
||||
* if the animator source (set by ecore_animator_source_set() ) is not set
|
||||
* to ECORE_ANIMATOR_SOURCE_CUSTOM.
|
||||
*/
|
||||
EAPI void
|
||||
ecore_animator_custom_tick(void)
|
||||
{
|
||||
if (src == ECORE_ANIMATOR_SOURCE_CUSTOM) _do_tick();
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_animator_shutdown(void)
|
||||
{
|
||||
if (timer)
|
||||
{
|
||||
ecore_timer_del(timer);
|
||||
timer = NULL;
|
||||
}
|
||||
_end_tick();
|
||||
while (animators)
|
||||
{
|
||||
Ecore_Animator *animator;
|
||||
|
@ -382,42 +565,7 @@ _ecore_animator_run(void *data)
|
|||
static Eina_Bool
|
||||
_ecore_animator(void *data __UNUSED__)
|
||||
{
|
||||
Ecore_Animator *animator;
|
||||
|
||||
EINA_INLIST_FOREACH(animators, animator)
|
||||
{
|
||||
if (!animator->delete_me && !animator->suspended)
|
||||
{
|
||||
if (!animator->func(animator->data))
|
||||
{
|
||||
animator->delete_me = EINA_TRUE;
|
||||
animators_delete_me++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (animators_delete_me)
|
||||
{
|
||||
Ecore_Animator *l;
|
||||
for(l = animators; l;)
|
||||
{
|
||||
animator = l;
|
||||
l = (Ecore_Animator *) EINA_INLIST_GET(l)->next;
|
||||
if (animator->delete_me)
|
||||
{
|
||||
animators = (Ecore_Animator *) eina_inlist_remove(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
|
||||
ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE);
|
||||
free(animator);
|
||||
animators_delete_me--;
|
||||
if (animators_delete_me == 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!animators)
|
||||
{
|
||||
timer = NULL;
|
||||
return ECORE_CALLBACK_CANCEL;
|
||||
}
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
return _do_tick();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue