summaryrefslogtreecommitdiff
path: root/hw/xfree86/xwayland/xwayland-drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/xwayland/xwayland-drm.c')
-rw-r--r--hw/xfree86/xwayland/xwayland-drm.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c
new file mode 100644
index 000000000..52508575f
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-drm.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <xf86drm.h>
+#include <wayland-util.h>
+#include <wayland-client.h>
+#include <drm-client-protocol.h>
+
+#include <xf86Xinput.h>
+#include <xf86Crtc.h>
+#include <xf86str.h>
+#include <windowstr.h>
+#include <input.h>
+#include <inputstr.h>
+#include <exevents.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "../dri2/dri2.h"
+
+struct xwl_auth_req {
+ struct xorg_list link;
+
+ ClientPtr client;
+ struct xwl_screen *xwl_screen;
+ uint32_t magic;
+};
+
+static void
+drm_handle_device (void *data, struct wl_drm *drm, const char *device)
+{
+ struct xwl_screen *xwl_screen = data;
+
+ xwl_screen->device_name = strdup (device);
+}
+
+static void
+drm_handle_format(void *data, struct wl_drm *wl_drm, uint32_t format)
+{
+}
+
+static void
+drm_handle_authenticated (void *data, struct wl_drm *drm)
+{
+ struct xwl_screen *xwl_screen = data;
+ struct xwl_auth_req *req;
+
+ xwl_screen->authenticated = 1;
+
+ /* it does one authentication transaction at a time, so if there's an
+ * element in the list, we call DRI2SendAuthReply for that client, remove
+ * the head and free the struct. If there are still elements in the list,
+ * it means that we have one or more clients waiting to be authenticated
+ * and we send out a wl_drm authenticate request for the first client in
+ * the list */
+ if (xorg_list_is_empty(&xwl_screen->authenticate_client_list))
+ return;
+
+ req = xorg_list_first_entry(&xwl_screen->authenticate_client_list,
+ struct xwl_auth_req, link);
+ DRI2SendAuthReply(req->client, TRUE);
+ AttendClient(req->client);
+ xorg_list_del(&req->link);
+ free(req);
+
+ xorg_list_for_each_entry(req, &xwl_screen->authenticate_client_list,
+ link) {
+ wl_drm_authenticate (xwl_screen->drm, req->magic);
+ return;
+ }
+}
+
+static const struct wl_drm_listener xwl_drm_listener =
+{
+ drm_handle_device,
+ drm_handle_format,
+ drm_handle_authenticated
+};
+
+static void
+drm_handler(void *data, struct wl_registry *registry, uint32_t id,
+ const char *interface, uint32_t version)
+{
+ struct xwl_screen *xwl_screen = data;
+
+ if (strcmp (interface, "wl_drm") == 0) {
+ xwl_screen->drm = wl_registry_bind(xwl_screen->registry, id,
+ &wl_drm_interface, 1);
+ wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
+ }
+}
+
+static void
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+ /* Nothing to do here, wl_drm should not be removed */
+}
+
+static const struct wl_registry_listener drm_listener = {
+ drm_handler,
+ global_remove
+};
+
+int
+xwl_drm_pre_init(struct xwl_screen *xwl_screen)
+{
+ uint32_t magic;
+
+ xwl_screen->drm_registry = wl_display_get_registry(xwl_screen->display);
+ wl_registry_add_listener(xwl_screen->drm_registry, &drm_listener,
+ xwl_screen);
+
+ /* Ensure drm_handler has seen all the interfaces */
+ wl_display_roundtrip(xwl_screen->display);
+ /* Ensure the xwl_drm_listener has seen the drm device, if any */
+ wl_display_roundtrip(xwl_screen->display);
+
+ ErrorF("wayland_drm_screen_init, device name %s\n",
+ xwl_screen->device_name);
+
+ xwl_screen->drm_fd = open(xwl_screen->device_name, O_RDWR);
+ if (xwl_screen->drm_fd < 0) {
+ ErrorF("failed to open the drm fd\n");
+ return BadAccess;
+ }
+
+ if (drmGetMagic(xwl_screen->drm_fd, &magic)) {
+ ErrorF("failed to get drm magic");
+ return BadAccess;
+ }
+
+ wl_drm_authenticate(xwl_screen->drm, magic);
+
+ wl_display_roundtrip(xwl_screen->display);
+
+ ErrorF("opened drm fd: %d\n", xwl_screen->drm_fd);
+
+ if (!xwl_screen->authenticated) {
+ ErrorF("Failed to auth drm fd\n");
+ return BadAccess;
+ }
+
+ return Success;
+}
+
+Bool xwl_drm_initialised(struct xwl_screen *xwl_screen)
+{
+ return xwl_screen->authenticated;
+}
+
+int xwl_screen_get_drm_fd(struct xwl_screen *xwl_screen)
+{
+ return xwl_screen->drm_fd;
+}
+
+int xwl_drm_authenticate(ClientPtr client, struct xwl_screen *xwl_screen,
+ uint32_t magic)
+{
+ struct xwl_auth_req *req;
+
+ if (!xwl_screen->drm)
+ return BadAccess;
+
+ req = malloc (sizeof *req);
+ if (req == NULL)
+ return BadAlloc;
+
+ req->client = client;
+ req->xwl_screen = xwl_screen;
+ req->magic = magic;
+
+ if (xorg_list_is_empty(&xwl_screen->authenticate_client_list))
+ wl_drm_authenticate (xwl_screen->drm, magic);
+
+ xorg_list_append(&req->link, &xwl_screen->authenticate_client_list);
+
+ IgnoreClient(req->client);
+ xwl_screen->authenticated = 0;
+
+ return Success;
+}
+
+
+int
+xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, uint32_t name)
+{
+ VisualID visual;
+ WindowPtr window = xwl_window->window;
+ ScreenPtr screen = window->drawable.pScreen;
+ uint32_t format;
+ int i;
+
+ visual = wVisual(window);
+ for (i = 0; i < screen->numVisuals; i++)
+ if (screen->visuals[i].vid == visual)
+ break;
+
+ switch (screen->visuals[i].nplanes) {
+ case 32:
+ format = WL_DRM_FORMAT_ARGB8888;
+ break;
+ case 24:
+ default:
+ format = WL_DRM_FORMAT_XRGB8888;
+ break;
+ case 16:
+ format = WL_DRM_FORMAT_RGB565;
+ break;
+ }
+
+ xwl_window->buffer =
+ wl_drm_create_buffer(xwl_window->xwl_screen->drm,
+ name,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->devKind,
+ format);
+
+ return xwl_window->buffer ? Success : BadDrawable;
+}