summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-05-23 09:28:45 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-05-23 09:34:57 +0100
commit4a88067b2ee3a4ff368889323d5ed036ab16531e (patch)
tree5d5f0bf914f2e8fff3bd5a284677d3a2ae3f8755
parenta555fbf7693338d8b545d89f87a45852958a2166 (diff)
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.
-rw-r--r--src/lib/ecore_x/ecore_x_vsync.c154
1 files changed, 138 insertions, 16 deletions
diff --git a/src/lib/ecore_x/ecore_x_vsync.c b/src/lib/ecore_x/ecore_x_vsync.c
index a47e6df21c..d9b8529296 100644
--- a/src/lib/ecore_x/ecore_x_vsync.c
+++ b/src/lib/ecore_x/ecore_x_vsync.c
@@ -154,6 +154,9 @@ static Ecore_Thread *drm_thread = NULL;
154static Eina_Spinlock tick_queue_lock; 154static Eina_Spinlock tick_queue_lock;
155static int tick_queue_count = 0; 155static int tick_queue_count = 0;
156static Eina_Bool tick_skip = EINA_FALSE; 156static Eina_Bool tick_skip = EINA_FALSE;
157static Eina_Bool threaded_vsync = EINA_FALSE;
158static Ecore_Timer *fail_timer = NULL;
159static Ecore_Timer *fallback_timer = NULL;
157 160
158typedef struct 161typedef struct
159{ 162{
@@ -167,6 +170,37 @@ typedef struct
167# define D(args...) 170# define D(args...)
168#endif 171#endif
169 172
173static void _drm_send_time(double t);
174
175static Eina_Bool
176_fallback_timeout(void *data EINA_UNUSED)
177{
178 if (drm_event_is_busy)
179 {
180 _drm_send_time(ecore_loop_time_get());
181 return EINA_TRUE;
182 }
183 fallback_timer = NULL;
184 return EINA_FALSE;
185}
186
187static Eina_Bool
188_fail_timeout(void *data EINA_UNUSED)
189{
190 fail_timer = NULL;
191 _drm_fail_count++;
192 if (_drm_fail_count >= 10)
193 {
194 _drm_fail_count = 10;
195 if (!fallback_timer)
196 fallback_timer = ecore_timer_add
197 (1.0 / 60.0, _fallback_timeout, NULL);
198 }
199 if (drm_event_is_busy)
200 _drm_send_time(ecore_loop_time_get());
201 return EINA_FALSE;
202}
203
170static Eina_Bool 204static Eina_Bool
171_drm_tick_schedule(void) 205_drm_tick_schedule(void)
172{ 206{
@@ -196,7 +230,33 @@ _drm_tick_begin(void *data EINA_UNUSED)
196{ 230{
197 _drm_fail_count = 0; 231 _drm_fail_count = 0;
198 drm_event_is_busy = 1; 232 drm_event_is_busy = 1;
199 _tick_send(1); 233 if (threaded_vsync)
234 {
235 _tick_send(1);
236 }
237 else
238 {
239 if (fail_timer) ecore_timer_reset(fail_timer);
240 else fail_timer = ecore_timer_add(1.0 / 15.0, _fail_timeout, NULL);
241 if (_drm_fail_count < 10)
242 {
243 if (!_drm_tick_schedule())
244 {
245 _drm_fail_count = 999999;
246 if (!fallback_timer)
247 fallback_timer = ecore_timer_add
248 (1.0 / 60.0, _fallback_timeout, NULL);
249 }
250 }
251 else
252 {
253 if (!_drm_tick_schedule())
254 _drm_fail_count = 999999;
255 if (!fallback_timer)
256 fallback_timer = ecore_timer_add
257 (1.0 / 60.0, _fallback_timeout, NULL);
258 }
259 }
200} 260}
201 261
202static void 262static void
@@ -204,22 +264,64 @@ _drm_tick_end(void *data EINA_UNUSED)
204{ 264{
205 _drm_fail_count = 0; 265 _drm_fail_count = 0;
206 drm_event_is_busy = 0; 266 drm_event_is_busy = 0;
207 _tick_send(0); 267 if (threaded_vsync)
268 {
269 _tick_send(0);
270 }
271 else
272 {
273 if (fail_timer)
274 {
275 ecore_timer_del(fail_timer);
276 fail_timer = NULL;
277 }
278 if (fallback_timer)
279 {
280 ecore_timer_del(fallback_timer);
281 fallback_timer = NULL;
282 }
283 }
208} 284}
209 285
210static void 286static void
211_drm_send_time(double t) 287_drm_send_time(double t)
212{ 288{
213 double *tim = malloc(sizeof(*tim)); 289 if (threaded_vsync)
214 if (tim) 290 {
291 double *tim = malloc(sizeof(*tim));
292 if (tim)
293 {
294 *tim = t;
295 DBG(" ... send %1.8f", t);
296 D(" @%1.5f ... send %1.8f\n", ecore_time_get(), t);
297 eina_spinlock_take(&tick_queue_lock);
298 tick_queue_count++;
299 eina_spinlock_release(&tick_queue_lock);
300 ecore_thread_feedback(drm_thread, tim);
301 }
302 }
303 else
215 { 304 {
216 *tim = t; 305 if (drm_event_is_busy)
217 DBG(" ... send %1.8f", t); 306 {
218 D(" @%1.5f ... send %1.8f\n", ecore_time_get(), t); 307 if (_drm_fail_count == 0)
219 eina_spinlock_take(&tick_queue_lock); 308 {
220 tick_queue_count++; 309 if (fallback_timer)
221 eina_spinlock_release(&tick_queue_lock); 310 {
222 ecore_thread_feedback(drm_thread, tim); 311 ecore_timer_del(fallback_timer);
312 fallback_timer = NULL;
313 }
314 }
315 ecore_loop_time_set(t);
316 ecore_animator_custom_tick();
317 if (drm_event_is_busy)
318 {
319 if (fail_timer) ecore_timer_reset(fail_timer);
320 else fail_timer = ecore_timer_add(1.0 / 15.0, _fail_timeout, NULL);
321 if (!_drm_tick_schedule())
322 _drm_fail_count = 999999;
323 }
324 }
223 } 325 }
224} 326}
225 327
@@ -272,6 +374,7 @@ _drm_vblank_handler(int fd EINA_UNUSED,
272 tdelta_avg = 0.0; 374 tdelta_avg = 0.0;
273 tdelta_n = 0; 375 tdelta_n = 0;
274 } 376 }
377 _drm_fail_count = 0;
275 _drm_send_time(t); 378 _drm_send_time(t);
276 pframe = frame; 379 pframe = frame;
277 } 380 }
@@ -428,6 +531,15 @@ _drm_tick_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void
428 free(msg); 531 free(msg);
429} 532}
430 533
534static Eina_Bool
535_ecore_vsync_fd_handler(void *data EINA_UNUSED,
536 Ecore_Fd_Handler *fd_handler EINA_UNUSED)
537{
538 _ecore_x_vsync_wakeup_time = ecore_time_get();
539 sym_drmHandleEvent(drm_fd, &drm_evctx);
540 return ECORE_CALLBACK_RENEW;
541}
542
431// yes. most evil. we dlopen libdrm and libGL etc. to manually find smbols 543// yes. most evil. we dlopen libdrm and libGL etc. to manually find smbols
432// so we can be as compatible as possible given the whole mess of the 544// so we can be as compatible as possible given the whole mess of the
433// gl/dri/drm etc. world. and handle graceful failure at runtime not 545// gl/dri/drm etc. world. and handle graceful failure at runtime not
@@ -701,11 +813,20 @@ checkdone:
701 } 813 }
702 814
703 if (getenv("ECORE_ANIMATOR_SKIP")) tick_skip = EINA_TRUE; 815 if (getenv("ECORE_ANIMATOR_SKIP")) tick_skip = EINA_TRUE;
704 tick_queue_count = 0; 816 if (threaded_vsync)
705 eina_spinlock_new(&tick_queue_lock); 817 {
706 thq = eina_thread_queue_new(); 818 tick_queue_count = 0;
707 drm_thread = ecore_thread_feedback_run(_drm_tick_core, _drm_tick_notify, 819 eina_spinlock_new(&tick_queue_lock);
708 NULL, NULL, NULL, EINA_TRUE); 820 thq = eina_thread_queue_new();
821 drm_thread = ecore_thread_feedback_run(_drm_tick_core, _drm_tick_notify,
822 NULL, NULL, NULL, EINA_TRUE);
823 }
824 else
825 {
826 ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ,
827 _ecore_vsync_fd_handler, NULL,
828 NULL, NULL);
829 }
709 return 1; 830 return 1;
710} 831}
711 832
@@ -785,6 +906,7 @@ ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
785 const char *home; 906 const char *home;
786 struct stat st; 907 struct stat st;
787 908
909 if (getenv("ECORE_VSYNC_TRHEAD")) threaded_vsync = EINA_TRUE;
788 home = eina_environment_home_get(); 910 home = eina_environment_home_get();
789 if (!home) eina_environment_tmp_get(); 911 if (!home) eina_environment_tmp_get();
790 snprintf(buf, sizeof(buf), "%s/.ecore-no-vsync", home); 912 snprintf(buf, sizeof(buf), "%s/.ecore-no-vsync", home);