1 #include "ecore_xcb_private.h"
4 # include <X11/Xlib-xcb.h>
6 #define ECORE_XCB_VSYNC_DRI2 1
7 #define DRM_EVENT_CONTEXT_VERSION 2
9 #ifdef ECORE_XCB_VSYNC_DRI2
11 /* relevant header bits of dri/drm inlined here to avoid needing external */
12 /* headers to build drm */
13 typedef unsigned int drm_magic_t;
17 DRM_VBLANK_ABSOLUTE = 0x00000000,
18 DRM_VBLANK_RELATIVE = 0x00000001,
19 DRM_VBLANK_EVENT = 0x04000000,
20 DRM_VBLANK_FLIP = 0x08000000,
21 DRM_VBLANK_NEXTONMISS = 0x10000000,
22 DRM_VBLANK_SECONDARY = 0x20000000,
23 DRM_VBLANK_SIGNAL = 0x40000000
26 typedef struct _drmVBlankReq
28 drmVBlankSeqType type;
29 unsigned int sequence;
33 typedef struct _drmVBlankReply
35 drmVBlankSeqType type;
36 unsigned int sequence;
37 long tval_sec, tval_usec;
40 typedef union _drmVBlank
46 typedef struct _drmEventContext
49 void (*vblank_handler)(int fd,
50 unsigned int sequence,
54 void (*page_flip_handler)(int fd,
55 unsigned int sequence,
61 static int (*sym_drmClose)(int fd) = NULL;
62 static int (*sym_drmGetMagic)(int fd,
63 drm_magic_t *magic) = NULL;
64 static int (*sym_drmWaitVBlank)(int fd,
65 drmVBlank *vbl) = NULL;
66 static int (*sym_drmHandleEvent)(int fd,
67 drmEventContext *evctx) = NULL;
70 static Bool (*sym_DRI2QueryExtension)(Display *display,
72 int *errorBase) = NULL;
73 static Bool (*sym_DRI2QueryVersion)(Display *display,
76 static Bool (*sym_DRI2Connect)(Display *display,
79 char **deviceName) = NULL;
80 static Bool (*sym_DRI2Authenticate)(Display *display,
82 drm_magic_t magic) = NULL;
84 /* local function prototypes */
85 static Eina_Bool _ecore_xcb_dri_link(void);
86 static Eina_Bool _ecore_xcb_dri_start(void);
87 static void _ecore_xcb_dri_shutdown(void);
89 static Eina_Bool _ecore_xcb_dri_cb(void *data __UNUSED__,
90 Ecore_Fd_Handler *fdh __UNUSED__);
91 static void _ecore_xcb_dri_tick_begin(void *data __UNUSED__);
92 static void _ecore_xcb_dri_tick_end(void *data __UNUSED__);
93 static void _ecore_xcb_dri_tick_schedule(void);
94 static void _ecore_xcb_dri_vblank_handler(int fd __UNUSED__,
95 unsigned int frame __UNUSED__,
96 unsigned int sec __UNUSED__,
97 unsigned int usec __UNUSED__,
98 void *data __UNUSED__);
100 /* local variables */
101 static Ecore_X_Window _vsync_root = 0;
102 static int _drm_fd = -1;
103 static Ecore_Fd_Handler *_drm_fdh = NULL;
104 static unsigned int _drm_magic = 0;
105 static Eina_Bool _drm_event_busy = EINA_FALSE;
106 static void *_drm_lib = NULL;
107 static void *_dri_lib = NULL;
108 static drmEventContext _drm_evctx;
112 _ecore_xcb_dri_init(void)
114 LOGFN(__FILE__, __LINE__, __FUNCTION__);
118 _ecore_xcb_dri_finalize(void)
120 LOGFN(__FILE__, __LINE__, __FUNCTION__);
124 ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
126 #ifdef ECORE_XCB_VSYNC_DRI2
130 LOGFN(__FILE__, __LINE__, __FUNCTION__);
133 #ifdef ECORE_XCB_VSYNC_DRI2
134 root = ecore_x_window_root_get(win);
135 if (root != _vsync_root)
140 if (!_ecore_xcb_dri_link())
142 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
145 _ecore_xcb_dri_shutdown();
146 if (!_ecore_xcb_dri_start())
149 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
152 ecore_animator_custom_source_tick_begin_callback_set
153 (_ecore_xcb_dri_tick_begin, NULL);
154 ecore_animator_custom_source_tick_end_callback_set
155 (_ecore_xcb_dri_tick_end, NULL);
156 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
162 _ecore_xcb_dri_shutdown();
163 ecore_animator_custom_source_tick_begin_callback_set
165 ecore_animator_custom_source_tick_end_callback_set
167 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
178 /* local functions */
179 #ifdef ECORE_XCB_VSYNC_DRI2
181 _ecore_xcb_dri_link(void)
183 const char *_drm_libs[] =
191 const char *_dri_libs[] =
207 LOGFN(__FILE__, __LINE__, __FUNCTION__);
209 # define SYM(lib, xx) \
211 sym_## xx = dlsym(lib, #xx); \
212 if (!(sym_## xx)) { \
213 fprintf(stderr, "%s\n", dlerror()); \
218 if (_drm_lib) return EINA_TRUE;
220 for (i = 0; _drm_libs[i]; i++)
222 _drm_lib = dlopen(_drm_libs[i], (RTLD_LOCAL | RTLD_LAZY));
226 SYM(_drm_lib, drmClose);
227 SYM(_drm_lib, drmGetMagic);
228 SYM(_drm_lib, drmWaitVBlank);
229 SYM(_drm_lib, drmHandleEvent);
239 if (!_drm_lib) return EINA_FALSE;
240 for (i = 0; _dri_libs[i]; i++)
242 if ((_dri_lib = dlopen(_dri_libs[i], (RTLD_LOCAL | RTLD_LAZY))))
245 SYM(_dri_lib, DRI2QueryExtension);
246 SYM(_dri_lib, DRI2QueryVersion);
247 SYM(_dri_lib, DRI2Connect);
248 SYM(_dri_lib, DRI2Authenticate);
269 _ecore_xcb_dri_start(void)
271 Ecore_X_Display *disp;
272 int _dri2_event = 0, _dri2_error = 0;
273 int _dri2_major = 0, _dri2_minor = 0;
274 char *device = NULL, *driver = NULL;
276 disp = ecore_x_display_get();
277 if (!sym_DRI2QueryExtension(disp, &_dri2_event, &_dri2_error))
279 if (!sym_DRI2QueryVersion(disp, &_dri2_major, &_dri2_minor))
281 if (_dri2_major < 2) return 0;
282 if (!sym_DRI2Connect(disp, _vsync_root, &driver, &device))
285 _drm_fd = open(device, O_RDWR);
286 if (_drm_fd < 0) return 0;
288 sym_drmGetMagic(_drm_fd, &_drm_magic);
289 if (!sym_DRI2Authenticate(disp, _vsync_root, _drm_magic))
296 memset(&_drm_evctx, 0, sizeof(_drm_evctx));
297 _drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
298 _drm_evctx.vblank_handler = _ecore_xcb_dri_vblank_handler;
299 _drm_evctx.page_flip_handler = NULL;
301 _drm_fdh = ecore_main_fd_handler_add(_drm_fd, ECORE_FD_READ,
302 _ecore_xcb_dri_cb, NULL, NULL, NULL);
314 _ecore_xcb_dri_shutdown(void)
323 ecore_main_fd_handler_del(_drm_fdh);
329 _ecore_xcb_dri_cb(void *data __UNUSED__,
330 Ecore_Fd_Handler *fdh __UNUSED__)
332 sym_drmHandleEvent(_drm_fd, &_drm_evctx);
333 return ECORE_CALLBACK_RENEW;
337 _ecore_xcb_dri_tick_begin(void *data __UNUSED__)
339 _drm_event_busy = EINA_TRUE;
340 _ecore_xcb_dri_tick_schedule();
344 _ecore_xcb_dri_tick_end(void *data __UNUSED__)
346 _drm_event_busy = EINA_FALSE;
350 _ecore_xcb_dri_tick_schedule(void)
354 LOGFN(__FILE__, __LINE__, __FUNCTION__);
357 vbl.request.type = (DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT);
358 vbl.request.sequence = 1;
359 vbl.request.signal = 0;
361 sym_drmWaitVBlank(_drm_fd, &vbl);
365 _ecore_xcb_dri_vblank_handler(int fd __UNUSED__,
366 unsigned int frame __UNUSED__,
367 unsigned int sec __UNUSED__,
368 unsigned int usec __UNUSED__,
369 void *data __UNUSED__)
371 ecore_animator_custom_tick();
372 if (_drm_event_busy) _ecore_xcb_dri_tick_schedule();