#include <xf86drm.h>
#include <wayland-server.h>
#include "wayland-kms.h"
+#include "wayland-kms-auth.h"
#include "wayland-kms-server-protocol.h"
#if defined(DEBUG)
# define WLKMS_DEBUG(s, x...) { }
#endif
+/*
+ * Taken from EGL/egl.h. Better to refer the egl.h
+ * in the future.
+ */
+#ifndef EGL_TEXTURE_RGBA
+# define EGL_TEXTURE_RGBA 0x305E
+#endif
+
struct wl_kms {
struct wl_display *display;
int fd; /* FD for DRM */
char *device_name;
+
+ struct kms_auth *auth; /* for nested authentication */
};
+/*
+ * wl_kms server
+ */
+
static void destroy_buffer(struct wl_resource *resource)
{
struct wl_kms_buffer *buffer = resource->data;
+ struct drm_gem_close close;
+ int ret;
+
+ if (buffer->handle) {
+ close.handle = buffer->handle;
+ ret = drmIoctl(buffer->kms->fd, DRM_IOCTL_GEM_CLOSE, &close);
+ if (ret)
+ WLKMS_DEBUG("%s: %s: DRM_IOCTL_GEM_CLOSE failed.(%s)\n",
+ __FILE__, __func__, strerror(errno));
+ }
+
free(buffer);
}
WLKMS_DEBUG("%s: %s: magic=%lu\n", __FILE__, __func__, magic);
- if (drmAuthMagic(kms->fd, magic) < 0) {
+ if (kms->auth) {
+ err = kms_auth_request(kms->auth, magic);
+ } else {
+ err = drmAuthMagic(kms->fd, magic);
+ }
+
+ if (err < 0) {
wl_resource_post_error(resource, WL_KMS_ERROR_AUTHENTICATION_FAILED,
"authentication failed");
WLKMS_DEBUG("%s: %s: authentication failed.\n", __FILE__, __func__);
}
static void
-kms_create_buffer(struct wl_client *client, struct wl_resource *resource,
- uint32_t id, int32_t prime_fd, int32_t width, int32_t height,
- uint32_t stride, uint32_t format, uint32_t handle)
+kms_create_mp_buffer(struct wl_client *client, struct wl_resource *resource,
+ uint32_t id, int32_t width, int32_t height, uint32_t format,
+ int32_t fd0, uint32_t stride0, int32_t fd1, uint32_t stride1,
+ int32_t fd2, uint32_t stride2)
{
struct wl_kms *kms = resource->data;
struct wl_kms_buffer *buffer;
- int err;
+ int err, nplanes;
switch (format) {
case WL_KMS_FORMAT_ARGB8888:
case WL_KMS_FORMAT_XRGB8888:
+ case WL_KMS_FORMAT_ABGR8888:
+ case WL_KMS_FORMAT_XBGR8888:
+ case WL_KMS_FORMAT_RGB888:
+ case WL_KMS_FORMAT_BGR888:
+ case WL_KMS_FORMAT_YUYV:
+ case WL_KMS_FORMAT_UYVY:
+ case WL_KMS_FORMAT_RGB565:
+ case WL_KMS_FORMAT_BGR565:
+ nplanes = 1;
+ break;
+
+ case WL_KMS_FORMAT_NV12:
+ case WL_KMS_FORMAT_NV21:
+ case WL_KMS_FORMAT_NV16:
+ case WL_KMS_FORMAT_NV61:
+ nplanes = 2;
break;
+
default:
wl_resource_post_error(resource,
WL_KMS_ERROR_INVALID_FORMAT,
buffer->width = width;
buffer->height = height;
buffer->format = format;
- buffer->stride = stride;
- buffer->fd = prime_fd;
+ buffer->num_planes = nplanes;
+ buffer->stride = buffer->planes[0].stride = stride0;
+ buffer->fd = buffer->planes[0].fd = fd0;
+
+ if (nplanes > 1) {
+ buffer->planes[1].stride = stride1;
+ buffer->planes[1].fd = fd1;
+ }
+
+ if (nplanes > 2) {
+ buffer->planes[2].stride = stride2;
+ buffer->planes[2].fd = fd2;
+ }
- WLKMS_DEBUG("%s: %s: prime_fd=%d\n", __FILE__, __func__, prime_fd);
-#if 0
- if ((err = drmPrimeFDToHandle(kms->fd, prime_fd, &buffer->handle))) {
+ WLKMS_DEBUG("%s: %s: %d planes (%d, %d, %d)\n", __FILE__, __func__, nplanes, fd0, fd1, fd2);
+
+ // XXX: Do we need to support multiplaner KMS BO?
+ if ((nplanes == 1) && (err = drmPrimeFDToHandle(kms->fd, fd0, &buffer->handle))) {
WLKMS_DEBUG("%s: %s: drmPrimeFDToHandle() failed...%d (%s)\n", __FILE__, __func__, err, strerror(errno));
wl_resource_post_error(resource,
WL_KMS_ERROR_INVALID_FD,
"invalid prime FD");
return;
}
-#else
- {
- struct drm_gem_open op;
- int ret;
-
- op.name = prime_fd;
- op.handle = 0;
-
- ret = drmIoctl(kms->fd, DRM_IOCTL_GEM_OPEN, &op);
- if (ret) {
- WLKMS_DEBUG("%s: %s: DRM_IOCTL_GEM_OPEN failed...(%s)\n", __FILE__, __func__, strerror(errno));
- wl_resource_post_error(resource, WL_KMS_ERROR_INVALID_FD, "invalid prime FD");
- return;
- }
- buffer->handle = op.handle;
- }
-#endif
// We create a wl_buffer
buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id);
buffer, destroy_buffer);
}
+
+static void
+kms_create_buffer(struct wl_client *client, struct wl_resource *resource,
+ uint32_t id, int32_t prime_fd, int32_t width, int32_t height,
+ uint32_t stride, uint32_t format, uint32_t handle)
+{
+ kms_create_mp_buffer(client, resource, id, width, height, format, prime_fd, stride,
+ 0, 0, 0, 0);
+}
+
const static struct wl_kms_interface kms_interface = {
.authenticate = kms_authenticate,
.create_buffer = kms_create_buffer,
+ .create_mp_buffer = kms_create_mp_buffer,
};
static void
wl_resource_post_event(resource, WL_KMS_FORMAT, WL_KMS_FORMAT_XRGB8888);
}
+int wayland_kms_fd_get(struct wl_kms* kms)
+{
+ return kms->fd;
+}
+
struct wl_kms_buffer *wayland_kms_buffer_get(struct wl_resource *resource)
{
if (resource == NULL)
return NULL;
}
-struct wl_kms *wayland_kms_init(struct wl_display *display, char *device_name, int fd)
+struct wl_kms *wayland_kms_init(struct wl_display *display,
+ struct wl_display *server, char *device_name, int fd)
{
struct wl_kms *kms;
- kms = malloc(sizeof *kms);
+ if (!(kms = calloc(1, sizeof(struct wl_kms))))
+ return NULL;
kms->display = display;
kms->device_name = strdup(device_name);
kms->fd = fd;
- wl_global_create(display, &wl_kms_interface, 1, kms, bind_kms);
+ wl_global_create(display, &wl_kms_interface, 2, kms, bind_kms);
+
+ /*
+ * we're the server in the middle. we should forward the auth
+ * request to our server.
+ */
+ if (server) {
+ drm_magic_t magic;
+
+ if (!(kms->auth = kms_auth_init(server)))
+ goto error;
+
+ /* get a magic */
+ if (drmGetMagic(fd, &magic) < 0)
+ goto error;
+
+ /* authenticate myself */
+ if (kms_auth_request(kms->auth, magic) < 0)
+ goto error;
+ }
return kms;
+
+error:
+ free(kms);
+ return NULL;
}
void wayland_kms_uninit(struct wl_kms *kms)
return 0;
case WL_KMS_TEXTURE_FORMAT:
- *value = WL_KMS_FORMAT_ARGB8888;
+ *value = EGL_TEXTURE_RGBA;
return 0;
}