60d89ef1d9304427a1289174d9a311ab06e39b44 — Drew DeVault a month ago 7f065bc
Replace XCB DRM leasing with Wayland DRM leasing
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_CFLAGS = \
  	-O0 -g \
  	-Wall -Wextra \
- 	$(XCB_CFLAGS) \
+ 	$(WAYLAND_CFLAGS) \
  	$(DRM_CFLAGS) \
  	$(GBM_CFLAGS) \
  	$(EGL_CFLAGS) \


@@ 56,4 56,5 @@ 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(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 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 @@ drmModeRes *resources;
  	drmModeConnector *connector = NULL;
  	drmModeEncoder *encoder = NULL;
- 	int i;
+ 	int i, crtc_i = -1;
  
  	resources = drmModeGetResources(fd);
  	if (!resources) {


@@ 150,9 150,9 @@ 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 @@ }
  
  	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 @@ 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 @@ 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 +112 -0
@@ 0,0 1,112 @@
+ /* 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,
+ 	&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 + 1 },
+ 	{ "stop", "", types + 0 },
+ };
+ 
+ static const struct wl_message zwp_drm_lease_manager_v1_events[] = {
+ 	{ "connector", "n", types + 2 },
+ 	{ "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", "a", 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 + 3 },
+ 	{ "submit", "n", types + 4 },
+ };
+ 
+ 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 +618 -0
@@ 0,0 1,618 @@
+ /* 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 inform the client of this connector's EDID, to assist in
+ 	 * selecting the correct connectors for lease. The EDID is supplied
+ 	 * as an array of unsigned 8-bit integers.
+ 	 * @param edid EDID for this connector
+ 	 */
+ 	void (*edid)(void *data,
+ 		     struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ 		     struct wl_array *edid);
+ 	/**
+ 	 * 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 +237 -0
@@ 0,0 1,237 @@
+ <?xml version="1.0" encoding="UTF-8"?>
+ <protocol name="drm_lease_unstable_v1">
+   <copyright>
+     Copyright © 2018 NXP
+     Copyright © 2019 Status Research &amp; 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
+         inform the client of this connector's EDID, to assist in selecting the
+         correct connectors for lease. The EDID is supplied as an array of
+         unsigned 8-bit integers.
+       </description>
+       <arg name="edid" type="array" summary="EDID for this connector" />
+     </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 @@ {"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 @@ 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 @@ 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 @@ 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, &registry_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);
  }