3 #endif /* ifdef HAVE_CONFIG_H */
6 #include "ecore_x_private.h"
14 #include <sys/types.h>
18 #define ECORE_X_VSYNC_DRI2 1
20 #ifdef ECORE_X_VSYNC_DRI2
21 // relevant header bits of dri/drm inlined here to avoid needing external
24 typedef unsigned int drm_magic_t;
28 DRM_VBLANK_ABSOLUTE = 0x00000000,
29 DRM_VBLANK_RELATIVE = 0x00000001,
30 DRM_VBLANK_EVENT = 0x04000000,
31 DRM_VBLANK_FLIP = 0x08000000,
32 DRM_VBLANK_NEXTONMISS = 0x10000000,
33 DRM_VBLANK_SECONDARY = 0x20000000,
34 DRM_VBLANK_SIGNAL = 0x40000000
38 typedef struct _drmVBlankReq
40 drmVBlankSeqType type;
41 unsigned int sequence;
45 typedef struct _drmVBlankReply
47 drmVBlankSeqType type;
48 unsigned int sequence;
53 typedef union _drmVBlank
59 #define DRM_EVENT_CONTEXT_VERSION 2
61 typedef struct _drmEventContext
64 void (*vblank_handler)(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data);
65 void (*page_flip_handler)(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data);
68 static int (*sym_drmClose) (int fd) = NULL;
69 static int (*sym_drmGetMagic) (int fd, drm_magic_t * magic) = NULL;
70 static int (*sym_drmWaitVBlank) (int fd, drmVBlank *vbl) = NULL;
71 static int (*sym_drmHandleEvent) (int fd, drmEventContext *evctx) = NULL;
75 static Bool (*sym_DRI2QueryExtension) (Display *display, int *eventBase, int *errorBase) = NULL;
76 static Bool (*sym_DRI2QueryVersion) (Display *display, int *major, int *minor) = NULL;
77 static Bool (*sym_DRI2Connect) (Display *display, XID window, char **driverName, char **deviceName) = NULL;
78 static Bool (*sym_DRI2Authenticate) (Display *display, XID window, drm_magic_t magic) = NULL;
81 //// dri/drm data needed
82 static int dri2_event = 0;
83 static int dri2_error = 0;
84 static int dri2_major = 0;
85 static int dri2_minor = 0;
86 static char *device_name = 0;
87 static char *driver_name = 0;
88 static drm_magic_t drm_magic;
90 static int drm_fd = -1;
91 static int drm_event_is_busy = 0;
92 static int drm_animators_interval = 1;
93 static drmEventContext drm_evctx;
94 static Ecore_Fd_Handler *dri_drm_fdh = NULL;
96 static void *dri_lib = NULL;
97 static void *drm_lib = NULL;
99 static Window dri_drm_vsync_root = 0;
102 _dri_drm_tick_schedule(void)
106 vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
107 vbl.request.sequence = drm_animators_interval;
108 vbl.request.signal = 0;
109 sym_drmWaitVBlank(drm_fd, &vbl);
113 _dri_drm_tick_begin(void *data __UNUSED__)
115 drm_event_is_busy = 1;
116 _dri_drm_tick_schedule();
120 _dri_drm_tick_end(void *data __UNUSED__)
122 drm_event_is_busy = 0;
126 _dri_drm_vblank_handler(int fd __UNUSED__, unsigned int frame __UNUSED__,
127 unsigned int sec __UNUSED__,
128 unsigned int usec __UNUSED__, void *data __UNUSED__)
130 ecore_animator_custom_tick();
131 if (drm_event_is_busy) _dri_drm_tick_schedule();
135 _dri_drm_cb(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
137 sym_drmHandleEvent(drm_fd, &drm_evctx);
138 return ECORE_CALLBACK_RENEW;
141 // yes. most evil. we dlopen libdrm and libGL etc. to manually find smbols
142 // so we can be as compatible as possible given the whole mess of the
143 // gl/dri/drm etc. world. and handle graceful failure at runtime not
148 const char *drm_libs[] =
156 const char *dri_libs[] =
171 #define SYM(lib, xx) \
173 sym_ ## xx = dlsym(lib, #xx); \
174 if (!(sym_ ## xx)) { \
175 fprintf(stderr, "%s\n", dlerror()); \
180 if (dri_lib) return 1;
181 for (i = 0; drm_libs[i]; i++)
183 drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY);
187 SYM(drm_lib, drmClose);
188 SYM(drm_lib, drmWaitVBlank);
189 SYM(drm_lib, drmHandleEvent);
198 if (!drm_lib) return 0;
199 for (i = 0; dri_libs[i]; i++)
201 dri_lib = dlopen(dri_libs[i], RTLD_LOCAL | RTLD_LAZY);
205 SYM(dri_lib, DRI2QueryExtension);
206 SYM(dri_lib, DRI2QueryVersion);
207 SYM(dri_lib, DRI2Connect);
208 SYM(dri_lib, DRI2Authenticate);
229 if (!sym_DRI2QueryExtension(_ecore_x_disp, &dri2_event, &dri2_error))
231 if (!sym_DRI2QueryVersion(_ecore_x_disp, &dri2_major, &dri2_minor))
235 if (!sym_DRI2Connect(_ecore_x_disp, dri_drm_vsync_root, &driver_name, &device_name))
237 drm_fd = open(device_name, O_RDWR);
240 sym_drmGetMagic(drm_fd, &drm_magic);
241 if (!sym_DRI2Authenticate(_ecore_x_disp, dri_drm_vsync_root, drm_magic))
247 memset(&drm_evctx, 0, sizeof(drm_evctx));
248 drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
249 drm_evctx.vblank_handler = _dri_drm_vblank_handler;
250 drm_evctx.page_flip_handler = NULL;
252 dri_drm_fdh = ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ,
253 _dri_drm_cb, NULL, NULL, NULL);
264 _dri_drm_shutdown(void)
273 ecore_main_fd_handler_del(dri_drm_fdh);
280 ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
282 #ifdef ECORE_X_VSYNC_DRI2
285 root = ecore_x_window_root_get(win);
286 if (root != dri_drm_vsync_root)
288 dri_drm_vsync_root = root;
289 if (dri_drm_vsync_root)
291 if (!_dri_drm_link())
293 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
297 if (!_dri_drm_init())
299 dri_drm_vsync_root = 0;
300 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
303 ecore_animator_custom_source_tick_begin_callback_set
304 (_dri_drm_tick_begin, NULL);
305 ecore_animator_custom_source_tick_end_callback_set
306 (_dri_drm_tick_end, NULL);
307 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
314 ecore_animator_custom_source_tick_begin_callback_set
316 ecore_animator_custom_source_tick_end_callback_set
318 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);