+static void
+drm_handle_device(void *data, struct wl_drm *drm, const char *device)
+{
+ struct dri2_egl_display *dri2_dpy = data;
+ drm_magic_t magic;
+
+ dri2_dpy->device_name = strdup(device);
+ if (!dri2_dpy->device_name)
+ return;
+
+#ifdef O_CLOEXEC
+ dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
+ if (dri2_dpy->fd == -1 && errno == EINVAL)
+#endif
+ {
+ dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
+ if (dri2_dpy->fd != -1)
+ fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) |
+ FD_CLOEXEC);
+ }
+ if (dri2_dpy->fd == -1) {
+ _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
+ dri2_dpy->device_name, strerror(errno));
+ return;
+ }
+
+ drmGetMagic(dri2_dpy->fd, &magic);
+ wl_drm_authenticate(dri2_dpy->wl_drm, magic);
+}
+
+static void
+drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
+{
+ struct dri2_egl_display *dri2_dpy = data;
+
+ switch (format) {
+ case WL_DRM_FORMAT_ARGB8888:
+ dri2_dpy->formats |= HAS_ARGB8888;
+ break;
+ case WL_DRM_FORMAT_XRGB8888:
+ dri2_dpy->formats |= HAS_XRGB8888;
+ break;
+ case WL_DRM_FORMAT_RGB565:
+ dri2_dpy->formats |= HAS_RGB565;
+ break;
+ }
+}
+
+static void
+drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
+{
+ struct dri2_egl_display *dri2_dpy = data;
+
+ dri2_dpy->capabilities = value;
+}
+
+static void
+drm_handle_authenticated(void *data, struct wl_drm *drm)
+{
+ struct dri2_egl_display *dri2_dpy = data;
+
+ dri2_dpy->authenticated = 1;
+}
+
+static const struct wl_drm_listener drm_listener = {
+ drm_handle_device,
+ drm_handle_format,
+ drm_handle_authenticated,
+ drm_handle_capabilities
+};
+
+static void
+registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
+ const char *interface, uint32_t version)
+{
+ struct dri2_egl_display *dri2_dpy = data;
+
+ if (version > 1)
+ version = 2;
+ if (strcmp(interface, "wl_drm") == 0) {
+ dri2_dpy->wl_drm =
+ wl_registry_bind(registry, name, &wl_drm_interface, version);
+ wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
+ }
+}
+
+static void
+registry_handle_global_remove(void *data, struct wl_registry *registry,
+ uint32_t name)
+{
+}
+
+static const struct wl_registry_listener registry_listener = {
+ registry_handle_global,
+ registry_handle_global_remove
+};
+
+static EGLBoolean
+dri2_wl_swap_interval(_EGLDriver *drv,
+ _EGLDisplay *disp,
+ _EGLSurface *surf,
+ EGLint interval)
+{
+ if (interval > surf->Config->MaxSwapInterval)
+ interval = surf->Config->MaxSwapInterval;
+ else if (interval < surf->Config->MinSwapInterval)
+ interval = surf->Config->MinSwapInterval;
+
+ surf->SwapInterval = interval;
+
+ return EGL_TRUE;
+}
+
+static void
+dri2_wl_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
+{
+ GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+
+ /* We can't use values greater than 1 on Wayland because we are using the
+ * frame callback to synchronise the frame and the only way we be sure to
+ * get a frame callback is to attach a new buffer. Therefore we can't just
+ * sit drawing nothing to wait until the next ‘n’ frame callbacks */
+
+ if (dri2_dpy->config)
+ dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
+ "vblank_mode", &vblank_mode);
+ switch (vblank_mode) {
+ case DRI_CONF_VBLANK_NEVER:
+ dri2_dpy->min_swap_interval = 0;
+ dri2_dpy->max_swap_interval = 0;
+ dri2_dpy->default_swap_interval = 0;
+ break;
+ case DRI_CONF_VBLANK_ALWAYS_SYNC:
+ dri2_dpy->min_swap_interval = 1;
+ dri2_dpy->max_swap_interval = 1;
+ dri2_dpy->default_swap_interval = 1;
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_0:
+ dri2_dpy->min_swap_interval = 0;
+ dri2_dpy->max_swap_interval = 1;
+ dri2_dpy->default_swap_interval = 0;
+ break;
+ default:
+ case DRI_CONF_VBLANK_DEF_INTERVAL_1:
+ dri2_dpy->min_swap_interval = 0;
+ dri2_dpy->max_swap_interval = 1;
+ dri2_dpy->default_swap_interval = 1;
+ break;
+ }
+}
+
+static struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
+ .authenticate = dri2_wl_authenticate,
+ .create_window_surface = dri2_wl_create_window_surface,
+ .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
+ .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
+ .destroy_surface = dri2_wl_destroy_surface,
+ .swap_interval = dri2_wl_swap_interval,
+ .swap_buffers = dri2_wl_swap_buffers,
+ .swap_buffers_with_damage = dri2_wl_swap_buffers_with_damage,
+ .swap_buffers_region = dri2_fallback_swap_buffers_region,
+ .copy_buffers = dri2_fallback_copy_buffers,
+ .query_buffer_age = dri2_wl_query_buffer_age,
+};
+