M Makefile.am => Makefile.am +5 -4
@@ 23,10 23,10 @@
bin_PROGRAMS = kmscube
-CFLAGS=-O0 -g
+CFLAGS=-O0 -g -Wno-unused-parameter
kmscube_LDADD = \
- $(XCB_LIBS) \
+ $(WAYLAND_LIBS) \
$(DRM_LIBS) \
$(GBM_LIBS) \
$(EGL_LIBS) \
@@ 37,7 37,7 @@ kmscube_LDADD = \
kmscube_CFLAGS = \
-O0 -g \
-Wall -Wextra \
- $(XCB_CFLAGS) \
+ $(WAYLAND_CFLAGS) \
$(DRM_CFLAGS) \
$(GBM_CFLAGS) \
$(EGL_CFLAGS) \
@@ 56,4 56,5 @@ kmscube_SOURCES = \
esUtil.h \
frame-512x512-NV12.c \
frame-512x512-RGBA.c \
- kmscube.c
+ kmscube.c \
+ drm-lease-protocol.c
M configure.ac => configure.ac +1 -1
@@ 39,7 39,7 @@ PKG_CHECK_MODULES(DRM, libdrm)
PKG_CHECK_MODULES(GBM, gbm)
PKG_CHECK_MODULES(EGL, egl)
PKG_CHECK_MODULES(GLES2, glesv2)
-PKG_CHECK_MODULES(XCB, xcb-randr xcb)
+PKG_CHECK_MODULES(WAYLAND, wayland-client)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
M drm-common.c => drm-common.c +65 -36
@@ 93,22 93,22 @@ static uint32_t find_crtc_for_encoder(const drmModeRes *resources,
static int leased(int fd, int nfd, int id)
{
- if (fd != nfd && nfd != -1) {
- drmModeObjectListPtr lease = drmModeGetLease(nfd);
- int ret = 0;
-
- if (lease) {
- uint32_t u;
- for (u = 0; u < lease->count; u++)
- if (lease->objects[u] == (uint32_t) id) {
- ret = 1;
- break;
- }
- free(lease);
- return ret;
- }
- }
- return 0;
+ if (fd != nfd && nfd != -1) {
+ drmModeObjectListPtr lease = drmModeGetLease(nfd);
+ int ret = 0;
+
+ if (lease) {
+ uint32_t u;
+ for (u = 0; u < lease->count; u++)
+ if (lease->objects[u] == (uint32_t) id) {
+ ret = 1;
+ break;
+ }
+ free(lease);
+ return ret;
+ }
+ }
+ return 0;
}
static uint32_t find_crtc_for_connector(int fd, int nfd, const struct drm *drm, const drmModeRes *resources,
@@ 138,7 138,7 @@ int find_drm(struct drm_resources *drm_resources, int fd, int nfd)
drmModeRes *resources;
drmModeConnector *connector = NULL;
drmModeEncoder *encoder = NULL;
- int i;
+ int i, crtc_i = -1;
resources = drmModeGetResources(fd);
if (!resources) {
@@ 150,9 150,9 @@ int find_drm(struct drm_resources *drm_resources, int fd, int nfd)
for (i = 0; i < resources->count_connectors; i++) {
connector = drmModeGetConnector(fd, resources->connectors[i]);
if (connector->connection == DRM_MODE_CONNECTED && !leased(fd, nfd, connector->connector_id)) {
- printf("connector id %u\n", connector->connector_id);
+ printf("connector id %u\n", connector->connector_id);
/* it's connected, let's use this! */
- drm_resources->connector = connector->connector_id;
+ drm_resources->connector = connector->connector_id;
break;
}
drmModeFreeConnector(connector);
@@ 177,31 177,60 @@ int find_drm(struct drm_resources *drm_resources, int fd, int nfd)
}
if (encoder) {
- drm_resources->encoder = encoder->encoder_id;
- drm_resources->crtc = encoder->crtc_id;
+ drm_resources->encoder = encoder->encoder_id;
+ drm_resources->crtc = encoder->crtc_id;
} else {
- uint32_t crtc_id;
- for (i = 0; i < connector->count_encoders; i++) {
- const uint32_t encoder_id = connector->encoders[i];
- drmModeEncoder *encoder = drmModeGetEncoder(fd, encoder_id);
-
- if (encoder && !leased(fd, nfd, encoder->encoder_id)) {
- crtc_id = find_crtc_for_encoder(resources, encoder);
-
- if (crtc_id != 0)
- break;
- drmModeFreeEncoder(encoder);
- }
- }
+ uint32_t crtc_id;
+ for (i = 0; i < connector->count_encoders; i++) {
+ const uint32_t encoder_id = connector->encoders[i];
+ drmModeEncoder *encoder = drmModeGetEncoder(fd, encoder_id);
+
+ if (encoder && !leased(fd, nfd, encoder->encoder_id)) {
+ crtc_id = find_crtc_for_encoder(resources, encoder);
+
+ if (crtc_id != 0) {
+ break;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+ }
if (crtc_id == 0) {
printf("no crtc found!\n");
return -1;
}
- drm_resources->crtc = crtc_id;
+ drm_resources->crtc = crtc_id;
+ }
+ for (i = 0; i < resources->count_crtcs; i++) {
+ if (resources->crtcs[i] == drm_resources->crtc) {
+ crtc_i = i;
+ break;
+ }
+ }
+
+ drmModePlaneRes *plane_res = drmModeGetPlaneResources(fd);
+ if (!plane_res) {
+ printf("no planes!\n");
+ return -1;
+ }
+
+ for (uint32_t i = 0; i < plane_res->count_planes; ++i) {
+ uint32_t id = plane_res->planes[i];
+ drmModePlane *plane = drmModeGetPlane(fd, id);
+ printf("plane %d possible CRTCs: %x (need %d)\n",
+ id, plane->possible_crtcs, crtc_i);
+ if (((1 << crtc_i) & plane->possible_crtcs)) {
+ printf("plane %d is compatible with crtc %d\n",
+ id, drm_resources->crtc);
+ drm_resources->plane = id;
+ break;
+ }
+ drmModeFreePlane(plane);
}
+ drmModeFreePlaneResources(plane_res);
+
drmModeFreeResources(resources);
return 0;
@@ 226,7 255,7 @@ int init_drm(struct drm *drm, int fd, int nfd)
for (i = 0; i < resources->count_connectors; i++) {
connector = drmModeGetConnector(drm->fd, resources->connectors[i]);
if (!leased(fd, nfd, connector->connector_id) && connector->connection == DRM_MODE_CONNECTED) {
- printf("connector id %u\n", connector->connector_id);
+ printf("connector id %u\n", connector->connector_id);
/* it's connected, let's use this! */
break;
}
M drm-common.h => drm-common.h +1 -0
@@ 81,6 81,7 @@ struct drm_resources {
uint32_t encoder;
uint32_t connector;
uint32_t crtc;
+ uint32_t plane;
};
int find_drm(struct drm_resources *drm_resources, int fd, int nfd);
A drm-lease-protocol.c => drm-lease-protocol.c +113 -0
@@ 0,0 1,113 @@
+/* Generated by wayland-scanner 1.17.0 */
+
+/*
+ * Copyright © 2018 NXP
+ * Copyright © 2019 Status Research & Development GmbH.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
+#endif
+
+#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
+#define WL_PRIVATE __attribute__ ((visibility("hidden")))
+#else
+#define WL_PRIVATE
+#endif
+
+extern const struct wl_interface zwp_drm_lease_connector_v1_interface;
+extern const struct wl_interface zwp_drm_lease_request_v1_interface;
+extern const struct wl_interface zwp_drm_lease_v1_interface;
+
+static const struct wl_interface *types[] = {
+ NULL,
+ NULL,
+ &zwp_drm_lease_request_v1_interface,
+ &zwp_drm_lease_connector_v1_interface,
+ &zwp_drm_lease_connector_v1_interface,
+ &zwp_drm_lease_v1_interface,
+};
+
+static const struct wl_message zwp_drm_lease_manager_v1_requests[] = {
+ { "create_lease_request", "n", types + 2 },
+ { "stop", "", types + 0 },
+};
+
+static const struct wl_message zwp_drm_lease_manager_v1_events[] = {
+ { "connector", "n", types + 3 },
+ { "finished", "", types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface zwp_drm_lease_manager_v1_interface = {
+ "zwp_drm_lease_manager_v1", 1,
+ 2, zwp_drm_lease_manager_v1_requests,
+ 2, zwp_drm_lease_manager_v1_events,
+};
+
+static const struct wl_message zwp_drm_lease_connector_v1_requests[] = {
+ { "destroy", "", types + 0 },
+};
+
+static const struct wl_message zwp_drm_lease_connector_v1_events[] = {
+ { "name", "s", types + 0 },
+ { "description", "s", types + 0 },
+ { "edid", "hu", types + 0 },
+ { "withdrawn", "", types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface zwp_drm_lease_connector_v1_interface = {
+ "zwp_drm_lease_connector_v1", 1,
+ 1, zwp_drm_lease_connector_v1_requests,
+ 4, zwp_drm_lease_connector_v1_events,
+};
+
+static const struct wl_message zwp_drm_lease_request_v1_requests[] = {
+ { "destroy", "", types + 0 },
+ { "request_connector", "o", types + 4 },
+ { "submit", "n", types + 5 },
+};
+
+WL_PRIVATE const struct wl_interface zwp_drm_lease_request_v1_interface = {
+ "zwp_drm_lease_request_v1", 1,
+ 3, zwp_drm_lease_request_v1_requests,
+ 0, NULL,
+};
+
+static const struct wl_message zwp_drm_lease_v1_requests[] = {
+ { "destroy", "", types + 0 },
+};
+
+static const struct wl_message zwp_drm_lease_v1_events[] = {
+ { "lease_fd", "h", types + 0 },
+ { "finished", "", types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface zwp_drm_lease_v1_interface = {
+ "zwp_drm_lease_v1", 1,
+ 1, zwp_drm_lease_v1_requests,
+ 2, zwp_drm_lease_v1_events,
+};
+
A drm-lease-protocol.h => drm-lease-protocol.h +620 -0
@@ 0,0 1,620 @@
+/* Generated by wayland-scanner 1.17.0 */
+
+#ifndef DRM_LEASE_UNSTABLE_V1_CLIENT_PROTOCOL_H
+#define DRM_LEASE_UNSTABLE_V1_CLIENT_PROTOCOL_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @page page_drm_lease_unstable_v1 The drm_lease_unstable_v1 protocol
+ * @section page_ifaces_drm_lease_unstable_v1 Interfaces
+ * - @subpage page_iface_zwp_drm_lease_manager_v1 - lease manager
+ * - @subpage page_iface_zwp_drm_lease_connector_v1 - a leasable DRM connector
+ * - @subpage page_iface_zwp_drm_lease_request_v1 - DRM lease request
+ * - @subpage page_iface_zwp_drm_lease_v1 - a DRM lease
+ * @section page_copyright_drm_lease_unstable_v1 Copyright
+ * <pre>
+ *
+ * Copyright © 2018 NXP
+ * Copyright © 2019 Status Research & Development GmbH.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * </pre>
+ */
+struct zwp_drm_lease_connector_v1;
+struct zwp_drm_lease_manager_v1;
+struct zwp_drm_lease_request_v1;
+struct zwp_drm_lease_v1;
+
+/**
+ * @page page_iface_zwp_drm_lease_manager_v1 zwp_drm_lease_manager_v1
+ * @section page_iface_zwp_drm_lease_manager_v1_desc Description
+ *
+ * This protocol is used by Wayland compositors which act as Direct
+ * Renderering Manager (DRM) masters to lease DRM resources to Wayland
+ * clients. Once leased, the compositor will not use the leased resources
+ * until the lease is revoked or the client closes the file descriptor.
+ *
+ * The lease manager is used to advertise connectors which are available for
+ * leasing, and by the client to negotiate a lease request.
+ *
+ * Warning! The protocol described in this file is experimental and
+ * backward incompatible changes may be made. Backward compatible changes
+ * may be added together with the corresponding interface version bump.
+ * Backward incompatible changes are done by bumping the version number in
+ * the protocol and interface names and resetting the interface version.
+ * Once the protocol is to be declared stable, the 'z' prefix and the
+ * version number in the protocol and interface names are removed and the
+ * interface version number is reset.
+ * @section page_iface_zwp_drm_lease_manager_v1_api API
+ * See @ref iface_zwp_drm_lease_manager_v1.
+ */
+/**
+ * @defgroup iface_zwp_drm_lease_manager_v1 The zwp_drm_lease_manager_v1 interface
+ *
+ * This protocol is used by Wayland compositors which act as Direct
+ * Renderering Manager (DRM) masters to lease DRM resources to Wayland
+ * clients. Once leased, the compositor will not use the leased resources
+ * until the lease is revoked or the client closes the file descriptor.
+ *
+ * The lease manager is used to advertise connectors which are available for
+ * leasing, and by the client to negotiate a lease request.
+ *
+ * Warning! The protocol described in this file is experimental and
+ * backward incompatible changes may be made. Backward compatible changes
+ * may be added together with the corresponding interface version bump.
+ * Backward incompatible changes are done by bumping the version number in
+ * the protocol and interface names and resetting the interface version.
+ * Once the protocol is to be declared stable, the 'z' prefix and the
+ * version number in the protocol and interface names are removed and the
+ * interface version number is reset.
+ */
+extern const struct wl_interface zwp_drm_lease_manager_v1_interface;
+/**
+ * @page page_iface_zwp_drm_lease_connector_v1 zwp_drm_lease_connector_v1
+ * @section page_iface_zwp_drm_lease_connector_v1_desc Description
+ *
+ * Represents a DRM connector which is available for lease. These objects are
+ * created via zwp_drm_lease_manager_v1.connector, and should be passed into
+ * lease requests via zwp_drm_lease_request_v1.add_connector.
+ * @section page_iface_zwp_drm_lease_connector_v1_api API
+ * See @ref iface_zwp_drm_lease_connector_v1.
+ */
+/**
+ * @defgroup iface_zwp_drm_lease_connector_v1 The zwp_drm_lease_connector_v1 interface
+ *
+ * Represents a DRM connector which is available for lease. These objects are
+ * created via zwp_drm_lease_manager_v1.connector, and should be passed into
+ * lease requests via zwp_drm_lease_request_v1.add_connector.
+ */
+extern const struct wl_interface zwp_drm_lease_connector_v1_interface;
+/**
+ * @page page_iface_zwp_drm_lease_request_v1 zwp_drm_lease_request_v1
+ * @section page_iface_zwp_drm_lease_request_v1_desc Description
+ *
+ * A client that wishes to lease DRM resources will attach the list of
+ * connectors advertised with zwp_drm_lease_manager_v1.connector that they
+ * wish to lease, then use zwp_drm_lease_request_v1.submit to submit the
+ * request.
+ * @section page_iface_zwp_drm_lease_request_v1_api API
+ * See @ref iface_zwp_drm_lease_request_v1.
+ */
+/**
+ * @defgroup iface_zwp_drm_lease_request_v1 The zwp_drm_lease_request_v1 interface
+ *
+ * A client that wishes to lease DRM resources will attach the list of
+ * connectors advertised with zwp_drm_lease_manager_v1.connector that they
+ * wish to lease, then use zwp_drm_lease_request_v1.submit to submit the
+ * request.
+ */
+extern const struct wl_interface zwp_drm_lease_request_v1_interface;
+/**
+ * @page page_iface_zwp_drm_lease_v1 zwp_drm_lease_v1
+ * @section page_iface_zwp_drm_lease_v1_desc Description
+ *
+ * A DRM lease object is used to transfer the DRM file descriptor to the
+ * client and manage the lifetime of the lease.
+ * @section page_iface_zwp_drm_lease_v1_api API
+ * See @ref iface_zwp_drm_lease_v1.
+ */
+/**
+ * @defgroup iface_zwp_drm_lease_v1 The zwp_drm_lease_v1 interface
+ *
+ * A DRM lease object is used to transfer the DRM file descriptor to the
+ * client and manage the lifetime of the lease.
+ */
+extern const struct wl_interface zwp_drm_lease_v1_interface;
+
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ * @struct zwp_drm_lease_manager_v1_listener
+ */
+struct zwp_drm_lease_manager_v1_listener {
+ /**
+ * advertise connectors available for leases
+ *
+ * The compositor may choose to advertise 0 or more connectors
+ * which may be leased to clients, and will use this event to do
+ * so. This object may be passed into a lease request to lease that
+ * connector. See zwp_drm_lease_request_v1.add_connector for
+ * details.
+ *
+ * When this global is bound, the compositor will send all
+ * connectors available for lease, but may send additional
+ * connectors at any time.
+ */
+ void (*connector)(void *data,
+ struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1,
+ struct zwp_drm_lease_connector_v1 *id);
+ /**
+ * the compositor has finished using the manager
+ *
+ * This event indicates that the compositor is done sending
+ * connector events. The compositor will destroy this object
+ * immediately after sending this event, and it will become
+ * invalid. The client should release any resources associated with
+ * this manager after receiving this event.
+ */
+ void (*finished)(void *data,
+ struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1);
+};
+
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ */
+static inline int
+zwp_drm_lease_manager_v1_add_listener(struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1,
+ const struct zwp_drm_lease_manager_v1_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) zwp_drm_lease_manager_v1,
+ (void (**)(void)) listener, data);
+}
+
+#define ZWP_DRM_LEASE_MANAGER_V1_CREATE_LEASE_REQUEST 0
+#define ZWP_DRM_LEASE_MANAGER_V1_STOP 1
+
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ */
+#define ZWP_DRM_LEASE_MANAGER_V1_CONNECTOR_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ */
+#define ZWP_DRM_LEASE_MANAGER_V1_FINISHED_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ */
+#define ZWP_DRM_LEASE_MANAGER_V1_CREATE_LEASE_REQUEST_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ */
+#define ZWP_DRM_LEASE_MANAGER_V1_STOP_SINCE_VERSION 1
+
+/** @ingroup iface_zwp_drm_lease_manager_v1 */
+static inline void
+zwp_drm_lease_manager_v1_set_user_data(struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) zwp_drm_lease_manager_v1, user_data);
+}
+
+/** @ingroup iface_zwp_drm_lease_manager_v1 */
+static inline void *
+zwp_drm_lease_manager_v1_get_user_data(struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) zwp_drm_lease_manager_v1);
+}
+
+static inline uint32_t
+zwp_drm_lease_manager_v1_get_version(struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) zwp_drm_lease_manager_v1);
+}
+
+/** @ingroup iface_zwp_drm_lease_manager_v1 */
+static inline void
+zwp_drm_lease_manager_v1_destroy(struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1)
+{
+ wl_proxy_destroy((struct wl_proxy *) zwp_drm_lease_manager_v1);
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ *
+ * Creates a lease request object.
+ *
+ * See the documentation for zwp_drm_lease_request_v1 for details.
+ */
+static inline struct zwp_drm_lease_request_v1 *
+zwp_drm_lease_manager_v1_create_lease_request(struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_drm_lease_manager_v1,
+ ZWP_DRM_LEASE_MANAGER_V1_CREATE_LEASE_REQUEST, &zwp_drm_lease_request_v1_interface, NULL);
+
+ return (struct zwp_drm_lease_request_v1 *) id;
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_manager_v1
+ *
+ * Indicates the client no longer wishes to receive connector events. The
+ * compositor may still send connector events until it sends the finish
+ * event, however.
+ *
+ * The client must not send any requests after this one.
+ */
+static inline void
+zwp_drm_lease_manager_v1_stop(struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1)
+{
+ wl_proxy_marshal((struct wl_proxy *) zwp_drm_lease_manager_v1,
+ ZWP_DRM_LEASE_MANAGER_V1_STOP);
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ * @struct zwp_drm_lease_connector_v1_listener
+ */
+struct zwp_drm_lease_connector_v1_listener {
+ /**
+ * name
+ *
+ * The compositor sends this event once the connector is created
+ * to indicate the name of this connector. This will not change for
+ * the duration of the Wayland session, but is not guaranteed to be
+ * consistent between sessions.
+ *
+ * If the compositor also supports zxdg_output_manager_v1 and this
+ * connector corresponds to a zxdg_output_v1, this name will match
+ * the name of this zxdg_output_v1 object.
+ * @param name connector name
+ */
+ void (*name)(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ const char *name);
+ /**
+ * description
+ *
+ * The compositor sends this event once the connector is created
+ * to provide a human-readable description for this connector,
+ * which may be presented to the user. This will not change for the
+ * duration of the Wayland session, but is not guaranteed to be
+ * consistent between sessions.
+ *
+ * If the compositor also supports zxdg_output_manager_v1 and this
+ * connector corresponds to a zxdg_output_v1, this description will
+ * match the description of this zxdg_output_v1 object.
+ * @param name connector name
+ */
+ void (*description)(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ const char *name);
+ /**
+ * edid
+ *
+ * The compositor sends this event once the connector is created
+ * to provide a file descriptor which may be memory-mapped to read
+ * the connector's EDID, to assist in selecting the correct
+ * connectors for lease.
+ * @param edid EDID file descriptor
+ * @param size EDID size, in bytes
+ */
+ void (*edid)(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ int32_t edid,
+ uint32_t size);
+ /**
+ * lease offer withdrawn
+ *
+ * Sent to indicate that the compositor will no longer honor
+ * requests for DRM leases which include this connector. The client
+ * may still issue a lease request including this connector, but
+ * the compositor will send zwp_drm_lease_v1.finished without
+ * issuing a lease fd.
+ */
+ void (*withdrawn)(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1);
+};
+
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ */
+static inline int
+zwp_drm_lease_connector_v1_add_listener(struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ const struct zwp_drm_lease_connector_v1_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) zwp_drm_lease_connector_v1,
+ (void (**)(void)) listener, data);
+}
+
+#define ZWP_DRM_LEASE_CONNECTOR_V1_DESTROY 0
+
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ */
+#define ZWP_DRM_LEASE_CONNECTOR_V1_NAME_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ */
+#define ZWP_DRM_LEASE_CONNECTOR_V1_DESCRIPTION_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ */
+#define ZWP_DRM_LEASE_CONNECTOR_V1_EDID_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ */
+#define ZWP_DRM_LEASE_CONNECTOR_V1_WITHDRAWN_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ */
+#define ZWP_DRM_LEASE_CONNECTOR_V1_DESTROY_SINCE_VERSION 1
+
+/** @ingroup iface_zwp_drm_lease_connector_v1 */
+static inline void
+zwp_drm_lease_connector_v1_set_user_data(struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) zwp_drm_lease_connector_v1, user_data);
+}
+
+/** @ingroup iface_zwp_drm_lease_connector_v1 */
+static inline void *
+zwp_drm_lease_connector_v1_get_user_data(struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) zwp_drm_lease_connector_v1);
+}
+
+static inline uint32_t
+zwp_drm_lease_connector_v1_get_version(struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) zwp_drm_lease_connector_v1);
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_connector_v1
+ *
+ * The client may send this request to indicate that it will not issue a
+ * lease request for this connector. Clients are encouraged to send this
+ * after receiving the "withdrawn" request so that the server can release
+ * the resources associated with this connector offer.
+ */
+static inline void
+zwp_drm_lease_connector_v1_destroy(struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1)
+{
+ wl_proxy_marshal((struct wl_proxy *) zwp_drm_lease_connector_v1,
+ ZWP_DRM_LEASE_CONNECTOR_V1_DESTROY);
+
+ wl_proxy_destroy((struct wl_proxy *) zwp_drm_lease_connector_v1);
+}
+
+#ifndef ZWP_DRM_LEASE_REQUEST_V1_ERROR_ENUM
+#define ZWP_DRM_LEASE_REQUEST_V1_ERROR_ENUM
+enum zwp_drm_lease_request_v1_error {
+ /**
+ * request submitted with zero connectors
+ */
+ ZWP_DRM_LEASE_REQUEST_V1_ERROR_NO_CONNECTORS = 0,
+ /**
+ * attempted to reuse a submitted lease
+ */
+ ZWP_DRM_LEASE_REQUEST_V1_ERROR_SUBMITTED_LEASE = 1,
+};
+#endif /* ZWP_DRM_LEASE_REQUEST_V1_ERROR_ENUM */
+
+#define ZWP_DRM_LEASE_REQUEST_V1_DESTROY 0
+#define ZWP_DRM_LEASE_REQUEST_V1_REQUEST_CONNECTOR 1
+#define ZWP_DRM_LEASE_REQUEST_V1_SUBMIT 2
+
+
+/**
+ * @ingroup iface_zwp_drm_lease_request_v1
+ */
+#define ZWP_DRM_LEASE_REQUEST_V1_DESTROY_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_request_v1
+ */
+#define ZWP_DRM_LEASE_REQUEST_V1_REQUEST_CONNECTOR_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_request_v1
+ */
+#define ZWP_DRM_LEASE_REQUEST_V1_SUBMIT_SINCE_VERSION 1
+
+/** @ingroup iface_zwp_drm_lease_request_v1 */
+static inline void
+zwp_drm_lease_request_v1_set_user_data(struct zwp_drm_lease_request_v1 *zwp_drm_lease_request_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) zwp_drm_lease_request_v1, user_data);
+}
+
+/** @ingroup iface_zwp_drm_lease_request_v1 */
+static inline void *
+zwp_drm_lease_request_v1_get_user_data(struct zwp_drm_lease_request_v1 *zwp_drm_lease_request_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) zwp_drm_lease_request_v1);
+}
+
+static inline uint32_t
+zwp_drm_lease_request_v1_get_version(struct zwp_drm_lease_request_v1 *zwp_drm_lease_request_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) zwp_drm_lease_request_v1);
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_request_v1
+ *
+ * Indicates that the client will no longer use this lease request.
+ */
+static inline void
+zwp_drm_lease_request_v1_destroy(struct zwp_drm_lease_request_v1 *zwp_drm_lease_request_v1)
+{
+ wl_proxy_marshal((struct wl_proxy *) zwp_drm_lease_request_v1,
+ ZWP_DRM_LEASE_REQUEST_V1_DESTROY);
+
+ wl_proxy_destroy((struct wl_proxy *) zwp_drm_lease_request_v1);
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_request_v1
+ *
+ * Indicates that the client would like to lease the given connector.
+ * This is only used as a suggestion, the compositor may choose to
+ * include any resources in the lease it issues, or change the set of
+ * leased resources at any time.
+ */
+static inline void
+zwp_drm_lease_request_v1_request_connector(struct zwp_drm_lease_request_v1 *zwp_drm_lease_request_v1, struct zwp_drm_lease_connector_v1 *connector)
+{
+ wl_proxy_marshal((struct wl_proxy *) zwp_drm_lease_request_v1,
+ ZWP_DRM_LEASE_REQUEST_V1_REQUEST_CONNECTOR, connector);
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_request_v1
+ *
+ * Submits the lease request and creates a new zwp_drm_lease_v1 object.
+ * After calling submit, issuing any other request than destroy is a
+ * protocol error. Submitting a lease request with no connectors is a
+ * protocol error.
+ */
+static inline struct zwp_drm_lease_v1 *
+zwp_drm_lease_request_v1_submit(struct zwp_drm_lease_request_v1 *zwp_drm_lease_request_v1)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_drm_lease_request_v1,
+ ZWP_DRM_LEASE_REQUEST_V1_SUBMIT, &zwp_drm_lease_v1_interface, NULL);
+
+ return (struct zwp_drm_lease_v1 *) id;
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_v1
+ * @struct zwp_drm_lease_v1_listener
+ */
+struct zwp_drm_lease_v1_listener {
+ /**
+ * shares the DRM file descriptor
+ *
+ * This event returns a file descriptor suitable for use with
+ * DRM-related ioctls. The client should use drmModeGetLease to
+ * enumerate the DRM objects which have been leased to them, which
+ * may not be the objects they requested. The lease may have zero
+ * DRM objects.
+ *
+ * The compositor may also issue and immediately revoke the lease
+ * if no connectors are leasable, in which case this event is not
+ * sent.
+ *
+ * It is a protocol error for the compositor to send this event
+ * more than once for a given lease.
+ * @param leased_fd leased DRM file descriptor
+ */
+ void (*lease_fd)(void *data,
+ struct zwp_drm_lease_v1 *zwp_drm_lease_v1,
+ int32_t leased_fd);
+ /**
+ * sent when the lease has been revoked
+ *
+ * When the compositor revokes the lease, it will issue this
+ * event to notify clients of the change. If the client requires a
+ * new lease, they should destroy this object and submit a new
+ * lease request. The compositor will send no further events for
+ * this object after sending the finish event.
+ */
+ void (*finished)(void *data,
+ struct zwp_drm_lease_v1 *zwp_drm_lease_v1);
+};
+
+/**
+ * @ingroup iface_zwp_drm_lease_v1
+ */
+static inline int
+zwp_drm_lease_v1_add_listener(struct zwp_drm_lease_v1 *zwp_drm_lease_v1,
+ const struct zwp_drm_lease_v1_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) zwp_drm_lease_v1,
+ (void (**)(void)) listener, data);
+}
+
+#define ZWP_DRM_LEASE_V1_DESTROY 0
+
+/**
+ * @ingroup iface_zwp_drm_lease_v1
+ */
+#define ZWP_DRM_LEASE_V1_LEASE_FD_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwp_drm_lease_v1
+ */
+#define ZWP_DRM_LEASE_V1_FINISHED_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_zwp_drm_lease_v1
+ */
+#define ZWP_DRM_LEASE_V1_DESTROY_SINCE_VERSION 1
+
+/** @ingroup iface_zwp_drm_lease_v1 */
+static inline void
+zwp_drm_lease_v1_set_user_data(struct zwp_drm_lease_v1 *zwp_drm_lease_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) zwp_drm_lease_v1, user_data);
+}
+
+/** @ingroup iface_zwp_drm_lease_v1 */
+static inline void *
+zwp_drm_lease_v1_get_user_data(struct zwp_drm_lease_v1 *zwp_drm_lease_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) zwp_drm_lease_v1);
+}
+
+static inline uint32_t
+zwp_drm_lease_v1_get_version(struct zwp_drm_lease_v1 *zwp_drm_lease_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) zwp_drm_lease_v1);
+}
+
+/**
+ * @ingroup iface_zwp_drm_lease_v1
+ *
+ * The client should send this to indicate that it no longer wishes to use
+ * this lease. The compositor should use drmModeRevokeLease on the
+ * appropriate file descriptor, if necessary, then release this object.
+ */
+static inline void
+zwp_drm_lease_v1_destroy(struct zwp_drm_lease_v1 *zwp_drm_lease_v1)
+{
+ wl_proxy_marshal((struct wl_proxy *) zwp_drm_lease_v1,
+ ZWP_DRM_LEASE_V1_DESTROY);
+
+ wl_proxy_destroy((struct wl_proxy *) zwp_drm_lease_v1);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
A drm-lease-unstable-v1.xml => drm-lease-unstable-v1.xml +238 -0
@@ 0,0 1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm_lease_unstable_v1">
+ <copyright>
+ Copyright © 2018 NXP
+ Copyright © 2019 Status Research & Development GmbH.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="zwp_drm_lease_manager_v1" version="1">
+ <description summary="lease manager">
+ This protocol is used by Wayland compositors which act as Direct
+ Renderering Manager (DRM) masters to lease DRM resources to Wayland
+ clients. Once leased, the compositor will not use the leased resources
+ until the lease is revoked or the client closes the file descriptor.
+
+ The lease manager is used to advertise connectors which are available for
+ leasing, and by the client to negotiate a lease request.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+ </description>
+
+ <request name="create_lease_request">
+ <description summary="create a lease request object">
+ Creates a lease request object.
+
+ See the documentation for zwp_drm_lease_request_v1 for details.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_drm_lease_request_v1" />
+ </request>
+
+ <request name="stop">
+ <description summary="stop sending events">
+ Indicates the client no longer wishes to receive connector events. The
+ compositor may still send connector events until it sends the finish
+ event, however.
+
+ The client must not send any requests after this one.
+ </description>
+ </request>
+
+ <event name="connector">
+ <description summary="advertise connectors available for leases">
+ The compositor may choose to advertise 0 or more connectors which may be
+ leased to clients, and will use this event to do so. This object may be
+ passed into a lease request to lease that connector. See
+ zwp_drm_lease_request_v1.add_connector for details.
+
+ When this global is bound, the compositor will send all connectors
+ available for lease, but may send additional connectors at any time.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_drm_lease_connector_v1" />
+ </event>
+
+ <event name="finished">
+ <description summary="the compositor has finished using the manager">
+ This event indicates that the compositor is done sending connector
+ events. The compositor will destroy this object immediately after
+ sending this event, and it will become invalid. The client should
+ release any resources associated with this manager after receiving this
+ event.
+ </description>
+ </event>
+ </interface>
+
+ <interface name="zwp_drm_lease_connector_v1" version="1">
+ <description summary="a leasable DRM connector">
+ Represents a DRM connector which is available for lease. These objects are
+ created via zwp_drm_lease_manager_v1.connector, and should be passed into
+ lease requests via zwp_drm_lease_request_v1.add_connector.
+ </description>
+
+ <event name="name">
+ <description summary="name">
+ The compositor sends this event once the connector is created to
+ indicate the name of this connector. This will not change for the
+ duration of the Wayland session, but is not guaranteed to be consistent
+ between sessions.
+
+ If the compositor also supports zxdg_output_manager_v1 and this
+ connector corresponds to a zxdg_output_v1, this name will match the
+ name of this zxdg_output_v1 object.
+ </description>
+ <arg name="name" type="string" summary="connector name" />
+ </event>
+
+ <event name="description">
+ <description summary="description">
+ The compositor sends this event once the connector is created to provide
+ a human-readable description for this connector, which may be presented
+ to the user. This will not change for the duration of the Wayland
+ session, but is not guaranteed to be consistent between sessions.
+
+ If the compositor also supports zxdg_output_manager_v1 and this
+ connector corresponds to a zxdg_output_v1, this description will match
+ the description of this zxdg_output_v1 object.
+ </description>
+ <arg name="name" type="string" summary="connector name" />
+ </event>
+
+ <event name="edid">
+ <description summary="edid">
+ The compositor sends this event once the connector is created to
+ provide a file descriptor which may be memory-mapped to read the
+ connector's EDID, to assist in selecting the correct connectors
+ for lease.
+ </description>
+ <arg name="edid" type="fd" summary="EDID file descriptor" />
+ <arg name="size" type="uint" summary="EDID size, in bytes"/>
+ </event>
+
+ <event name="withdrawn">
+ <description summary="lease offer withdrawn">
+ Sent to indicate that the compositor will no longer honor requests for
+ DRM leases which include this connector. The client may still issue a
+ lease request including this connector, but the compositor will send
+ zwp_drm_lease_v1.finished without issuing a lease fd.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy connector">
+ The client may send this request to indicate that it will not issue a
+ lease request for this connector. Clients are encouraged to send this
+ after receiving the "withdrawn" request so that the server can release
+ the resources associated with this connector offer.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwp_drm_lease_request_v1" version="1">
+ <description summary="DRM lease request">
+ A client that wishes to lease DRM resources will attach the list of
+ connectors advertised with zwp_drm_lease_manager_v1.connector that they
+ wish to lease, then use zwp_drm_lease_request_v1.submit to submit the
+ request.
+ </description>
+
+ <enum name="error">
+ <entry name="no_connectors" value="0"
+ summary="request submitted with zero connectors"/>
+ <entry name="submitted_lease" value="1"
+ summary="attempted to reuse a submitted lease"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroys the lease request object">
+ Indicates that the client will no longer use this lease request.
+ </description>
+ </request>
+
+ <request name="request_connector">
+ <description summary="request a connector for this lease">
+ Indicates that the client would like to lease the given connector.
+ This is only used as a suggestion, the compositor may choose to
+ include any resources in the lease it issues, or change the set of
+ leased resources at any time.
+ </description>
+ <arg name="connector" type="object"
+ interface="zwp_drm_lease_connector_v1" />
+ </request>
+
+ <request name="submit">
+ <description summary="submit the lease request">
+ Submits the lease request and creates a new zwp_drm_lease_v1 object.
+ After calling submit, issuing any other request than destroy is a
+ protocol error. Submitting a lease request with no connectors is a
+ protocol error.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_drm_lease_v1" />
+ </request>
+ </interface>
+
+ <interface name="zwp_drm_lease_v1" version="1">
+ <description summary="a DRM lease">
+ A DRM lease object is used to transfer the DRM file descriptor to the
+ client and manage the lifetime of the lease.
+ </description>
+
+ <event name="lease_fd">
+ <description summary="shares the DRM file descriptor">
+ This event returns a file descriptor suitable for use with DRM-related
+ ioctls. The client should use drmModeGetLease to enumerate the DRM
+ objects which have been leased to them, which may not be the objects
+ they requested. The lease may have zero DRM objects.
+
+ The compositor may also issue and immediately revoke the lease if no
+ connectors are leasable, in which case this event is not sent.
+
+ It is a protocol error for the compositor to send this event more than
+ once for a given lease.
+ </description>
+ <arg name="leased_fd" type="fd" summary="leased DRM file descriptor" />
+ </event>
+
+ <event name="finished">
+ <description summary="sent when the lease has been revoked">
+ When the compositor revokes the lease, it will issue this event to
+ notify clients of the change. If the client requires a new lease, they
+ should destroy this object and submit a new lease request. The
+ compositor will send no further events for this object after sending
+ the finish event.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroys the lease object">
+ The client should send this to indicate that it no longer wishes to use
+ this lease. The compositor should use drmModeRevokeLease on the
+ appropriate file descriptor, if necessary, then release this object.
+ </description>
+ </request>
+ </interface>
+</protocol>
M kmscube.c => kmscube.c +199 -212
@@ 30,11 30,11 @@
#include <stdio.h>
#include <getopt.h>
#include <pthread.h>
-#include <xcb/xcb.h>
-#include <xcb/randr.h>
+#include <wayland-client.h>
#include "common.h"
#include "drm-common.h"
+#include "drm-lease-protocol.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ 48,62 48,67 @@ static const struct option longopts[] = {
{"atomic", no_argument, 0, 'A'},
{"device", required_argument, 0, 'D'},
{"mode", required_argument, 0, 'M'},
- {"thread", no_argument, 0, 't'},
- {"lease", no_argument, 0, 'l'},
+ {"thread", no_argument, 0, 't'},
+ {"lease", no_argument, 0, 'l'},
{0, 0, 0, 0}
};
+struct wayland_state {
+ struct zwp_drm_lease_manager_v1 *lease_manager;
+ struct zwp_drm_lease_connector_v1 *lease_connector;
+};
+
static void usage(const char *name)
{
printf("Usage: %s [-ADM]\n"
"\n"
"options:\n"
- " -A, --atomic use atomic modesetting and fencing\n"
+ " -A, --atomic use atomic modesetting and fencing\n"
" -D, --device=DEVICE use the given device\n"
- " -t, --thread two threads and cubes on two monitors\n"
- " -l, --lease lease output from the X server\n"
- " -M, --mode=MODE specify mode, one of:\n"
- " smooth - smooth shaded cube (default)\n"
- " rgba - rgba textured cube\n"
- " nv12-2img - yuv textured (color conversion in shader)\n"
- " nv12-1img - yuv textured (single nv12 texture)\n",
+ " -t, --thread two threads and cubes on two monitors\n"
+ " -l, --lease lease output from the X server\n"
+ " -M, --mode=MODE specify mode, one of:\n"
+ " smooth - smooth shaded cube (default)\n"
+ " rgba - rgba textured cube\n"
+ " nv12-2img - yuv textured (color conversion in shader)\n"
+ " nv12-1img - yuv textured (single nv12 texture)\n",
name);
}
static void dump_lessees(char *head, drmModeLesseeListPtr lessees) {
- uint32_t i;
- printf("%s lessees:", head);
- if (!lessees) {
- printf("null\n");
- return;
- }
- for (i = 0; i < lessees->count; i++)
- printf(" %u", lessees->lessees[i]);
- printf("\n");
+ uint32_t i;
+ printf("%s lessees:", head);
+ if (!lessees) {
+ printf("null\n");
+ return;
+ }
+ for (i = 0; i < lessees->count; i++)
+ printf(" %u", lessees->lessees[i]);
+ printf("\n");
}
static void dump_objects(char *head, drmModeObjectListPtr objects) {
- uint32_t i;
- printf("%s objects:", head);
- if (!objects) {
- printf("null\n");
- return;
- }
- for (i = 0; i < objects->count; i++)
- printf(" %u", objects->objects[i]);
- printf("\n");
+ uint32_t i;
+ printf("%s objects:", head);
+ if (!objects) {
+ printf("null\n");
+ return;
+ }
+ for (i = 0; i < objects->count; i++)
+ printf(" %u", objects->objects[i]);
+ printf("\n");
}
int run(int fd, int nfd) {
- struct egl *egl;
- struct gbm *gbm;
- struct drm *drm;
- int ret;
+ struct egl *egl;
+ struct gbm *gbm;
+ struct drm *drm;
+ int ret;
if (atomic)
- drm = init_drm_atomic(fd, nfd);
+ drm = init_drm_atomic(fd, nfd);
else
- drm = init_drm_legacy(fd, nfd);
+ drm = init_drm_legacy(fd, nfd);
if (!drm) {
printf("failed to initialize %s DRM\n", atomic ? "atomic" : "legacy");
return -1;
@@ 131,8 136,8 @@ int run(int fd, int nfd) {
glClear(GL_COLOR_BUFFER_BIT);
ret = drm->run(drm, gbm, egl);
- printf ("drm->run returns %d\n", ret);
- return ret;
+ printf ("drm->run returns %d\n", ret);
+ return ret;
}
static void *thread_run(void *arg)
@@ 145,14 150,64 @@ static void *thread_run(void *arg)
return 0;
}
+void lease_handle_lease_fd(void *data,
+ struct zwp_drm_lease_v1 *zwp_drm_lease_v1, int32_t leased_fd) {
+ int *fd = data;
+ *fd = leased_fd;
+}
+
+void lease_handle_finished(void *data,
+ struct zwp_drm_lease_v1 *zwp_drm_lease_v1) {
+ // Who cares
+}
+
+static const struct zwp_drm_lease_v1_listener lease_listener = {
+ .lease_fd = lease_handle_lease_fd,
+ .finished = lease_handle_finished,
+};
+
+static void drm_lease_manager_connector(void *data,
+ struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1,
+ struct zwp_drm_lease_connector_v1 *conn) {
+ struct wayland_state *state = data;
+ if (!state->lease_connector) {
+ state->lease_connector = conn;
+ }
+}
+
+static const struct zwp_drm_lease_manager_v1_listener lease_manager_listener = {
+ .connector = drm_lease_manager_connector,
+};
+
+static void registry_global(void *data, struct wl_registry *wl_registry,
+ uint32_t name, const char *interface, uint32_t version) {
+ struct wayland_state *state = data;
+ if (strcmp(interface, zwp_drm_lease_manager_v1_interface.name) == 0) {
+ state->lease_manager = wl_registry_bind(wl_registry, name,
+ &zwp_drm_lease_manager_v1_interface, 1);
+ zwp_drm_lease_manager_v1_add_listener(state->lease_manager,
+ &lease_manager_listener, state);
+ }
+}
+
+static void registry_global_remove(
+ void *data, struct wl_registry *wl_registry, uint32_t name) {
+ // who cares
+}
+
+static const struct wl_registry_listener registry_listener = {
+ .global = registry_global,
+ .global_remove = registry_global_remove,
+};
+
int main(int argc, char *argv[])
{
const char *device = "/dev/dri/card0";
- int do_thread = 0;
- int do_lease = 0;
+ int do_thread = 0;
+ int do_lease = 0;
int opt;
- int fd;
- int nfd = -1;
+ int fd;
+ int nfd = -1;
while ((opt = getopt_long_only(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (opt) {
@@ 177,204 232,136 @@ int main(int argc, char *argv[])
return -1;
}
break;
- case 't':
- do_thread = 1;
- break;
- case 'l':
- do_lease = 1;
- break;
+ case 't':
+ do_thread = 1;
+ break;
+ case 'l':
+ do_lease = 1;
+ break;
default:
usage(argv[0]);
return -1;
}
}
- if (do_lease) {
- xcb_connection_t *connection;
- int screen;
-
- connection = xcb_connect(NULL, &screen);
- if (!connection) {
- printf("Connection to X server failed\n");
- exit(1);
- }
- xcb_randr_query_version_cookie_t rqv_c = xcb_randr_query_version(connection,
- XCB_RANDR_MAJOR_VERSION,
- XCB_RANDR_MINOR_VERSION);
- xcb_randr_query_version_reply_t *rqv_r = xcb_randr_query_version_reply(connection, rqv_c, NULL);
-
- if (!rqv_r || rqv_r->minor_version < 6) {
- printf("No new-enough RandR version\n");
- exit(1);
- }
-
- xcb_screen_iterator_t s_i;
-
- int i_s = 0;
-
- for (s_i = xcb_setup_roots_iterator(xcb_get_setup(connection));
- s_i.rem;
- xcb_screen_next(&s_i), i_s++) {
- printf ("index %d screen %d\n", s_i.index, screen);
- if (i_s == screen)
- break;
- }
-
- xcb_window_t root = s_i.data->root;
-
- printf("root %x\n", root);
-
- xcb_randr_get_screen_resources_cookie_t gsr_c = xcb_randr_get_screen_resources(connection, root);
-
- xcb_randr_get_screen_resources_reply_t *gsr_r = xcb_randr_get_screen_resources_reply(connection, gsr_c, NULL);
-
- if (!gsr_r) {
- printf("get_screen_resources failed\n");
- exit(1);
- }
-
- xcb_randr_output_t *ro = xcb_randr_get_screen_resources_outputs(gsr_r);
- int o, c;
-
- xcb_randr_output_t output = 0;
-
- /* Find a connected but idle output */
- for (o = 0; output == 0 && o < gsr_r->num_outputs; o++) {
- xcb_randr_get_output_info_cookie_t goi_c = xcb_randr_get_output_info(connection, ro[o], gsr_r->config_timestamp);
-
- xcb_randr_get_output_info_reply_t *goi_r = xcb_randr_get_output_info_reply(connection, goi_c, NULL);
-
- /* Find the first connected but unused output */
- if (goi_r->connection == XCB_RANDR_CONNECTION_CONNECTED &&
- goi_r->crtc == 0) {
- output = ro[o];
- }
-
- free(goi_r);
- }
-
- xcb_randr_crtc_t *rc = xcb_randr_get_screen_resources_crtcs(gsr_r);
-
- xcb_randr_crtc_t crtc = 0;
-
- /* Find an idle crtc */
- for (c = 0; crtc == 0 && c < gsr_r->num_crtcs; c++) {
- xcb_randr_get_crtc_info_cookie_t gci_c = xcb_randr_get_crtc_info(connection, rc[c], gsr_r->config_timestamp);
-
- xcb_randr_get_crtc_info_reply_t *gci_r = xcb_randr_get_crtc_info_reply(connection, gci_c, NULL);
-
- /* Find the first connected but unused crtc */
- if (gci_r->mode == 0)
- crtc = rc[c];
-
- free(gci_r);
- }
-
- free(gsr_r);
-
- printf("output %x crtc %x\n", output, crtc);
-
- xcb_randr_lease_t lease = xcb_generate_id(connection);
-
- xcb_randr_create_lease_cookie_t rcl_c = xcb_randr_create_lease(connection,
- root,
- lease,
- 1,
- 1,
- &crtc,
- &output);
- xcb_randr_create_lease_reply_t *rcl_r = xcb_randr_create_lease_reply(connection, rcl_c, NULL);
-
- if (!rcl_r) {
- printf("create_lease failed\n");
- exit(1);
- }
-
- int *rcl_f = xcb_randr_create_lease_reply_fds(connection, rcl_r);
-
- fd = rcl_f[0];
-
- printf("fd %d\n", fd);
-
- } else {
- fd = open(device, O_RDWR);
- if (fd < 0) {
- printf("could not open drm device\n");
- return -1;
- }
- }
- if (do_thread) {
- struct drm_resources resources;
- uint32_t objects[3];
- int nobjects;
- uint32_t lessee;
- pthread_t thread;
-
- drmModeLesseeListPtr l_list;
- drmModeObjectListPtr o_list;
+ if (do_lease) {
+ struct wayland_state state = { 0 };
+ struct wl_display *display = wl_display_connect(NULL);
+ if (!display) {
+ fprintf(stderr, "Failed to establish Wayland connection\n");
+ return -1;
+ }
+ struct wl_registry *registry = wl_display_get_registry(display);
+ wl_registry_add_listener(registry, ®istry_listener, &state);
+ wl_display_dispatch(display);
+ wl_display_roundtrip(display);
+ if (!state.lease_manager) {
+ fprintf(stderr, "zwp_lease_manager_v1 global not available\n");
+ return -1;
+ }
+ if (!state.lease_connector) {
+ fprintf(stderr, "no connectors offered for lease\n");
+ return -1;
+ }
+ struct zwp_drm_lease_request_v1 *req =
+ zwp_drm_lease_manager_v1_create_lease_request(state.lease_manager);
+ zwp_drm_lease_request_v1_request_connector(req, state.lease_connector);
+ struct zwp_drm_lease_v1 *lease = zwp_drm_lease_request_v1_submit(req);
+ zwp_drm_lease_v1_add_listener(lease, &lease_listener, &fd);
+ wl_display_dispatch(display);
+ wl_display_roundtrip(display);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to acquire lease\n");
+ return -1;
+ }
+ } else {
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ printf("could not open drm device\n");
+ return -1;
+ }
+ }
+ if (do_thread) {
+ struct drm_resources resources;
+ uint32_t objects[3];
+ int nobjects;
+ uint32_t lessee;
+ pthread_t thread;
+
+ drmModeLesseeListPtr l_list;
+ drmModeObjectListPtr o_list;
+
+ if (find_drm(&resources, fd, -1) != 0) {
+ printf("Could not get DRM resources for fork\n");
+ return -1;
+ }
- if (find_drm(&resources, fd, -1) != 0) {
- printf("Could not get DRM resources for fork\n");
- return -1;
- }
+ printf("connector %d crtc %d plane %d\n",
+ resources.connector, resources.crtc, resources.plane);
- printf("connector %d encoder %d crtc %d\n", resources.connector, resources.encoder, resources.crtc);
+ nobjects = 0;
+ if (resources.connector)
+ objects[nobjects++] = resources.connector;
+ if (resources.crtc)
+ objects[nobjects++] = resources.crtc;
+ if (resources.plane)
+ objects[nobjects++] = resources.plane;
- nobjects = 0;
- if (resources.connector)
- objects[nobjects++] = resources.connector;
- if (resources.encoder)
- objects[nobjects++] = resources.encoder;
- if (resources.crtc)
- objects[nobjects++] = resources.crtc;
+ printf("objects to lease: %d\n", nobjects);
+ for (int i = 0; i < nobjects; ++i) {
+ printf("%d\n", objects[i]);
+ }
- o_list = drmModeGetLease(fd);
+ o_list = drmModeGetLease(fd);
- dump_objects("owner before lease", o_list);
- free(o_list);
+ dump_objects("owner before lease", o_list);
+ free(o_list);
- l_list = drmModeListLessees(fd);
+ l_list = drmModeListLessees(fd);
- dump_lessees("owner before lease", l_list);
+ dump_lessees("owner before lease", l_list);
- free(l_list);
+ free(l_list);
- nfd = drmModeCreateLease(fd, objects, nobjects, 0, &lessee);
+ nfd = drmModeCreateLease(fd, objects, nobjects, 0, &lessee);
+ if (nfd < 0) {
+ fprintf(stderr, "drmModeCreateLease: %s\n", strerror(errno));
+ }
- o_list = drmModeGetLease(fd);
+ o_list = drmModeGetLease(fd);
- dump_objects("owner after lease", o_list);
- free(o_list);
+ dump_objects("owner after lease", o_list);
+ free(o_list);
- l_list = drmModeListLessees(fd);
+ l_list = drmModeListLessees(fd);
- dump_lessees("owner after lease", l_list);
+ dump_lessees("owner after lease", l_list);
- free(l_list);
+ free(l_list);
- o_list = drmModeGetLease(nfd);
+ o_list = drmModeGetLease(nfd);
- dump_objects("lessee after lease", o_list);
- free(o_list);
+ dump_objects("lessee after lease", o_list);
+ free(o_list);
- l_list = drmModeListLessees(nfd);
+ l_list = drmModeListLessees(nfd);
- dump_lessees("lessee after lease", l_list);
+ dump_lessees("lessee after lease", l_list);
- free(l_list);
+ free(l_list);
#if 0
- printf("closing lease\n");
- close(nfd);
- printf("closing owner\n");
- close(fd);
- exit(0);
+ printf("closing lease\n");
+ close(nfd);
+ printf("closing owner\n");
+ close(fd);
+ exit(0);
#endif
- pthread_create(&thread, NULL, thread_run, (void *) (intptr_t) nfd);
- printf("parent running on owner %d\n", fd);
- printf("parent running now...\n");
- }
+ pthread_create(&thread, NULL, thread_run, (void *) (intptr_t) nfd);
+ printf("parent running on owner %d\n", fd);
+ printf("parent running now...\n");
+ }
- return run(fd, nfd);
+ return run(fd, nfd);
}