backends/drm: remove Wayland bits for drm leasing
This commit is contained in:
parent
fcaf0cad9e
commit
49ad013295
15 changed files with 734 additions and 751 deletions
|
@ -300,6 +300,7 @@ DrmGpu *DrmBackend::addGpu(const QString &fileName)
|
|||
m_active = true;
|
||||
connect(gpu, &DrmGpu::outputAdded, this, &DrmBackend::addOutput);
|
||||
connect(gpu, &DrmGpu::outputRemoved, this, &DrmBackend::removeOutput);
|
||||
Q_EMIT gpuAdded(gpu);
|
||||
return gpu;
|
||||
}
|
||||
|
||||
|
@ -333,7 +334,9 @@ void DrmBackend::updateOutputs()
|
|||
DrmGpu *gpu = it->get();
|
||||
if (gpu->isRemoved() || (gpu != primaryGpu() && gpu->drmOutputs().isEmpty())) {
|
||||
qCDebug(KWIN_DRM) << "Removing GPU" << (*it)->devNode();
|
||||
const std::unique_ptr<DrmGpu> keepAlive = std::move(*it);
|
||||
it = m_gpus.erase(it);
|
||||
Q_EMIT gpuRemoved(keepAlive.get());
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
|
@ -526,4 +529,9 @@ void DrmBackend::releaseBuffers()
|
|||
gpu->releaseBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<DrmGpu>> &DrmBackend::gpus() const
|
||||
{
|
||||
return m_gpus;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,12 +75,16 @@ public:
|
|||
void releaseBuffers();
|
||||
void updateOutputs();
|
||||
|
||||
const std::vector<std::unique_ptr<DrmGpu>> &gpus() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void turnOutputsOn();
|
||||
void sceneInitialized() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void activeChanged();
|
||||
void gpuAdded(DrmGpu *gpu);
|
||||
void gpuRemoved(DrmGpu *gpu);
|
||||
|
||||
protected:
|
||||
bool applyOutputChanges(const OutputConfiguration &config) override;
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#include "drm_plane.h"
|
||||
#include "drm_virtual_output.h"
|
||||
#include "gbm_dmabuf.h"
|
||||
#include "wayland/drmleasedevice_v1_interface.h"
|
||||
#include "wayland_server.h"
|
||||
// system
|
||||
#include <algorithm>
|
||||
#include <errno.h>
|
||||
|
@ -85,30 +83,6 @@ DrmGpu::DrmGpu(DrmBackend *backend, const QString &devNode, int fd, dev_t device
|
|||
connect(m_socketNotifier.get(), &QSocketNotifier::activated, this, &DrmGpu::dispatchEvents);
|
||||
|
||||
initDrmResources();
|
||||
|
||||
m_leaseDevice = std::make_unique<KWaylandServer::DrmLeaseDeviceV1Interface>(waylandServer()->display(), [this] {
|
||||
char *path = drmGetDeviceNameFromFd2(m_fd);
|
||||
FileDescriptor fd{open(path, O_RDWR | O_CLOEXEC)};
|
||||
if (!fd.isValid()) {
|
||||
qCWarning(KWIN_DRM) << "Could not open DRM fd for leasing!" << strerror(errno);
|
||||
} else {
|
||||
if (drmIsMaster(fd.get())) {
|
||||
if (drmDropMaster(fd.get()) != 0) {
|
||||
qCWarning(KWIN_DRM) << "Could not create a non-master DRM fd for leasing!" << strerror(errno);
|
||||
return FileDescriptor{};
|
||||
}
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
});
|
||||
connect(m_leaseDevice.get(), &KWaylandServer::DrmLeaseDeviceV1Interface::leaseRequested, this, &DrmGpu::handleLeaseRequest);
|
||||
connect(m_leaseDevice.get(), &KWaylandServer::DrmLeaseDeviceV1Interface::leaseRevoked, this, &DrmGpu::handleLeaseRevoked);
|
||||
connect(m_platform, &DrmBackend::activeChanged, m_leaseDevice.get(), [this]() {
|
||||
if (!m_platform->isActive()) {
|
||||
// when we gain drm master we want to update outputs first and only then notify the lease device
|
||||
m_leaseDevice->setDrmMaster(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DrmGpu::~DrmGpu()
|
||||
|
@ -120,7 +94,6 @@ DrmGpu::~DrmGpu()
|
|||
m_crtcs.clear();
|
||||
m_connectors.clear();
|
||||
m_planes.clear();
|
||||
m_leaseDevice.reset();
|
||||
m_socketNotifier.reset();
|
||||
if (m_gbmDevice) {
|
||||
gbm_device_destroy(m_gbmDevice);
|
||||
|
@ -128,6 +101,23 @@ DrmGpu::~DrmGpu()
|
|||
m_platform->session()->closeRestricted(m_fd);
|
||||
}
|
||||
|
||||
FileDescriptor DrmGpu::createNonMasterFd() const
|
||||
{
|
||||
char *path = drmGetDeviceNameFromFd2(m_fd);
|
||||
FileDescriptor fd{open(path, O_RDWR | O_CLOEXEC)};
|
||||
if (!fd.isValid()) {
|
||||
qCWarning(KWIN_DRM) << "Could not open DRM fd for leasing!" << strerror(errno);
|
||||
} else {
|
||||
if (drmIsMaster(fd.get())) {
|
||||
if (drmDropMaster(fd.get()) != 0) {
|
||||
qCWarning(KWIN_DRM) << "Could not create a non-master DRM fd for leasing!" << strerror(errno);
|
||||
return FileDescriptor{};
|
||||
}
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
clockid_t DrmGpu::presentationClock() const
|
||||
{
|
||||
return m_presentationClock;
|
||||
|
@ -227,7 +217,7 @@ bool DrmGpu::updateOutputs()
|
|||
}
|
||||
}
|
||||
if (!leaseActive) {
|
||||
output->lease()->revoke();
|
||||
Q_EMIT output->lease()->revokeRequested();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +256,7 @@ bool DrmGpu::updateOutputs()
|
|||
qCDebug(KWIN_DRM, "New %soutput on GPU %s: %s", conn->isNonDesktop() ? "non-desktop " : "", qPrintable(m_devNode), qPrintable(conn->modelName()));
|
||||
const auto pipeline = conn->pipeline();
|
||||
m_pipelines << pipeline;
|
||||
auto output = new DrmOutput(pipeline, m_leaseDevice.get());
|
||||
auto output = new DrmOutput(pipeline);
|
||||
m_drmOutputs << output;
|
||||
addedOutputs << output;
|
||||
Q_EMIT outputAdded(output);
|
||||
|
@ -324,10 +314,6 @@ bool DrmGpu::updateOutputs()
|
|||
output->pipeline()->applyPendingChanges();
|
||||
}
|
||||
}
|
||||
m_leaseDevice->setDrmMaster(true);
|
||||
// after (potential) lease offer changes, a done event needs to be sent
|
||||
// to signal clients to handle the changes
|
||||
m_leaseDevice->done();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -604,22 +590,12 @@ void DrmGpu::removeVirtualOutput(DrmVirtualOutput *output)
|
|||
}
|
||||
}
|
||||
|
||||
void DrmGpu::handleLeaseRequest(KWaylandServer::DrmLeaseV1Interface *leaseRequest)
|
||||
std::unique_ptr<DrmLease> DrmGpu::leaseOutputs(const QVector<DrmOutput *> &outputs)
|
||||
{
|
||||
QVector<uint32_t> objects;
|
||||
QVector<DrmOutput *> outputs;
|
||||
|
||||
const auto connectors = leaseRequest->connectors();
|
||||
for (KWaylandServer::DrmLeaseConnectorV1Interface *connector : connectors) {
|
||||
if (DrmOutput *output = findOutput(connector->id())) {
|
||||
if (output->lease()) {
|
||||
continue; // already leased
|
||||
}
|
||||
if (!output->addLeaseObjects(objects)) {
|
||||
leaseRequest->deny();
|
||||
return;
|
||||
}
|
||||
outputs << output;
|
||||
for (DrmOutput *output : outputs) {
|
||||
if (output->lease() || !output->addLeaseObjects(objects)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -631,31 +607,16 @@ void DrmGpu::handleLeaseRequest(KWaylandServer::DrmLeaseV1Interface *leaseReques
|
|||
for (const auto &res : qAsConst(objects)) {
|
||||
qCWarning(KWIN_DRM) << res;
|
||||
}
|
||||
leaseRequest->deny();
|
||||
return nullptr;
|
||||
} else {
|
||||
qCDebug(KWIN_DRM, "Created lease for %d resources:", objects.count());
|
||||
for (const auto &res : qAsConst(objects)) {
|
||||
qCDebug(KWIN_DRM) << res;
|
||||
}
|
||||
leaseRequest->grant(std::move(fd), lesseeId);
|
||||
for (const auto &output : qAsConst(outputs)) {
|
||||
output->leased(leaseRequest);
|
||||
}
|
||||
return std::make_unique<DrmLease>(this, std::move(fd), lesseeId, outputs);
|
||||
}
|
||||
}
|
||||
|
||||
void DrmGpu::handleLeaseRevoked(KWaylandServer::DrmLeaseV1Interface *lease)
|
||||
{
|
||||
const auto connectors = lease->connectors();
|
||||
for (KWaylandServer::DrmLeaseConnectorV1Interface *connector : connectors) {
|
||||
if (DrmOutput *output = findOutput(connector->id())) {
|
||||
output->leaseEnded();
|
||||
}
|
||||
}
|
||||
qCDebug(KWIN_DRM, "Revoking lease with leaseID %d", lease->lesseeId());
|
||||
drmModeRevokeLease(m_fd, lease->lesseeId());
|
||||
}
|
||||
|
||||
QVector<DrmVirtualOutput *> DrmGpu::virtualOutputs() const
|
||||
{
|
||||
return m_virtualOutputs;
|
||||
|
@ -817,4 +778,33 @@ void DrmGpu::recreateSurfaces()
|
|||
}
|
||||
}
|
||||
|
||||
DrmLease::DrmLease(DrmGpu *gpu, FileDescriptor &&fd, uint32_t lesseeId, const QVector<DrmOutput *> &outputs)
|
||||
: m_gpu(gpu)
|
||||
, m_fd(std::move(fd))
|
||||
, m_lesseeId(lesseeId)
|
||||
, m_outputs(outputs)
|
||||
{
|
||||
for (const auto output : m_outputs) {
|
||||
output->leased(this);
|
||||
}
|
||||
}
|
||||
|
||||
DrmLease::~DrmLease()
|
||||
{
|
||||
qCDebug(KWIN_DRM, "Revoking lease with leaseID %d", m_lesseeId);
|
||||
drmModeRevokeLease(m_gpu->fd(), m_lesseeId);
|
||||
for (const auto &output : m_outputs) {
|
||||
output->leaseEnded();
|
||||
}
|
||||
}
|
||||
|
||||
FileDescriptor &DrmLease::fd()
|
||||
{
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
uint32_t DrmLease::lesseeId() const
|
||||
{
|
||||
return m_lesseeId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "drm_pipeline.h"
|
||||
#include "utils/filedescriptor.h"
|
||||
|
||||
#include <QPointer>
|
||||
#include <QSize>
|
||||
|
@ -21,12 +22,6 @@
|
|||
|
||||
struct gbm_device;
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
class DrmLeaseDeviceV1Interface;
|
||||
class DrmLeaseV1Interface;
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -41,6 +36,26 @@ class DrmAbstractOutput;
|
|||
class DrmRenderBackend;
|
||||
class DrmVirtualOutput;
|
||||
|
||||
class DrmLease : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DrmLease(DrmGpu *gpu, FileDescriptor &&fd, uint32_t lesseeId, const QVector<DrmOutput *> &outputs);
|
||||
~DrmLease();
|
||||
|
||||
FileDescriptor &fd();
|
||||
uint32_t lesseeId() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void revokeRequested();
|
||||
|
||||
private:
|
||||
DrmGpu *const m_gpu;
|
||||
FileDescriptor m_fd;
|
||||
const uint32_t m_lesseeId;
|
||||
const QVector<DrmOutput *> m_outputs;
|
||||
};
|
||||
|
||||
class DrmGpu : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -87,6 +102,9 @@ public:
|
|||
void releaseBuffers();
|
||||
void recreateSurfaces();
|
||||
|
||||
FileDescriptor createNonMasterFd() const;
|
||||
std::unique_ptr<DrmLease> leaseOutputs(const QVector<DrmOutput *> &outputs);
|
||||
|
||||
Q_SIGNALS:
|
||||
void outputAdded(DrmAbstractOutput *output);
|
||||
void outputRemoved(DrmAbstractOutput *output);
|
||||
|
@ -102,9 +120,6 @@ private:
|
|||
DrmPipeline::Error testPipelines();
|
||||
QVector<DrmObject *> unusedObjects() const;
|
||||
|
||||
void handleLeaseRequest(KWaylandServer::DrmLeaseV1Interface *leaseRequest);
|
||||
void handleLeaseRevoked(KWaylandServer::DrmLeaseV1Interface *lease);
|
||||
|
||||
static void pageFlipHandler(int fd, unsigned int sequence, unsigned int sec, unsigned int usec, unsigned int crtc_id, void *user_data);
|
||||
|
||||
const int m_fd;
|
||||
|
@ -128,7 +143,6 @@ private:
|
|||
|
||||
QVector<DrmOutput *> m_drmOutputs;
|
||||
QVector<DrmVirtualOutput *> m_virtualOutputs;
|
||||
std::unique_ptr<KWaylandServer::DrmLeaseDeviceV1Interface> m_leaseDevice;
|
||||
|
||||
std::unique_ptr<QSocketNotifier> m_socketNotifier;
|
||||
QSize m_cursorSize;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "drm_layer.h"
|
||||
#include "drm_logging.h"
|
||||
#include "kwinglutils.h"
|
||||
#include "wayland/drmleasedevice_v1_interface.h"
|
||||
// Qt
|
||||
#include <QCryptographicHash>
|
||||
#include <QMatrix4x4>
|
||||
|
@ -40,7 +39,7 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
DrmOutput::DrmOutput(DrmPipeline *pipeline, KWaylandServer::DrmLeaseDeviceV1Interface *leaseDevice)
|
||||
DrmOutput::DrmOutput(DrmPipeline *pipeline)
|
||||
: DrmAbstractOutput(pipeline->connector()->gpu())
|
||||
, m_pipeline(pipeline)
|
||||
, m_connector(pipeline->connector())
|
||||
|
@ -95,13 +94,7 @@ DrmOutput::DrmOutput(DrmPipeline *pipeline, KWaylandServer::DrmLeaseDeviceV1Inte
|
|||
setDrmDpmsMode(DpmsMode::Off);
|
||||
});
|
||||
|
||||
if (conn->isNonDesktop()) {
|
||||
m_offer = std::make_unique<KWaylandServer::DrmLeaseConnectorV1Interface>(
|
||||
leaseDevice,
|
||||
conn->id(),
|
||||
conn->modelName(),
|
||||
QStringLiteral("%1 %2").arg(conn->edid()->manufacturerString(), conn->modelName()));
|
||||
} else {
|
||||
if (!conn->isNonDesktop()) {
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &DrmOutput::updateCursor);
|
||||
connect(Cursors::self(), &Cursors::hiddenChanged, this, &DrmOutput::updateCursor);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, &DrmOutput::moveCursor);
|
||||
|
@ -115,7 +108,6 @@ DrmOutput::~DrmOutput()
|
|||
|
||||
bool DrmOutput::addLeaseObjects(QVector<uint32_t> &objectList)
|
||||
{
|
||||
Q_ASSERT(m_offer);
|
||||
if (!m_pipeline->crtc()) {
|
||||
qCWarning(KWIN_DRM) << "Can't lease connector: No suitable crtc available";
|
||||
return false;
|
||||
|
@ -129,20 +121,18 @@ bool DrmOutput::addLeaseObjects(QVector<uint32_t> &objectList)
|
|||
return true;
|
||||
}
|
||||
|
||||
void DrmOutput::leased(KWaylandServer::DrmLeaseV1Interface *lease)
|
||||
void DrmOutput::leased(DrmLease *lease)
|
||||
{
|
||||
Q_ASSERT(m_offer);
|
||||
m_lease = lease;
|
||||
}
|
||||
|
||||
void DrmOutput::leaseEnded()
|
||||
{
|
||||
Q_ASSERT(m_offer);
|
||||
qCDebug(KWIN_DRM) << "ended lease for connector" << m_pipeline->connector()->id();
|
||||
m_lease = nullptr;
|
||||
}
|
||||
|
||||
KWaylandServer::DrmLeaseV1Interface *DrmOutput::lease() const
|
||||
DrmLease *DrmOutput::lease() const
|
||||
{
|
||||
return m_lease;
|
||||
}
|
||||
|
|
|
@ -20,13 +20,6 @@
|
|||
#include <chrono>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
class DrmLeaseConnectorV1Interface;
|
||||
class DrmLeaseDeviceV1Interface;
|
||||
class DrmLeaseV1Interface;
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -36,12 +29,13 @@ class DrmPipeline;
|
|||
class DumbSwapchain;
|
||||
class GLTexture;
|
||||
class RenderTarget;
|
||||
class DrmLease;
|
||||
|
||||
class KWIN_EXPORT DrmOutput : public DrmAbstractOutput
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DrmOutput(DrmPipeline *pipeline, KWaylandServer::DrmLeaseDeviceV1Interface *leaseDevice);
|
||||
DrmOutput(DrmPipeline *pipeline);
|
||||
~DrmOutput() override;
|
||||
|
||||
DrmConnector *connector() const;
|
||||
|
@ -60,9 +54,9 @@ public:
|
|||
void updateCursor();
|
||||
void moveCursor();
|
||||
|
||||
KWaylandServer::DrmLeaseV1Interface *lease() const;
|
||||
DrmLease *lease() const;
|
||||
bool addLeaseObjects(QVector<uint32_t> &objectList);
|
||||
void leased(KWaylandServer::DrmLeaseV1Interface *lease);
|
||||
void leased(DrmLease *lease);
|
||||
void leaseEnded();
|
||||
|
||||
void setColorTransformation(const std::shared_ptr<ColorTransformation> &transformation) override;
|
||||
|
@ -84,8 +78,7 @@ private:
|
|||
bool m_cursorTextureDirty = true;
|
||||
std::unique_ptr<GLTexture> m_cursorTexture;
|
||||
QTimer m_turnOffTimer;
|
||||
std::unique_ptr<KWaylandServer::DrmLeaseConnectorV1Interface> m_offer;
|
||||
KWaylandServer::DrmLeaseV1Interface *m_lease = nullptr;
|
||||
DrmLease *m_lease = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ target_sources(kwin PRIVATE
|
|||
display.cpp
|
||||
dpms_interface.cpp
|
||||
drmclientbuffer.cpp
|
||||
drmleasedevice_v1_interface.cpp
|
||||
drmlease_v1_interface.cpp
|
||||
fakeinput_interface.cpp
|
||||
filtered_display.cpp
|
||||
idle_interface.cpp
|
||||
|
|
456
src/wayland/drmlease_v1_interface.cpp
Normal file
456
src/wayland/drmlease_v1_interface.cpp
Normal file
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021-2022 Xaver Hugl <xaver.hugl@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "drmlease_v1_interface.h"
|
||||
#include "display.h"
|
||||
#include "drmlease_v1_interface_p.h"
|
||||
#include "utils.h"
|
||||
#include "utils/common.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
static const quint32 s_version = 1;
|
||||
|
||||
DrmLeaseManagerV1::DrmLeaseManagerV1(KWin::DrmBackend *backend, Display *display, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_backend(backend)
|
||||
, m_display(display)
|
||||
{
|
||||
const auto &gpus = m_backend->gpus();
|
||||
for (const auto &gpu : gpus) {
|
||||
addGpu(gpu.get());
|
||||
}
|
||||
connect(m_backend, &KWin::DrmBackend::gpuAdded, this, &DrmLeaseManagerV1::addGpu);
|
||||
connect(m_backend, &KWin::DrmBackend::gpuRemoved, this, &DrmLeaseManagerV1::removeGpu);
|
||||
connect(m_backend, &KWin::DrmBackend::outputsQueried, this, &DrmLeaseManagerV1::handleOutputsQueried);
|
||||
connect(m_backend, &KWin::DrmBackend::activeChanged, this, [this]() {
|
||||
if (!m_backend->isActive()) {
|
||||
for (const auto device : m_leaseDevices) {
|
||||
device->setDrmMaster(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DrmLeaseManagerV1::~DrmLeaseManagerV1()
|
||||
{
|
||||
for (const auto device : m_leaseDevices) {
|
||||
device->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseManagerV1::addGpu(KWin::DrmGpu *gpu)
|
||||
{
|
||||
m_leaseDevices[gpu] = new DrmLeaseDeviceV1Interface(m_display, gpu);
|
||||
}
|
||||
|
||||
void DrmLeaseManagerV1::removeGpu(KWin::DrmGpu *gpu)
|
||||
{
|
||||
if (auto device = m_leaseDevices.take(gpu)) {
|
||||
device->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseManagerV1::handleOutputsQueried()
|
||||
{
|
||||
for (const auto device : m_leaseDevices) {
|
||||
device->done();
|
||||
device->setDrmMaster(m_backend->isActive());
|
||||
}
|
||||
}
|
||||
|
||||
DrmLeaseDeviceV1Interface::DrmLeaseDeviceV1Interface(Display *display, KWin::DrmGpu *gpu)
|
||||
: QtWaylandServer::wp_drm_lease_device_v1(*display, s_version)
|
||||
, m_gpu(gpu)
|
||||
{
|
||||
const auto outputs = gpu->drmOutputs();
|
||||
for (const auto output : outputs) {
|
||||
addOutput(output);
|
||||
}
|
||||
connect(gpu, &KWin::DrmGpu::outputAdded, this, &DrmLeaseDeviceV1Interface::addOutput);
|
||||
connect(gpu, &KWin::DrmGpu::outputRemoved, this, &DrmLeaseDeviceV1Interface::removeOutput);
|
||||
}
|
||||
|
||||
DrmLeaseDeviceV1Interface::~DrmLeaseDeviceV1Interface()
|
||||
{
|
||||
for (auto it = m_connectors.begin(); it != m_connectors.end(); it++) {
|
||||
removeOutput(it.key());
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::addOutput(KWin::DrmAbstractOutput *output)
|
||||
{
|
||||
KWin::DrmOutput *drmOutput = qobject_cast<KWin::DrmOutput *>(output);
|
||||
if (!drmOutput || !drmOutput->isNonDesktop()) {
|
||||
return;
|
||||
}
|
||||
auto connector = new DrmLeaseConnectorV1Interface(this, drmOutput);
|
||||
m_connectors[drmOutput] = connector;
|
||||
|
||||
if (m_hasDrmMaster) {
|
||||
offerConnector(connector);
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::removeOutput(KWin::DrmAbstractOutput *output)
|
||||
{
|
||||
const auto it = m_connectors.find(output);
|
||||
if (it != m_connectors.end()) {
|
||||
DrmLeaseConnectorV1Interface *connector = *it;
|
||||
connector->withdraw();
|
||||
for (const auto &lease : qAsConst(m_leases)) {
|
||||
if (lease->connectors().contains(connector)) {
|
||||
lease->connectors().removeOne(connector);
|
||||
lease->revoke();
|
||||
}
|
||||
}
|
||||
for (const auto &leaseRequest : qAsConst(m_leaseRequests)) {
|
||||
if (leaseRequest->connectors().contains(connector)) {
|
||||
leaseRequest->invalidate();
|
||||
}
|
||||
}
|
||||
m_connectors.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::setDrmMaster(bool hasDrmMaster)
|
||||
{
|
||||
if (hasDrmMaster == m_hasDrmMaster) {
|
||||
return;
|
||||
}
|
||||
if (hasDrmMaster) {
|
||||
// send pending drm fds
|
||||
while (!m_pendingFds.isEmpty()) {
|
||||
KWin::FileDescriptor fd = m_gpu->createNonMasterFd();
|
||||
send_drm_fd(m_pendingFds.dequeue(), fd.get());
|
||||
}
|
||||
// offer all connectors again
|
||||
for (const auto connector : qAsConst(m_connectors)) {
|
||||
offerConnector(connector);
|
||||
}
|
||||
} else {
|
||||
// withdraw all connectors
|
||||
for (const auto connector : qAsConst(m_connectors)) {
|
||||
connector->withdraw();
|
||||
}
|
||||
// and revoke all leases
|
||||
for (const auto &lease : qAsConst(m_leases)) {
|
||||
lease->revoke();
|
||||
}
|
||||
}
|
||||
m_hasDrmMaster = hasDrmMaster;
|
||||
done();
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::done()
|
||||
{
|
||||
const auto resources = resourceMap();
|
||||
for (const auto resource : resources) {
|
||||
send_done(resource->handle);
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::remove()
|
||||
{
|
||||
for (const auto &lease : qAsConst(m_leases)) {
|
||||
lease->deny();
|
||||
}
|
||||
for (const auto connector : qAsConst(m_connectors)) {
|
||||
connector->withdraw();
|
||||
}
|
||||
for (const auto &request : qAsConst(m_leaseRequests)) {
|
||||
request->invalidate();
|
||||
}
|
||||
done();
|
||||
globalRemove();
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::addLeaseRequest(DrmLeaseRequestV1Interface *leaseRequest)
|
||||
{
|
||||
m_leaseRequests.push_back(leaseRequest);
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::removeLeaseRequest(DrmLeaseRequestV1Interface *leaseRequest)
|
||||
{
|
||||
m_leaseRequests.removeOne(leaseRequest);
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::addLease(DrmLeaseV1Interface *lease)
|
||||
{
|
||||
m_leases.push_back(lease);
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::removeLease(DrmLeaseV1Interface *lease)
|
||||
{
|
||||
m_leases.removeOne(lease);
|
||||
}
|
||||
|
||||
bool DrmLeaseDeviceV1Interface::hasDrmMaster() const
|
||||
{
|
||||
return m_hasDrmMaster;
|
||||
}
|
||||
|
||||
KWin::DrmGpu *DrmLeaseDeviceV1Interface::gpu() const
|
||||
{
|
||||
return m_gpu;
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::offerConnector(DrmLeaseConnectorV1Interface *connector)
|
||||
{
|
||||
for (const auto &resource : resourceMap()) {
|
||||
auto connectorResource = connector->add(resource->client(), 0, resource->version());
|
||||
send_connector(resource->handle, connectorResource->handle);
|
||||
connector->send(connectorResource->handle);
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::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;
|
||||
}
|
||||
m_leaseRequests << new DrmLeaseRequestV1Interface(this, requestResource);
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::wp_drm_lease_device_v1_release(Resource *resource)
|
||||
{
|
||||
send_released(resource->handle);
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::wp_drm_lease_device_v1_bind_resource(Resource *resource)
|
||||
{
|
||||
if (isGlobalRemoved()) {
|
||||
return;
|
||||
}
|
||||
if (!m_hasDrmMaster) {
|
||||
m_pendingFds << resource->handle;
|
||||
return;
|
||||
}
|
||||
KWin::FileDescriptor fd = m_gpu->createNonMasterFd();
|
||||
send_drm_fd(resource->handle, fd.get());
|
||||
for (const auto connector : qAsConst(m_connectors)) {
|
||||
if (!connector->withdrawn()) {
|
||||
auto connectorResource = connector->add(resource->client(), 0, s_version);
|
||||
send_connector(resource->handle, connectorResource->handle);
|
||||
connector->send(connectorResource->handle);
|
||||
}
|
||||
}
|
||||
send_done(resource->handle);
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::wp_drm_lease_device_v1_destroy_global()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
DrmLeaseConnectorV1Interface::DrmLeaseConnectorV1Interface(DrmLeaseDeviceV1Interface *leaseDevice, KWin::DrmOutput *output)
|
||||
: wp_drm_lease_connector_v1()
|
||||
, m_device(leaseDevice)
|
||||
, m_output(output)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t DrmLeaseConnectorV1Interface::id() const
|
||||
{
|
||||
return m_output->connector()->id();
|
||||
}
|
||||
|
||||
DrmLeaseDeviceV1Interface *DrmLeaseConnectorV1Interface::device() const
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
KWin::DrmOutput *DrmLeaseConnectorV1Interface::output() const
|
||||
{
|
||||
return m_output;
|
||||
}
|
||||
|
||||
bool DrmLeaseConnectorV1Interface::withdrawn() const
|
||||
{
|
||||
return m_withdrawn;
|
||||
}
|
||||
|
||||
void DrmLeaseConnectorV1Interface::send(wl_resource *resource)
|
||||
{
|
||||
m_withdrawn = false;
|
||||
send_connector_id(resource, m_output->connector()->id());
|
||||
send_name(resource, m_output->name());
|
||||
send_description(resource, m_output->description());
|
||||
send_done(resource);
|
||||
}
|
||||
|
||||
void DrmLeaseConnectorV1Interface::withdraw()
|
||||
{
|
||||
if (!m_withdrawn) {
|
||||
m_withdrawn = true;
|
||||
for (const auto &resource : resourceMap()) {
|
||||
send_withdrawn(resource->handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseConnectorV1Interface::wp_drm_lease_connector_v1_destroy(Resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
DrmLeaseRequestV1Interface::DrmLeaseRequestV1Interface(DrmLeaseDeviceV1Interface *device, wl_resource *resource)
|
||||
: wp_drm_lease_request_v1(resource)
|
||||
, m_device(device)
|
||||
{
|
||||
}
|
||||
|
||||
DrmLeaseRequestV1Interface::~DrmLeaseRequestV1Interface()
|
||||
{
|
||||
m_device->removeLeaseRequest(this);
|
||||
}
|
||||
|
||||
QVector<DrmLeaseConnectorV1Interface *> DrmLeaseRequestV1Interface::connectors() const
|
||||
{
|
||||
return m_connectors;
|
||||
}
|
||||
|
||||
void DrmLeaseRequestV1Interface::invalidate()
|
||||
{
|
||||
m_connectors.clear();
|
||||
m_invalid = true;
|
||||
}
|
||||
|
||||
void DrmLeaseRequestV1Interface::wp_drm_lease_request_v1_request_connector(Resource *resource, struct ::wl_resource *connector_handle)
|
||||
{
|
||||
Q_UNUSED(resource);
|
||||
if (auto connector = resource_cast<DrmLeaseConnectorV1Interface *>(connector_handle)) {
|
||||
if (connector->device() != m_device) {
|
||||
wl_resource_post_error(resource->handle, WP_DRM_LEASE_REQUEST_V1_ERROR_WRONG_DEVICE, "Requested connector from invalid lease device");
|
||||
} else if (connector->withdrawn()) {
|
||||
qCWarning(KWIN_CORE) << "DrmLease: withdrawn connector requested";
|
||||
} else if (m_connectors.contains(connector)) {
|
||||
wl_resource_post_error(resource->handle, WP_DRM_LEASE_REQUEST_V1_ERROR_DUPLICATE_CONNECTOR, "Requested connector twice");
|
||||
} else {
|
||||
m_connectors << connector;
|
||||
}
|
||||
} else {
|
||||
qCWarning(KWIN_CORE, "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(m_device, m_connectors, leaseResource);
|
||||
m_device->addLease(lease);
|
||||
if (!m_device->hasDrmMaster()) {
|
||||
qCWarning(KWIN_CORE) << "DrmLease: rejecting lease request without drm master";
|
||||
lease->deny();
|
||||
} else if (m_invalid) {
|
||||
qCWarning(KWIN_CORE) << "DrmLease: rejecting lease request with a withdrawn connector";
|
||||
lease->deny();
|
||||
} else if (m_connectors.isEmpty()) {
|
||||
wl_resource_post_error(resource->handle, WP_DRM_LEASE_REQUEST_V1_ERROR_EMPTY_LEASE, "Requested lease without connectors");
|
||||
} else {
|
||||
QVector<KWin::DrmOutput *> outputs;
|
||||
for (const auto &connector : m_connectors) {
|
||||
outputs.push_back(connector->output());
|
||||
}
|
||||
auto drmLease = m_device->gpu()->leaseOutputs(outputs);
|
||||
if (drmLease) {
|
||||
lease->grant(std::move(drmLease));
|
||||
} else {
|
||||
lease->deny();
|
||||
}
|
||||
}
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
void DrmLeaseRequestV1Interface::wp_drm_lease_request_v1_destroy_resource(Resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
delete this;
|
||||
}
|
||||
|
||||
DrmLeaseV1Interface::DrmLeaseV1Interface(DrmLeaseDeviceV1Interface *device, const QVector<DrmLeaseConnectorV1Interface *> &connectors, wl_resource *resource)
|
||||
: wp_drm_lease_v1(resource)
|
||||
, m_device(device)
|
||||
, m_connectors(connectors)
|
||||
{
|
||||
}
|
||||
|
||||
DrmLeaseV1Interface::~DrmLeaseV1Interface()
|
||||
{
|
||||
if (m_lease) {
|
||||
revoke();
|
||||
} else {
|
||||
deny();
|
||||
}
|
||||
m_device->removeLease(this);
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::grant(std::unique_ptr<KWin::DrmLease> &&lease)
|
||||
{
|
||||
KWin::FileDescriptor tmp = std::move(lease->fd());
|
||||
send_lease_fd(tmp.get());
|
||||
m_lease = std::move(lease);
|
||||
connect(lease.get(), &KWin::DrmLease::revokeRequested, this, &DrmLeaseV1Interface::revoke);
|
||||
for (const auto &connector : qAsConst(m_connectors)) {
|
||||
connector->withdraw();
|
||||
}
|
||||
m_device->done();
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::deny()
|
||||
{
|
||||
Q_ASSERT(!m_lease);
|
||||
if (!m_finished) {
|
||||
m_finished = true;
|
||||
send_finished();
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::revoke()
|
||||
{
|
||||
Q_ASSERT(m_lease);
|
||||
if (!m_finished) {
|
||||
m_finished = true;
|
||||
send_finished();
|
||||
}
|
||||
m_lease.reset();
|
||||
// check if we should offer connectors again
|
||||
if (m_device->hasDrmMaster()) {
|
||||
for (const auto &connector : qAsConst(m_connectors)) {
|
||||
m_device->offerConnector(connector);
|
||||
}
|
||||
m_device->done();
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::wp_drm_lease_v1_destroy(Resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::wp_drm_lease_v1_destroy_resource(Resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
delete this;
|
||||
}
|
||||
|
||||
QVector<DrmLeaseConnectorV1Interface *> DrmLeaseV1Interface::connectors() const
|
||||
{
|
||||
return m_connectors;
|
||||
}
|
||||
|
||||
}
|
42
src/wayland/drmlease_v1_interface.h
Normal file
42
src/wayland/drmlease_v1_interface.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021-2022 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 <QHash>
|
||||
#include <QObject>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class DrmBackend;
|
||||
class DrmGpu;
|
||||
}
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class DrmLeaseDeviceV1Interface;
|
||||
class DrmLeaseConnectorV1Interface;
|
||||
class Display;
|
||||
|
||||
class DrmLeaseManagerV1 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DrmLeaseManagerV1(KWin::DrmBackend *backend, Display *display, QObject *parent = nullptr);
|
||||
~DrmLeaseManagerV1();
|
||||
|
||||
private:
|
||||
void addGpu(KWin::DrmGpu *gpu);
|
||||
void removeGpu(KWin::DrmGpu *gpu);
|
||||
void handleOutputsQueried();
|
||||
|
||||
KWin::DrmBackend *const m_backend;
|
||||
Display *const m_display;
|
||||
QHash<KWin::DrmGpu *, DrmLeaseDeviceV1Interface *> m_leaseDevices;
|
||||
};
|
||||
}
|
127
src/wayland/drmlease_v1_interface_p.h
Normal file
127
src/wayland/drmlease_v1_interface_p.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021-2022 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 "backends/drm/drm_backend.h"
|
||||
#include "backends/drm/drm_connector.h"
|
||||
#include "backends/drm/drm_gpu.h"
|
||||
#include "backends/drm/drm_output.h"
|
||||
#include "utils/filedescriptor.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QQueue>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class Display;
|
||||
class DrmLeaseConnectorV1Interface;
|
||||
class DrmLeaseRequestV1Interface;
|
||||
class DrmLeaseV1Interface;
|
||||
class DrmLeaseConnectorV1InterfacePrivate;
|
||||
|
||||
class DrmLeaseDeviceV1Interface : public QObject, public QtWaylandServer::wp_drm_lease_device_v1
|
||||
{
|
||||
public:
|
||||
explicit DrmLeaseDeviceV1Interface(Display *display, KWin::DrmGpu *gpu);
|
||||
~DrmLeaseDeviceV1Interface();
|
||||
|
||||
void addOutput(KWin::DrmAbstractOutput *output);
|
||||
void removeOutput(KWin::DrmAbstractOutput *output);
|
||||
void setDrmMaster(bool hasDrmMaster);
|
||||
void done();
|
||||
void remove();
|
||||
void addLeaseRequest(DrmLeaseRequestV1Interface *leaseRequest);
|
||||
void removeLeaseRequest(DrmLeaseRequestV1Interface *leaseRequest);
|
||||
void addLease(DrmLeaseV1Interface *lease);
|
||||
void removeLease(DrmLeaseV1Interface *lease);
|
||||
void offerConnector(DrmLeaseConnectorV1Interface *connector);
|
||||
|
||||
bool hasDrmMaster() const;
|
||||
KWin::DrmGpu *gpu() const;
|
||||
|
||||
private:
|
||||
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_global() override;
|
||||
|
||||
KWin::DrmGpu *const m_gpu;
|
||||
bool m_hasDrmMaster = true;
|
||||
QHash<KWin::DrmAbstractOutput *, DrmLeaseConnectorV1Interface *> m_connectors;
|
||||
QQueue<wl_resource *> m_pendingFds;
|
||||
QVector<DrmLeaseRequestV1Interface *> m_leaseRequests;
|
||||
QVector<DrmLeaseV1Interface *> m_leases;
|
||||
};
|
||||
|
||||
class DrmLeaseConnectorV1Interface : public QObject, public QtWaylandServer::wp_drm_lease_connector_v1
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DrmLeaseConnectorV1Interface(DrmLeaseDeviceV1Interface *leaseDevice, KWin::DrmOutput *output);
|
||||
|
||||
uint32_t id() const;
|
||||
void send(wl_resource *resource);
|
||||
void withdraw();
|
||||
|
||||
DrmLeaseDeviceV1Interface *device() const;
|
||||
KWin::DrmOutput *output() const;
|
||||
bool withdrawn() const;
|
||||
|
||||
private:
|
||||
void wp_drm_lease_connector_v1_destroy(Resource *resource) override;
|
||||
|
||||
QPointer<DrmLeaseDeviceV1Interface> m_device;
|
||||
bool m_withdrawn = false;
|
||||
KWin::DrmOutput *const m_output;
|
||||
};
|
||||
|
||||
class DrmLeaseRequestV1Interface : public QtWaylandServer::wp_drm_lease_request_v1
|
||||
{
|
||||
public:
|
||||
DrmLeaseRequestV1Interface(DrmLeaseDeviceV1Interface *device, wl_resource *resource);
|
||||
~DrmLeaseRequestV1Interface();
|
||||
|
||||
QVector<DrmLeaseConnectorV1Interface *> connectors() const;
|
||||
void invalidate();
|
||||
|
||||
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;
|
||||
|
||||
DrmLeaseDeviceV1Interface *const m_device;
|
||||
QVector<DrmLeaseConnectorV1Interface *> m_connectors;
|
||||
bool m_invalid = false;
|
||||
};
|
||||
|
||||
class DrmLeaseV1Interface : public QObject, private QtWaylandServer::wp_drm_lease_v1
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DrmLeaseV1Interface(DrmLeaseDeviceV1Interface *device, const QVector<DrmLeaseConnectorV1Interface *> &connectors, wl_resource *resource);
|
||||
~DrmLeaseV1Interface();
|
||||
|
||||
void grant(std::unique_ptr<KWin::DrmLease> &&lease);
|
||||
void deny();
|
||||
void revoke();
|
||||
|
||||
QVector<DrmLeaseConnectorV1Interface *> connectors() const;
|
||||
|
||||
private:
|
||||
DrmLeaseDeviceV1Interface *m_device;
|
||||
QVector<DrmLeaseConnectorV1Interface *> m_connectors;
|
||||
std::unique_ptr<KWin::DrmLease> m_lease;
|
||||
bool m_finished = false;
|
||||
|
||||
void wp_drm_lease_v1_destroy(Resource *resource) override;
|
||||
void wp_drm_lease_v1_destroy_resource(Resource *resource) override;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,407 +0,0 @@
|
|||
/*
|
||||
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 "display.h"
|
||||
#include "drmleasedevice_v1_interface_p.h"
|
||||
#include "utils.h"
|
||||
#include "utils/common.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
static const quint32 s_version = 1;
|
||||
|
||||
DrmLeaseDeviceV1Interface::DrmLeaseDeviceV1Interface(Display *display, std::function<KWin::FileDescriptor()> createNonMasterFd)
|
||||
: d(new DrmLeaseDeviceV1InterfacePrivate(display, this, createNonMasterFd))
|
||||
{
|
||||
}
|
||||
|
||||
DrmLeaseDeviceV1Interface::~DrmLeaseDeviceV1Interface()
|
||||
{
|
||||
d->remove();
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::setDrmMaster(bool hasDrmMaster)
|
||||
{
|
||||
if (hasDrmMaster == d->hasDrmMaster) {
|
||||
return;
|
||||
}
|
||||
if (hasDrmMaster) {
|
||||
// send pending drm fds
|
||||
while (!d->pendingFds.isEmpty()) {
|
||||
KWin::FileDescriptor fd = d->createNonMasterFd();
|
||||
d->send_drm_fd(d->pendingFds.dequeue(), fd.get());
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
d->hasDrmMaster = hasDrmMaster;
|
||||
done();
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1Interface::done()
|
||||
{
|
||||
const auto resources = d->resourceMap();
|
||||
for (const auto resource : resources) {
|
||||
d->send_done(resource->handle);
|
||||
}
|
||||
}
|
||||
|
||||
DrmLeaseDeviceV1InterfacePrivate::DrmLeaseDeviceV1InterfacePrivate(Display *display, DrmLeaseDeviceV1Interface *device, std::function<KWin::FileDescriptor()> 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();
|
||||
}
|
||||
q->done();
|
||||
globalRemove();
|
||||
}
|
||||
|
||||
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 (isGlobalRemoved()) {
|
||||
return;
|
||||
}
|
||||
if (!hasDrmMaster) {
|
||||
pendingFds << resource->handle;
|
||||
return;
|
||||
}
|
||||
KWin::FileDescriptor fd = createNonMasterFd();
|
||||
send_drm_fd(resource->handle, fd.get());
|
||||
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);
|
||||
}
|
||||
}
|
||||
send_done(resource->handle);
|
||||
}
|
||||
|
||||
void DrmLeaseDeviceV1InterfacePrivate::wp_drm_lease_device_v1_destroy_global()
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DrmLeaseConnectorV1Interface::id() const
|
||||
{
|
||||
return d->connectorId;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(KWIN_CORE) << "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(KWIN_CORE, "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(KWIN_CORE) << "DrmLease: rejecting lease request without drm master";
|
||||
lease->deny();
|
||||
} else if (invalid) {
|
||||
qCWarning(KWIN_CORE) << "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;
|
||||
Q_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()
|
||||
{
|
||||
if (d->lesseeId) {
|
||||
revoke();
|
||||
} else {
|
||||
deny();
|
||||
}
|
||||
|
||||
d->device->leases.removeOne(this);
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::grant(KWin::FileDescriptor &&leaseFd, uint32_t lesseeId)
|
||||
{
|
||||
KWin::FileDescriptor tmp = std::move(leaseFd);
|
||||
d->send_lease_fd(tmp.get());
|
||||
d->lesseeId = lesseeId;
|
||||
for (const auto &connector : qAsConst(d->connectors)) {
|
||||
DrmLeaseConnectorV1InterfacePrivate::get(connector)->withdraw();
|
||||
}
|
||||
d->device->q->done();
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::deny()
|
||||
{
|
||||
if (!d->finished) {
|
||||
d->finished = true;
|
||||
d->send_finished();
|
||||
}
|
||||
}
|
||||
|
||||
void DrmLeaseV1Interface::revoke()
|
||||
{
|
||||
Q_ASSERT(d->lesseeId != 0);
|
||||
if (!d->finished) {
|
||||
d->finished = true;
|
||||
d->send_finished();
|
||||
}
|
||||
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) {
|
||||
d->device->q->done();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
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 "kwin_export.h"
|
||||
#include "utils/filedescriptor.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 KWIN_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<KWin::FileDescriptor()> createNonMasterFd);
|
||||
~DrmLeaseDeviceV1Interface() override;
|
||||
|
||||
/**
|
||||
* Must be called by the compositor when it loses or gains drm master
|
||||
*/
|
||||
void setDrmMaster(bool hasDrmMaster);
|
||||
|
||||
/**
|
||||
* Must be called after connectors have been added or removed
|
||||
*/
|
||||
void done();
|
||||
|
||||
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 KWIN_EXPORT DrmLeaseConnectorV1Interface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DrmLeaseConnectorV1Interface(DrmLeaseDeviceV1Interface *leaseDevice, uint32_t id, const QString &name, const QString &description);
|
||||
~DrmLeaseConnectorV1Interface() override;
|
||||
|
||||
uint32_t id() const;
|
||||
|
||||
static DrmLeaseConnectorV1Interface *get(wl_resource *resource);
|
||||
|
||||
private:
|
||||
friend class DrmLeaseConnectorV1InterfacePrivate;
|
||||
std::unique_ptr<DrmLeaseConnectorV1InterfacePrivate> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a lease request or active lease
|
||||
*/
|
||||
class KWIN_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(KWin::FileDescriptor &&leaseFd, uint32_t lesseeId);
|
||||
|
||||
/**
|
||||
* Deny the lease request. The compositor may call this in response to
|
||||
* DrmLeaseDeviceV1Interface::leaseRequested
|
||||
*/
|
||||
void deny();
|
||||
|
||||
/**
|
||||
* revoke a granted lease request and offer the leased connectors again
|
||||
*/
|
||||
void revoke();
|
||||
|
||||
/**
|
||||
* 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;
|
||||
std::unique_ptr<DrmLeaseV1InterfacePrivate> d;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
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 "utils/filedescriptor.h"
|
||||
#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<KWin::FileDescriptor()> 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<KWin::FileDescriptor()> 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_global() 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <config-kwin.h>
|
||||
|
||||
#include "backends/drm/drm_backend.h"
|
||||
#include "composite.h"
|
||||
#include "core/output.h"
|
||||
#include "core/platform.h"
|
||||
|
@ -31,6 +32,7 @@
|
|||
#include "wayland/datasource_interface.h"
|
||||
#include "wayland/display.h"
|
||||
#include "wayland/dpms_interface.h"
|
||||
#include "wayland/drmlease_v1_interface.h"
|
||||
#include "wayland/filtered_display.h"
|
||||
#include "wayland/idle_interface.h"
|
||||
#include "wayland/idleinhibit_v1_interface.h"
|
||||
|
@ -563,6 +565,11 @@ void WaylandServer::initWorkspace()
|
|||
if (hasScreenLockerIntegration()) {
|
||||
initScreenLocker();
|
||||
}
|
||||
|
||||
if (auto backend = qobject_cast<DrmBackend *>(kwinApp()->platform())) {
|
||||
m_leaseManager = new KWaylandServer::DrmLeaseManagerV1(backend, m_display, m_display);
|
||||
}
|
||||
|
||||
Q_EMIT initialized();
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ class KeyboardShortcutsInhibitManagerV1Interface;
|
|||
class XdgDecorationManagerV1Interface;
|
||||
class XWaylandKeyboardGrabManagerV1Interface;
|
||||
class ContentTypeManagerV1Interface;
|
||||
class DrmLeaseManagerV1;
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
|
@ -293,6 +294,7 @@ private:
|
|||
InitializationFlags m_initFlags;
|
||||
QHash<Output *, KWaylandServer::OutputInterface *> m_waylandOutputs;
|
||||
QHash<Output *, KWaylandServer::OutputDeviceV2Interface *> m_waylandOutputDevices;
|
||||
KWaylandServer::DrmLeaseManagerV1 *m_leaseManager = nullptr;
|
||||
KWIN_SINGLETON(WaylandServer)
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue