forked from enlightenment/efl
ecore-x : move x vsync device back to mainloop from thread
after i noticed some jitters, it seesms one thread to listen for vsync events then to wake up the mainloop can suffer from irregular scheduling jitters. it seems to be highly depenedent on both gpu driver and cpu but it seemed the vsync thread itself was more reliably woken than the mainlooop it then signalled, so merging this back is just batter. it's configurable via an environment variable so we can try either right now and see, but default is now to be in main loop.
This commit is contained in:
parent
a555fbf769
commit
4a88067b2e
|
@ -154,6 +154,9 @@ static Ecore_Thread *drm_thread = NULL;
|
|||
static Eina_Spinlock tick_queue_lock;
|
||||
static int tick_queue_count = 0;
|
||||
static Eina_Bool tick_skip = EINA_FALSE;
|
||||
static Eina_Bool threaded_vsync = EINA_FALSE;
|
||||
static Ecore_Timer *fail_timer = NULL;
|
||||
static Ecore_Timer *fallback_timer = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -167,6 +170,37 @@ typedef struct
|
|||
# define D(args...)
|
||||
#endif
|
||||
|
||||
static void _drm_send_time(double t);
|
||||
|
||||
static Eina_Bool
|
||||
_fallback_timeout(void *data EINA_UNUSED)
|
||||
{
|
||||
if (drm_event_is_busy)
|
||||
{
|
||||
_drm_send_time(ecore_loop_time_get());
|
||||
return EINA_TRUE;
|
||||
}
|
||||
fallback_timer = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_fail_timeout(void *data EINA_UNUSED)
|
||||
{
|
||||
fail_timer = NULL;
|
||||
_drm_fail_count++;
|
||||
if (_drm_fail_count >= 10)
|
||||
{
|
||||
_drm_fail_count = 10;
|
||||
if (!fallback_timer)
|
||||
fallback_timer = ecore_timer_add
|
||||
(1.0 / 60.0, _fallback_timeout, NULL);
|
||||
}
|
||||
if (drm_event_is_busy)
|
||||
_drm_send_time(ecore_loop_time_get());
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_drm_tick_schedule(void)
|
||||
{
|
||||
|
@ -196,7 +230,33 @@ _drm_tick_begin(void *data EINA_UNUSED)
|
|||
{
|
||||
_drm_fail_count = 0;
|
||||
drm_event_is_busy = 1;
|
||||
_tick_send(1);
|
||||
if (threaded_vsync)
|
||||
{
|
||||
_tick_send(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fail_timer) ecore_timer_reset(fail_timer);
|
||||
else fail_timer = ecore_timer_add(1.0 / 15.0, _fail_timeout, NULL);
|
||||
if (_drm_fail_count < 10)
|
||||
{
|
||||
if (!_drm_tick_schedule())
|
||||
{
|
||||
_drm_fail_count = 999999;
|
||||
if (!fallback_timer)
|
||||
fallback_timer = ecore_timer_add
|
||||
(1.0 / 60.0, _fallback_timeout, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_drm_tick_schedule())
|
||||
_drm_fail_count = 999999;
|
||||
if (!fallback_timer)
|
||||
fallback_timer = ecore_timer_add
|
||||
(1.0 / 60.0, _fallback_timeout, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -204,22 +264,64 @@ _drm_tick_end(void *data EINA_UNUSED)
|
|||
{
|
||||
_drm_fail_count = 0;
|
||||
drm_event_is_busy = 0;
|
||||
_tick_send(0);
|
||||
if (threaded_vsync)
|
||||
{
|
||||
_tick_send(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fail_timer)
|
||||
{
|
||||
ecore_timer_del(fail_timer);
|
||||
fail_timer = NULL;
|
||||
}
|
||||
if (fallback_timer)
|
||||
{
|
||||
ecore_timer_del(fallback_timer);
|
||||
fallback_timer = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_drm_send_time(double t)
|
||||
{
|
||||
double *tim = malloc(sizeof(*tim));
|
||||
if (tim)
|
||||
if (threaded_vsync)
|
||||
{
|
||||
*tim = t;
|
||||
DBG(" ... send %1.8f", t);
|
||||
D(" @%1.5f ... send %1.8f\n", ecore_time_get(), t);
|
||||
eina_spinlock_take(&tick_queue_lock);
|
||||
tick_queue_count++;
|
||||
eina_spinlock_release(&tick_queue_lock);
|
||||
ecore_thread_feedback(drm_thread, tim);
|
||||
double *tim = malloc(sizeof(*tim));
|
||||
if (tim)
|
||||
{
|
||||
*tim = t;
|
||||
DBG(" ... send %1.8f", t);
|
||||
D(" @%1.5f ... send %1.8f\n", ecore_time_get(), t);
|
||||
eina_spinlock_take(&tick_queue_lock);
|
||||
tick_queue_count++;
|
||||
eina_spinlock_release(&tick_queue_lock);
|
||||
ecore_thread_feedback(drm_thread, tim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (drm_event_is_busy)
|
||||
{
|
||||
if (_drm_fail_count == 0)
|
||||
{
|
||||
if (fallback_timer)
|
||||
{
|
||||
ecore_timer_del(fallback_timer);
|
||||
fallback_timer = NULL;
|
||||
}
|
||||
}
|
||||
ecore_loop_time_set(t);
|
||||
ecore_animator_custom_tick();
|
||||
if (drm_event_is_busy)
|
||||
{
|
||||
if (fail_timer) ecore_timer_reset(fail_timer);
|
||||
else fail_timer = ecore_timer_add(1.0 / 15.0, _fail_timeout, NULL);
|
||||
if (!_drm_tick_schedule())
|
||||
_drm_fail_count = 999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,6 +374,7 @@ _drm_vblank_handler(int fd EINA_UNUSED,
|
|||
tdelta_avg = 0.0;
|
||||
tdelta_n = 0;
|
||||
}
|
||||
_drm_fail_count = 0;
|
||||
_drm_send_time(t);
|
||||
pframe = frame;
|
||||
}
|
||||
|
@ -428,6 +531,15 @@ _drm_tick_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void
|
|||
free(msg);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ecore_vsync_fd_handler(void *data EINA_UNUSED,
|
||||
Ecore_Fd_Handler *fd_handler EINA_UNUSED)
|
||||
{
|
||||
_ecore_x_vsync_wakeup_time = ecore_time_get();
|
||||
sym_drmHandleEvent(drm_fd, &drm_evctx);
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
// yes. most evil. we dlopen libdrm and libGL etc. to manually find smbols
|
||||
// so we can be as compatible as possible given the whole mess of the
|
||||
// gl/dri/drm etc. world. and handle graceful failure at runtime not
|
||||
|
@ -701,11 +813,20 @@ checkdone:
|
|||
}
|
||||
|
||||
if (getenv("ECORE_ANIMATOR_SKIP")) tick_skip = EINA_TRUE;
|
||||
tick_queue_count = 0;
|
||||
eina_spinlock_new(&tick_queue_lock);
|
||||
thq = eina_thread_queue_new();
|
||||
drm_thread = ecore_thread_feedback_run(_drm_tick_core, _drm_tick_notify,
|
||||
NULL, NULL, NULL, EINA_TRUE);
|
||||
if (threaded_vsync)
|
||||
{
|
||||
tick_queue_count = 0;
|
||||
eina_spinlock_new(&tick_queue_lock);
|
||||
thq = eina_thread_queue_new();
|
||||
drm_thread = ecore_thread_feedback_run(_drm_tick_core, _drm_tick_notify,
|
||||
NULL, NULL, NULL, EINA_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ,
|
||||
_ecore_vsync_fd_handler, NULL,
|
||||
NULL, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -785,6 +906,7 @@ ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
|
|||
const char *home;
|
||||
struct stat st;
|
||||
|
||||
if (getenv("ECORE_VSYNC_TRHEAD")) threaded_vsync = EINA_TRUE;
|
||||
home = eina_environment_home_get();
|
||||
if (!home) eina_environment_tmp_get();
|
||||
snprintf(buf, sizeof(buf), "%s/.ecore-no-vsync", home);
|
||||
|
|
Loading…
Reference in New Issue