aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/ecore_x/xlib/ecore_x_vsync.c
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-07-29 20:00:53 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-07-29 20:02:33 +0900
commitaaefbaa43ebea08ecd67732a785bf89c3b7f847e (patch)
tree8d320999bf5c8bfe7360408e35b175766313fb3c /src/lib/ecore_x/xlib/ecore_x_vsync.c
parentEvas GL Generic: Don't install an internal header. (diff)
downloadefl-aaefbaa43ebea08ecd67732a785bf89c3b7f847e.tar.gz
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
Diffstat (limited to 'src/lib/ecore_x/xlib/ecore_x_vsync.c')
-rw-r--r--src/lib/ecore_x/xlib/ecore_x_vsync.c252
1 files changed, 115 insertions, 137 deletions
diff --git a/src/lib/ecore_x/xlib/ecore_x_vsync.c b/src/lib/ecore_x/xlib/ecore_x_vsync.c
index a228e9e046..7aed4bee9f 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();