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:
Carsten Haitzler 2020-05-23 09:28:45 +01:00
parent a555fbf769
commit 4a88067b2e
1 changed files with 138 additions and 16 deletions

View File

@ -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);