summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--data/Makefile.am6
-rw-r--r--data/ecore_x/checkme1
-rw-r--r--src/Makefile_Ecore_X.am24
-rw-r--r--src/lib/ecore_x/ecore_x_vsync_tool.c256
-rw-r--r--src/lib/ecore_x/ecore_x_vsync_tool_glx.c302
-rw-r--r--src/lib/ecore_x/xlib/ecore_x_vsync.c264
7 files changed, 808 insertions, 46 deletions
diff --git a/.gitignore b/.gitignore
index ad5734a129..9ba26f070d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,4 @@ tags
64/ABOUT-NLS 64/ABOUT-NLS
65/config.rpath 65/config.rpath
66/coverage 66/coverage
67/src/lib/ecore_x/ecore_x_vsync
diff --git a/data/Makefile.am b/data/Makefile.am
index 6d42a099de..d4986193d0 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -28,6 +28,12 @@ ecorefiles_DATA = ecore/checkme
28EXTRA_DIST += $(ecorefiles_DATA) 28EXTRA_DIST += $(ecorefiles_DATA)
29 29
30######################################################################## 30########################################################################
31# Ecore_X
32ecore_xfilesdir = $(datadir)/ecore_x
33ecore_xfiles_DATA = ecore_x/checkme
34EXTRA_DIST += $(ecore_xfiles_DATA)
35
36########################################################################
31# Ecore_Imf 37# Ecore_Imf
32ecoreimffilesdir = $(datadir)/ecore_imf 38ecoreimffilesdir = $(datadir)/ecore_imf
33ecoreimffiles_DATA = ecore_imf/checkme 39ecoreimffiles_DATA = ecore_imf/checkme
diff --git a/data/ecore_x/checkme b/data/ecore_x/checkme
new file mode 100644
index 0000000000..1688a66696
--- /dev/null
+++ b/data/ecore_x/checkme
@@ -0,0 +1 @@
This is just a test file used to help ecore determine its prefix location.
diff --git a/src/Makefile_Ecore_X.am b/src/Makefile_Ecore_X.am
index fcb4bb4a8b..5cc4ccf138 100644
--- a/src/Makefile_Ecore_X.am
+++ b/src/Makefile_Ecore_X.am
@@ -1,5 +1,19 @@
1if HAVE_ECORE_X 1if HAVE_ECORE_X
2 2
3ecore_x_vsync_bin_PROGRAMS = lib/ecore_x/ecore_x_vsync
4ecore_x_vsync_bindir = $(libdir)/ecore_x/bin/$(MODULE_ARCH)
5lib_ecore_x_ecore_x_vsync_SOURCES = \
6lib/ecore_x/ecore_x_vsync_tool.c \
7lib/ecore_x/ecore_x_vsync_tool_glx.c
8lib_ecore_x_ecore_x_vsync_CPPFLAGS = \
9-I$(top_builddir)/src/lib/efl \
10@ECORE_CFLAGS@ @ECORE_CON_CFLAGS@ @EINA_CFLAGS@ \
11-DPACKAGE_BIN_DIR=\"$(bindir)\" \
12-DPACKAGE_LIB_DIR=\"$(libdir)\" \
13-DPACKAGE_DATA_DIR=\"$(datadir)/ecore_x\"
14lib_ecore_x_ecore_x_vsync_LDADD = @USE_EINA_LIBS@ @USE_ECORE_LIBS@ @USE_ECORE_CON_LIBS@
15lib_ecore_x_ecore_x_vsync_DEPENDENCIES = @EINA_INTERNAL_LIBS@ @ECORE_INTERNAL_LIBS@ @ECORE_CON_INTERNAL_LIBS@
16
3### Library 17### Library
4 18
5lib_LTLIBRARIES += lib/ecore_x/libecore_x.la 19lib_LTLIBRARIES += lib/ecore_x/libecore_x.la
@@ -93,12 +107,17 @@ lib/ecore_x/xlib/ecore_x_gesture.c \
93lib/ecore_x/xlib/ecore_x_private.h 107lib/ecore_x/xlib/ecore_x_private.h
94endif 108endif
95 109
96lib_ecore_x_libecore_x_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_X_CFLAGS@ 110lib_ecore_x_libecore_x_la_CPPFLAGS = \
111-I$(top_builddir)/src/lib/efl \
112@ECORE_X_CFLAGS@ @ECORE_CON_CFLAGS@ \
113-DPACKAGE_BIN_DIR=\"$(bindir)\" \
114-DPACKAGE_LIB_DIR=\"$(libdir)\" \
115-DPACKAGE_DATA_DIR=\"$(datadir)/ecore_x\"
97if HAVE_ECORE_X_XCB 116if HAVE_ECORE_X_XCB
98lib_ecore_x_libecore_x_la_CPPFLAGS += -I$(top_builddir)/src/lib/ecore_x/xcb 117lib_ecore_x_libecore_x_la_CPPFLAGS += -I$(top_builddir)/src/lib/ecore_x/xcb
99endif 118endif
100 119
101lib_ecore_x_libecore_x_la_LIBADD = @ECORE_X_LIBS@ 120lib_ecore_x_libecore_x_la_LIBADD = @ECORE_X_LIBS@ @USE_ECORE_CON_LIBS@
102lib_ecore_x_libecore_x_la_DEPENDENCIES = @ECORE_X_INTERNAL_LIBS@ 121lib_ecore_x_libecore_x_la_DEPENDENCIES = @ECORE_X_INTERNAL_LIBS@
103lib_ecore_x_libecore_x_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ 122lib_ecore_x_libecore_x_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
104 123
@@ -125,4 +144,3 @@ utils_ecore_makekeys_CFLAGS = @ECORE_X_CFLAGS@
125 144
126endif 145endif
127EXTRA_DIST += utils/ecore/mkks.sh 146EXTRA_DIST += utils/ecore/mkks.sh
128
diff --git a/src/lib/ecore_x/ecore_x_vsync_tool.c b/src/lib/ecore_x/ecore_x_vsync_tool.c
new file mode 100644
index 0000000000..34c93403ef
--- /dev/null
+++ b/src/lib/ecore_x/ecore_x_vsync_tool.c
@@ -0,0 +1,256 @@
1#include <Eina.h>
2#include <Ecore.h>
3#include <Ecore_Con.h>
4
5#include <unistd.h>
6
7enum
8{
9 MODE_NONE,
10 MODE_GLX
11};
12
13int _vsync_init_glx(void);
14double _vsync_wait_glx(void);
15
16static void _svr_broadcast_time(double t);
17
18static int _vsync_mode = MODE_NONE;
19
20static int
21_vsync_init(void)
22{
23 if (_vsync_init_glx()) _vsync_mode = MODE_GLX;
24 else return 0;
25 return 1;
26}
27
28static double
29_vsync_wait(void)
30{
31 if (_vsync_mode == MODE_GLX) return _vsync_wait_glx();
32 return 0.0;
33}
34
35typedef struct
36{
37 Eina_Thread_Queue_Msg head;
38 char val;
39} Msg;
40
41static int tick = 0;
42static Eina_Thread_Queue *thq = NULL;
43
44static void
45_tick_core(void *data EINA_UNUSED, Ecore_Thread *thread)
46{
47 Msg *msg;
48 void *ref;
49
50 for (;;)
51 {
52 if (!tick)
53 {
54 msg = eina_thread_queue_wait(thq, &ref);
55 if (msg)
56 {
57 tick = msg->val;
58 eina_thread_queue_wait_done(thq, ref);
59 }
60 }
61 else
62 {
63again:
64 msg = eina_thread_queue_poll(thq, &ref);
65 if (msg)
66 {
67 tick = msg->val;
68 eina_thread_queue_wait_done(thq, ref);
69 }
70 if (msg) goto again;
71 }
72 if (tick == -1) exit(0);
73 if (tick)
74 {
75 double *t;
76
77 t = malloc(sizeof(*t));
78 if (t)
79 {
80 *t = _vsync_wait();
81 ecore_thread_feedback(thread, t);
82 }
83 }
84 }
85}
86
87static void
88_tick_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
89{
90 double *t = msg;
91
92 if (t)
93 {
94 _svr_broadcast_time(*t);
95 free(t);
96 }
97}
98
99static void
100_tick_init(void)
101{
102 thq = eina_thread_queue_new();
103 ecore_thread_feedback_run(_tick_core, _tick_notify,
104 NULL, NULL, NULL, EINA_TRUE);
105}
106
107static void
108_tick_send(char val)
109{
110 Msg *msg;
111 void *ref;
112 msg = eina_thread_queue_send(thq, sizeof(Msg), &ref);
113 msg->val = val;
114 eina_thread_queue_send_done(thq, ref);
115}
116
117static void
118_tick_start(void)
119{
120 tick++;
121 if (tick > 1) return;
122 _tick_send(1);
123}
124
125static void
126_tick_end(void)
127{
128 tick--;
129 if (tick > 0) return;
130 _tick_send(0);
131}
132
133/*--------------------------------------------------------------------*/
134
135typedef struct
136{
137 Ecore_Con_Client *client;
138 Eina_Bool enabled : 1;
139} Clientdata;
140
141static Ecore_Con_Server *svr = NULL;
142static Eina_List *clients = NULL;
143
144static void
145_svr_broadcast_time(double t)
146{
147 Eina_List *l;
148 Clientdata *cdat;
149
150 EINA_LIST_FOREACH(clients, l, cdat)
151 {
152 ecore_con_client_send(cdat->client, &t, sizeof(t));
153 }
154}
155
156static Eina_Bool
157_svr_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
158{
159 Ecore_Con_Event_Client_Add *ev = event;
160 if (svr != ecore_con_client_server_get(ev->client)) return EINA_TRUE;
161 Clientdata *cdat = calloc(1, sizeof(Clientdata));
162 if (cdat)
163 {
164 cdat->client = ev->client;
165 clients = eina_list_append(clients, cdat);
166 ecore_con_client_data_set(ev->client, cdat);
167 }
168 return EINA_FALSE;
169}
170
171static Eina_Bool
172_svr_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
173{
174 Ecore_Con_Event_Client_Del *ev = event;
175 if (svr != ecore_con_client_server_get(ev->client)) return EINA_TRUE;
176 Clientdata *cdat = ecore_con_client_data_get(ev->client);
177 if (cdat)
178 {
179 clients = eina_list_remove(clients, cdat);
180 if (cdat->enabled) _tick_end();
181 free(cdat);
182 }
183 return EINA_FALSE;
184}
185
186static Eina_Bool
187_svr_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
188{
189 Ecore_Con_Event_Client_Data *ev = event;
190 if (svr != ecore_con_client_server_get(ev->client)) return EINA_TRUE;
191 Clientdata *cdat = ecore_con_client_data_get(ev->client);
192 if (cdat)
193 {
194 char *dat = ev->data;
195
196 if (ev->size > 0)
197 {
198 if (dat[ev->size - 1])
199 {
200 if (!cdat->enabled)
201 {
202 _tick_start();
203 cdat->enabled = EINA_TRUE;
204 }
205 }
206 else
207 {
208 if (cdat->enabled)
209 {
210 _tick_end();
211 cdat->enabled = EINA_FALSE;
212 }
213 }
214 }
215 }
216 return EINA_FALSE;
217}
218
219static void
220_svr_init(void)
221{
222 char buf[4096], *disp, *s;
223
224 disp = getenv("DISPLAY");
225 if (disp) disp = ":0";
226 snprintf(buf, sizeof(buf), "ecore-x-vsync-%s", disp);
227 for (s = buf; *s; s++)
228 {
229 if (*s == ':') *s = '=';
230 }
231 svr = ecore_con_server_add(ECORE_CON_LOCAL_USER, buf, 1, NULL);
232 if (!svr) exit(0);
233 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, _svr_add, NULL);
234 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, _svr_del, NULL);
235 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, _svr_data, NULL);
236}
237
238/*--------------------------------------------------------------------*/
239
240int
241main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
242{
243 eina_init();
244 ecore_app_no_system_modules();
245 ecore_init();
246 ecore_con_init();
247
248 if (!_vsync_init()) return 7;
249 _svr_init();
250 _tick_init();
251
252 ecore_main_loop_begin();
253 _tick_send(-1);
254 pause();
255 return 0;
256}
diff --git a/src/lib/ecore_x/ecore_x_vsync_tool_glx.c b/src/lib/ecore_x/ecore_x_vsync_tool_glx.c
new file mode 100644
index 0000000000..1d5b347e33
--- /dev/null
+++ b/src/lib/ecore_x/ecore_x_vsync_tool_glx.c
@@ -0,0 +1,302 @@
1#include <Eina.h>
2#include <Ecore.h>
3#include <string.h>
4#include <stdlib.h>
5#include <string.h>
6#include <unistd.h>
7#include <dlfcn.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11
12/*-------------------------------------------------------------------------*/
13
14#define SYM(lib, xx) \
15 do { \
16 sym_ ## xx = dlsym(lib, #xx); \
17 if (!(sym_ ## xx)) { \
18 fail = 1; \
19 } \
20 } while (0)
21
22#define GLX_DRAWABLE_TYPE 0x8010
23#define GLX_WINDOW_BIT 0x00000001
24#define GLX_RENDER_TYPE 0x8011
25#define GLX_RGBA_BIT 0x00000001
26#define GLX_DOUBLEBUFFER 5
27#define GLX_RED_SIZE 8
28#define GLX_GREEN_SIZE 9
29#define GLX_BLUE_SIZE 10
30#define GLX_RGBA_TYPE 0x8014
31typedef struct __GLXFBConfigRec *GLXFBConfig;
32
33typedef struct
34{
35 void *visual;
36 long visualid;
37 int screen;
38 int depth;
39 int c_class;
40 unsigned long red_mask;
41 unsigned long green_mask;
42 unsigned long blue_mask;
43 int colormap_size;
44 int bits_per_rgb;
45} XVisualInfo;
46
47typedef struct
48{
49 long background_pixmap;
50 unsigned long background_pixel;
51 long border_pixmap;
52 unsigned long border_pixel;
53 int bit_gravity;
54 int win_gravity;
55 int backing_store;
56 unsigned long backing_planes;
57 unsigned long backing_pixel;
58 int save_under;
59 long event_mask;
60 long do_not_propagate_mask;
61 int override_redirect;
62 long colormap;
63 long cursor;
64} XSetWindowAttributes;
65
66typedef struct {
67 void *ext_data;
68 void *display;
69 long root;
70 int width, height;
71 int mwidth, mheight;
72 int ndepths;
73 void *depths;
74 int root_depth;
75 void *root_visual;
76 long default_gc;
77 long cmap;
78 unsigned long white_pixel;
79 unsigned long black_pixel;
80 int max_maps, min_maps;
81 int backing_store;
82 int save_unders;
83 long root_input_mask;
84} Screen;
85
86typedef struct
87{
88 void *ext_data;
89 void *private1;
90 int fd;
91 int private2;
92 int proto_major_version;
93 int proto_minor_version;
94 char *vendor;
95 long private3;
96 long private4;
97 long private5;
98 int private6;
99 long (*resource_alloc)(void *);
100 int byte_order;
101 int bitmap_unit;
102 int bitmap_pad;
103 int bitmap_bit_order;
104 int nformats;
105 void *pixmap_format;
106 int private8;
107 int release;
108 void *private9, *private10;
109 int qlen;
110 unsigned long last_request_read;
111 unsigned long request;
112 char *private11;
113 char *private12;
114 char *private13;
115 char *private14;
116 unsigned max_request_size;
117 void *db;
118 int (*private15)(void *);
119 char *display_name;
120 int default_screen;
121 int nscreens;
122 Screen *screens;
123 unsigned long motion_buffer;
124 unsigned long private16;
125 int min_keycode;
126 int max_keycode;
127 char *private17;
128 char *private18;
129 int private19;
130 char *xdefaults;
131} *_XPrivDisplay;
132
133#define InputOutput 1
134#define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root)
135#define ScreenOfDisplay(dpy, scr) (&((_XPrivDisplay)dpy)->screens[scr])
136#define CWBorderPixel (1L<<3)
137#define CWColormap (1L<<13)
138#define CWOverrideRedirect (1L<<9)
139#define AllocNone 0
140
141/*-------------------------------------------------------------------------*/
142
143static const char *lib_x11_files[] =
144{
145 "libX11.so.6",
146 "libX11.so.5",
147 "libX11.so.4",
148 "libX11.so",
149 NULL
150};
151static void *lib_x11 = NULL;
152static void * (*sym_XOpenDisplay) (char *name) = NULL;
153static long (*sym_XCreateColormap) (void *d, long w, void *vis, int alloc) = NULL;
154static long (*sym_XCreateWindow) (void *d, long par, int x, int y, unsigned int w, unsigned int h, unsigned int bd, int depth, unsigned int clas, void *vis, unsigned long valmask, void *attr) = NULL;
155static int (*sym_XCloseDisplay) (void *d) = NULL;
156//static void * (*sym_) () = NULL;
157
158static const char *lib_gl_files[] =
159{
160 "libGL.so.9",
161 "libGL.so.8",
162 "libGL.so.7",
163 "libGL.so.6",
164 "libGL.so.5",
165 "libGL.so.4",
166 "libGL.so.3",
167 "libGL.so.2",
168 "libGL.so.1",
169 "libGL.so",
170 NULL
171};
172static void *lib_gl = NULL;
173static GLXFBConfig * (*sym_glXChooseFBConfig) (void *d, int sc, const int *att, int *n) = NULL;
174static void * (*sym_glXGetVisualFromFBConfig) (void *d, GLXFBConfig fbconfig) = NULL;
175static void *(*sym_glXCreateNewContext) (void *d, GLXFBConfig config, int rtype, void *shr, int direct) = NULL;
176static long (*sym_glXCreateWindow) (void *d, GLXFBConfig config, long win, const int *attr) = NULL;
177static int (*sym_glXMakeContextCurrent) (void *d, long draw, long draw2, void *context) = NULL;
178static void (*sym_glXSwapBuffers) (void *d, long draw) = NULL;
179static const char * (*sym_glXQueryExtensionsString) (void *d, int ival) = NULL;
180static void * (*sym_glXGetProcAddressARB) (const char *sym) = NULL;
181static int (*sym_glXGetVideoSyncSGI) (unsigned int *cnt) = NULL;
182static int (*sym_glXWaitVideoSyncSGI) (int divisor, int remainder, unsigned int *cnt) = NULL;
183//static void * (*sym_) () = NULL;
184
185/*-------------------------------------------------------------------------*/
186
187static void *disp = NULL;
188static long gwin = 0;
189static void *context = NULL;
190
191static void *
192lib_load(const char *files[])
193{
194 int i;
195 void *lib = NULL;
196
197 for (i = 0; files[i]; i++)
198 {
199 lib = dlopen(files[i], RTLD_LOCAL | RTLD_LAZY);
200 if (lib) return lib;
201 }
202 return NULL;
203}
204
205int
206_vsync_init_glx(void)
207{
208 int fail = 0;
209 GLXFBConfig *fbconfigs;
210 int num = 0;
211 int attr[] =
212 {
213 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
214 GLX_RENDER_TYPE, GLX_RGBA_BIT,
215 GLX_DOUBLEBUFFER, 1,
216 GLX_RED_SIZE, 1,
217 GLX_GREEN_SIZE, 1,
218 GLX_BLUE_SIZE, 1,
219 0
220 };
221 XVisualInfo *vi;
222 XSetWindowAttributes wa;
223 long win;
224 const char *extns;
225
226 /*---------------------------*/
227 lib_x11 = lib_load(lib_x11_files);
228 if (!lib_x11) goto err;
229
230 SYM(lib_x11, XOpenDisplay);
231 SYM(lib_x11, XCreateColormap);
232 SYM(lib_x11, XCreateWindow);
233 SYM(lib_x11, XCloseDisplay);
234 if (fail) goto err;
235
236 /*---------------------------*/
237 lib_gl = lib_load(lib_gl_files);
238 if (!lib_gl)
239 {
240 dlclose(lib_x11);
241 return 0;
242 }
243
244 SYM(lib_gl, glXChooseFBConfig);
245 SYM(lib_gl, glXGetVisualFromFBConfig);
246 SYM(lib_gl, glXCreateNewContext);
247 SYM(lib_gl, glXCreateWindow);
248 SYM(lib_gl, glXMakeContextCurrent);
249 SYM(lib_gl, glXSwapBuffers);
250 SYM(lib_gl, glXQueryExtensionsString);
251 SYM(lib_gl, glXGetProcAddressARB);
252 if (fail) goto err;
253
254 /*---------------------------*/
255 disp = sym_XOpenDisplay(NULL);
256 if (!disp) goto err;
257 fbconfigs = sym_glXChooseFBConfig(disp, 0, attr, &num);
258 if (!fbconfigs) goto err;
259 vi = sym_glXGetVisualFromFBConfig(disp, fbconfigs[0]);
260 if (!vi) goto err;
261 wa.override_redirect = 1;
262 wa.border_pixel = 0;
263 wa.colormap = sym_XCreateColormap(disp, RootWindow(disp, vi->screen),
264 vi->visual, AllocNone);
265 if (!wa.colormap) goto err;
266 win = sym_XCreateWindow(disp, RootWindow(disp, vi->screen),
267 -77, -777, 1, 1, 0, vi->depth, InputOutput,
268 vi->visual,
269 CWBorderPixel | CWColormap | CWOverrideRedirect, &wa);
270 if (!win) goto err;
271 context = sym_glXCreateNewContext(disp, fbconfigs[0], GLX_RGBA_TYPE,
272 NULL, 1);
273 if (!context) goto err;
274 gwin = sym_glXCreateWindow(disp, fbconfigs[0], win, NULL);
275 if (!gwin) goto err;
276 extns = sym_glXQueryExtensionsString(disp, 0);
277 if (!extns) goto err;
278 if (!strstr(extns, "GLX_SGI_swap_control")) goto err;
279 sym_glXGetVideoSyncSGI = sym_glXGetProcAddressARB("glXGetVideoSyncSGI");
280 sym_glXWaitVideoSyncSGI = sym_glXGetProcAddressARB("glXWaitVideoSyncSGI");
281 if ((!sym_glXGetVideoSyncSGI) || (!sym_glXWaitVideoSyncSGI)) goto err;
282
283 return 1;
284err:
285 if (disp) sym_XCloseDisplay(disp);
286 if (lib_gl) dlclose(lib_gl);
287 if (lib_x11) dlclose(lib_x11);
288 return 0;
289}
290
291double
292_vsync_wait_glx(void)
293{
294 double t;
295 unsigned int rc = 0;
296
297 sym_glXMakeContextCurrent(disp, gwin, gwin, context);
298 sym_glXGetVideoSyncSGI(&rc);
299 sym_glXWaitVideoSyncSGI(1, 0, &rc);
300 t = ecore_time_get();
301 return t;
302}
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 @@
5#include "Ecore.h" 5#include "Ecore.h"
6#include "ecore_x_private.h" 6#include "ecore_x_private.h"
7#include "Ecore_X.h" 7#include "Ecore_X.h"
8#include "Ecore_Con.h"
8 9
9#include <string.h> 10#include <string.h>
10#include <stdlib.h> 11#include <stdlib.h>
@@ -17,6 +18,12 @@
17 18
18#define ECORE_X_VSYNC_DRI2 1 19#define ECORE_X_VSYNC_DRI2 1
19 20
21static Ecore_X_Window vsync_root = 0;
22
23
24
25
26
20#ifdef ECORE_X_VSYNC_DRI2 27#ifdef ECORE_X_VSYNC_DRI2
21// relevant header bits of dri/drm inlined here to avoid needing external 28// relevant header bits of dri/drm inlined here to avoid needing external
22// headers to build 29// headers to build
@@ -115,8 +122,6 @@ static Ecore_Fd_Handler *dri_drm_fdh = NULL;
115static void *dri_lib = NULL; 122static void *dri_lib = NULL;
116static void *drm_lib = NULL; 123static void *drm_lib = NULL;
117 124
118static Window dri_drm_vsync_root = 0;
119
120static Eina_Bool 125static Eina_Bool
121_dri_drm_tick_schedule(void) 126_dri_drm_tick_schedule(void)
122{ 127{
@@ -151,6 +156,7 @@ _dri_drm_vblank_handler(int fd EINA_UNUSED,
151{ 156{
152 if (drm_event_is_busy) 157 if (drm_event_is_busy)
153 { 158 {
159 // XXX: set looptime
154 ecore_animator_custom_tick(); 160 ecore_animator_custom_tick();
155 _dri_drm_tick_schedule(); 161 _dri_drm_tick_schedule();
156 } 162 }
@@ -257,13 +263,13 @@ _dri_drm_init(void)
257 return 0; 263 return 0;
258 if (dri2_major < 2) 264 if (dri2_major < 2)
259 return 0; 265 return 0;
260 if (!sym_DRI2Connect(_ecore_x_disp, dri_drm_vsync_root, &driver_name, &device_name)) 266 if (!sym_DRI2Connect(_ecore_x_disp, vsync_root, &driver_name, &device_name))
261 return 0; 267 return 0;
262 drm_fd = open(device_name, O_RDWR); 268 drm_fd = open(device_name, O_RDWR);
263 if (drm_fd < 0) 269 if (drm_fd < 0)
264 return 0; 270 return 0;
265 sym_drmGetMagic(drm_fd, &drm_magic); 271 sym_drmGetMagic(drm_fd, &drm_magic);
266 if (!sym_DRI2Authenticate(_ecore_x_disp, dri_drm_vsync_root, drm_magic)) 272 if (!sym_DRI2Authenticate(_ecore_x_disp, vsync_root, drm_magic))
267 { 273 {
268 close(drm_fd); 274 close(drm_fd);
269 drm_fd = -1; 275 drm_fd = -1;
@@ -280,7 +286,7 @@ _dri_drm_init(void)
280 drm_fd = -1; 286 drm_fd = -1;
281 return 0; 287 return 0;
282 } 288 }
283 289
284 dri_drm_fdh = ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ, 290 dri_drm_fdh = ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ,
285 _dri_drm_cb, NULL, NULL, NULL); 291 _dri_drm_cb, NULL, NULL, NULL);
286 if (!dri_drm_fdh) 292 if (!dri_drm_fdh)
@@ -307,55 +313,227 @@ _dri_drm_shutdown(void)
307 } 313 }
308} 314}
309 315
310#endif 316static Eina_Bool
311 317_dri_animator_tick_source_set(void)
312EAPI Eina_Bool
313ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
314{ 318{
315#ifdef ECORE_X_VSYNC_DRI2 319 if (vsync_root)
316 Ecore_X_Window root;
317
318 root = ecore_x_window_root_get(win);
319 if (root != dri_drm_vsync_root)
320 { 320 {
321 dri_drm_vsync_root = root; 321 if (!_dri_drm_link())
322 if (dri_drm_vsync_root) 322 {
323 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
324 return EINA_FALSE;
325 }
326 _dri_drm_shutdown();
327 if (!_dri_drm_init())
328 {
329 vsync_root = 0;
330 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
331 return EINA_FALSE;
332 }
333 ecore_animator_custom_source_tick_begin_callback_set
334 (_dri_drm_tick_begin, NULL);
335 ecore_animator_custom_source_tick_end_callback_set
336 (_dri_drm_tick_end, NULL);
337 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
338 }
339 else
340 {
341 if (drm_fd >= 0)
323 { 342 {
324 if (!_dri_drm_link())
325 {
326 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
327 return EINA_FALSE;
328 }
329 _dri_drm_shutdown(); 343 _dri_drm_shutdown();
330 if (!_dri_drm_init())
331 {
332 dri_drm_vsync_root = 0;
333 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
334 return EINA_FALSE;
335 }
336 ecore_animator_custom_source_tick_begin_callback_set 344 ecore_animator_custom_source_tick_begin_callback_set
337 (_dri_drm_tick_begin, NULL); 345 (NULL, NULL);
338 ecore_animator_custom_source_tick_end_callback_set 346 ecore_animator_custom_source_tick_end_callback_set
339 (_dri_drm_tick_end, NULL); 347 (NULL, NULL);
340 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); 348 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
341 } 349 }
342 else 350 }
351 return EINA_TRUE;
352}
353#endif
354
355
356
357
358
359
360
361
362
363static Ecore_Con_Server *vsync_server = NULL;
364static Eina_Bool handlers = EINA_FALSE;
365static Eina_Prefix *_prefix = NULL;
366
367static Eina_Bool
368vsync_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
369{
370 Ecore_Con_Event_Server_Add *ev = event;
371 if (ev->server != vsync_server) return EINA_TRUE;
372 return EINA_FALSE;
373}
374
375static Eina_Bool
376vsync_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
377{
378 Ecore_Con_Event_Server_Del *ev = event;
379 if (ev->server != vsync_server) return EINA_TRUE;
380 if (vsync_server)
381 {
382 ecore_con_server_del(vsync_server);
383 vsync_server = NULL;
384 ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
385 ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
386 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
387 }
388 return EINA_FALSE;
389}
390
391static Eina_Bool
392vsync_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
393{
394 Ecore_Con_Event_Server_Data *ev = event;
395 int i;
396 double t;
397 char *d;
398 if (ev->server != vsync_server) return EINA_TRUE;
399 d = ev->data;;
400 for (i = 0; i < ev->size - (int)(sizeof(double) - 1); i++)
401 {
402 memcpy(&t, &(d[i]), sizeof(double));
403 ecore_loop_time_set(t);
404 ecore_animator_custom_tick();
405 }
406 return EINA_FALSE;
407}
408
409static void
410vsync_tick_begin(void *data EINA_UNUSED)
411{
412 char val = 1;
413 ecore_con_server_send(vsync_server, &val, 1);
414}
415
416static void
417vsync_tick_end(void *data EINA_UNUSED)
418{
419 char val = 0;
420 ecore_con_server_send(vsync_server, &val, 1);
421}
422
423static Eina_Bool
424_glvsync_animator_tick_source_set(void)
425{
426 if (!vsync_server)
427 {
428 char buf[4096], *disp, *s;
429 int tries = 0;
430
431 if (!handlers)
343 { 432 {
344 if (drm_fd >= 0) 433 _prefix = eina_prefix_new(NULL, ecore_x_vsync_animator_tick_source_set,
345 { 434 "ECORE_X", "ecore_x", "checkme",
346 _dri_drm_shutdown(); 435 PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
347 ecore_animator_custom_source_tick_begin_callback_set 436 PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
348 (NULL, NULL); 437 ecore_con_init();
349 ecore_animator_custom_source_tick_end_callback_set
350 (NULL, NULL);
351 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
352 }
353 } 438 }
439 disp = getenv("DISPLAY");
440 if (disp) disp = ":0";
441 snprintf(buf, sizeof(buf), "ecore-x-vsync-%s", disp);
442 for (s = buf; *s; s++)
443 {
444 if (*s == ':') *s = '=';
445 }
446 vsync_server = ecore_con_server_connect(ECORE_CON_LOCAL_USER, buf, 1, NULL);
447 while (!vsync_server)
448 {
449 tries++;
450 if (tries > 50) return EINA_FALSE;
451 snprintf(buf, sizeof(buf), "%s/ecore_x/bin/%s/ecore_x_vsync",
452 eina_prefix_lib_get(_prefix), MODULE_ARCH);
453 ecore_exe_run(buf, NULL);
454 usleep(10000);
455 vsync_server = ecore_con_server_connect(ECORE_CON_LOCAL_USER, buf, 0, NULL);
456 }
457 if (!handlers)
458 {
459 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, vsync_server_add, NULL);
460 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, vsync_server_del, NULL);
461 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, vsync_server_data, NULL);
462 handlers = EINA_FALSE;
463 }
464 }
465 if (vsync_root)
466 {
467 ecore_animator_custom_source_tick_begin_callback_set(vsync_tick_begin, NULL);
468 ecore_animator_custom_source_tick_end_callback_set(vsync_tick_end, NULL);
469 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
470 }
471 else
472 {
473 if (vsync_server)
474 {
475 ecore_con_server_del(vsync_server);
476 vsync_server = NULL;
477 }
478 ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
479 ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
480 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
354 } 481 }
355 return EINA_TRUE; 482 return EINA_TRUE;
356#else 483}
357 return EINA_FALSE; 484
358 win = 0; 485// XXX: missing mode 3 == separate x connection with compiled in dri2 proto
486// handling ala mesa (taken from mesa likely)
487
488static int mode = 0;
489
490static void
491_vsync_init(void)
492{
493 static int done = 0;
494
495 if (done) return;
496
497#ifdef ECORE_X_VSYNC_DRI2
498 // preferred inline dri/drm if possible
499 if (_dri_drm_link())
500 {
501 _dri_drm_shutdown();
502 if (_dri_drm_init())
503 {
504 mode = 1;
505 }
506 }
359#endif 507#endif
508 // nvidia gl vsync slave mode
509 if (mode == 0)
510 {
511 struct stat stb;
512
513 if (!stat("/dev/nvidiactl", &stb))
514 {
515 mode = 2;
516 }
517 }
518 done = 1;
360} 519}
361 520
521EAPI Eina_Bool
522ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
523{
524 Ecore_X_Window root;
525
526 root = ecore_x_window_root_get(win);
527 if (root != vsync_root)
528 {
529 _vsync_init();
530 vsync_root = root;
531#ifdef ECORE_X_VSYNC_DRI2
532 if (mode == 1) return _dri_animator_tick_source_set();
533 else
534#endif
535 if (mode == 2) return _glvsync_animator_tick_source_set();
536 else return EINA_FALSE;
537 }
538 return EINA_TRUE;
539}