~sircmpwn/kmscube

090120d733692cad2bc59c68e00c9417c7a662a7 — Drew DeVault 5 years ago 6c9f786 master
Update drm lease protocol
4 files changed, 143 insertions(+), 68 deletions(-)

M drm-lease-protocol.c
M drm-lease-protocol.h
M drm-lease-unstable-v1.xml
M kmscube.c
M drm-lease-protocol.c => drm-lease-protocol.c +7 -7
@@ 44,7 44,6 @@ 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,


@@ 52,19 51,20 @@ static const struct wl_interface *types[] = {
};

static const struct wl_message zwp_drm_lease_manager_v1_requests[] = {
	{ "create_lease_request", "n", types + 2 },
	{ "create_lease_request", "n", types + 1 },
	{ "stop", "", types + 0 },
};

static const struct wl_message zwp_drm_lease_manager_v1_events[] = {
	{ "connector", "n", types + 3 },
	{ "drm_fd", "h", types + 0 },
	{ "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,
	3, zwp_drm_lease_manager_v1_events,
};

static const struct wl_message zwp_drm_lease_connector_v1_requests[] = {


@@ 74,7 74,7 @@ static const struct wl_message zwp_drm_lease_connector_v1_requests[] = {
static const struct wl_message zwp_drm_lease_connector_v1_events[] = {
	{ "name", "s", types + 0 },
	{ "description", "s", types + 0 },
	{ "edid", "hu", types + 0 },
	{ "connector_id", "i", types + 0 },
	{ "withdrawn", "", types + 0 },
};



@@ 86,8 86,8 @@ WL_PRIVATE const struct wl_interface zwp_drm_lease_connector_v1_interface = {

static const struct wl_message zwp_drm_lease_request_v1_requests[] = {
	{ "destroy", "", types + 0 },
	{ "request_connector", "o", types + 4 },
	{ "submit", "n", types + 5 },
	{ "request_connector", "o", types + 3 },
	{ "submit", "n", types + 4 },
};

WL_PRIVATE const struct wl_interface zwp_drm_lease_request_v1_interface = {

M drm-lease-protocol.h => drm-lease-protocol.h +53 -36
@@ 56,7 56,9 @@ struct zwp_drm_lease_v1;
 * 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.
 * until the lease is revoked or the client closes the file descriptor. The
 * compositor will advertise one zwp_drm_lease_manager_v1 for each DRM node
 * which has resources available for leasing.
 *
 * The lease manager is used to advertise connectors which are available for
 * leasing, and by the client to negotiate a lease request.


@@ 78,7 80,9 @@ struct zwp_drm_lease_v1;
 * 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.
 * until the lease is revoked or the client closes the file descriptor. The
 * compositor will advertise one zwp_drm_lease_manager_v1 for each DRM node
 * which has resources available for leasing.
 *
 * The lease manager is used to advertise connectors which are available for
 * leasing, and by the client to negotiate a lease request.


@@ 148,12 152,37 @@ extern const struct wl_interface zwp_drm_lease_request_v1_interface;
 */
extern const struct wl_interface zwp_drm_lease_v1_interface;

#ifndef ZWP_DRM_LEASE_MANAGER_V1_ERROR_ENUM
#define ZWP_DRM_LEASE_MANAGER_V1_ERROR_ENUM
enum zwp_drm_lease_manager_v1_error {
	/**
	 * request sent to a manager which has been stopped
	 */
	ZWP_DRM_LEASE_MANAGER_V1_ERROR_STOPPED_MANAGER = 0,
};
#endif /* ZWP_DRM_LEASE_MANAGER_V1_ERROR_ENUM */

/**
 * @ingroup iface_zwp_drm_lease_manager_v1
 * @struct zwp_drm_lease_manager_v1_listener
 */
struct zwp_drm_lease_manager_v1_listener {
	/**
	 * open a non-master fd for this DRM node
	 *
	 * The compositor will send this event when the
	 * zwp_drm_lease_manager_v1 global is bound. The included fd is a
	 * non-master DRM file descriptor opened for this device. The
	 * purpose of this event is to give the client the ability to query
	 * DRM and discover information which may help them pick the
	 * appropriate DRM device or select the appropriate connectors
	 * therein.
	 * @param fd DRM file descriptor
	 */
	void (*drm_fd)(void *data,
		       struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1,
		       int32_t fd);
	/**
	 * advertise connectors available for leases
	 *
	 * The compositor may choose to advertise 0 or more connectors


@@ 199,6 228,10 @@ zwp_drm_lease_manager_v1_add_listener(struct zwp_drm_lease_manager_v1 *zwp_drm_l
/**
 * @ingroup iface_zwp_drm_lease_manager_v1
 */
#define ZWP_DRM_LEASE_MANAGER_V1_DRM_FD_SINCE_VERSION 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


@@ 301,32 334,24 @@ struct zwp_drm_lease_connector_v1_listener {
	 *
	 * 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
	 * which may be presented to the user.
	 * @param description connector description
	 */
	void (*description)(void *data,
			    struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
			    const char *name);
			    const char *description);
	/**
	 * edid
	 * connector_id
	 *
	 * 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
	 * The compositor will send this event to indicate the DRM ID
	 * which represents the underlying connector which is being
	 * offered. Note that the final lease may include additional object
	 * IDs, such as CRTCs and planes.
	 * @param connector_id DRM Connector ID
	 */
	void (*edid)(void *data,
		     struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
		     int32_t edid,
		     uint32_t size);
	void (*connector_id)(void *data,
			     struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
			     int32_t connector_id);
	/**
	 * lease offer withdrawn
	 *


@@ 364,7 389,7 @@ zwp_drm_lease_connector_v1_add_listener(struct zwp_drm_lease_connector_v1 *zwp_d
/**
 * @ingroup iface_zwp_drm_lease_connector_v1
 */
#define ZWP_DRM_LEASE_CONNECTOR_V1_EDID_SINCE_VERSION 1
#define ZWP_DRM_LEASE_CONNECTOR_V1_CONNECTOR_ID_SINCE_VERSION 1
/**
 * @ingroup iface_zwp_drm_lease_connector_v1
 */


@@ 416,13 441,9 @@ zwp_drm_lease_connector_v1_destroy(struct zwp_drm_lease_connector_v1 *zwp_drm_le
#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,
	ZWP_DRM_LEASE_REQUEST_V1_ERROR_SUBMITTED_LEASE = 0,
};
#endif /* ZWP_DRM_LEASE_REQUEST_V1_ERROR_ENUM */



@@ 498,7 519,6 @@ zwp_drm_lease_request_v1_request_connector(struct zwp_drm_lease_request_v1 *zwp_
 *
 * 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 *


@@ 522,13 542,10 @@ struct zwp_drm_lease_v1_listener {
	 *
	 * 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.
	 * enumerate the DRM objects which have been leased to them. If the
	 * compositor cannot or will not grant a lease for the requested
	 * connectors, it will not send this event, instead sending the
	 * finished event immediately.
	 *
	 * It is a protocol error for the compositor to send this event
	 * more than once for a given lease.

M drm-lease-unstable-v1.xml => drm-lease-unstable-v1.xml +33 -25
@@ 29,7 29,9 @@
      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.
      until the lease is revoked or the client closes the file descriptor. The
      compositor will advertise one zwp_drm_lease_manager_v1 for each DRM node
      which has resources available for leasing.

      The lease manager is used to advertise connectors which are available for
      leasing, and by the client to negotiate a lease request.


@@ 44,6 46,11 @@
      interface version number is reset.
    </description>

    <enum name="error">
      <entry name="stopped_manager" value="0"
        summary="request sent to a manager which has been stopped"/>
    </enum>

    <request name="create_lease_request">
      <description summary="create a lease request object">
        Creates a lease request object.


@@ 63,6 70,18 @@
      </description>
    </request>

    <event name="drm_fd">
      <description summary="open a non-master fd for this DRM node">
        The compositor will send this event when the zwp_drm_lease_manager_v1
        global is bound. The included fd is a non-master DRM file descriptor
        opened for this device. The purpose of this event is to give the client
        the ability to query DRM and discover information which may help them
        pick the appropriate DRM device or select the appropriate connectors
        therein.
      </description>
      <arg name="fd" type="fd" summary="DRM file descriptor" />
    </event>

    <event name="connector">
      <description summary="advertise connectors available for leases">
        The compositor may choose to advertise 0 or more connectors which may be


@@ 112,25 131,19 @@
      <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.
        to the user.
      </description>
      <arg name="name" type="string" summary="connector name" />
      <arg name="description" type="string" summary="connector description" />
    </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.
    <event name="connector_id">
      <description summary="connector_id">
        The compositor will send this event to indicate the DRM ID which
        represents the underlying connector which is being offered. Note that
        the final lease may include additional object IDs, such as CRTCs and
        planes.
      </description>
      <arg name="edid" type="fd" summary="EDID file descriptor" />
      <arg name="size" type="uint" summary="EDID size, in bytes"/>
      <arg name="connector_id" type="int" summary="DRM Connector ID" />
    </event>

    <event name="withdrawn">


@@ 161,9 174,7 @@
    </description>

    <enum name="error">
      <entry name="no_connectors" value="0"
        summary="request submitted with zero connectors"/>
      <entry name="submitted_lease" value="1"
      <entry name="submitted_lease" value="0"
        summary="attempted to reuse a submitted lease"/>
    </enum>



@@ 188,7 199,6 @@
       <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" />


@@ 205,11 215,9 @@
      <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.
        objects which have been leased to them. If the compositor cannot or
        will not grant a lease for the requested connectors, it will not send
        this event, instead sending the finished event immediately.

        It is a protocol error for the compositor to send this event more than
        once for a given lease.

M kmscube.c => kmscube.c +50 -0
@@ 99,6 99,25 @@ static void dump_objects(char *head, drmModeObjectListPtr objects) {
	printf("\n");
}

static int32_t calculate_refresh_rate(const drmModeModeInfo *mode) {
	int32_t refresh = (mode->clock * 1000000LL / mode->htotal +
		mode->vtotal / 2) / mode->vtotal;

	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
		refresh *= 2;
	}

	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
		refresh /= 2;
	}

	if (mode->vscan > 1) {
		refresh /= mode->vscan;
	}

	return refresh;
}

int run(int fd, int nfd) {
	struct egl *egl;
	struct gbm *gbm;


@@ 114,6 133,9 @@ int run(int fd, int nfd) {
		return -1;
	}

	printf("using DRM mode %dx%d@%fHz\n",
			drm->mode->hdisplay, drm->mode->vdisplay,
			drm->mode);
	gbm = init_gbm(drm->fd, drm->mode->hdisplay, drm->mode->vdisplay);
	if (!gbm) {
		printf("failed to initialize GBM\n");


@@ 166,6 188,12 @@ static const struct zwp_drm_lease_v1_listener lease_listener = {
	.finished = lease_handle_finished,
};

static void drm_lease_manager_drm_fd(void *data,
		struct zwp_drm_lease_manager_v1 *zwp_drm_lease_manager_v1,
		int fd) {
	close(fd);
}

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) {


@@ 176,6 204,7 @@ static void drm_lease_manager_connector(void *data,
}

static const struct zwp_drm_lease_manager_v1_listener lease_manager_listener = {
	.drm_fd = drm_lease_manager_drm_fd,
	.connector = drm_lease_manager_connector,
};



@@ 274,6 303,27 @@ int main(int argc, char *argv[])
			fprintf(stderr, "Failed to acquire lease\n");
			return -1;
		}

		drmModeResPtr res = drmModeGetResources(fd);
		if (!res) {
			fprintf(stderr, "drmModeGetResources failed\n");
			return -1;
		}
		fprintf(stderr, "count_connectors: %d\n", res->count_connectors);
		for (int i = 0; i < res->count_connectors; ++i) {
			drmModeConnectorPtr conn = drmModeGetConnector(
					fd, res->connectors[i]);
			fprintf(stderr, "conn %d: %d modes\n",
					conn->connector_id, conn->count_modes);
			for (int j = 0; j < conn->count_modes; ++j) {
				fprintf(stderr, "mode %s: %dx%d\n",
						conn->modes[j].name,
						conn->modes[j].vdisplay,
						conn->modes[j].hdisplay);
			}
			drmModeFreeConnector(conn);
		}
		drmModeFreeResources(res);
	} else {
		fd = open(device, O_RDWR);
		if (fd < 0) {