diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 5e2fedd57db..01ff47eed4e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -167,8 +167,12 @@ void CMonitor::onConnect(bool noRule) { if (output->nonDesktop) { Debug::log(LOG, "Not configuring non-desktop output"); - if (PROTO::lease) - PROTO::lease->offer(self.lock()); + + for (auto& lease : PROTO::lease) { + if (lease.second && output->getBackend() == lease.second->getBackend()) { + lease.second->offer(self.lock()); + } + } return; } diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 06987daeb7d..71ed549eba5 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -197,10 +197,12 @@ CProtocolManager::CProtocolManager() { if (b->type() != Aquamarine::AQ_BACKEND_DRM) continue; - PROTO::lease = makeUnique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); - if (*PENABLEEXPLICIT) + auto lease = makeShared(&wp_drm_lease_device_v1_interface, 1, "DRMLease", b); + if (lease->good()) + PROTO::lease.emplace(lease->getDeviceName(), lease); + + if (*PENABLEEXPLICIT && !PROTO::sync) PROTO::sync = makeUnique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); - break; } if (g_pHyprOpenGL->getDRMFormats().size() > 0) { @@ -272,7 +274,9 @@ CProtocolManager::~CProtocolManager() { PROTO::xxColorManagement.reset(); PROTO::frogColorManagement.reset(); - PROTO::lease.reset(); + for (auto& lease : PROTO::lease) { + lease.second.reset(); + } PROTO::sync.reset(); PROTO::mesaDRM.reset(); PROTO::linuxDma.reset(); diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index e70f0441508..b28bd73d86f 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -1,7 +1,9 @@ #include "DRMLease.hpp" #include "../Compositor.hpp" #include "../helpers/Monitor.hpp" +#include "drm-lease-v1.hpp" #include "managers/eventLoop/EventLoopManager.hpp" +#include "protocols/WaylandProtocol.hpp" #include #include using namespace Hyprutils::OS; @@ -10,12 +12,18 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPsetOnDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); }); - resource->setDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); }); - parent = request->parent; requested = request->requested; + resource->setOnDestroy([this](CWpDrmLeaseV1* r) { + if (parent && PROTO::lease.contains(parent->deviceName)) + PROTO::lease[parent->deviceName]->destroyResource(this); + }); + resource->setDestroy([this](CWpDrmLeaseV1* r) { + if (parent && PROTO::lease.contains(parent->deviceName)) + PROTO::lease[parent->deviceName]->destroyResource(this); + }); + for (auto const& m : requested) { if (!m->monitor || m->monitor->isBeingLeased) { LOGM(ERR, "Rejecting lease: no monitor or monitor is being leased for {}", (m->monitor ? m->monitor->szName : "null")); @@ -82,11 +90,14 @@ CDRMLeaseResource::~CDRMLeaseResource() { listeners.destroyLease.reset(); } -CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP resource_) : resource(resource_) { +CDRMLeaseRequestResource::CDRMLeaseRequestResource(WP parent_, SP resource_) : parent(parent_), resource(resource_) { if UNLIKELY (!good()) return; - resource->setOnDestroy([this](CWpDrmLeaseRequestV1* r) { PROTO::lease->destroyResource(this); }); + resource->setOnDestroy([this](CWpDrmLeaseRequestV1* r) { + if (parent && PROTO::lease.contains(parent->deviceName)) + PROTO::lease[parent->deviceName]->destroyResource(this); + }); resource->setRequestConnector([this](CWpDrmLeaseRequestV1* r, wl_resource* conn) { if (!conn) { @@ -101,7 +112,12 @@ CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP reso return; } - // TODO: when (if) we add multi, make sure this is from the correct device. + auto& lease = PROTO::lease[parent->deviceName]; + + if (std::find(lease->m_vConnectors.begin(), lease->m_vConnectors.end(), CONNECTOR) == lease->m_vConnectors.end()) { + resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_WRONG_DEVICE, "Connector requested for wrong device"); + return; + } requested.emplace_back(CONNECTOR); }); @@ -118,10 +134,10 @@ CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP reso return; } - PROTO::lease->m_vLeases.emplace_back(RESOURCE); + PROTO::lease[parent->deviceName]->m_vLeases.emplace_back(RESOURCE); // per protcol, after submit, this is dead. - PROTO::lease->destroyResource(this); + PROTO::lease[parent->deviceName]->destroyResource(this); }); } @@ -134,12 +150,19 @@ SP CDRMLeaseConnectorResource::fromResource(wl_resou return data ? data->self.lock() : nullptr; } -CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, PHLMONITOR monitor_) : monitor(monitor_), resource(resource_) { +CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(WP parent_, SP resource_, PHLMONITOR monitor_) : + parent(parent_), monitor(monitor_), resource(resource_) { if UNLIKELY (!good()) return; - resource->setOnDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); }); - resource->setDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); }); + resource->setOnDestroy([this](CWpDrmLeaseConnectorV1* r) { + if (parent && PROTO::lease.contains(parent->deviceName)) + PROTO::lease[parent->deviceName]->destroyResource(this); + }); + resource->setDestroy([this](CWpDrmLeaseConnectorV1* r) { + if (parent && PROTO::lease.contains(parent->deviceName)) + PROTO::lease[parent->deviceName]->destroyResource(this); + }); resource->setData(this); @@ -163,15 +186,21 @@ void CDRMLeaseConnectorResource::sendData() { resource->sendDone(); } -CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resource_) : resource(resource_) { +CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(std::string deviceName_, SP resource_) : deviceName(deviceName_), resource(resource_) { if UNLIKELY (!good()) return; - resource->setOnDestroy([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); }); - resource->setRelease([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); }); + resource->setOnDestroy([this](CWpDrmLeaseDeviceV1* r) { + if (PROTO::lease.contains(deviceName)) + PROTO::lease[deviceName]->destroyResource(this); + }); + resource->setRelease([this](CWpDrmLeaseDeviceV1* r) { + if (PROTO::lease.contains(deviceName)) + PROTO::lease[deviceName]->destroyResource(this); + }); resource->setCreateLeaseRequest([this](CWpDrmLeaseDeviceV1* r, uint32_t id) { - auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id)); + auto RESOURCE = makeShared(self, makeShared(resource->client(), resource->version(), id)); if UNLIKELY (!RESOURCE) { resource->noMemory(); return; @@ -179,14 +208,15 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resourc RESOURCE->self = RESOURCE; - PROTO::lease->m_vRequests.emplace_back(RESOURCE); + PROTO::lease[deviceName]->m_vRequests.emplace_back(RESOURCE); LOGM(LOG, "New lease request {}", id); RESOURCE->parent = self; }); - CFileDescriptor fd{((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD()}; + auto& primaryDevice = PROTO::lease[deviceName]->primaryDevice; + CFileDescriptor fd{((Aquamarine::CDRMBackend*)primaryDevice->backend.get())->getNonMasterFD()}; if (!fd.isValid()) { LOGM(ERR, "Failed to dup fd in lease"); return; @@ -195,7 +225,7 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resourc LOGM(LOG, "Sending DRMFD {} to new lease device", fd.get()); resource->sendDrmFd(fd.get()); - for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) { + for (auto const& m : primaryDevice->offeredOutputs) { if (m) sendConnector(m.lock()); } @@ -211,7 +241,7 @@ void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) { if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e && !e->dead && e->monitor == monitor; }) != connectorsSent.end()) return; - auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), 0), monitor); + auto RESOURCE = makeShared(self, makeShared(resource->client(), resource->version(), 0), monitor); if UNLIKELY (!RESOURCE) { resource->noMemory(); return; @@ -223,7 +253,7 @@ void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) { LOGM(LOG, "Sending new connector {}", monitor->szName); connectorsSent.emplace_back(RESOURCE); - PROTO::lease->m_vConnectors.emplace_back(RESOURCE); + PROTO::lease[deviceName]->m_vConnectors.emplace_back(RESOURCE); resource->sendConnector(RESOURCE->resource.get()); @@ -244,25 +274,14 @@ CDRMLeaseDevice::CDRMLeaseDevice(SP drmBackend) : backe name = drm->gpuName; } -CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { - for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { - if (b->type() != Aquamarine::AQ_BACKEND_DRM) - continue; - - auto drm = ((Aquamarine::CDRMBackend*)b.get())->self.lock(); - - primaryDevice = makeShared(drm); - - if (primaryDevice->success) - break; - } - - if (!primaryDevice || !primaryDevice->success) - g_pEventLoopManager->doLater([]() { PROTO::lease.reset(); }); +CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP backend) : + IWaylandProtocol(iface, ver, name) { + auto drm = ((Aquamarine::CDRMBackend*)backend.get())->self.lock(); + primaryDevice = makeShared(drm); } void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + const auto RESOURCE = m_vManagers.emplace_back(makeShared(primaryDevice->name, makeShared(client, ver, id))); if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); @@ -296,10 +315,8 @@ void CDRMLeaseProtocol::offer(PHLMONITOR monitor) { std::erase_if(primaryDevice->offeredOutputs, [](const auto& e) { return e.expired(); }); if (std::find(primaryDevice->offeredOutputs.begin(), primaryDevice->offeredOutputs.end(), monitor) != primaryDevice->offeredOutputs.end()) return; - if (monitor->output->getBackend()->type() != Aquamarine::AQ_BACKEND_DRM) return; - if (monitor->output->getBackend() != primaryDevice->backend) { LOGM(ERR, "Monitor {} cannot be leased: primaryDevice lease is for a different device", monitor->szName); return; @@ -312,3 +329,15 @@ void CDRMLeaseProtocol::offer(PHLMONITOR monitor) { m->resource->sendDone(); } } + +std::string CDRMLeaseProtocol::getDeviceName() { + return primaryDevice->name; +} + +SP CDRMLeaseProtocol::getBackend() { + return primaryDevice->backend; +} + +bool CDRMLeaseProtocol::good() { + return primaryDevice && primaryDevice->success; +} diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp index c7849149d8a..7896012c997 100644 --- a/src/protocols/DRMLease.hpp +++ b/src/protocols/DRMLease.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include "WaylandProtocol.hpp" @@ -42,7 +43,7 @@ class CDRMLeaseResource { class CDRMLeaseRequestResource { public: - CDRMLeaseRequestResource(SP resource_); + CDRMLeaseRequestResource(WP parent_, SP resource_); bool good(); @@ -56,7 +57,7 @@ class CDRMLeaseRequestResource { class CDRMLeaseConnectorResource { public: - CDRMLeaseConnectorResource(SP resource_, PHLMONITOR monitor_); + CDRMLeaseConnectorResource(WP parent_, SP resource_, PHLMONITOR monitor_); static SP fromResource(wl_resource*); bool good(); @@ -79,7 +80,7 @@ class CDRMLeaseConnectorResource { class CDRMLeaseDeviceResource { public: - CDRMLeaseDeviceResource(SP resource_); + CDRMLeaseDeviceResource(std::string deviceName, SP resource_); bool good(); void sendConnector(PHLMONITOR monitor); @@ -87,6 +88,7 @@ class CDRMLeaseDeviceResource { std::vector> connectorsSent; WP self; + std::string deviceName; private: SP resource; @@ -107,12 +109,16 @@ class CDRMLeaseDevice { class CDRMLeaseProtocol : public IWaylandProtocol { public: - CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name); + CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP drm); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); void offer(PHLMONITOR monitor); + SP getBackend(); + std::string getDeviceName(); + bool good(); + private: void destroyResource(CDRMLeaseDeviceResource* resource); void destroyResource(CDRMLeaseConnectorResource* resource); @@ -126,6 +132,7 @@ class CDRMLeaseProtocol : public IWaylandProtocol { std::vector> m_vLeases; SP primaryDevice; + WP self; friend class CDRMLeaseDeviceResource; friend class CDRMLeaseConnectorResource; @@ -134,5 +141,5 @@ class CDRMLeaseProtocol : public IWaylandProtocol { }; namespace PROTO { - inline UP lease; + inline std::unordered_map> lease; };