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
{
# 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)
{
{
_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
{
_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)
+ {
+ 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
{
- *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);
+ 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;
+ }
+ }
}
}
tdelta_avg = 0.0;
tdelta_n = 0;
}
+ _drm_fail_count = 0;
_drm_send_time(t);
pframe = frame;
}
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
}
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;
}
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);