diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index a13a920ae..8cbe6cf4a 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -653,6 +653,17 @@ meta_wayland_init (void) if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) g_error ("Failed to initialize Clutter"); +#if defined(CLUTTER_WINDOWING_EGL) + if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) + { + ClutterBackend *backend = clutter_get_default_backend (); + CoglContext *cogl_context = clutter_backend_get_cogl_context (backend); + CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context)); + int drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); + meta_launcher_set_drm_fd (compositor->launcher, drm_fd, NULL); + } +#endif + meta_monitor_manager_initialize (); monitors = meta_monitor_manager_get (); g_signal_connect (monitors, "monitors-changed", diff --git a/src/wayland/meta-weston-launch.c b/src/wayland/meta-weston-launch.c index 624d95146..99a444215 100644 --- a/src/wayland/meta-weston-launch.c +++ b/src/wayland/meta-weston-launch.c @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -157,11 +156,36 @@ send_message_to_wl (MetaLauncher *self, return TRUE; } +gboolean +meta_launcher_set_drm_fd (MetaLauncher *self, + int drm_fd, + GError **error) +{ + struct weston_launcher_message message; + GSocketControlMessage *cmsg; + gboolean ok; + + message.opcode = WESTON_LAUNCHER_DRM_SET_FD; + + cmsg = g_unix_fd_message_new (); + if (g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (cmsg), + drm_fd, error) == FALSE) + { + g_object_unref (cmsg); + return FALSE; + } + + ok = send_message_to_wl (self, &message, sizeof message, cmsg, NULL, error); + + g_object_unref (cmsg); + return ok; +} + static int -meta_launcher_open_device (MetaLauncher *self, - const char *name, - int flags, - GError **error) +meta_launcher_open_input_device (MetaLauncher *self, + const char *name, + int flags, + GError **error) { struct weston_launcher_open *message; GSocketControlMessage *cmsg; @@ -237,7 +261,7 @@ on_evdev_device_open (const char *path, { MetaLauncher *launcher = user_data; - return meta_launcher_open_device (launcher, path, flags, error); + return meta_launcher_open_input_device (launcher, path, flags, error); } static void @@ -358,18 +382,6 @@ meta_launcher_new (void) clutter_evdev_set_open_callback (on_evdev_device_open, self); -#if defined(CLUTTER_WINDOWING_EGL) - if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) - { - GError *error = NULL; - int fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error); - if (error) - g_error ("Failed to open /dev/dri/card0: %s", error->message); - - clutter_egl_native_set_kms_fd (fd); - } -#endif - return self; } diff --git a/src/wayland/meta-weston-launch.h b/src/wayland/meta-weston-launch.h index b70faf88e..7fdd03c23 100644 --- a/src/wayland/meta-weston-launch.h +++ b/src/wayland/meta-weston-launch.h @@ -31,4 +31,8 @@ void meta_launcher_free (MetaLauncher *self); gboolean meta_launcher_activate_vt (MetaLauncher *self, signed char vt, GError **error); + +gboolean meta_launcher_set_drm_fd (MetaLauncher *self, + int drm_fd, + GError **error); #endif diff --git a/src/wayland/weston-launch.c b/src/wayland/weston-launch.c index ae713ed23..240cfef16 100644 --- a/src/wayland/weston-launch.c +++ b/src/wayland/weston-launch.c @@ -165,6 +165,69 @@ setenv_fd(const char *env, int fd) setenv(env, buf, 1); } +static int +handle_setdrmfd(struct weston_launch *wl, struct msghdr *msg, ssize_t len) +{ + struct weston_launcher_reply reply; + struct cmsghdr *cmsg; + union cmsg_data *data; + struct stat s; + + reply.header.opcode = WESTON_LAUNCHER_DRM_SET_FD; + reply.ret = -1; + + if (wl->drm_fd != -1) { + error(0, 0, "DRM FD already set"); + reply.ret = -EINVAL; + goto out; + } + + cmsg = CMSG_FIRSTHDR(msg); + if (!cmsg || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { + error(0, 0, "invalid control message"); + reply.ret = -EINVAL; + goto out; + } + + data = (union cmsg_data *) CMSG_DATA(cmsg); + if (data->fd < 0) { + error(0, 0, "missing drm fd in socket request"); + reply.ret = -EINVAL; + goto out; + } + + if (fstat(data->fd, &s) < 0) { + reply.ret = -errno; + goto out; + } + + if (major(s.st_rdev) != DRM_MAJOR) { + fprintf(stderr, "FD is not for DRM\n"); + reply.ret = -EPERM; + goto out; + } + + wl->drm_fd = data->fd; + reply.ret = drmSetMaster(data->fd); + if (reply.ret < 0) + reply.ret = -errno; + + if (wl->verbose) + fprintf(stderr, "mutter-launch: set drm FD, ret: %d, fd: %d\n", + reply.ret, data->fd); + +out: + do { + len = send(wl->sock[0], &reply, sizeof reply, 0); + } while (len < 0 && errno == EINTR); + if (len < 0) + return -1; + + return 0; +} + static int handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len) { @@ -260,7 +323,6 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) struct iovec iov; struct weston_launcher_open *message; union cmsg_data *data; - int dev_major; reply.header.opcode = WESTON_LAUNCHER_OPEN; reply.ret = -1; @@ -277,22 +339,13 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) goto err0; } - dev_major = major(s.st_rdev); - - if (dev_major != INPUT_MAJOR || - dev_major != DRM_MAJOR) { - fprintf(stderr, "Device %s is not an input or DRM device\n", + if (major(s.st_rdev) != INPUT_MAJOR) { + fprintf(stderr, "Device %s is not an input device\n", message->path); reply.ret = -EPERM; goto err0; } - if (dev_major == DRM_MAJOR && wl->drm_fd != -1) { - fprintf(stderr, "Already have a DRM device open\n"); - reply.ret = -EPERM; - goto err0; - } - fd = open(message->path, message->flags); if (fd < 0) { fprintf(stderr, "Error opening device %s: %m\n", @@ -301,10 +354,6 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) goto err0; } - if (dev_major == DRM_MAJOR) { - wl->drm_fd = fd; - } - err0: memset(&nmsg, 0, sizeof nmsg); nmsg.msg_iov = &iov; @@ -370,6 +419,9 @@ handle_socket_msg(struct weston_launch *wl) case WESTON_LAUNCHER_OPEN: ret = handle_open(wl, &msg, len); break; + case WESTON_LAUNCHER_DRM_SET_FD: + ret = handle_setdrmfd(wl, &msg, len); + break; case WESTON_LAUNCHER_CONFIRM_VT_SWITCH: ret = handle_confirm_vt_switch(wl, &msg, len); break; diff --git a/src/wayland/weston-launch.h b/src/wayland/weston-launch.h index 1e716c5ac..968dd7416 100644 --- a/src/wayland/weston-launch.h +++ b/src/wayland/weston-launch.h @@ -31,8 +31,9 @@ enum weston_launcher_message_type { enum weston_launcher_opcode { WESTON_LAUNCHER_OPEN = (1 << 1 | WESTON_LAUNCHER_REQUEST), - WESTON_LAUNCHER_ACTIVATE_VT = (2 << 1 | WESTON_LAUNCHER_REQUEST), - WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (3 << 1 | WESTON_LAUNCHER_REQUEST), + WESTON_LAUNCHER_DRM_SET_FD = (2 << 1 | WESTON_LAUNCHER_REQUEST), + WESTON_LAUNCHER_ACTIVATE_VT = (3 << 1 | WESTON_LAUNCHER_REQUEST), + WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (4 << 1 | WESTON_LAUNCHER_REQUEST), }; enum weston_launcher_server_opcode {