Implement drm-lease-v1
This commit is contained in:
parent
3abbc31272
commit
177d35cace
4 changed files with 622 additions and 0 deletions
|
@ -19,6 +19,7 @@ set(SERVER_LIB_SRCS
|
||||||
display.cpp
|
display.cpp
|
||||||
dpms_interface.cpp
|
dpms_interface.cpp
|
||||||
drmclientbuffer.cpp
|
drmclientbuffer.cpp
|
||||||
|
drmleasedevice_v1_interface.cpp
|
||||||
eglstream_controller_interface.cpp
|
eglstream_controller_interface.cpp
|
||||||
fakeinput_interface.cpp
|
fakeinput_interface.cpp
|
||||||
filtered_display.cpp
|
filtered_display.cpp
|
||||||
|
@ -278,6 +279,11 @@ ecm_add_qtwayland_server_protocol_kde(SERVER_LIB_SRCS
|
||||||
BASENAME xdg-activation-v1
|
BASENAME xdg-activation-v1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ecm_add_qtwayland_server_protocol_kde(SERVER_LIB_SRCS
|
||||||
|
PROTOCOL ${WaylandProtocols_DATADIR}/staging/drm-lease/drm-lease-v1.xml
|
||||||
|
BASENAME drm-lease-v1
|
||||||
|
)
|
||||||
|
|
||||||
add_library(KWaylandServer ${SERVER_LIB_SRCS})
|
add_library(KWaylandServer ${SERVER_LIB_SRCS})
|
||||||
add_library(Plasma::KWaylandServer ALIAS KWaylandServer)
|
add_library(Plasma::KWaylandServer ALIAS KWaylandServer)
|
||||||
ecm_generate_export_header(KWaylandServer
|
ecm_generate_export_header(KWaylandServer
|
||||||
|
@ -339,6 +345,7 @@ set(SERVER_LIB_HEADERS
|
||||||
display.h
|
display.h
|
||||||
dpms_interface.h
|
dpms_interface.h
|
||||||
drmclientbuffer.h
|
drmclientbuffer.h
|
||||||
|
drmleasedevice_v1_interface.h
|
||||||
eglstream_controller_interface.h
|
eglstream_controller_interface.h
|
||||||
fakeinput_interface.h
|
fakeinput_interface.h
|
||||||
filtered_display.h
|
filtered_display.h
|
||||||
|
|
389
src/wayland/drmleasedevice_v1_interface.cpp
Normal file
389
src/wayland/drmleasedevice_v1_interface.cpp
Normal file
|
@ -0,0 +1,389 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "drmleasedevice_v1_interface.h"
|
||||||
|
#include "drmleasedevice_v1_interface_p.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace KWaylandServer
|
||||||
|
{
|
||||||
|
|
||||||
|
static const quint32 s_version = 1;
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1Interface::DrmLeaseDeviceV1Interface(Display *display, std::function<int()> createNonMasterFd)
|
||||||
|
: d(new DrmLeaseDeviceV1InterfacePrivate(display, this, createNonMasterFd))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1Interface::~DrmLeaseDeviceV1Interface()
|
||||||
|
{
|
||||||
|
d->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1Interface::setDrmMaster(bool hasDrmMaster)
|
||||||
|
{
|
||||||
|
if (hasDrmMaster && !d->hasDrmMaster) {
|
||||||
|
// withdraw all connectors
|
||||||
|
for (const auto &connector : qAsConst(d->connectors)) {
|
||||||
|
DrmLeaseConnectorV1InterfacePrivate::get(connector)->withdraw();
|
||||||
|
}
|
||||||
|
// and revoke all leases
|
||||||
|
for (const auto &lease : qAsConst(d->leases)) {
|
||||||
|
lease->deny();
|
||||||
|
}
|
||||||
|
} else if (!hasDrmMaster && d->hasDrmMaster) {
|
||||||
|
// send pending drm fds
|
||||||
|
while (!d->pendingFds.isEmpty()) {
|
||||||
|
int fd = d->createNonMasterFd();
|
||||||
|
d->send_drm_fd(d->pendingFds.dequeue(), fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
// offer all connectors again
|
||||||
|
for (const auto &connector : qAsConst(d->connectors)) {
|
||||||
|
auto connectorPrivate = DrmLeaseConnectorV1InterfacePrivate::get(connector);
|
||||||
|
connectorPrivate->withdrawn = false;
|
||||||
|
for (const auto &resource : d->resourceMap()) {
|
||||||
|
auto connectorResource = connectorPrivate->add(resource->client(), 0, s_version);
|
||||||
|
d->send_connector(resource->handle, connectorResource->handle);
|
||||||
|
connectorPrivate->send(connectorResource->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d->hasDrmMaster = hasDrmMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate::DrmLeaseDeviceV1InterfacePrivate(Display *display, DrmLeaseDeviceV1Interface *device, std::function<int()> createNonMasterFd)
|
||||||
|
: QtWaylandServer::wp_drm_lease_device_v1(*display, s_version)
|
||||||
|
, q(device)
|
||||||
|
, createNonMasterFd(createNonMasterFd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate::~DrmLeaseDeviceV1InterfacePrivate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1InterfacePrivate::remove()
|
||||||
|
{
|
||||||
|
for (const auto &lease : qAsConst(leases)) {
|
||||||
|
lease->deny();
|
||||||
|
}
|
||||||
|
for (const auto &connector : qAsConst(connectors)) {
|
||||||
|
DrmLeaseConnectorV1InterfacePrivate::get(connector)->withdraw();
|
||||||
|
}
|
||||||
|
for (const auto &request : qAsConst(leaseRequests)) {
|
||||||
|
request->connectors.clear();
|
||||||
|
}
|
||||||
|
globalRemove();
|
||||||
|
removed = true;
|
||||||
|
if (resourceMap().isEmpty()) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1InterfacePrivate::registerConnector(DrmLeaseConnectorV1Interface *connector)
|
||||||
|
{
|
||||||
|
connectors << connector;
|
||||||
|
if (!hasDrmMaster) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto &resource : resourceMap()) {
|
||||||
|
auto connectorPrivate = DrmLeaseConnectorV1InterfacePrivate::get(connector);
|
||||||
|
auto connectorResource = connectorPrivate->add(resource->client(), 0, resource->version());
|
||||||
|
send_connector(resource->handle, connectorResource->handle);
|
||||||
|
connectorPrivate->send(connectorResource->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1InterfacePrivate::unregisterConnector(DrmLeaseConnectorV1Interface *connector)
|
||||||
|
{
|
||||||
|
connectors.removeOne(connector);
|
||||||
|
for (const auto &lease : qAsConst(leases)) {
|
||||||
|
if (lease->d->connectors.contains(connector)) {
|
||||||
|
lease->d->connectors.removeOne(connector);
|
||||||
|
lease->deny();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &leaseRequest : qAsConst(leaseRequests)) {
|
||||||
|
if (leaseRequest->connectors.removeOne(connector)) {
|
||||||
|
leaseRequest->invalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate *DrmLeaseDeviceV1InterfacePrivate::get(DrmLeaseDeviceV1Interface *device)
|
||||||
|
{
|
||||||
|
return device->d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1InterfacePrivate::wp_drm_lease_device_v1_create_lease_request(Resource *resource, uint32_t id)
|
||||||
|
{
|
||||||
|
wl_resource *requestResource = wl_resource_create(resource->client(), &wp_drm_lease_request_v1_interface,
|
||||||
|
resource->version(), id);
|
||||||
|
if (!requestResource) {
|
||||||
|
wl_resource_post_no_memory(resource->handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
leaseRequests << new DrmLeaseRequestV1Interface(this, requestResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1InterfacePrivate::wp_drm_lease_device_v1_release(Resource *resource)
|
||||||
|
{
|
||||||
|
send_released(resource->handle);
|
||||||
|
wl_resource_destroy(resource->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1InterfacePrivate::wp_drm_lease_device_v1_bind_resource(Resource *resource)
|
||||||
|
{
|
||||||
|
if (!hasDrmMaster) {
|
||||||
|
pendingFds << resource->handle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int fd = createNonMasterFd();
|
||||||
|
send_drm_fd(resource->handle, fd);
|
||||||
|
close(fd);
|
||||||
|
for (const auto &connector : qAsConst(connectors)) {
|
||||||
|
auto connectorPrivate = DrmLeaseConnectorV1InterfacePrivate::get(connector);
|
||||||
|
if (!connectorPrivate->withdrawn) {
|
||||||
|
auto connectorResource = connectorPrivate->add(resource->client(), 0, s_version);
|
||||||
|
send_connector(resource->handle, connectorResource->handle);
|
||||||
|
connectorPrivate->send(connectorResource->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseDeviceV1InterfacePrivate::wp_drm_lease_device_v1_destroy_resource(Resource *resource)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
if (removed && resourceMap().isEmpty()) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DrmLeaseConnectorV1Interface::DrmLeaseConnectorV1Interface(DrmLeaseDeviceV1Interface *leaseDevice,
|
||||||
|
uint32_t id,
|
||||||
|
const QString &name,
|
||||||
|
const QString &description)
|
||||||
|
: d(new DrmLeaseConnectorV1InterfacePrivate(leaseDevice, this, id, name, description))
|
||||||
|
{
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate::get(leaseDevice)->registerConnector(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseConnectorV1Interface::~DrmLeaseConnectorV1Interface()
|
||||||
|
{
|
||||||
|
d->withdraw();
|
||||||
|
if (d->device) {
|
||||||
|
auto devicePrivate = DrmLeaseDeviceV1InterfacePrivate::get(d->device);
|
||||||
|
devicePrivate->unregisterConnector(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseConnectorV1Interface *DrmLeaseConnectorV1Interface::get(wl_resource *resource)
|
||||||
|
{
|
||||||
|
if (auto connectorPrivate = resource_cast<DrmLeaseConnectorV1InterfacePrivate*>(resource)) {
|
||||||
|
return connectorPrivate->q;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseConnectorV1InterfacePrivate::DrmLeaseConnectorV1InterfacePrivate(DrmLeaseDeviceV1Interface *device,
|
||||||
|
DrmLeaseConnectorV1Interface *connector,
|
||||||
|
uint32_t connectorId,
|
||||||
|
const QString &name,
|
||||||
|
const QString &description)
|
||||||
|
: wp_drm_lease_connector_v1()
|
||||||
|
, q(connector)
|
||||||
|
, device(device)
|
||||||
|
, connectorId(connectorId)
|
||||||
|
, name(name)
|
||||||
|
, description(description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseConnectorV1InterfacePrivate::~DrmLeaseConnectorV1InterfacePrivate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseConnectorV1InterfacePrivate::send(wl_resource *resource)
|
||||||
|
{
|
||||||
|
send_connector_id(resource, connectorId);
|
||||||
|
send_name(resource, name);
|
||||||
|
send_description(resource, description);
|
||||||
|
send_done(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseConnectorV1InterfacePrivate::withdraw()
|
||||||
|
{
|
||||||
|
if (!withdrawn) {
|
||||||
|
withdrawn = true;
|
||||||
|
for (const auto &resource : resourceMap()) {
|
||||||
|
send_withdrawn(resource->handle);
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate::get(device)->send_done(resource->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseConnectorV1InterfacePrivate *DrmLeaseConnectorV1InterfacePrivate::get(DrmLeaseConnectorV1Interface *connector)
|
||||||
|
{
|
||||||
|
return connector->d.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseConnectorV1InterfacePrivate::wp_drm_lease_connector_v1_destroy(Resource *resource)
|
||||||
|
{
|
||||||
|
wl_resource_destroy(resource->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DrmLeaseRequestV1Interface::DrmLeaseRequestV1Interface(DrmLeaseDeviceV1InterfacePrivate *device, wl_resource *resource)
|
||||||
|
: wp_drm_lease_request_v1(resource)
|
||||||
|
, device(device)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseRequestV1Interface::~DrmLeaseRequestV1Interface()
|
||||||
|
{
|
||||||
|
device->leaseRequests.removeOne(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseRequestV1Interface::wp_drm_lease_request_v1_request_connector(Resource *resource, struct ::wl_resource *connector_handle)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource);
|
||||||
|
if (auto connector = DrmLeaseConnectorV1Interface::get(connector_handle)) {
|
||||||
|
auto connectorPrivate = DrmLeaseConnectorV1InterfacePrivate::get(connector);
|
||||||
|
if (connectorPrivate->device != device->q) {
|
||||||
|
wl_resource_post_error(resource->handle, WP_DRM_LEASE_REQUEST_V1_ERROR_WRONG_DEVICE, "Requested connector from invalid lease device");
|
||||||
|
} else if (connectorPrivate->withdrawn) {
|
||||||
|
qCWarning(KWAYLAND_SERVER) << "DrmLease: withdrawn connector requested";
|
||||||
|
} else if (connectors.contains(connector)) {
|
||||||
|
wl_resource_post_error(resource->handle, WP_DRM_LEASE_REQUEST_V1_ERROR_DUPLICATE_CONNECTOR, "Requested connector twice");
|
||||||
|
} else {
|
||||||
|
connectors << connector;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qCWarning(KWAYLAND_SERVER, "DrmLease: Invalid connector requested");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseRequestV1Interface::wp_drm_lease_request_v1_submit(Resource *resource, uint32_t id)
|
||||||
|
{
|
||||||
|
wl_resource *leaseResource = wl_resource_create(resource->client(), &wp_drm_lease_v1_interface, s_version, id);
|
||||||
|
if (!leaseResource) {
|
||||||
|
wl_resource_post_no_memory(resource->handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DrmLeaseV1Interface *lease = new DrmLeaseV1Interface(device, leaseResource);
|
||||||
|
device->leases << lease;
|
||||||
|
if (!device->hasDrmMaster) {
|
||||||
|
qCWarning(KWAYLAND_SERVER) << "DrmLease: rejecting lease request without drm master";
|
||||||
|
lease->deny();
|
||||||
|
} else if (invalid) {
|
||||||
|
qCWarning(KWAYLAND_SERVER()) << "DrmLease: rejecting lease request with a withdrawn connector";
|
||||||
|
lease->deny();
|
||||||
|
} else if (connectors.isEmpty()) {
|
||||||
|
wl_resource_post_error(resource->handle, WP_DRM_LEASE_REQUEST_V1_ERROR_EMPTY_LEASE, "Requested lease without connectors");
|
||||||
|
} else {
|
||||||
|
lease->d->connectors = connectors;
|
||||||
|
emit device->q->leaseRequested(lease);
|
||||||
|
}
|
||||||
|
wl_resource_destroy(resource->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseRequestV1Interface::wp_drm_lease_request_v1_destroy_resource(Resource *resource)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseV1Interface::DrmLeaseV1Interface(DrmLeaseDeviceV1InterfacePrivate *device, wl_resource *resource)
|
||||||
|
: d(new DrmLeaseV1InterfacePrivate(device, this, resource))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmLeaseV1Interface::~DrmLeaseV1Interface()
|
||||||
|
{
|
||||||
|
deny();
|
||||||
|
d->device->leases.removeOne(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseV1Interface::grant(int leaseFd, uint32_t lesseeId)
|
||||||
|
{
|
||||||
|
d->send_lease_fd(leaseFd);
|
||||||
|
close(leaseFd);
|
||||||
|
d->lesseeId = lesseeId;
|
||||||
|
for (const auto &connector : qAsConst(d->connectors)) {
|
||||||
|
DrmLeaseConnectorV1InterfacePrivate::get(connector)->withdraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseV1Interface::deny()
|
||||||
|
{
|
||||||
|
if (!d->finished) {
|
||||||
|
d->finished = true;
|
||||||
|
d->send_finished();
|
||||||
|
}
|
||||||
|
if (!d->lesseeId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Q_EMIT d->device->q->leaseRevoked(this);
|
||||||
|
// check if we should offer connectors again
|
||||||
|
if (d->device->hasDrmMaster) {
|
||||||
|
bool sent = false;
|
||||||
|
for (const auto &connector : qAsConst(d->connectors)) {
|
||||||
|
auto connectorPrivate = DrmLeaseConnectorV1InterfacePrivate::get(connector);
|
||||||
|
connectorPrivate->withdrawn = false;
|
||||||
|
for (const auto &resource : d->device->resourceMap()) {
|
||||||
|
auto connectorResource = connectorPrivate->add(resource->client(), 0, s_version);
|
||||||
|
d->device->send_connector(resource->handle, connectorResource->handle);
|
||||||
|
connectorPrivate->send(connectorResource->handle);
|
||||||
|
sent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sent) {
|
||||||
|
for (const auto &resource : d->device->resourceMap()) {
|
||||||
|
d->device->send_done(resource->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d->lesseeId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DrmLeaseV1Interface::lesseeId() const
|
||||||
|
{
|
||||||
|
return d->lesseeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<DrmLeaseConnectorV1Interface *> DrmLeaseV1Interface::connectors() const
|
||||||
|
{
|
||||||
|
return d->connectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DrmLeaseV1InterfacePrivate::DrmLeaseV1InterfacePrivate(DrmLeaseDeviceV1InterfacePrivate *device, DrmLeaseV1Interface *q, wl_resource *resource)
|
||||||
|
: wp_drm_lease_v1(resource)
|
||||||
|
, device(device)
|
||||||
|
, q(q)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseV1InterfacePrivate::wp_drm_lease_v1_destroy(Resource *resource)
|
||||||
|
{
|
||||||
|
wl_resource_destroy(resource->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrmLeaseV1InterfacePrivate::wp_drm_lease_v1_destroy_resource(Resource *resource)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
delete q;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
122
src/wayland/drmleasedevice_v1_interface.h
Normal file
122
src/wayland/drmleasedevice_v1_interface.h
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <KWaylandServer/kwaylandserver_export.h>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
struct wl_resource;
|
||||||
|
|
||||||
|
namespace KWaylandServer
|
||||||
|
{
|
||||||
|
|
||||||
|
class Display;
|
||||||
|
class DrmLeaseDeviceV1InterfacePrivate;
|
||||||
|
class DrmLeaseV1Interface;
|
||||||
|
class DrmLeaseV1InterfacePrivate;
|
||||||
|
class DrmLeaseRequestV1Interface;
|
||||||
|
class DrmLeaseConnectorV1InterfacePrivate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DrmLeaseV1DeviceInterface allows the wayland compositor to offer unused
|
||||||
|
* drm connectors for lease by clients. The main use for this is VR headsets
|
||||||
|
*/
|
||||||
|
class KWAYLANDSERVER_EXPORT DrmLeaseDeviceV1Interface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @param createNonMasterFd a function that creates non-master drm file descriptors for
|
||||||
|
* this device that clients can use to enumerate connectors and their properties
|
||||||
|
*/
|
||||||
|
explicit DrmLeaseDeviceV1Interface(Display *display, std::function<int()> createNonMasterFd);
|
||||||
|
~DrmLeaseDeviceV1Interface() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called by the compositor when it loses or gains drm master
|
||||||
|
*/
|
||||||
|
void setDrmMaster(bool hasDrmMaster);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
/**
|
||||||
|
* Emitted when a lease is requested. The compositor needs to either
|
||||||
|
* grant or deny the lease when receiving this signal
|
||||||
|
*/
|
||||||
|
void leaseRequested(DrmLeaseV1Interface *leaseRequest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when a granted lease gets revoked
|
||||||
|
*/
|
||||||
|
void leaseRevoked(DrmLeaseV1Interface *lease);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class DrmLeaseDeviceV1InterfacePrivate;
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a lease offer from the compositor. Creating the DrmLeaseConnectorV1Interface
|
||||||
|
* will allow clients to requests a lease for the connector, deleting it will result in the
|
||||||
|
* offer and possibly an active lease being revoked
|
||||||
|
*/
|
||||||
|
class KWAYLANDSERVER_EXPORT DrmLeaseConnectorV1Interface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DrmLeaseConnectorV1Interface(DrmLeaseDeviceV1Interface *leaseDevice, uint32_t id, const QString &name, const QString &description);
|
||||||
|
~DrmLeaseConnectorV1Interface() override;
|
||||||
|
|
||||||
|
static DrmLeaseConnectorV1Interface *get(wl_resource *resource);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class DrmLeaseConnectorV1InterfacePrivate;
|
||||||
|
QScopedPointer<DrmLeaseConnectorV1InterfacePrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a lease request or active lease
|
||||||
|
*/
|
||||||
|
class KWAYLANDSERVER_EXPORT DrmLeaseV1Interface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Grant the client requesting the lease access to DRM resources needed to
|
||||||
|
* drive the outputs corresponding to the requested connectors.
|
||||||
|
* Must only be called once in response to DrmLeaseDeviceV1Interface::leaseRequested
|
||||||
|
*/
|
||||||
|
void grant(int leaseFd, uint32_t lesseeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deny the lease request. The compositor may call this in response to
|
||||||
|
* DrmLeaseDeviceV1Interface::leaseRequested or when it detects a lease being ended with libdrm
|
||||||
|
*/
|
||||||
|
void deny();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connectors this lease (request) encompasses
|
||||||
|
*/
|
||||||
|
QVector<DrmLeaseConnectorV1Interface *> connectors() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lesseeId passed to DrmLeaseV1Interface::grant, or 0 if this lease was not granted
|
||||||
|
*/
|
||||||
|
uint32_t lesseeId() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DrmLeaseV1Interface(DrmLeaseDeviceV1InterfacePrivate *device, wl_resource *resource);
|
||||||
|
~DrmLeaseV1Interface();
|
||||||
|
|
||||||
|
friend class DrmLeaseDeviceV1InterfacePrivate;
|
||||||
|
friend class DrmLeaseRequestV1Interface;
|
||||||
|
friend class DrmLeaseV1InterfacePrivate;
|
||||||
|
QScopedPointer<DrmLeaseV1InterfacePrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
104
src/wayland/drmleasedevice_v1_interface_p.h
Normal file
104
src/wayland/drmleasedevice_v1_interface_p.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qwayland-server-drm-lease-v1.h>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QQueue>
|
||||||
|
|
||||||
|
namespace KWaylandServer
|
||||||
|
{
|
||||||
|
|
||||||
|
class Display;
|
||||||
|
class DrmLeaseConnectorV1Interface;
|
||||||
|
class DrmLeaseRequestV1Interface;
|
||||||
|
class DrmLeaseV1Interface;
|
||||||
|
|
||||||
|
class DrmLeaseDeviceV1InterfacePrivate : public QtWaylandServer::wp_drm_lease_device_v1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate(Display *display, DrmLeaseDeviceV1Interface *device, std::function<int()> createNonMasterFd);
|
||||||
|
~DrmLeaseDeviceV1InterfacePrivate();
|
||||||
|
void remove();
|
||||||
|
|
||||||
|
void registerConnector(DrmLeaseConnectorV1Interface *connector);
|
||||||
|
void unregisterConnector(DrmLeaseConnectorV1Interface *connector);
|
||||||
|
|
||||||
|
static DrmLeaseDeviceV1InterfacePrivate *get(DrmLeaseDeviceV1Interface *device);
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1Interface *q;
|
||||||
|
QVector<DrmLeaseConnectorV1Interface *> connectors;
|
||||||
|
QVector<DrmLeaseRequestV1Interface *> leaseRequests;
|
||||||
|
QVector<DrmLeaseV1Interface *> leases;
|
||||||
|
QQueue<wl_resource *> pendingFds;
|
||||||
|
std::function<int()> createNonMasterFd;
|
||||||
|
bool hasDrmMaster = true;
|
||||||
|
bool removed = false;
|
||||||
|
protected:
|
||||||
|
void wp_drm_lease_device_v1_create_lease_request(Resource *resource, uint32_t id) override;
|
||||||
|
void wp_drm_lease_device_v1_release(Resource *resource) override;
|
||||||
|
void wp_drm_lease_device_v1_bind_resource(Resource *resource) override;
|
||||||
|
void wp_drm_lease_device_v1_destroy_resource(Resource *resource) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DrmLeaseConnectorV1InterfacePrivate : public QObject, public QtWaylandServer::wp_drm_lease_connector_v1
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DrmLeaseConnectorV1InterfacePrivate(DrmLeaseDeviceV1Interface *device, DrmLeaseConnectorV1Interface *connector,
|
||||||
|
uint32_t connectorId, const QString &name, const QString &description);
|
||||||
|
~DrmLeaseConnectorV1InterfacePrivate();
|
||||||
|
|
||||||
|
void send(wl_resource *resource);
|
||||||
|
void withdraw();
|
||||||
|
|
||||||
|
static DrmLeaseConnectorV1InterfacePrivate *get(DrmLeaseConnectorV1Interface *connector);
|
||||||
|
|
||||||
|
DrmLeaseConnectorV1Interface *q;
|
||||||
|
QPointer<DrmLeaseDeviceV1Interface> device;
|
||||||
|
uint32_t connectorId;
|
||||||
|
QString name;
|
||||||
|
QString description;
|
||||||
|
bool withdrawn = false;
|
||||||
|
protected:
|
||||||
|
void wp_drm_lease_connector_v1_destroy(Resource *resource) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DrmLeaseRequestV1Interface : public QtWaylandServer::wp_drm_lease_request_v1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DrmLeaseRequestV1Interface(DrmLeaseDeviceV1InterfacePrivate *device, wl_resource *resource);
|
||||||
|
~DrmLeaseRequestV1Interface();
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate *device;
|
||||||
|
QVector<DrmLeaseConnectorV1Interface *> connectors;
|
||||||
|
bool invalid = false;
|
||||||
|
protected:
|
||||||
|
void wp_drm_lease_request_v1_request_connector(Resource *resource, struct ::wl_resource *connector) override;
|
||||||
|
void wp_drm_lease_request_v1_submit(Resource *resource, uint32_t id) override;
|
||||||
|
void wp_drm_lease_request_v1_destroy_resource(Resource *resource) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DrmLeaseV1InterfacePrivate : public QtWaylandServer::wp_drm_lease_v1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DrmLeaseV1InterfacePrivate(DrmLeaseDeviceV1InterfacePrivate *device, DrmLeaseV1Interface *q, wl_resource *resource);
|
||||||
|
|
||||||
|
DrmLeaseDeviceV1InterfacePrivate *device;
|
||||||
|
DrmLeaseV1Interface *q;
|
||||||
|
QVector<DrmLeaseConnectorV1Interface *> connectors;
|
||||||
|
uint32_t lesseeId = 0;
|
||||||
|
bool finished = false;
|
||||||
|
protected:
|
||||||
|
void wp_drm_lease_v1_destroy(Resource *resource) override;
|
||||||
|
void wp_drm_lease_v1_destroy_resource(Resource *resource) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue