Introduce wlr_drm_lease_v1
This commit is contained in:
parent
1b96ba8232
commit
d84eb9e9f5
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||||
|
* future consistency of this API.
|
||||||
|
*/
|
||||||
|
#ifndef WLR_USE_UNSTABLE
|
||||||
|
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WLR_TYPES_WLR_DRM_LEASE_V1_H
|
||||||
|
#define WLR_TYPES_WLR_DRM_LEASE_V1_H
|
||||||
|
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#include <wlr/backend.h>
|
||||||
|
|
||||||
|
struct wlr_drm_backend;
|
||||||
|
|
||||||
|
struct wlr_drm_lease_manager_v1 {
|
||||||
|
struct wl_list resources; // wl_resource_get_link
|
||||||
|
struct wl_global *global;
|
||||||
|
struct wlr_drm_backend *backend;
|
||||||
|
|
||||||
|
struct wl_list connectors; // wlr_drm_lease_connector_v1::link
|
||||||
|
struct wl_list leases; // wl_resource_get_link
|
||||||
|
struct wl_list lease_requests; // wl_resource_get_link
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/**
|
||||||
|
* Upon receiving this signal, call
|
||||||
|
* wlr_drm_lease_manager_v1_grant_lease_request to grant a lease of the
|
||||||
|
* requested DRM resources, or
|
||||||
|
* wlr_drm_lease_manager_v1_reject_lease_request to reject the request.
|
||||||
|
*/
|
||||||
|
struct wl_signal lease_requested; // wlr_drm_lease_request_v1
|
||||||
|
} events;
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_drm_connector;
|
||||||
|
struct wlr_drm_lease_v1;
|
||||||
|
|
||||||
|
/** Represents a connector which is available for leasing, and may be leased */
|
||||||
|
struct wlr_drm_lease_connector_v1 {
|
||||||
|
struct wlr_output *output;
|
||||||
|
struct wlr_drm_connector *drm_connector;
|
||||||
|
struct wl_list resources; // wl_resource_get_link
|
||||||
|
|
||||||
|
/** NULL if no client is currently leasing this connector */
|
||||||
|
struct wlr_drm_lease_v1 *active_lease;
|
||||||
|
|
||||||
|
struct wl_list link; // wlr_drm_lease_manager_v1::connectors
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Represents a connector which has been added to a lease or lease request */
|
||||||
|
struct wlr_drm_connector_lease_v1 {
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager;
|
||||||
|
struct wlr_drm_lease_connector_v1 *connector;
|
||||||
|
struct wl_list link; // wlr_drm_lease_request_v1::connectors
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Represents a pending or submitted lease request */
|
||||||
|
struct wlr_drm_lease_request_v1 {
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager;
|
||||||
|
struct wl_resource *resource; // wlr_drm_manager_v1::lease_requests
|
||||||
|
struct wl_list connectors; // wlr_drm_connector_lease_v1::link
|
||||||
|
bool invalid;
|
||||||
|
|
||||||
|
/** NULL until the lease is submitted */
|
||||||
|
struct wlr_drm_lease_v1 *lease;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Represents an active or previously active lease */
|
||||||
|
struct wlr_drm_lease_v1 {
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager;
|
||||||
|
struct wl_resource *resource; // wlr_drm_manager_v1::leases
|
||||||
|
struct wl_list connectors; // wlr_drm_connector_lease_v1::link
|
||||||
|
uint32_t lessee_id;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/**
|
||||||
|
* Upon receiving this signal, it is safe to re-use the leased
|
||||||
|
* resources. After the signal is processed, the backend will re-signal
|
||||||
|
* new_output events for each leased output.
|
||||||
|
*
|
||||||
|
* The lifetime of the lease reference after the signal handler returns
|
||||||
|
* is not defined.
|
||||||
|
*/
|
||||||
|
struct wl_signal revoked; // wlr_drm_lease_v1
|
||||||
|
} events;
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DRM lease manager. The backend supplied must be a DRM backend, or a
|
||||||
|
* multi-backend with a single DRM backend within. If the supplied backend is
|
||||||
|
* not suitable, NULL is returned.
|
||||||
|
*/
|
||||||
|
struct wlr_drm_lease_manager_v1 *wlr_drm_lease_manager_v1_create(
|
||||||
|
struct wl_display *display, struct wlr_backend *backend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offers a wlr_output for lease. The offered output must be owned by the DRM
|
||||||
|
* backend associated with this lease manager.
|
||||||
|
*/
|
||||||
|
void wlr_drm_lease_manager_v1_offer_output(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager, struct wlr_output *output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Withdraws a previously offered output for lease. It is a programming error to
|
||||||
|
* call this function when there are any active leases for this output.
|
||||||
|
*/
|
||||||
|
void wlr_drm_lease_manager_v1_widthraw_output(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager, struct wlr_output *output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grants a client's lease request. The lease manager will then provision the
|
||||||
|
* DRM lease and transfer the file descriptor to the client. After calling this,
|
||||||
|
* each wlr_output leased is destroyed, and will be re-issued through
|
||||||
|
* wlr_backend.events.new_outputs when the lease is revoked.
|
||||||
|
*
|
||||||
|
* This will return NULL without leasing any resources if the lease is invalid;
|
||||||
|
* this can happen for example if two clients request the same resources and an
|
||||||
|
* attempt to grant both leases is made.
|
||||||
|
*/
|
||||||
|
struct wlr_drm_lease_v1 *wlr_drm_lease_manager_v1_grant_lease_request(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager,
|
||||||
|
struct wlr_drm_lease_request_v1 *request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rejects a client's lease request.
|
||||||
|
*/
|
||||||
|
void wlr_drm_lease_manager_v1_reject_lease_request(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager,
|
||||||
|
struct wlr_drm_lease_request_v1 *request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revokes a client's lease request. You may resume use of any of the outputs
|
||||||
|
* leased after making this call.
|
||||||
|
*/
|
||||||
|
void wlr_drm_lease_manager_v1_revoke_lease(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager,
|
||||||
|
struct wlr_drm_lease_v1 *lease);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,246 @@
|
||||||
|
<?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>
|
||||||
|
|
||||||
|
<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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
<arg name="description" type="string" summary="connector description" />
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<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="connector_id" type="int" summary="DRM Connector ID" />
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="edid">
|
||||||
|
<description summary="edid">
|
||||||
|
The compositor may send 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. The fd must be mapped with MAP_PRIVATE by the recipient.
|
||||||
|
|
||||||
|
Note that not all displays have an EDID, and this event will not be
|
||||||
|
sent in such cases.
|
||||||
|
</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="submitted_lease" value="0"
|
||||||
|
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.
|
||||||
|
</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. 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.
|
||||||
|
</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>
|
|
@ -25,6 +25,7 @@ protocols = [
|
||||||
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
||||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||||
[wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
|
[wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
|
||||||
|
'drm-lease-unstable-v1.xml',
|
||||||
'gtk-primary-selection.xml',
|
'gtk-primary-selection.xml',
|
||||||
'idle.xml',
|
'idle.xml',
|
||||||
'input-method-unstable-v2.xml',
|
'input-method-unstable-v2.xml',
|
||||||
|
|
|
@ -28,6 +28,7 @@ lib_wlr_types = static_library(
|
||||||
'wlr_compositor.c',
|
'wlr_compositor.c',
|
||||||
'wlr_cursor.c',
|
'wlr_cursor.c',
|
||||||
'wlr_data_control_v1.c',
|
'wlr_data_control_v1.c',
|
||||||
|
'wlr_drm_lease_v1.c',
|
||||||
'wlr_export_dmabuf_v1.c',
|
'wlr_export_dmabuf_v1.c',
|
||||||
'wlr_foreign_toplevel_management_v1.c',
|
'wlr_foreign_toplevel_management_v1.c',
|
||||||
'wlr_fullscreen_shell_v1.c',
|
'wlr_fullscreen_shell_v1.c',
|
||||||
|
|
|
@ -0,0 +1,582 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wlr/backend/drm.h>
|
||||||
|
#include <wlr/backend/multi.h>
|
||||||
|
#include <wlr/types/wlr_surface.h>
|
||||||
|
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#include <xf86drmMode.h>
|
||||||
|
#include "backend/drm/drm.h"
|
||||||
|
#include "drm-lease-unstable-v1-protocol.h"
|
||||||
|
#include "util/shm.h"
|
||||||
|
#include "util/signal.h"
|
||||||
|
|
||||||
|
static struct zwp_drm_lease_manager_v1_interface lease_manager_impl;
|
||||||
|
static struct zwp_drm_lease_request_v1_interface lease_request_impl;
|
||||||
|
static struct zwp_drm_lease_connector_v1_interface lease_connector_impl;
|
||||||
|
static struct zwp_drm_lease_v1_interface lease_impl;
|
||||||
|
|
||||||
|
static void drm_lease_connector_v1_send_to_client(
|
||||||
|
struct wlr_drm_lease_connector_v1 *connector,
|
||||||
|
struct wl_client *wl_client, struct wl_resource *manager);
|
||||||
|
|
||||||
|
static struct wlr_drm_lease_manager_v1 *wlr_drm_lease_manager_v1_from_resource(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&zwp_drm_lease_manager_v1_interface, &lease_manager_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wlr_drm_lease_request_v1 *wlr_drm_lease_request_v1_from_resource(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&zwp_drm_lease_request_v1_interface, &lease_request_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wlr_drm_lease_connector_v1 *
|
||||||
|
wlr_drm_lease_connector_v1_from_resource(struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&zwp_drm_lease_connector_v1_interface, &lease_connector_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wlr_drm_lease_v1 *wlr_drm_lease_v1_from_resource(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&zwp_drm_lease_v1_interface, &lease_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool drm_lease_request_v1_validate(
|
||||||
|
struct wlr_drm_lease_request_v1 *req) {
|
||||||
|
if (req->invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Don't lease connectors which are already leased */
|
||||||
|
struct wlr_drm_connector_lease_v1 *connector;
|
||||||
|
wl_list_for_each(connector, &req->connectors, link) {
|
||||||
|
if (connector->connector->active_lease) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lease_terminated_by_drm(
|
||||||
|
struct wlr_drm_connector *conn, void *data) {
|
||||||
|
wlr_log(WLR_DEBUG, "Lease terminated by DRM");
|
||||||
|
struct wlr_drm_lease_v1 *lease = data;
|
||||||
|
lease->lessee_id = 0;
|
||||||
|
wlr_drm_lease_manager_v1_revoke_lease(lease->manager, lease);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_lease_v1 *wlr_drm_lease_manager_v1_grant_lease_request(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager,
|
||||||
|
struct wlr_drm_lease_request_v1 *request) {
|
||||||
|
assert(manager && request);
|
||||||
|
assert(request->lease);
|
||||||
|
|
||||||
|
struct wlr_drm_lease_v1 *lease = request->lease;
|
||||||
|
if (!drm_lease_request_v1_validate(request)) {
|
||||||
|
zwp_drm_lease_v1_send_finished(lease->resource);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nconns = 0;
|
||||||
|
|
||||||
|
/** Adopt the connector leases from the lease request */
|
||||||
|
struct wlr_drm_connector_lease_v1 *conn, *temp;
|
||||||
|
wl_list_for_each_safe(conn, temp, &request->connectors, link) {
|
||||||
|
wl_list_remove(&conn->link);
|
||||||
|
wl_list_init(&conn->link);
|
||||||
|
wl_list_insert(&lease->connectors, &conn->link);
|
||||||
|
++nconns;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_connector *conns[nconns + 1];
|
||||||
|
int i = 0;
|
||||||
|
wl_list_for_each(conn, &lease->connectors, link) {
|
||||||
|
conns[i] = conn->connector->drm_connector;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = drm_create_lease(manager->backend,
|
||||||
|
conns, nconns, &lease->lessee_id,
|
||||||
|
lease_terminated_by_drm, lease);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "drm_create_lease failed");
|
||||||
|
zwp_drm_lease_v1_send_finished(lease->resource);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_for_each(conn, &lease->connectors, link) {
|
||||||
|
struct wlr_drm_lease_connector_v1 *conn_lease =
|
||||||
|
conn->connector;
|
||||||
|
conn_lease->active_lease = lease;
|
||||||
|
|
||||||
|
struct wl_resource *wl_resource, *temp;
|
||||||
|
wl_resource_for_each_safe(wl_resource, temp, &conn_lease->resources) {
|
||||||
|
zwp_drm_lease_connector_v1_send_withdrawn(wl_resource);
|
||||||
|
wl_resource_set_user_data(wl_resource, NULL);
|
||||||
|
wl_list_remove(wl_resource_get_link(wl_resource));
|
||||||
|
wl_list_init(wl_resource_get_link(wl_resource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zwp_drm_lease_v1_send_lease_fd(lease->resource, fd);
|
||||||
|
close(fd);
|
||||||
|
return lease;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_drm_lease_manager_v1_reject_lease_request(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager,
|
||||||
|
struct wlr_drm_lease_request_v1 *request) {
|
||||||
|
assert(manager && request);
|
||||||
|
assert(request->lease);
|
||||||
|
zwp_drm_lease_v1_send_finished(request->lease->resource);
|
||||||
|
request->invalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_drm_lease_manager_v1_revoke_lease(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager,
|
||||||
|
struct wlr_drm_lease_v1 *lease) {
|
||||||
|
assert(manager && lease);
|
||||||
|
if (lease->resource != NULL) {
|
||||||
|
zwp_drm_lease_v1_send_finished(lease->resource);
|
||||||
|
}
|
||||||
|
if (lease->lessee_id != 0) {
|
||||||
|
if (drm_terminate_lease(manager->backend, lease->lessee_id) < 0) {
|
||||||
|
wlr_log_errno(WLR_DEBUG, "drm_terminate_lease");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct wlr_drm_connector_lease_v1 *conn;
|
||||||
|
wl_list_for_each(conn, &lease->connectors, link) {
|
||||||
|
struct wlr_drm_lease_connector_v1 *conn_lease =
|
||||||
|
conn->connector;
|
||||||
|
conn_lease->active_lease = NULL;
|
||||||
|
|
||||||
|
struct wl_resource *wl_resource;
|
||||||
|
wl_resource_for_each(wl_resource, &manager->resources) {
|
||||||
|
struct wl_client *wl_client = wl_resource_get_client(wl_resource);
|
||||||
|
drm_lease_connector_v1_send_to_client(
|
||||||
|
conn_lease, wl_client, wl_resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wlr_signal_emit_safe(&lease->events.revoked, lease);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_v1_destroy(struct wlr_drm_lease_v1 *lease) {
|
||||||
|
wlr_drm_lease_manager_v1_revoke_lease(lease->manager, lease);
|
||||||
|
free(lease);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_v1_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
|
struct wlr_drm_lease_v1 *lease = wlr_drm_lease_v1_from_resource(resource);
|
||||||
|
wl_list_remove(wl_resource_get_link(resource));
|
||||||
|
wl_list_init(wl_resource_get_link(resource));
|
||||||
|
lease->resource = NULL;
|
||||||
|
drm_lease_v1_destroy(lease);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_v1_handle_destroy(
|
||||||
|
struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zwp_drm_lease_v1_interface lease_impl = {
|
||||||
|
.destroy = drm_lease_v1_handle_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void drm_lease_request_v1_destroy(struct wlr_drm_lease_request_v1 *req) {
|
||||||
|
if (!req) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct wlr_drm_connector_lease_v1 *conn, *temp;
|
||||||
|
wl_list_for_each_safe(conn, temp, &req->connectors, link) {
|
||||||
|
wl_list_remove(&conn->link);
|
||||||
|
wl_list_init(&conn->link);
|
||||||
|
free(conn);
|
||||||
|
}
|
||||||
|
free(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_request_v1_handle_resource_destroy(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
struct wlr_drm_lease_request_v1 *req =
|
||||||
|
wlr_drm_lease_request_v1_from_resource(resource);
|
||||||
|
drm_lease_request_v1_destroy(req);
|
||||||
|
wl_list_remove(wl_resource_get_link(resource));
|
||||||
|
wl_list_init(wl_resource_get_link(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_request_v1_handle_destroy(
|
||||||
|
struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_request_v1_handle_request_connector(
|
||||||
|
struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
struct wl_resource *connector) {
|
||||||
|
struct wlr_drm_lease_request_v1 *request =
|
||||||
|
wlr_drm_lease_request_v1_from_resource(resource);
|
||||||
|
struct wlr_drm_lease_connector_v1 *conn =
|
||||||
|
wlr_drm_lease_connector_v1_from_resource(connector);
|
||||||
|
|
||||||
|
if (conn == NULL) {
|
||||||
|
/* This connector offer has been withdrawn */
|
||||||
|
request->invalid = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_connector_lease_v1 *lease =
|
||||||
|
calloc(1, sizeof(struct wlr_drm_connector_lease_v1));
|
||||||
|
if (!lease) {
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lease->connector = conn;
|
||||||
|
wl_list_insert(&request->connectors, &lease->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_request_v1_handle_submit(
|
||||||
|
struct wl_client *client, struct wl_resource *resource, uint32_t id) {
|
||||||
|
struct wlr_drm_lease_request_v1 *lease_request =
|
||||||
|
wlr_drm_lease_request_v1_from_resource(resource);
|
||||||
|
|
||||||
|
struct wlr_drm_lease_v1 *lease = calloc(1, sizeof(struct wlr_drm_lease_v1));
|
||||||
|
if (!lease) {
|
||||||
|
wl_resource_post_no_memory(resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_resource *wl_resource = wl_resource_create(
|
||||||
|
client, &zwp_drm_lease_v1_interface, 1, id);
|
||||||
|
if (!wl_resource) {
|
||||||
|
free(lease);
|
||||||
|
wl_resource_post_no_memory(resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_signal_init(&lease->events.revoked);
|
||||||
|
wl_list_init(&lease->connectors);
|
||||||
|
lease->manager = lease_request->manager;
|
||||||
|
lease->resource = wl_resource;
|
||||||
|
lease_request->lease = lease;
|
||||||
|
wl_list_insert(&lease->manager->leases, wl_resource_get_link(wl_resource));
|
||||||
|
|
||||||
|
wl_resource_set_implementation(wl_resource, &lease_impl,
|
||||||
|
lease, drm_lease_v1_handle_resource_destroy);
|
||||||
|
|
||||||
|
if (!drm_lease_request_v1_validate(lease_request)) {
|
||||||
|
/* Pre-emptively reject invalid lease requests */
|
||||||
|
zwp_drm_lease_v1_send_finished(lease->resource);
|
||||||
|
} else {
|
||||||
|
wlr_signal_emit_safe(
|
||||||
|
&lease_request->manager->events.lease_requested,
|
||||||
|
lease_request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zwp_drm_lease_request_v1_interface lease_request_impl = {
|
||||||
|
.destroy = drm_lease_request_v1_handle_destroy,
|
||||||
|
.request_connector = drm_lease_request_v1_handle_request_connector,
|
||||||
|
.submit = drm_lease_request_v1_handle_submit,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void drm_lease_manager_v1_validate_destroy(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager, struct wl_client *client) {
|
||||||
|
// TODO: send protocol error if there are any bound resources
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_manager_v1_handle_resource_destroy(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
drm_lease_manager_v1_validate_destroy(
|
||||||
|
wlr_drm_lease_manager_v1_from_resource(resource),
|
||||||
|
wl_resource_get_client(resource));
|
||||||
|
wl_list_remove(wl_resource_get_link(resource));
|
||||||
|
wl_list_init(wl_resource_get_link(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_lease_manager_v1_handle_stop(
|
||||||
|
struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
zwp_drm_lease_manager_v1_send_finished(resource);
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drm_lease_manager_v1_handle_create_lease_request(
|
||||||
|
struct wl_client *client, struct wl_resource *resource, uint32_t id) {
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager =
|
||||||
|
wlr_drm_lease_manager_v1_from_resource(resource);
|
||||||
|
|
||||||
|
struct wlr_drm_lease_request_v1 *req =
|
||||||
|
calloc(1, sizeof(struct wlr_drm_lease_request_v1));
|
||||||
|
if (!req) {
|
||||||
|
wl_resource_post_no_memory(resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_resource *wl_resource = wl_resource_create(client,
|
||||||
|
&zwp_drm_lease_request_v1_interface, 1, id);
|
||||||
|
if (!wl_resource) {
|
||||||
|
wl_resource_post_no_memory(resource);
|
||||||
|
free(req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->manager = manager;
|
||||||
|
req->resource = wl_resource;
|
||||||
|
wl_list_init(&req->connectors);
|
||||||
|
|
||||||
|
wl_resource_set_implementation(wl_resource, &lease_request_impl,
|
||||||
|
req, drm_lease_request_v1_handle_resource_destroy);
|
||||||
|
|
||||||
|
wl_list_insert(&manager->lease_requests, wl_resource_get_link(wl_resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zwp_drm_lease_manager_v1_interface lease_manager_impl = {
|
||||||
|
.stop = drm_lease_manager_v1_handle_stop,
|
||||||
|
.create_lease_request = drm_lease_manager_v1_handle_create_lease_request,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void drm_connector_v1_handle_resource_destroy(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
wl_list_remove(wl_resource_get_link(resource));
|
||||||
|
wl_list_init(wl_resource_get_link(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_connector_v1_handle_destroy(
|
||||||
|
struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zwp_drm_lease_connector_v1_interface lease_connector_impl = {
|
||||||
|
.destroy = drm_connector_v1_handle_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void drm_lease_connector_v1_send_to_client(
|
||||||
|
struct wlr_drm_lease_connector_v1 *connector,
|
||||||
|
struct wl_client *wl_client, struct wl_resource *manager) {
|
||||||
|
if (connector->active_lease) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_resource *wl_resource = wl_resource_create(wl_client,
|
||||||
|
&zwp_drm_lease_connector_v1_interface, 1, 0);
|
||||||
|
wl_resource_set_implementation(wl_resource, &lease_connector_impl,
|
||||||
|
connector, drm_connector_v1_handle_resource_destroy);
|
||||||
|
zwp_drm_lease_manager_v1_send_connector(manager, wl_resource);
|
||||||
|
|
||||||
|
struct wlr_output *output = connector->output;
|
||||||
|
zwp_drm_lease_connector_v1_send_name(wl_resource, output->name);
|
||||||
|
|
||||||
|
char description[128];
|
||||||
|
snprintf(description, sizeof(description), "%s %s %s (%s)",
|
||||||
|
output->make, output->model, output->serial, output->name);
|
||||||
|
zwp_drm_lease_connector_v1_send_description(wl_resource, description);
|
||||||
|
|
||||||
|
zwp_drm_lease_connector_v1_send_connector_id(
|
||||||
|
wl_resource, connector->drm_connector->id);
|
||||||
|
|
||||||
|
struct wlr_drm_lease_manager_v1 *lease_manager =
|
||||||
|
wlr_drm_lease_manager_v1_from_resource(manager);
|
||||||
|
struct wlr_drm_connector *conn = connector->drm_connector;
|
||||||
|
size_t edid_len = 0;
|
||||||
|
uint8_t *edid = get_drm_prop_blob(lease_manager->backend->fd,
|
||||||
|
conn->id, conn->props.edid, &edid_len);
|
||||||
|
int edid_fd = allocate_shm_file(edid_len);
|
||||||
|
void *ptr = mmap(NULL, edid_len, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED, edid_fd, 0);
|
||||||
|
memcpy(ptr, edid, edid_len);
|
||||||
|
munmap(ptr, edid_len);
|
||||||
|
|
||||||
|
zwp_drm_lease_connector_v1_send_edid(wl_resource, edid_fd, edid_len);
|
||||||
|
free(edid);
|
||||||
|
close(edid_fd);
|
||||||
|
|
||||||
|
wl_list_insert(&connector->resources, wl_resource_get_link(wl_resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lease_manager_bind(struct wl_client *wl_client, void *data,
|
||||||
|
uint32_t version, uint32_t id) {
|
||||||
|
struct wlr_drm_lease_manager_v1 *lease_manager = data;
|
||||||
|
|
||||||
|
struct wl_resource *wl_resource = wl_resource_create(wl_client,
|
||||||
|
&zwp_drm_lease_manager_v1_interface, version, id);
|
||||||
|
|
||||||
|
if (!wl_resource) {
|
||||||
|
wl_client_post_no_memory(wl_client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_insert(&lease_manager->resources,
|
||||||
|
wl_resource_get_link(wl_resource));
|
||||||
|
|
||||||
|
wl_resource_set_implementation(wl_resource, &lease_manager_impl,
|
||||||
|
lease_manager, drm_lease_manager_v1_handle_resource_destroy);
|
||||||
|
|
||||||
|
struct wlr_drm_lease_connector_v1 *connector;
|
||||||
|
wl_list_for_each(connector, &lease_manager->connectors, link) {
|
||||||
|
drm_lease_connector_v1_send_to_client(
|
||||||
|
connector, wl_client, wl_resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_drm_lease_manager_v1_offer_output(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager, struct wlr_output *output) {
|
||||||
|
assert(manager && output);
|
||||||
|
assert(wlr_output_is_drm(output));
|
||||||
|
struct wlr_drm_connector *drm_connector =
|
||||||
|
(struct wlr_drm_connector *)output;
|
||||||
|
/*
|
||||||
|
* When the compositor grants a lease, we "destroy" all of the outputs on
|
||||||
|
* that lease. When the lease ends, the outputs re-appear. However, the
|
||||||
|
* underlying DRM connector remains the same. If the compositor offers
|
||||||
|
* outputs based on some criteria, then sees the output re-appear with the
|
||||||
|
* same critera, this code allows it to safely re-offer outputs which are
|
||||||
|
* backed by DRM connectors it has leased in the past.
|
||||||
|
*/
|
||||||
|
struct wlr_drm_lease_connector_v1 *connector;
|
||||||
|
wl_list_for_each(connector, &manager->connectors, link) {
|
||||||
|
if (connector->drm_connector == drm_connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connector = calloc(1, sizeof(struct wlr_drm_lease_connector_v1));
|
||||||
|
connector->drm_connector = drm_connector;
|
||||||
|
connector->output = &drm_connector->output;
|
||||||
|
wl_list_init(&connector->resources);
|
||||||
|
wl_list_insert(&manager->connectors, &connector->link);
|
||||||
|
|
||||||
|
struct wl_resource *resource;
|
||||||
|
wl_resource_for_each(resource, &manager->resources) {
|
||||||
|
drm_lease_connector_v1_send_to_client(
|
||||||
|
connector, wl_resource_get_client(resource), resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_drm_lease_manager_v1_widthraw_output(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager, struct wlr_output *output) {
|
||||||
|
struct wlr_drm_lease_connector_v1 *connector = NULL, *_connector;
|
||||||
|
wl_list_for_each(_connector, &manager->connectors, link) {
|
||||||
|
if (_connector->output == output) {
|
||||||
|
connector = _connector;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(connector->active_lease == NULL && "Cannot withdraw a leased output");
|
||||||
|
|
||||||
|
struct wl_resource *wl_resource, *temp;
|
||||||
|
wl_resource_for_each_safe(wl_resource, temp, &connector->resources) {
|
||||||
|
zwp_drm_lease_connector_v1_send_withdrawn(wl_resource);
|
||||||
|
wl_resource_set_user_data(wl_resource, NULL);
|
||||||
|
wl_list_remove(wl_resource_get_link(wl_resource));
|
||||||
|
wl_list_init(wl_resource_get_link(wl_resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_for_each(wl_resource, &manager->lease_requests) {
|
||||||
|
struct wlr_drm_lease_request_v1 *request =
|
||||||
|
wlr_drm_lease_request_v1_from_resource(wl_resource);
|
||||||
|
request->invalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_remove(&connector->link);
|
||||||
|
wl_list_init(&connector->link);
|
||||||
|
free(connector);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void multi_backend_cb(struct wlr_backend *backend, void *data) {
|
||||||
|
struct wlr_backend **ptr = data;
|
||||||
|
if (wlr_backend_is_drm(backend)) {
|
||||||
|
*ptr = backend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_lease_manager_v1 *wlr_drm_lease_manager_v1_create(
|
||||||
|
struct wl_display *display, struct wlr_backend *backend) {
|
||||||
|
assert(display);
|
||||||
|
|
||||||
|
if (!wlr_backend_is_drm(backend) && wlr_backend_is_multi(backend)) {
|
||||||
|
wlr_multi_for_each_backend(backend, multi_backend_cb, &backend);
|
||||||
|
if (!wlr_backend_is_drm(backend)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_lease_manager_v1 *lease_manager =
|
||||||
|
calloc(1, sizeof(struct wlr_drm_lease_manager_v1));
|
||||||
|
|
||||||
|
if (!lease_manager) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lease_manager->backend = get_drm_backend_from_backend(backend);
|
||||||
|
wl_list_init(&lease_manager->resources);
|
||||||
|
wl_list_init(&lease_manager->connectors);
|
||||||
|
wl_list_init(&lease_manager->lease_requests);
|
||||||
|
wl_list_init(&lease_manager->leases);
|
||||||
|
|
||||||
|
wl_signal_init(&lease_manager->events.lease_requested);
|
||||||
|
|
||||||
|
lease_manager->global = wl_global_create(display,
|
||||||
|
&zwp_drm_lease_manager_v1_interface, 1,
|
||||||
|
lease_manager, lease_manager_bind);
|
||||||
|
|
||||||
|
if (!lease_manager->global) {
|
||||||
|
free(lease_manager);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lease_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_drm_lease_manager_v1_destroy(
|
||||||
|
struct wlr_drm_lease_manager_v1 *manager) {
|
||||||
|
if (!manager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_resource *resource;
|
||||||
|
struct wl_resource *tmp_resource;
|
||||||
|
wl_resource_for_each_safe(resource, tmp_resource, &manager->resources) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_for_each_safe(resource, tmp_resource,
|
||||||
|
&manager->lease_requests) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_for_each_safe(resource, tmp_resource, &manager->leases) {
|
||||||
|
struct wlr_drm_lease_v1 *lease =
|
||||||
|
wlr_drm_lease_v1_from_resource(resource);
|
||||||
|
wlr_drm_lease_manager_v1_revoke_lease(manager, lease);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_lease_connector_v1 *connector, *tmp_connector;
|
||||||
|
wl_list_for_each_safe(connector, tmp_connector,
|
||||||
|
&manager->connectors, link) {
|
||||||
|
wl_list_remove(&connector->link);
|
||||||
|
wl_list_init(&connector->link);
|
||||||
|
free(connector);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(manager);
|
||||||
|
}
|
Loading…
Reference in New Issue