raster pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=aaefbaa43ebea08ecd67732a785bf89c3b7f847e
commit aaefbaa43ebea08ecd67732a785bf89c3b7f847e Author: Carsten Haitzler (Rasterman) <[email protected]> Date: Tue Jul 29 20:00:53 2014 +0900 ecore_x - vsync fix drm support to work again due to mesa changes to hide dri2 symbols, i have had to work on a fix that makes this work again by going right to drm. now it works and animators shoudl be vsynced on drm drivers if possible (only 1 card - use card 0). already existing nvidia solution that uses a lot more memory is there. others - no support. timers only --- src/lib/ecore_x/xlib/ecore_x_image.c | 15 ++- src/lib/ecore_x/xlib/ecore_x_vsync.c | 252 ++++++++++++++++------------------- 2 files changed, 123 insertions(+), 144 deletions(-) diff --git a/src/lib/ecore_x/xlib/ecore_x_image.c b/src/lib/ecore_x/xlib/ecore_x_image.c index 6188cb0..6dfe931 100644 --- a/src/lib/ecore_x/xlib/ecore_x_image.c +++ b/src/lib/ecore_x/xlib/ecore_x_image.c @@ -86,7 +86,7 @@ _ecore_x_image_error_handler(Display *d EINA_UNUSED, XErrorEvent *ev) return 0; } -static void +int _ecore_x_image_shm_check(void) { XErrorHandler ph; @@ -94,12 +94,12 @@ _ecore_x_image_shm_check(void) XImage *xim; if (_ecore_x_image_shm_can != -1) - return; + return _ecore_x_image_shm_can; if (!XShmQueryExtension(_ecore_x_disp)) { _ecore_x_image_shm_can = 0; - return; + return _ecore_x_image_shm_can; } XSync(_ecore_x_disp, False); @@ -116,7 +116,7 @@ _ecore_x_image_shm_check(void) if (!xim) { _ecore_x_image_shm_can = 0; - return; + return _ecore_x_image_shm_can; } shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height, @@ -126,7 +126,7 @@ _ecore_x_image_shm_check(void) ERR("%s", strerror(errno)); XDestroyImage(xim); _ecore_x_image_shm_can = 0; - return; + return _ecore_x_image_shm_can; } shminfo.readOnly = False; @@ -137,7 +137,7 @@ _ecore_x_image_shm_check(void) { XDestroyImage(xim); _ecore_x_image_shm_can = 0; - return; + return _ecore_x_image_shm_can; } ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler); @@ -153,7 +153,7 @@ _ecore_x_image_shm_check(void) shmdt(shminfo.shmaddr); shmctl(shminfo.shmid, IPC_RMID, 0); _ecore_x_image_shm_can = 0; - return; + return _ecore_x_image_shm_can; } XShmDetach(_ecore_x_disp, &shminfo); @@ -162,6 +162,7 @@ _ecore_x_image_shm_check(void) shmctl(shminfo.shmid, IPC_RMID, 0); _ecore_x_image_shm_can = 1; + return _ecore_x_image_shm_can; } struct _Ecore_X_Image diff --git a/src/lib/ecore_x/xlib/ecore_x_vsync.c b/src/lib/ecore_x/xlib/ecore_x_vsync.c index a228e9e..7aed4be 100644 --- a/src/lib/ecore_x/xlib/ecore_x_vsync.c +++ b/src/lib/ecore_x/xlib/ecore_x_vsync.c @@ -16,20 +16,19 @@ #include <sys/stat.h> #include <fcntl.h> -#define ECORE_X_VSYNC_DRI2 1 +#define ECORE_X_VSYNC_DRM 1 static Ecore_X_Window vsync_root = 0; +int _ecore_x_image_shm_check(void); -#ifdef ECORE_X_VSYNC_DRI2 +#ifdef ECORE_X_VSYNC_DRM // relevant header bits of dri/drm inlined here to avoid needing external // headers to build /// drm -typedef unsigned int drm_magic_t; - typedef enum { DRM_VBLANK_ABSOLUTE = 0x00000000, @@ -81,49 +80,24 @@ typedef struct _drmEventContext } drmEventContext; static int (*sym_drmClose)(int fd) = NULL; -static int (*sym_drmGetMagic)(int fd, - drm_magic_t *magic) = NULL; static int (*sym_drmWaitVBlank)(int fd, drmVBlank *vbl) = NULL; static int (*sym_drmHandleEvent)(int fd, drmEventContext *evctx) = NULL; - -//// dri - -static Bool (*sym_DRI2QueryExtension)(Display *display, - int *eventBase, - int *errorBase) = NULL; -static Bool (*sym_DRI2QueryVersion)(Display *display, - int *major, - int *minor) = NULL; -static Bool (*sym_DRI2Connect)(Display *display, - XID window, - char **driverName, - char **deviceName) = NULL; -static Bool (*sym_DRI2Authenticate)(Display *display, - XID window, - drm_magic_t magic) = NULL; - -//// dri/drm data needed -static int dri2_event = 0; -static int dri2_error = 0; -static int dri2_major = 0; -static int dri2_minor = 0; -static char *device_name = 0; -static char *driver_name = 0; -static drm_magic_t drm_magic; - static int drm_fd = -1; static int drm_event_is_busy = 0; static int drm_animators_interval = 1; static drmEventContext drm_evctx; static Ecore_Fd_Handler *dri_drm_fdh = NULL; +static Ecore_Timer *_drm_fail_timer = NULL; +static double _drm_fail_time = 0.1; +static double _drm_fail_time2 = 1.0 / 60.0; +static int _drm_fail_count = 0; -static void *dri_lib = NULL; static void *drm_lib = NULL; static Eina_Bool -_dri_drm_tick_schedule(void) +_drm_tick_schedule(void) { drmVBlank vbl; @@ -135,35 +109,72 @@ _dri_drm_tick_schedule(void) } static void -_dri_drm_tick_begin(void *data EINA_UNUSED) +_drm_tick_begin(void *data EINA_UNUSED) { drm_event_is_busy = 1; - _dri_drm_tick_schedule(); + _drm_tick_schedule(); } static void -_dri_drm_tick_end(void *data EINA_UNUSED) +_drm_tick_end(void *data EINA_UNUSED) { + if (_drm_fail_timer) + { + ecore_timer_del(_drm_fail_timer); + _drm_fail_timer = NULL; + } drm_event_is_busy = 0; } -static void -_dri_drm_vblank_handler(int fd EINA_UNUSED, - unsigned int frame EINA_UNUSED, - unsigned int sec EINA_UNUSED, - unsigned int usec EINA_UNUSED, - void *data EINA_UNUSED) +static Eina_Bool +_drm_fail_cb(void *data EINA_UNUSED) { if (drm_event_is_busy) { - // XXX: set looptime + _drm_fail_count++; + DBG("VSYNC FAIL %i %3.8f", _drm_fail_count, ecore_loop_time_get()); ecore_animator_custom_tick(); - _dri_drm_tick_schedule(); + _drm_tick_schedule(); + if (_drm_fail_count == 10) + { + _drm_fail_timer = ecore_timer_add(_drm_fail_time2, _drm_fail_cb, NULL); + return EINA_FALSE; + } + } + return EINA_TRUE; +} + +static void +_drm_vblank_handler(int fd EINA_UNUSED, + unsigned int frame, + unsigned int sec, + unsigned int usec, + void *data EINA_UNUSED) +{ + if (drm_event_is_busy) + { + double tim; + static double ptim = 0.0; + static unsigned int pframe = 0; + + if (pframe != frame) + { + tim = (double)sec + ((double)usec / 1000000); + DBG("VSYNC %1.8f [%i] = delt %1.8f\n", tim, frame - pframe, tim - ptim); + ecore_loop_time_set(tim); + ecore_animator_custom_tick(); + _drm_tick_schedule(); + pframe = frame; + ptim = tim; + if (_drm_fail_timer) ecore_timer_del(_drm_fail_timer); + _drm_fail_timer = ecore_timer_add(_drm_fail_time, _drm_fail_cb, NULL); + _drm_fail_count = 0; + } } } static Eina_Bool -_dri_drm_cb(void *data EINA_UNUSED, +_drm_cb(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler EINA_UNUSED) { sym_drmHandleEvent(drm_fd, &drm_evctx); @@ -175,7 +186,7 @@ _dri_drm_cb(void *data EINA_UNUSED, // gl/dri/drm etc. world. and handle graceful failure at runtime not // compile time static int -_dri_drm_link(void) +_drm_link(void) { const char *drm_libs[] = { @@ -185,30 +196,16 @@ _dri_drm_link(void) "libdrm.so", NULL, }; - const char *dri_libs[] = - { - "libdri2.so.2", - "libdri2.so.1", - "libdri2.so.0", - "libdri2.so", - "libGL.so.4", - "libGL.so.3", - "libGL.so.2", - "libGL.so.1", - "libGL.so.0", - "libGL.so", - NULL, - }; int i, fail; -#define SYM(lib, xx) \ - do { \ - sym_ ## xx = dlsym(lib, #xx); \ - if (!(sym_ ## xx)) { \ - fail = 1; \ - } \ - } while (0) - - if (dri_lib) return 1; +#define SYM(lib, xx) \ + do { \ + sym_ ## xx = dlsym(lib, #xx); \ + if (!(sym_ ## xx)) { \ + fail = 1; \ + } \ + } while (0) + + if (drm_lib) return 1; for (i = 0; drm_libs[i]; i++) { drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY); @@ -227,60 +224,31 @@ _dri_drm_link(void) } } if (!drm_lib) return 0; - for (i = 0; dri_libs[i]; i++) - { - dri_lib = dlopen(dri_libs[i], RTLD_LOCAL | RTLD_LAZY); - if (dri_lib) - { - fail = 0; - SYM(dri_lib, DRI2QueryExtension); - SYM(dri_lib, DRI2QueryVersion); - SYM(dri_lib, DRI2Connect); - SYM(dri_lib, DRI2Authenticate); - if (fail) - { - dlclose(dri_lib); - dri_lib = NULL; - } - else break; - } - } - if (!dri_lib) - { - dlclose(drm_lib); - drm_lib = NULL; - return 0; - } return 1; } static int -_dri_drm_init(void) +_drm_init(void) { - if (!sym_DRI2QueryExtension(_ecore_x_disp, &dri2_event, &dri2_error)) - return 0; - if (!sym_DRI2QueryVersion(_ecore_x_disp, &dri2_major, &dri2_minor)) - return 0; - if (dri2_major < 2) - return 0; - if (!sym_DRI2Connect(_ecore_x_disp, vsync_root, &driver_name, &device_name)) - return 0; - drm_fd = open(device_name, O_RDWR); - if (drm_fd < 0) - return 0; - sym_drmGetMagic(drm_fd, &drm_magic); - if (!sym_DRI2Authenticate(_ecore_x_disp, vsync_root, drm_magic)) + struct stat st; + char buf[512]; + + snprintf(buf, sizeof(buf), "/dev/dri/card1"); + if (stat(buf, &st) == 0) { - close(drm_fd); - drm_fd = -1; + // XXX: 2 dri cards - ambiguous. unknown device for screen return 0; } + snprintf(buf, sizeof(buf), "/dev/dri/card0"); + if (stat(buf, &st) != 0) return 0; + drm_fd = open(buf, O_RDWR); + if (drm_fd < 0) return 0; memset(&drm_evctx, 0, sizeof(drm_evctx)); drm_evctx.version = DRM_EVENT_CONTEXT_VERSION; - drm_evctx.vblank_handler = _dri_drm_vblank_handler; + drm_evctx.vblank_handler = _drm_vblank_handler; drm_evctx.page_flip_handler = NULL; - if (!_dri_drm_tick_schedule()) + if (!_drm_tick_schedule()) { close(drm_fd); drm_fd = -1; @@ -288,7 +256,7 @@ _dri_drm_init(void) } dri_drm_fdh = ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ, - _dri_drm_cb, NULL, NULL, NULL); + _drm_cb, NULL, NULL, NULL); if (!dri_drm_fdh) { close(drm_fd); @@ -299,7 +267,7 @@ _dri_drm_init(void) } static void -_dri_drm_shutdown(void) +_drm_shutdown(void) { if (drm_fd >= 0) { @@ -311,36 +279,41 @@ _dri_drm_shutdown(void) ecore_main_fd_handler_del(dri_drm_fdh); dri_drm_fdh = NULL; } + if (_drm_fail_timer) + { + ecore_timer_del(_drm_fail_timer); + _drm_fail_timer = NULL; + } } static Eina_Bool -_dri_animator_tick_source_set(void) +_drm_animator_tick_source_set(void) { if (vsync_root) { - if (!_dri_drm_link()) + if (!_drm_link()) { ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); return EINA_FALSE; } - _dri_drm_shutdown(); - if (!_dri_drm_init()) + _drm_shutdown(); + if (!_drm_init()) { vsync_root = 0; ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); return EINA_FALSE; } ecore_animator_custom_source_tick_begin_callback_set - (_dri_drm_tick_begin, NULL); + (_drm_tick_begin, NULL); ecore_animator_custom_source_tick_end_callback_set - (_dri_drm_tick_end, NULL); + (_drm_tick_end, NULL); ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); } else { if (drm_fd >= 0) { - _dri_drm_shutdown(); + _drm_shutdown(); ecore_animator_custom_source_tick_begin_callback_set (NULL, NULL); ecore_animator_custom_source_tick_end_callback_set @@ -491,28 +464,33 @@ static void _vsync_init(void) { static int done = 0; + struct stat stb; if (done) return; -#ifdef ECORE_X_VSYNC_DRI2 - // preferred inline dri/drm if possible - if (_dri_drm_link()) + if (_ecore_x_image_shm_check()) { - _dri_drm_shutdown(); - if (_dri_drm_init()) +#ifdef ECORE_X_VSYNC_DRM + // preferred inline drm if possible + if (!stat("/dev/dri/card0", &stb)) { - mode = 1; + if (_drm_link()) + { + _drm_shutdown(); + if (_drm_init()) + { + mode = 1; + } + } } - } #endif - // nvidia gl vsync slave mode - if (mode == 0) - { - struct stat stb; - - if (!stat("/dev/nvidiactl", &stb)) + // nvidia gl vsync slave mode + if (mode == 0) { - mode = 2; + if (!stat("/dev/nvidiactl", &stb)) + { + mode = 2; + } } } done = 1; @@ -528,8 +506,8 @@ ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win) { _vsync_init(); vsync_root = root; -#ifdef ECORE_X_VSYNC_DRI2 - if (mode == 1) return _dri_animator_tick_source_set(); +#ifdef ECORE_X_VSYNC_DRM + if (mode == 1) return _drm_animator_tick_source_set(); else #endif if (mode == 2) return _glvsync_animator_tick_source_set(); --
