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-27 14:22:27 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-07-28 23:00:34 +0900
commit2d63a704222fa27d61a53d6b7248cd7e01ebb100 (patch)
tree5fc471053b54615d0bdf2d7d609520f10f661700 /src/lib/ecore_x/xlib/ecore_x_vsync.c
parentadd simple ecore_con_url test suite (diff)
downloadefl-2d63a704222fa27d61a53d6b7248cd7e01ebb100.tar.gz
ecore x vsync animator support - add a glx based vsync ticker
this adds a slave process that is useful on nvidia drivers as there isn't another way to get vsync evenys (that i know about). i need to make another slave process to that includes a dri2 protocol implementation since mesa has now hidden its dri2 symbols.
Diffstat (limited to 'src/lib/ecore_x/xlib/ecore_x_vsync.c')
-rw-r--r--src/lib/ecore_x/xlib/ecore_x_vsync.c264
1 files changed, 221 insertions, 43 deletions
diff --git a/src/lib/ecore_x/xlib/ecore_x_vsync.c b/src/lib/ecore_x/xlib/ecore_x_vsync.c
index 799ccfea91..a228e9e046 100644
--- a/src/lib/ecore_x/xlib/ecore_x_vsync.c
+++ b/src/lib/ecore_x/xlib/ecore_x_vsync.c
@@ -5,6 +5,7 @@
#include "Ecore.h"
#include "ecore_x_private.h"
#include "Ecore_X.h"
+#include "Ecore_Con.h"
#include <string.h>
#include <stdlib.h>
@@ -17,6 +18,12 @@
#define ECORE_X_VSYNC_DRI2 1
+static Ecore_X_Window vsync_root = 0;
+
+
+
+
+
#ifdef ECORE_X_VSYNC_DRI2
// relevant header bits of dri/drm inlined here to avoid needing external
// headers to build
@@ -115,8 +122,6 @@ static Ecore_Fd_Handler *dri_drm_fdh = NULL;
static void *dri_lib = NULL;
static void *drm_lib = NULL;
-static Window dri_drm_vsync_root = 0;
-
static Eina_Bool
_dri_drm_tick_schedule(void)
{
@@ -151,6 +156,7 @@ _dri_drm_vblank_handler(int fd EINA_UNUSED,
{
if (drm_event_is_busy)
{
+ // XXX: set looptime
ecore_animator_custom_tick();
_dri_drm_tick_schedule();
}
@@ -257,13 +263,13 @@ _dri_drm_init(void)
return 0;
if (dri2_major < 2)
return 0;
- if (!sym_DRI2Connect(_ecore_x_disp, dri_drm_vsync_root, &driver_name, &device_name))
+ 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, dri_drm_vsync_root, drm_magic))
+ if (!sym_DRI2Authenticate(_ecore_x_disp, vsync_root, drm_magic))
{
close(drm_fd);
drm_fd = -1;
@@ -280,7 +286,7 @@ _dri_drm_init(void)
drm_fd = -1;
return 0;
}
-
+
dri_drm_fdh = ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ,
_dri_drm_cb, NULL, NULL, NULL);
if (!dri_drm_fdh)
@@ -307,55 +313,227 @@ _dri_drm_shutdown(void)
}
}
-#endif
-
-EAPI Eina_Bool
-ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
+static Eina_Bool
+_dri_animator_tick_source_set(void)
{
-#ifdef ECORE_X_VSYNC_DRI2
- Ecore_X_Window root;
-
- root = ecore_x_window_root_get(win);
- if (root != dri_drm_vsync_root)
+ if (vsync_root)
{
- dri_drm_vsync_root = root;
- if (dri_drm_vsync_root)
+ if (!_dri_drm_link())
+ {
+ ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
+ return EINA_FALSE;
+ }
+ _dri_drm_shutdown();
+ if (!_dri_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);
+ ecore_animator_custom_source_tick_end_callback_set
+ (_dri_drm_tick_end, NULL);
+ ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
+ }
+ else
+ {
+ if (drm_fd >= 0)
{
- if (!_dri_drm_link())
- {
- ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
- return EINA_FALSE;
- }
_dri_drm_shutdown();
- if (!_dri_drm_init())
- {
- dri_drm_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);
+ (NULL, NULL);
ecore_animator_custom_source_tick_end_callback_set
- (_dri_drm_tick_end, NULL);
- ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
+ (NULL, NULL);
+ ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
}
- else
+ }
+ return EINA_TRUE;
+}
+#endif
+
+
+
+
+
+
+
+
+
+static Ecore_Con_Server *vsync_server = NULL;
+static Eina_Bool handlers = EINA_FALSE;
+static Eina_Prefix *_prefix = NULL;
+
+static Eina_Bool
+vsync_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Add *ev = event;
+ if (ev->server != vsync_server) return EINA_TRUE;
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+vsync_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Del *ev = event;
+ if (ev->server != vsync_server) return EINA_TRUE;
+ if (vsync_server)
+ {
+ ecore_con_server_del(vsync_server);
+ vsync_server = NULL;
+ ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
+ ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
+ ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
+ }
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+vsync_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Data *ev = event;
+ int i;
+ double t;
+ char *d;
+ if (ev->server != vsync_server) return EINA_TRUE;
+ d = ev->data;;
+ for (i = 0; i < ev->size - (int)(sizeof(double) - 1); i++)
+ {
+ memcpy(&t, &(d[i]), sizeof(double));
+ ecore_loop_time_set(t);
+ ecore_animator_custom_tick();
+ }
+ return EINA_FALSE;
+}
+
+static void
+vsync_tick_begin(void *data EINA_UNUSED)
+{
+ char val = 1;
+ ecore_con_server_send(vsync_server, &val, 1);
+}
+
+static void
+vsync_tick_end(void *data EINA_UNUSED)
+{
+ char val = 0;
+ ecore_con_server_send(vsync_server, &val, 1);
+}
+
+static Eina_Bool
+_glvsync_animator_tick_source_set(void)
+{
+ if (!vsync_server)
+ {
+ char buf[4096], *disp, *s;
+ int tries = 0;
+
+ if (!handlers)
{
- if (drm_fd >= 0)
- {
- _dri_drm_shutdown();
- ecore_animator_custom_source_tick_begin_callback_set
- (NULL, NULL);
- ecore_animator_custom_source_tick_end_callback_set
- (NULL, NULL);
- ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
- }
+ _prefix = eina_prefix_new(NULL, ecore_x_vsync_animator_tick_source_set,
+ "ECORE_X", "ecore_x", "checkme",
+ PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
+ PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
+ ecore_con_init();
}
+ disp = getenv("DISPLAY");
+ if (disp) disp = ":0";
+ snprintf(buf, sizeof(buf), "ecore-x-vsync-%s", disp);
+ for (s = buf; *s; s++)
+ {
+ if (*s == ':') *s = '=';
+ }
+ vsync_server = ecore_con_server_connect(ECORE_CON_LOCAL_USER, buf, 1, NULL);
+ while (!vsync_server)
+ {
+ tries++;
+ if (tries > 50) return EINA_FALSE;
+ snprintf(buf, sizeof(buf), "%s/ecore_x/bin/%s/ecore_x_vsync",
+ eina_prefix_lib_get(_prefix), MODULE_ARCH);
+ ecore_exe_run(buf, NULL);
+ usleep(10000);
+ vsync_server = ecore_con_server_connect(ECORE_CON_LOCAL_USER, buf, 0, NULL);
+ }
+ if (!handlers)
+ {
+ ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, vsync_server_add, NULL);
+ ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, vsync_server_del, NULL);
+ ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, vsync_server_data, NULL);
+ handlers = EINA_FALSE;
+ }
+ }
+ if (vsync_root)
+ {
+ ecore_animator_custom_source_tick_begin_callback_set(vsync_tick_begin, NULL);
+ ecore_animator_custom_source_tick_end_callback_set(vsync_tick_end, NULL);
+ ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
+ }
+ else
+ {
+ if (vsync_server)
+ {
+ ecore_con_server_del(vsync_server);
+ vsync_server = NULL;
+ }
+ ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
+ ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
+ ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
}
return EINA_TRUE;
-#else
- return EINA_FALSE;
- win = 0;
+}
+
+// XXX: missing mode 3 == separate x connection with compiled in dri2 proto
+// handling ala mesa (taken from mesa likely)
+
+static int mode = 0;
+
+static void
+_vsync_init(void)
+{
+ static int done = 0;
+
+ if (done) return;
+
+#ifdef ECORE_X_VSYNC_DRI2
+ // preferred inline dri/drm if possible
+ if (_dri_drm_link())
+ {
+ _dri_drm_shutdown();
+ if (_dri_drm_init())
+ {
+ mode = 1;
+ }
+ }
#endif
+ // nvidia gl vsync slave mode
+ if (mode == 0)
+ {
+ struct stat stb;
+
+ if (!stat("/dev/nvidiactl", &stb))
+ {
+ mode = 2;
+ }
+ }
+ done = 1;
}
+EAPI Eina_Bool
+ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
+{
+ Ecore_X_Window root;
+
+ root = ecore_x_window_root_get(win);
+ if (root != vsync_root)
+ {
+ _vsync_init();
+ vsync_root = root;
+#ifdef ECORE_X_VSYNC_DRI2
+ if (mode == 1) return _dri_animator_tick_source_set();
+ else
+#endif
+ if (mode == 2) return _glvsync_animator_tick_source_set();
+ else return EINA_FALSE;
+ }
+ return EINA_TRUE;
+}