summaryrefslogtreecommitdiff
path: root/src/protocols
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2024-07-21 13:09:54 +0200
committerGitHub <noreply@github.com>2024-07-21 13:09:54 +0200
commit016da234d0e852de3ef20eb2e89ac58d2a85f6e7 (patch)
tree496085987176551b0794fffc069877d44943e2f1 /src/protocols
parentf642fb97df5c69267a03452533de383ff8023570 (diff)
Core: Move to aquamarine (#6608)
Moves Hyprland from wlroots to aquamarine for the backend. --------- Signed-off-by: Vaxry <vaxry@vaxry.net> Co-authored-by: Mihai Fufezan <mihai@fufexan.net> Co-authored-by: Jan Beich <jbeich@FreeBSD.org> Co-authored-by: vaxerski <vaxerski@users.noreply.github.com> Co-authored-by: UjinT34 <41110182+UjinT34@users.noreply.github.com> Co-authored-by: Tom Englund <tomenglund26@gmail.com> Co-authored-by: Ikalco <73481042+ikalco@users.noreply.github.com> Co-authored-by: diniamo <diniamo53@gmail.com>
Diffstat (limited to 'src/protocols')
-rw-r--r--src/protocols/CursorShape.cpp45
-rw-r--r--src/protocols/DRMLease.cpp302
-rw-r--r--src/protocols/DRMLease.hpp137
-rw-r--r--src/protocols/DRMSyncobj.cpp183
-rw-r--r--src/protocols/DRMSyncobj.hpp82
-rw-r--r--src/protocols/GammaControl.cpp32
-rw-r--r--src/protocols/GammaControl.hpp2
-rw-r--r--src/protocols/InputMethodV2.cpp22
-rw-r--r--src/protocols/InputMethodV2.hpp7
-rw-r--r--src/protocols/LinuxDMABUF.cpp311
-rw-r--r--src/protocols/LinuxDMABUF.hpp52
-rw-r--r--src/protocols/MesaDRM.cpp42
-rw-r--r--src/protocols/MesaDRM.hpp2
-rw-r--r--src/protocols/OutputManagement.cpp56
-rw-r--r--src/protocols/OutputManagement.hpp15
-rw-r--r--src/protocols/OutputPower.cpp2
-rw-r--r--src/protocols/PresentationTime.cpp18
-rw-r--r--src/protocols/Screencopy.cpp52
-rw-r--r--src/protocols/Screencopy.hpp9
-rw-r--r--src/protocols/Tablet.cpp61
-rw-r--r--src/protocols/Tablet.hpp5
-rw-r--r--src/protocols/ToplevelExport.cpp19
-rw-r--r--src/protocols/ToplevelExport.hpp2
-rw-r--r--src/protocols/Viewporter.cpp29
-rw-r--r--src/protocols/Viewporter.hpp5
-rw-r--r--src/protocols/VirtualKeyboard.cpp60
-rw-r--r--src/protocols/VirtualKeyboard.hpp13
-rw-r--r--src/protocols/VirtualPointer.cpp80
-rw-r--r--src/protocols/VirtualPointer.hpp31
-rw-r--r--src/protocols/XDGOutput.cpp6
-rw-r--r--src/protocols/XDGShell.cpp1
-rw-r--r--src/protocols/core/Compositor.cpp149
-rw-r--r--src/protocols/core/Compositor.hpp14
-rw-r--r--src/protocols/core/Output.cpp10
-rw-r--r--src/protocols/core/Output.hpp3
-rw-r--r--src/protocols/core/Seat.cpp4
-rw-r--r--src/protocols/core/Shm.cpp27
-rw-r--r--src/protocols/core/Shm.hpp8
-rw-r--r--src/protocols/types/Buffer.cpp41
-rw-r--r--src/protocols/types/Buffer.hpp82
-rw-r--r--src/protocols/types/DMABuffer.cpp12
-rw-r--r--src/protocols/types/DMABuffer.hpp12
-rw-r--r--src/protocols/types/WLBuffer.cpp15
-rw-r--r--src/protocols/types/WLBuffer.hpp8
44 files changed, 1470 insertions, 598 deletions
diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp
index 2f25b22b..812afe53 100644
--- a/src/protocols/CursorShape.cpp
+++ b/src/protocols/CursorShape.cpp
@@ -1,48 +1,9 @@
#include "CursorShape.hpp"
#include <algorithm>
+#include "../helpers/CursorShapes.hpp"
#define LOGM PROTO::cursorShape->protoLog
-// clang-format off
-constexpr const char* SHAPE_NAMES[] = {
- "invalid",
- "default",
- "context-menu",
- "help",
- "pointer",
- "progress",
- "wait",
- "cell",
- "crosshair",
- "text",
- "vertical-text",
- "alias",
- "copy",
- "move",
- "no-drop",
- "not-allowed",
- "grab",
- "grabbing",
- "e-resize",
- "n-resize",
- "ne-resize",
- "nw-resize",
- "s-resize",
- "se-resize",
- "sw-resize",
- "w-resize",
- "ew-resize",
- "ns-resize",
- "nesw-resize",
- "nwse-resize",
- "col-resize",
- "row-resize",
- "all-scroll",
- "zoom-in",
- "zoom-out",
-};
-// clang-format on
-
CCursorShapeProtocol::CCursorShapeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
;
}
@@ -82,7 +43,7 @@ void CCursorShapeProtocol::createCursorShapeDevice(CWpCursorShapeManagerV1* pMgr
}
void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t serial, wpCursorShapeDeviceV1Shape shape) {
- if ((uint32_t)shape == 0 || (uint32_t)shape > sizeof(SHAPE_NAMES)) {
+ if ((uint32_t)shape == 0 || (uint32_t)shape > CURSOR_SHAPE_NAMES.size()) {
pMgr->error(WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE, "The shape is invalid");
return;
}
@@ -90,7 +51,7 @@ void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t ser
SSetShapeEvent event;
event.pMgr = pMgr;
event.shape = shape;
- event.shapeName = SHAPE_NAMES[shape];
+ event.shapeName = CURSOR_SHAPE_NAMES.at(shape);
events.setShape.emit(event);
} \ No newline at end of file
diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp
new file mode 100644
index 00000000..9f5b6312
--- /dev/null
+++ b/src/protocols/DRMLease.cpp
@@ -0,0 +1,302 @@
+#include "DRMLease.hpp"
+#include "../Compositor.hpp"
+#include <aquamarine/backend/DRM.hpp>
+#include <fcntl.h>
+
+#define LOGM PROTO::lease->protoLog
+
+CDRMLeaseResource::CDRMLeaseResource(SP<CWpDrmLeaseV1> resource_, SP<CDRMLeaseRequestResource> request) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); });
+ resource->setDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); });
+
+ parent = request->parent;
+ requested = request->requested;
+
+ for (auto& 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"));
+ resource->sendFinished();
+ return;
+ }
+ }
+
+ // grant the lease if it is seemingly valid
+
+ LOGM(LOG, "Leasing outputs: {}", [this]() {
+ std::string roll;
+ for (auto& o : requested) {
+ roll += std::format("{} ", o->monitor->szName);
+ }
+ return roll;
+ }());
+
+ std::vector<SP<Aquamarine::IOutput>> outputs;
+ for (auto& m : requested) {
+ outputs.emplace_back(m->monitor->output);
+ }
+
+ auto aqlease = Aquamarine::CDRMLease::create(outputs);
+ if (!aqlease) {
+ LOGM(ERR, "Rejecting lease: backend failed to alloc a lease");
+ resource->sendFinished();
+ return;
+ }
+
+ LOGM(LOG, "Granting lease, sending fd {}", aqlease->leaseFD);
+
+ resource->sendLeaseFd(aqlease->leaseFD);
+
+ lease = aqlease;
+
+ for (auto& m : requested) {
+ m->monitor->isBeingLeased = true;
+ }
+
+ listeners.destroyLease = lease->events.destroy.registerListener([this](std::any d) {
+ for (auto& m : requested) {
+ if (m && m->monitor)
+ m->monitor->isBeingLeased = false;
+ }
+
+ resource->sendFinished();
+ });
+
+ close(lease->leaseFD);
+}
+
+bool CDRMLeaseResource::good() {
+ return resource->resource();
+}
+
+CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP<CWpDrmLeaseRequestV1> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWpDrmLeaseRequestV1* r) { PROTO::lease->destroyResource(this); });
+
+ resource->setRequestConnector([this](CWpDrmLeaseRequestV1* r, wl_resource* conn) {
+ if (!conn) {
+ resource->error(-1, "Null connector");
+ return;
+ }
+
+ auto CONNECTOR = CDRMLeaseConnectorResource::fromResource(conn);
+
+ if (std::find(requested.begin(), requested.end(), CONNECTOR) != requested.end()) {
+ resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_DUPLICATE_CONNECTOR, "Connector already requested");
+ return;
+ }
+
+ // TODO: when (if) we add multi, make sure this is from the correct device.
+
+ requested.emplace_back(CONNECTOR);
+ });
+
+ resource->setSubmit([this](CWpDrmLeaseRequestV1* r, uint32_t id) {
+ if (requested.empty()) {
+ resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_EMPTY_LEASE, "No connectors added");
+ return;
+ }
+
+ auto RESOURCE = makeShared<CDRMLeaseResource>(makeShared<CWpDrmLeaseV1>(resource->client(), resource->version(), -1), self.lock());
+ if (!RESOURCE) {
+ resource->noMemory();
+ return;
+ }
+
+ PROTO::lease->m_vLeases.emplace_back(RESOURCE);
+
+ // per protcol, after submit, this is dead.
+ PROTO::lease->destroyResource(this);
+ });
+}
+
+bool CDRMLeaseRequestResource::good() {
+ return resource->resource();
+}
+
+SP<CDRMLeaseConnectorResource> CDRMLeaseConnectorResource::fromResource(wl_resource* res) {
+ auto data = (CDRMLeaseConnectorResource*)(((CWpDrmLeaseConnectorV1*)wl_resource_get_user_data(res))->data());
+ return data ? data->self.lock() : nullptr;
+}
+
+CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP<CWpDrmLeaseConnectorV1> resource_, SP<CMonitor> monitor_) : monitor(monitor_), resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); });
+ resource->setDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); });
+
+ resource->setData(this);
+
+ listeners.destroyMonitor = monitor->events.destroy.registerListener([this](std::any d) {
+ resource->sendWithdrawn();
+ dead = true;
+ });
+}
+
+bool CDRMLeaseConnectorResource::good() {
+ return resource->resource();
+}
+
+void CDRMLeaseConnectorResource::sendData() {
+ resource->sendName(monitor->szName.c_str());
+ resource->sendDescription(monitor->szDescription.c_str());
+
+ auto AQDRMOutput = (Aquamarine::CDRMOutput*)monitor->output.get();
+ resource->sendConnectorId(AQDRMOutput->getConnectorID());
+
+ resource->sendDone();
+}
+
+CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP<CWpDrmLeaseDeviceV1> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); });
+ resource->setRelease([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); });
+
+ resource->setCreateLeaseRequest([this](CWpDrmLeaseDeviceV1* r, uint32_t id) {
+ auto RESOURCE = makeShared<CDRMLeaseRequestResource>(makeShared<CWpDrmLeaseRequestV1>(resource->client(), resource->version(), id));
+ if (!RESOURCE) {
+ resource->noMemory();
+ return;
+ }
+
+ RESOURCE->self = RESOURCE;
+
+ PROTO::lease->m_vRequests.emplace_back(RESOURCE);
+
+ LOGM(LOG, "New lease request {}", id);
+
+ RESOURCE->parent = self;
+ });
+
+ int fd = ((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD();
+ if (fd < 0) {
+ LOGM(ERR, "Failed to dup fd in lease");
+ return;
+ }
+
+ LOGM(LOG, "Sending DRMFD {} to new lease device", fd);
+ resource->sendDrmFd(fd);
+ close(fd);
+
+ for (auto& m : PROTO::lease->primaryDevice->offeredOutputs) {
+ sendConnector(m.lock());
+ }
+
+ resource->sendDone();
+}
+
+bool CDRMLeaseDeviceResource::good() {
+ return resource->resource();
+}
+
+void CDRMLeaseDeviceResource::sendConnector(SP<CMonitor> monitor) {
+ if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e->monitor == monitor; }) != connectorsSent.end())
+ return;
+
+ auto RESOURCE = makeShared<CDRMLeaseConnectorResource>(makeShared<CWpDrmLeaseConnectorV1>(resource->client(), resource->version(), -1), monitor);
+ if (!RESOURCE) {
+ resource->noMemory();
+ return;
+ }
+
+ RESOURCE->parent = self;
+ RESOURCE->self = RESOURCE;
+
+ LOGM(LOG, "Sending new connector {}", monitor->szName);
+
+ connectorsSent.emplace_back(RESOURCE);
+ PROTO::lease->m_vConnectors.emplace_back(RESOURCE);
+
+ resource->sendConnector(RESOURCE->resource.get());
+
+ RESOURCE->sendData();
+}
+
+CDRMLeaseDevice::CDRMLeaseDevice(SP<Aquamarine::CDRMBackend> drmBackend) : backend(drmBackend) {
+ auto drm = (Aquamarine::CDRMBackend*)drmBackend.get();
+
+ auto fd = drm->getNonMasterFD();
+
+ if (fd < 0) {
+ LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName);
+ return;
+ }
+
+ close(fd);
+ success = true;
+ name = drm->gpuName;
+}
+
+CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) {
+ if (b->type() != Aquamarine::AQ_BACKEND_DRM)
+ continue;
+
+ auto drm = ((Aquamarine::CDRMBackend*)b.get())->self.lock();
+
+ primaryDevice = makeShared<CDRMLeaseDevice>(drm);
+
+ if (primaryDevice->success)
+ break;
+ }
+
+ if (!primaryDevice || primaryDevice->success) {
+ PROTO::lease.reset();
+ return;
+ }
+}
+
+void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vManagers.emplace_back(makeShared<CDRMLeaseDeviceResource>(makeShared<CWpDrmLeaseDeviceV1>(client, ver, id)));
+
+ if (!RESOURCE->good()) {
+ wl_client_post_no_memory(client);
+ m_vManagers.pop_back();
+ return;
+ }
+
+ RESOURCE->self = RESOURCE;
+}
+
+void CDRMLeaseProtocol::destroyResource(CDRMLeaseDeviceResource* resource) {
+ std::erase_if(m_vManagers, [resource](const auto& e) { return e.get() == resource; });
+}
+
+void CDRMLeaseProtocol::destroyResource(CDRMLeaseConnectorResource* resource) {
+ std::erase_if(m_vConnectors, [resource](const auto& e) { return e.get() == resource; });
+}
+
+void CDRMLeaseProtocol::destroyResource(CDRMLeaseRequestResource* resource) {
+ std::erase_if(m_vRequests, [resource](const auto& e) { return e.get() == resource; });
+}
+
+void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) {
+ std::erase_if(m_vLeases, [resource](const auto& e) { return e.get() == resource; });
+}
+
+void CDRMLeaseProtocol::offer(SP<CMonitor> monitor) {
+ 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;
+ }
+
+ primaryDevice->offeredOutputs.emplace_back(monitor);
+
+ for (auto& m : m_vManagers) {
+ m->sendConnector(monitor);
+ m->resource->sendDone();
+ }
+}
diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp
new file mode 100644
index 00000000..56eaa3db
--- /dev/null
+++ b/src/protocols/DRMLease.hpp
@@ -0,0 +1,137 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_map>
+#include "WaylandProtocol.hpp"
+#include "drm-lease-v1.hpp"
+#include "../helpers/signal/Signal.hpp"
+
+/*
+ TODO: this protocol is not made for systems with multiple DRM nodes (e.g. multigpu)
+*/
+
+AQUAMARINE_FORWARD(CDRMBackend);
+AQUAMARINE_FORWARD(CDRMLease);
+class CDRMLeaseDeviceResource;
+class CMonitor;
+class CDRMLeaseProtocol;
+class CDRMLeaseConnectorResource;
+class CDRMLeaseRequestResource;
+
+class CDRMLeaseResource {
+ public:
+ CDRMLeaseResource(SP<CWpDrmLeaseV1> resource_, SP<CDRMLeaseRequestResource> request);
+
+ bool good();
+
+ WP<CDRMLeaseDeviceResource> parent;
+ std::vector<WP<CDRMLeaseConnectorResource>> requested;
+ WP<Aquamarine::CDRMLease> lease;
+
+ int leaseFD = -1;
+
+ struct {
+ CHyprSignalListener destroyLease;
+ } listeners;
+
+ private:
+ SP<CWpDrmLeaseV1> resource;
+};
+
+class CDRMLeaseRequestResource {
+ public:
+ CDRMLeaseRequestResource(SP<CWpDrmLeaseRequestV1> resource_);
+
+ bool good();
+
+ WP<CDRMLeaseDeviceResource> parent;
+ WP<CDRMLeaseRequestResource> self;
+ std::vector<WP<CDRMLeaseConnectorResource>> requested;
+
+ private:
+ SP<CWpDrmLeaseRequestV1> resource;
+};
+
+class CDRMLeaseConnectorResource {
+ public:
+ CDRMLeaseConnectorResource(SP<CWpDrmLeaseConnectorV1> resource_, SP<CMonitor> monitor_);
+ static SP<CDRMLeaseConnectorResource> fromResource(wl_resource*);
+
+ bool good();
+ void sendData();
+
+ WP<CDRMLeaseConnectorResource> self;
+ WP<CDRMLeaseDeviceResource> parent;
+ WP<CMonitor> monitor;
+ bool dead = false;
+
+ private:
+ SP<CWpDrmLeaseConnectorV1> resource;
+
+ struct {
+ CHyprSignalListener destroyMonitor;
+ } listeners;
+
+ friend class CDRMLeaseDeviceResource;
+};
+
+class CDRMLeaseDeviceResource {
+ public:
+ CDRMLeaseDeviceResource(SP<CWpDrmLeaseDeviceV1> resource_);
+
+ bool good();
+ void sendConnector(SP<CMonitor> monitor);
+
+ std::vector<WP<CDRMLeaseConnectorResource>> connectorsSent;
+
+ WP<CDRMLeaseDeviceResource> self;
+
+ private:
+ SP<CWpDrmLeaseDeviceV1> resource;
+
+ friend class CDRMLeaseProtocol;
+};
+
+class CDRMLeaseDevice {
+ public:
+ CDRMLeaseDevice(SP<Aquamarine::CDRMBackend> drmBackend);
+
+ std::string name = "";
+ bool success = false;
+ SP<Aquamarine::CDRMBackend> backend;
+
+ std::vector<WP<CMonitor>> offeredOutputs;
+};
+
+class CDRMLeaseProtocol : public IWaylandProtocol {
+ public:
+ CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name);
+
+ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+
+ void offer(SP<CMonitor> monitor);
+
+ private:
+ void destroyResource(CDRMLeaseDeviceResource* resource);
+ void destroyResource(CDRMLeaseConnectorResource* resource);
+ void destroyResource(CDRMLeaseRequestResource* resource);
+ void destroyResource(CDRMLeaseResource* resource);
+
+ //
+ std::vector<SP<CDRMLeaseDeviceResource>> m_vManagers;
+ std::vector<SP<CDRMLeaseConnectorResource>> m_vConnectors;
+ std::vector<SP<CDRMLeaseRequestResource>> m_vRequests;
+ std::vector<SP<CDRMLeaseResource>> m_vLeases;
+
+ SP<CDRMLeaseDevice> primaryDevice;
+
+ friend class CDRMLeaseDeviceResource;
+ friend class CDRMLeaseConnectorResource;
+ friend class CDRMLeaseRequestResource;
+ friend class CDRMLeaseResource;
+};
+
+namespace PROTO {
+ inline UP<CDRMLeaseProtocol> lease;
+};
diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp
new file mode 100644
index 00000000..41178109
--- /dev/null
+++ b/src/protocols/DRMSyncobj.cpp
@@ -0,0 +1,183 @@
+#include "DRMSyncobj.hpp"
+#include <algorithm>
+
+#include "core/Compositor.hpp"
+#include "../helpers/sync/SyncTimeline.hpp"
+#include "../Compositor.hpp"
+
+#include <fcntl.h>
+
+#define LOGM PROTO::sync->protoLog
+
+CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurfaceV1> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setData(this);
+
+ resource->setOnDestroy([this](CWpLinuxDrmSyncobjSurfaceV1* r) { PROTO::sync->destroyResource(this); });
+ resource->setDestroy([this](CWpLinuxDrmSyncobjSurfaceV1* r) { PROTO::sync->destroyResource(this); });
+
+ resource->setSetAcquirePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) {
+ if (!surface) {
+ resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, "Surface is gone");
+ return;
+ }
+
+ auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
+ acquireTimeline = timeline;
+ acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
+ });
+
+ resource->setSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) {
+ if (!surface) {
+ resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, "Surface is gone");
+ return;
+ }
+
+ auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
+ releaseTimeline = timeline;
+ releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
+ });
+
+ listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) {
+ if (!!acquireTimeline != !!releaseTimeline) {
+ resource->error(acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, "Missing timeline");
+ surface->pending.rejected = true;
+ return;
+ }
+
+ if ((acquireTimeline || releaseTimeline) && !surface->pending.buffer) {
+ resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer");
+ surface->pending.rejected = true;
+ return;
+ }
+
+ if (!acquireTimeline)
+ return;
+
+ // wait for the acquire timeline to materialize
+ auto materialized = acquireTimeline->timeline->check(acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
+ if (!materialized.has_value()) {
+ LOGM(ERR, "Failed to check the acquire timeline");
+ resource->noMemory();
+ return;
+ }
+
+ if (materialized)
+ return;
+
+ surface->lockPendingState();
+ acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
+ });
+}
+
+bool CDRMSyncobjSurfaceResource::good() {
+ return resource->resource();
+}
+
+CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTimelineV1> resource_, int fd_) : fd(fd_), resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setData(this);
+
+ resource->setOnDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); });
+ resource->setDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); });
+
+ timeline = CSyncTimeline::create(PROTO::sync->drmFD, fd);
+
+ if (!timeline) {
+ resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, "Timeline failed importing");
+ return;
+ }
+}
+
+SP<CDRMSyncobjTimelineResource> CDRMSyncobjTimelineResource::fromResource(wl_resource* res) {
+ auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data());
+ return data ? data->self.lock() : nullptr;
+}
+
+bool CDRMSyncobjTimelineResource::good() {
+ return resource->resource();
+}
+
+CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SP<CWpLinuxDrmSyncobjManagerV1> resource_) : resource(resource_) {
+ if (!good())
+ return;
+
+ resource->setOnDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); });
+ resource->setDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); });
+
+ resource->setGetSurface([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, wl_resource* surf) {
+ if (!surf) {
+ resource->error(-1, "Invalid surface");
+ return;
+ }
+
+ auto SURF = CWLSurfaceResource::fromResource(surf);
+ if (!SURF) {
+ resource->error(-1, "Invalid surface (2)");
+ return;
+ }
+
+ if (SURF->syncobj) {
+ resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_SURFACE_EXISTS, "Surface already has a syncobj attached");
+ return;
+ }
+
+ auto RESOURCE = makeShared<CDRMSyncobjSurfaceResource>(makeShared<CWpLinuxDrmSyncobjSurfaceV1>(resource->client(), resource->version(), id), SURF);
+ if (!RESOURCE->good()) {
+ resource->noMemory();
+ return;
+ }
+
+ PROTO::sync->m_vSurfaces.emplace_back(RESOURCE);
+ SURF->syncobj = RESOURCE;
+
+ LOGM(LOG, "New linux_syncobj at {:x} for surface {:x}", (uintptr_t)RESOURCE.get(), (uintptr_t)SURF.get());
+ });
+
+ resource->setImportTimeline([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, int32_t fd) {
+ auto RESOURCE = makeShared<CDRMSyncobjTimelineResource>(makeShared<CWpLinuxDrmSyncobjTimelineV1>(resource->client(), resource->version(), id), fd);
+ if (!RESOURCE->good()) {
+ resource->noMemory();
+ return;
+ }
+
+ PROTO::sync->m_vTimelines.emplace_back(RESOURCE);
+ RESOURCE->self = RESOURCE;
+
+ LOGM(LOG, "New linux_drm_timeline at {:x}", (uintptr_t)RESOURCE.get());
+ });
+}
+
+bool CDRMSyncobjManagerResource::good() {
+ return resource->resource();
+}
+
+CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ drmFD = g_pCompositor->m_iDRMFD;
+}
+
+void CDRMSyncobjProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vManagers.emplace_back(makeShared<CDRMSyncobjManagerResource>(makeShared<CWpLinuxDrmSyncobjManagerV1>(client, ver, id)));
+
+ if (!RESOURCE->good()) {
+ wl_client_post_no_memory(client);
+ m_vManagers.pop_back();
+ return;
+ }
+}
+
+void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjManagerResource* resource) {
+ std::erase_if(m_vManagers, [resource](const auto& e) { return e.get() == resource; });
+}
+
+void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjTimelineResource* resource) {
+ std::erase_if(m_vTimelines, [resource](const auto& e) { return e.get() == resource; });
+}
+
+void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjSurfaceResource* resource) {
+ std::erase_if(m_vSurfaces, [resource](const auto& e) { return e.get() == resource; });
+}
diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp
new file mode 100644
index 00000000..c1c884ff
--- /dev/null
+++ b/src/protocols/DRMSyncobj.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include "WaylandProtocol.hpp"
+#include "linux-drm-syncobj-v1.hpp"
+#include "../helpers/signal/Signal.hpp"
+
+class CWLSurfaceResource;
+class CDRMSyncobjTimelineResource;
+class CSyncTimeline;
+
+class CDRMSyncobjSurfaceResource {
+ public:
+ CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurfaceV1> resource_, SP<CWLSurfaceResource> surface_);
+
+ bool good();
+
+ WP<CWLSurfaceResource> surface;
+ WP<CDRMSyncobjTimelineResource> acquireTimeline, releaseTimeline;
+ uint64_t acquirePoint = 0, releasePoint = 0;
+
+ private:
+ SP<CWpLinuxDrmSyncobjSurfaceV1> resource;
+
+ struct {
+ CHyprSignalListener surfacePrecommit;
+ } listeners;
+};
+
+class CDRMSyncobjTimelineResource {
+ public:
+ CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTimelineV1> resource_, int fd_);
+ static SP<CDRMSyncobjTimelineResource> fromResource(wl_resource*);
+
+ bool good();
+
+ WP<CDRMSyncobjTimelineResource> self;
+ int fd = -1;
+ SP<CSyncTimeline> timeline;
+
+ private:
+ SP<CWpLinuxDrmSyncobjTimelineV1> resource;
+};
+
+class CDRMSyncobjManagerResource {
+ public:
+ CDRMSyncobjManagerResource(SP<CWpLinuxDrmSyncobjManagerV1> resource_);
+
+ bool good();
+
+ private:
+ SP<CWpLinuxDrmSyncobjManagerV1> resource;
+};
+
+class CDRMSyncobjProtocol : public IWaylandProtocol {
+ public:
+ CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name);
+
+ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+
+ private:
+ void destroyResource(CDRMSyncobjManagerResource* resource);
+ void destroyResource(CDRMSyncobjTimelineResource* resource);
+ void destroyResource(CDRMSyncobjSurfaceResource* resource);
+
+ //
+ std::vector<SP<CDRMSyncobjManagerResource>> m_vManagers;
+ std::vector<SP<CDRMSyncobjTimelineResource>> m_vTimelines;
+ std::vector<SP<CDRMSyncobjSurfaceResource>> m_vSurfaces;
+
+ //
+ int drmFD = -1;
+
+ friend class CDRMSyncobjManagerResource;
+ friend class CDRMSyncobjTimelineResource;
+ friend class CDRMSyncobjSurfaceResource;
+};
+
+namespace PROTO {
+ inline UP<CDRMSyncobjProtocol> sync;
+};
diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp
index 7c3b39ce..494d9862 100644
--- a/src/protocols/GammaControl.cpp
+++ b/src/protocols/GammaControl.cpp
@@ -34,7 +34,7 @@ CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* out
}
}
- gammaSize = wlr_output_get_gamma_size(pMonitor->output);
+ gammaSize = pMonitor->output->getGammaSize();
if (gammaSize <= 0) {
LOGM(ERR, "Output {} doesn't support gamma", pMonitor->szName);
@@ -81,6 +81,24 @@ CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* out
gammaTableSet = true;
close(fd);
+
+ // translate the table to AQ format
+ std::vector<uint16_t> red, green, blue;
+ red.resize(gammaTable.size() / 3);
+ green.resize(gammaTable.size() / 3);
+ blue.resize(gammaTable.size() / 3);
+ for (size_t i = 0; i < gammaTable.size() / 3; ++i) {
+ red.at(i) = gammaTable.at(i);
+ green.at(i) = gammaTable.at(gammaTable.size() / 3 + i);
+ blue.at(i) = gammaTable.at((gammaTable.size() / 3) * 2 + i);
+ }
+
+ for (size_t i = 0; i < gammaTable.size() / 3; ++i) {
+ gammaTable.at(i * 3) = red.at(i);
+ gammaTable.at(i * 3 + 1) = green.at(i);
+ gammaTable.at(i * 3 + 2) = blue.at(i);
+ }
+
applyToMonitor();
});
@@ -95,7 +113,7 @@ CGammaControl::~CGammaControl() {
return;
// reset the LUT if the client dies for whatever reason and doesn't unset the gamma
- wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr);
+ pMonitor->output->state->setGammaLut({});
}
bool CGammaControl::good() {
@@ -109,19 +127,15 @@ void CGammaControl::applyToMonitor() {
LOGM(LOG, "setting to monitor {}", pMonitor->szName);
if (!gammaTableSet) {
- wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr);
+ pMonitor->output->state->setGammaLut({});
return;
}
- uint16_t* red = &gammaTable.at(0);
- uint16_t* green = &gammaTable.at(gammaSize);
- uint16_t* blue = &gammaTable.at(gammaSize * 2);
-
- wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), gammaSize, red, green, blue);
+ pMonitor->output->state->setGammaLut(gammaTable);
if (!pMonitor->state.test()) {
LOGM(LOG, "setting to monitor {} failed", pMonitor->szName);
- wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr);
+ pMonitor->output->state->setGammaLut({});
}
g_pHyprRenderer->damageMonitor(pMonitor);
diff --git a/src/protocols/GammaControl.hpp b/src/protocols/GammaControl.hpp
index 93465b81..963eea5c 100644
--- a/src/protocols/GammaControl.hpp
+++ b/src/protocols/GammaControl.hpp
@@ -23,7 +23,7 @@ class CGammaControl {
CMonitor* pMonitor = nullptr;
size_t gammaSize = 0;
bool gammaTableSet = false;
- std::vector<uint16_t> gammaTable;
+ std::vector<uint16_t> gammaTable; // [r,g,b]+
void onMonitorDestroy();
diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp
index 24f7ad54..def4d837 100644
--- a/src/protocols/InputMethodV2.cpp
+++ b/src/protocols/InputMethodV2.cpp
@@ -4,6 +4,7 @@
#include "../devices/IKeyboard.hpp"
#include <sys/mman.h>
#include "core/Compositor.hpp"
+#include <cstring>
#define LOGM PROTO::ime->protoLog
@@ -19,7 +20,7 @@ CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SP<CZwpInputMethodKeyboar
return;
}
- sendKeyboardData(g_pSeatManager->keyboard->wlr());
+ sendKeyboardData(g_pSeatManager->keyboard.lock());
}
CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() {
@@ -27,37 +28,36 @@ CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() {
std::erase_if(owner->grabs, [](const auto& g) { return g.expired(); });
}
-void CInputMethodKeyboardGrabV2::sendKeyboardData(wlr_keyboard* keyboard) {
+void CInputMethodKeyboardGrabV2::sendKeyboardData(SP<IKeyboard> keyboard) {
if (keyboard == pLastKeyboard)
return;
pLastKeyboard = keyboard;
- int keymapFD = allocateSHMFile(keyboard->keymap_size);
+ int keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1);
if (keymapFD < 0) {
LOGM(ERR, "Failed to create a keymap file for keyboard grab");
return;
}
- void* data = mmap(nullptr, keyboard->keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0);
+ void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0);
if (data == MAP_FAILED) {
LOGM(ERR, "Failed to mmap a keymap file for keyboard grab");
close(keymapFD);
return;
}
- memcpy(data, keyboard->keymap_string, keyboard->keymap_size);
- munmap(data, keyboard->keymap_size);
+ memcpy(data, keyboard->xkbKeymapString.c_str(), keyboard->xkbKeymapString.length());
+ munmap(data, keyboard->xkbKeymapString.length() + 1);
- resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->keymap_size);
+ resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->xkbKeymapString.length() + 1);
close(keymapFD);
- const auto MODS = keyboard->modifiers;
- sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group);
+ sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group);
- resource->sendRepeatInfo(keyboard->repeat_info.rate, keyboard->repeat_info.delay);
+ resource->sendRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay);
}
void CInputMethodKeyboardGrabV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state) {
@@ -316,7 +316,7 @@ void CInputMethodV2::sendMods(uint32_t depressed, uint32_t latched, uint32_t loc
}
}
-void CInputMethodV2::setKeyboard(wlr_keyboard* keyboard) {
+void CInputMethodV2::setKeyboard(SP<IKeyboard> keyboard) {
for (auto& gw : grabs) {
auto g = gw.lock();
diff --git a/src/protocols/InputMethodV2.hpp b/src/protocols/InputMethodV2.hpp
index bc21270c..0b2c7a49 100644
--- a/src/protocols/InputMethodV2.hpp
+++ b/src/protocols/InputMethodV2.hpp
@@ -11,6 +11,7 @@
class CInputMethodKeyboardGrabV2;
class CInputMethodPopupV2;
+class IKeyboard;
class CInputMethodV2 {
public:
@@ -58,7 +59,7 @@ class CInputMethodV2 {
bool hasGrab();
void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state);
void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
- void setKeyboard(wlr_keyboard* keyboard);
+ void setKeyboard(SP<IKeyboard> keyboard);
wl_client* client();
wl_client* grabClient();
@@ -90,13 +91,13 @@ class CInputMethodKeyboardGrabV2 {
void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state);
void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
- void sendKeyboardData(wlr_keyboard* keyboard);
+ void sendKeyboardData(SP<IKeyboard> keyboard);
private:
SP<CZwpInputMethodKeyboardGrabV2> resource;
WP<CInputMethodV2> owner;
- wlr_keyboard* pLastKeyboard = nullptr; // READ-ONLY
+ WP<IKeyboard> pLastKeyboard;
};
class CInputMethodPopupV2 {
diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp
index cf8f8730..0fbf832e 100644
--- a/src/protocols/LinuxDMABUF.cpp
+++ b/src/protocols/LinuxDMABUF.cpp
@@ -6,6 +6,7 @@
#include <sys/mman.h>
#include <xf86drm.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include "core/Compositor.hpp"
#include "types/DMABuffer.hpp"
#include "types/WLBuffer.hpp"
@@ -22,21 +23,66 @@ static std::optional<dev_t> devIDFromFD(int fd) {
return stat.st_rdev;
}
-CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector<SDMABufTranche> tranches_) {
+CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector<std::pair<SP<CMonitor>, SDMABUFTranche>> tranches_) :
+ rendererTranche(_rendererTranche), monitorTranches(tranches_) {
+
+ std::vector<SDMABUFFormatTableEntry> formatsVec;
std::set<std::pair<uint32_t, uint64_t>> formats;
- for (auto& t : tranches_) {
- for (auto& fmt : t.formats) {
- for (auto& mod : fmt.mods) {
- formats.insert(std::make_pair<>(fmt.format, mod));
+
+ // insert formats into vec if they got inserted into set, meaning they're unique
+ size_t i = 0;
+
+ rendererTranche.indicies.clear();
+ for (auto& fmt : rendererTranche.formats) {
+ for (auto& mod : fmt.modifiers) {
+ auto format = std::make_pair<>(fmt.drmFormat, mod);
+ auto [_, inserted] = formats.insert(format);
+ if (inserted) {
+ // if it was inserted into set, then its unique and will have a new index in vec
+ rendererTranche.indicies.push_back(i++);
+ formatsVec.push_back(SDMABUFFormatTableEntry{
+ .fmt = fmt.drmFormat,
+ .modifier = mod,
+ });
+ } else {
+ // if it wasn't inserted then find its index in vec
+ auto it =
+ std::find_if(formatsVec.begin(), formatsVec.end(), [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; });
+ rendererTranche.indicies.push_back(it - formatsVec.begin());
}
}
}
- tableLen = formats.size() * sizeof(SDMABUFFeedbackTableEntry);
+ for (auto& [monitor, tranche] : monitorTranches) {
+ tranche.indicies.clear();
+ for (auto& fmt : tranche.formats) {
+ for (auto& mod : fmt.modifiers) {
+ // apparently these can implode on planes, so dont use them
+ if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR)
+ continue;
+ auto format = std::make_pair<>(fmt.drmFormat, mod);
+ auto [_, inserted] = formats.insert(format);
+ if (inserted) {
+ tranche.indicies.push_back(i++);
+ formatsVec.push_back(SDMABUFFormatTableEntry{
+ .fmt = fmt.drmFormat,
+ .modifier = mod,
+ });
+ } else {
+ auto it = std::find_if(formatsVec.begin(), formatsVec.end(),
+ [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; });
+ tranche.indicies.push_back(it - formatsVec.begin());
+ }
+ }
+ }
+ }
+
+ tableSize = formatsVec.size() * sizeof(SDMABUFFormatTableEntry);
+
int fds[2] = {0};
- allocateSHMFilePair(tableLen, &fds[0], &fds[1]);
+ allocateSHMFilePair(tableSize, &fds[0], &fds[1]);
- auto arr = (SDMABUFFeedbackTableEntry*)mmap(nullptr, tableLen, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0);
+ auto arr = (SDMABUFFormatTableEntry*)mmap(nullptr, tableSize, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0);
if (arr == MAP_FAILED) {
LOGM(ERR, "mmap failed");
@@ -47,33 +93,18 @@ CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector<SDMAB
close(fds[0]);
- std::vector<std::pair<uint32_t, uint64_t>> formatsVec;
- for (auto& f : formats) {
- formatsVec.push_back(f);
- }
-
- size_t i = 0;
- for (auto& [fmt, mod] : formatsVec) {
- arr[i++] = SDMABUFFeedbackTableEntry{
- .fmt = fmt,
- .modifier = mod,
- };
- }
+ std::copy(formatsVec.begin(), formatsVec.end(), arr);
- munmap(arr, tableLen);
+ munmap(arr, tableSize);
- mainDevice = device;
- tableFD = fds[1];
- tranches = formatsVec;
-
- // TODO: maybe calculate indices? currently we send all as available which could be wrong? I ain't no kernel dev tho.
+ tableFD = fds[1];
}
-CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() {
+CDMABUFFormatTable::~CDMABUFFormatTable() {
close(tableFD);
}
-CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs) {
+CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) {
buffer = makeShared<CDMABuffer>(id, client, attrs);
buffer->resource->buffer = buffer;
@@ -103,7 +134,7 @@ CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SP<CZwpLinuxBufferParam
resource->setOnDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
resource->setDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
- attrs = makeShared<SDMABUFAttrs>();
+ attrs = makeShared<Aquamarine::SDMABUFAttrs>();
attrs->success = true;
@@ -190,7 +221,7 @@ void CLinuxDMABBUFParamsResource::create(uint32_t id) {
return;
}
- LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs->size, attrs->format, attrs->planes);
+ LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs->size, FormatUtils::drmFormatName(attrs->format), attrs->planes);
for (int i = 0; i < attrs->planes; ++i) {
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs->modifier, attrs->fds[i], attrs->strides[i], attrs->offsets[i]);
}
@@ -277,40 +308,52 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SP<CZwpLinuxDmabufFee
resource->setOnDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); });
resource->setDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); });
- if (surface)
- LOGM(ERR, "FIXME: surface feedback stub");
+ auto& formatTable = PROTO::linuxDma->formatTable;
+ resource->sendFormatTable(formatTable->tableFD, formatTable->tableSize);
+ sendDefaultFeedback();
+}
- auto* feedback = PROTO::linuxDma->defaultFeedback.get();
+CLinuxDMABUFFeedbackResource::~CLinuxDMABUFFeedbackResource() {
+ ;
+}
- resource->sendFormatTable(feedback->tableFD, feedback->tableLen);
+bool CLinuxDMABUFFeedbackResource::good() {
+ return resource->resource();
+}
- // send default feedback
+void CLinuxDMABUFFeedbackResource::sendTranche(SDMABUFTranche& tranche) {
struct wl_array deviceArr = {
- .size = sizeof(feedback->mainDevice),
- .data = (void*)&feedback->mainDevice,
+ .size = sizeof(tranche.device),
+ .data = (void*)&tranche.device,
};
- resource->sendMainDevice(&deviceArr);
resource->sendTrancheTargetDevice(&deviceArr);
- resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)0);
- wl_array indices;
- wl_array_init(&indices);
- for (size_t i = 0; i < feedback->tranches.size(); ++i) {
- *((uint16_t*)wl_array_add(&indices, sizeof(uint16_t))) = i;
- }
+ resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)tranche.flags);
+
+ wl_array indices = {
+ .size = tranche.indicies.size() * sizeof(tranche.indicies.at(0)),
+ .data = tranche.indicies.data(),
+ };
resource->sendTrancheFormats(&indices);
- wl_array_release(&indices);
resource->sendTrancheDone();
-
- resource->sendDone();
}
-CLinuxDMABUFFeedbackResource::~CLinuxDMABUFFeedbackResource() {
- ;
-}
+// default tranche is based on renderer (egl)
+void CLinuxDMABUFFeedbackResource::sendDefaultFeedback() {
+ auto mainDevice = PROTO::linuxDma->mainDevice;
+ auto& formatTable = PROTO::linuxDma->formatTable;
-bool CLinuxDMABUFFeedbackResource::good() {
- return resource->resource();
+ struct wl_array deviceArr = {
+ .size = sizeof(mainDevice),
+ .data = (void*)&mainDevice,
+ };
+ resource->sendMainDevice(&deviceArr);
+
+ sendTranche(formatTable->rendererTranche);
+
+ resource->sendDone();
+
+ lastFeedbackWasScanout = false;
}
CLinuxDMABUFResource::CLinuxDMABUFResource(SP<CZwpLinuxDmabufV1> resource_) : resource(resource_) {
@@ -361,48 +404,81 @@ bool CLinuxDMABUFResource::good() {
}
void CLinuxDMABUFResource::sendMods() {
- for (auto& [fmt, mod] : PROTO::linuxDma->defaultFeedback->tranches) {
- if (resource->version() < 3) {
- if (mod == DRM_FORMAT_MOD_INVALID)
- resource->sendFormat(fmt);
- continue;
- }
+ for (auto& fmt : PROTO::linuxDma->formatTable->rendererTranche.formats) {
+ for (auto& mod : fmt.modifiers) {
+ if (resource->version() < 3) {
+ if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR)
+ resource->sendFormat(fmt.drmFormat);
+ continue;
+ }
- // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166
+ // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166
- resource->sendModifier(fmt, mod >> 32, mod & 0xFFFFFFFF);
+ resource->sendModifier(fmt.drmFormat, mod >> 32, mod & 0xFFFFFFFF);
+ }
}
}
CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
static auto P = g_pHookSystem->hookDynamic("ready", [this](void* self, SCallbackInfo& info, std::any d) {
- int rendererFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer);
+ int rendererFD = g_pCompositor->m_iDRMFD;
auto dev = devIDFromFD(rendererFD);
if (!dev.has_value()) {
- LOGM(ERR, "failed to get drm dev");
- PROTO::linuxDma.reset();
+ protoLog(ERR, "failed to get drm dev, disabling linux dmabuf");
+ removeGlobal();
return;
}
mainDevice = *dev;
- auto fmts = g_pHyprOpenGL->getDRMFormats();
-
- SDMABufTranche tranche = {
- .device = *dev,
- .formats = fmts,
+ SDMABUFTranche eglTranche = {
+ .device = mainDevice,
+ .flags = 0, // renderer isnt for ds so dont set flag.
+ .formats = g_pHyprOpenGL->getDRMFormats(),
};
- std::vector<SDMABufTranche> tches;
- tches.push_back(tranche);
+ std::vector<std::pair<SP<CMonitor>, SDMABUFTranche>> tches;
+
+ if (g_pCompositor->m_pAqBackend->hasSession()) {
+ // this assumes there's only 1 device used for both scanout and rendering
+ // also that each monitor never changes its primary plane
+
+ for (auto& mon : g_pCompositor->m_vMonitors) {
+ auto tranche = SDMABUFTranche{
+ .device = mainDevice,
+ .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT,
+ .formats = mon->output->getRenderFormats(),
+ };
+ tches.push_back(std::make_pair<>(mon, tranche));
+ }
+
+ static auto monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) {
+ auto pMonitor = std::any_cast<CMonitor*>(param);
+ auto mon = pMonitor->self.lock();
+ auto tranche = SDMABUFTranche{
+ .device = mainDevice,
+ .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT,
+ .formats = mon->output->getRenderFormats(),
+ };
+ formatTable->monitorTranches.push_back(std::make_pair<>(mon, tranche));
+ resetFormatTable();
+ });
+
+ static auto monitorRemoved = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) {
+ auto pMonitor = std::any_cast<CMonitor*>(param);
+ auto mon = pMonitor->self.lock();
+ std::erase_if(formatTable->monitorTranches, [mon](std::pair<SP<CMonitor>, SDMABUFTranche> pair) { return pair.first == mon; });
+ resetFormatTable();
+ });
+ }
- defaultFeedback = std::make_unique<CCompiledDMABUFFeedback>(*dev, tches);
+ formatTable = std::make_unique<CDMABUFFormatTable>(eglTranche, tches);
drmDevice* device = nullptr;
if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) {
- LOGM(ERR, "failed to get drm dev");
- PROTO::linuxDma.reset();
+ protoLog(ERR, "failed to get drm dev, disabling linux dmabuf");
+ removeGlobal();
return;
}
@@ -411,17 +487,51 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const
mainDeviceFD = open(name, O_RDWR | O_CLOEXEC);
drmFreeDevice(&device);
if (mainDeviceFD < 0) {
- LOGM(ERR, "failed to open drm dev");
- PROTO::linuxDma.reset();
+ protoLog(ERR, "failed to open drm dev, disabling linux dmabuf");
+ removeGlobal();
return;
}
} else {
- LOGM(ERR, "DRM device {} has no render node!!", device->nodes[DRM_NODE_PRIMARY]);
+ protoLog(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null");
drmFreeDevice(&device);
+ removeGlobal();
}
});
}
+void CLinuxDMABufV1Protocol::resetFormatTable() {
+ if (!formatTable)
+ return;
+
+ LOGM(LOG, "Resetting format table");
+
+ // this might be a big copy
+ auto newFormatTable = std::make_unique<CDMABUFFormatTable>(formatTable->rendererTranche, formatTable->monitorTranches);
+
+ for (auto& feedback : m_vFeedbacks) {
+ feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize);
+ if (feedback->lastFeedbackWasScanout) {
+ SP<CMonitor> mon;
+ auto HLSurface = CWLSurface::fromResource(feedback->surface);
+ if (auto w = HLSurface->getWindow(); w)
+ if (auto m = g_pCompositor->getMonitorFromID(w->m_iMonitorID); m)
+ mon = m->self.lock();
+
+ if (!mon) {
+ feedback->sendDefaultFeedback();
+ return;
+ }
+
+ updateScanoutTranche(feedback->surface, mon);
+ } else {
+ feedback->sendDefaultFeedback();
+ }
+ }
+
+ // delete old table after we sent new one
+ formatTable = std::move(newFormatTable);
+}
+
CLinuxDMABufV1Protocol::~CLinuxDMABufV1Protocol() {
if (mainDeviceFD >= 0)
close(mainDeviceFD);
@@ -452,3 +562,52 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABBUFParamsResource* resour
void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) {
std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; });
}
+
+void CLinuxDMABufV1Protocol::updateScanoutTranche(SP<CWLSurfaceResource> surface, SP<CMonitor> pMonitor) {
+ SP<CLinuxDMABUFFeedbackResource> feedbackResource;
+ for (auto& f : m_vFeedbacks) {
+ if (f->surface != surface)
+ continue;
+
+ feedbackResource = f;
+ break;
+ }
+
+ if (!feedbackResource) {
+ LOGM(LOG, "updateScanoutTranche: surface has no dmabuf_feedback");
+ return;
+ }
+
+ if (!pMonitor) {
+ LOGM(LOG, "updateScanoutTranche: resetting feedback");
+ feedbackResource->sendDefaultFeedback();
+ return;
+ }
+
+ const auto& monitorTranchePair = std::find_if(formatTable->monitorTranches.begin(), formatTable->monitorTranches.end(),
+ [pMonitor](std::pair<SP<CMonitor>, SDMABUFTranche> pair) { return pair.first == pMonitor; });
+
+ if (monitorTranchePair == formatTable->monitorTranches.end()) {
+ LOGM(LOG, "updateScanoutTranche: monitor has no tranche");
+ return;
+ }
+
+ auto& monitorTranche = (*monitorTranchePair).second;
+
+ LOGM(LOG, "updateScanoutTranche: sending a scanout tranche");
+
+ struct wl_array deviceArr = {
+ .size = sizeof(mainDevice),
+ .data = (void*)&mainDevice,
+ };
+ feedbackResource->resource->sendMainDevice(&deviceArr);
+
+ // prioritize scnaout tranche but have renderer fallback tranche
+ // also yes formats can be duped here because different tranche flags (ds and no ds)
+ feedbackResource->sendTranche(monitorTranche);
+ feedbackResource->sendTranche(formatTable->rendererTranche);
+
+ feedbackResource->resource->sendDone();
+
+ feedbackResource->lastFeedbackWasScanout = true;
+}
diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp
index 2b8ce736..0e25cdc6 100644
--- a/src/protocols/LinuxDMABUF.hpp
+++ b/src/protocols/LinuxDMABUF.hpp
@@ -7,15 +7,16 @@
#include "wayland.hpp"
#include "linux-dmabuf-v1.hpp"
#include "../helpers/signal/Signal.hpp"
+#include "../helpers/Format.hpp"
+#include "../helpers/Monitor.hpp"
+#include <aquamarine/buffer/Buffer.hpp>
class CDMABuffer;
-struct SDRMFormat;
-struct SDMABUFAttrs;
class CWLSurfaceResource;
class CLinuxDMABuffer {
public:
- CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs);
+ CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs);
~CLinuxDMABuffer();
bool good();
@@ -31,34 +32,29 @@ class CLinuxDMABuffer {
};
#pragma pack(push, 1)
-struct SDMABUFFeedbackTableEntry {
+struct SDMABUFFormatTableEntry {
uint32_t fmt = 0;
char pad[4];
uint64_t modifier = 0;
};
#pragma pack(pop)
-class SCompiledDMABUFTranche {
- dev_t device = 0;
- uint32_t flags = 0;
- std::vector<uint16_t> indices;
-};
-
-struct SDMABufTranche {
+struct SDMABUFTranche {
dev_t device = 0;
uint32_t flags = 0;
std::vector<SDRMFormat> formats;
+ std::vector<uint16_t> indicies;
};
-class CCompiledDMABUFFeedback {
+class CDMABUFFormatTable {
public:
- CCompiledDMABUFFeedback(dev_t device, std::vector<SDMABufTranche> tranches);
- ~CCompiledDMABUFFeedback();
+ CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector<std::pair<SP<CMonitor>, SDMABUFTranche>> tranches);
+ ~CDMABUFFormatTable();
- dev_t mainDevice = 0;
- int tableFD = -1;
- size_t tableLen = 0;
- std::vector<std::pair<uint32_t, uint64_t>> tranches;
+ int tableFD = -1;
+ size_t tableSize = 0;
+ SDMABUFTranche rendererTranche;
+ std::vector<std::pair<SP<CMonitor>, SDMABUFTranche>> monitorTranches;
};
class CLinuxDMABBUFParamsResource {
@@ -66,12 +62,12 @@ class CLinuxDMABBUFParamsResource {
CLinuxDMABBUFParamsResource(SP<CZwpLinuxBufferParamsV1> resource_);
~CLinuxDMABBUFParamsResource();
- bool good();
- void create(uint32_t id); // 0 means not immed
+ bool good();
+ void create(uint32_t id); // 0 means not immed
- SP<SDMABUFAttrs> attrs;
- WP<CLinuxDMABuffer> createdBuffer;
- bool used = false;
+ SP<Aquamarine::SDMABUFAttrs> attrs;
+ WP<CLinuxDMABuffer> createdBuffer;
+ bool used = false;
private:
SP<CZwpLinuxBufferParamsV1> resource;
@@ -86,11 +82,16 @@ class CLinuxDMABUFFeedbackResource {
~CLinuxDMABUFFeedbackResource();
bool good();
+ void sendDefaultFeedback();
+ void sendTranche(SDMABUFTranche& tranche);
SP<CWLSurfaceResource> surface; // optional, for surface feedbacks
private:
SP<CZwpLinuxDmabufFeedbackV1> resource;
+ bool lastFeedbackWasScanout = false;
+
+ friend class CLinuxDMABufV1Protocol;
};
class CLinuxDMABUFResource {
@@ -110,6 +111,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol {
~CLinuxDMABufV1Protocol();
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+ void updateScanoutTranche(SP<CWLSurfaceResource> surface, SP<CMonitor> pMonitor);
private:
void destroyResource(CLinuxDMABUFResource* resource);
@@ -117,13 +119,15 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol {
void destroyResource(CLinuxDMABBUFParamsResource* resource);
void destroyResource(CLinuxDMABuffer* resource);
+ void resetFormatTable();
+
//
std::vector<SP<CLinuxDMABUFResource>> m_vManagers;
std::vector<SP<CLinuxDMABUFFeedbackResource>> m_vFeedbacks;
std::vector<SP<CLinuxDMABBUFParamsResource>> m_vParams;
std::vector<SP<CLinuxDMABuffer>> m_vBuffers;
- UP<CCompiledDMABUFFeedback> defaultFeedback;
+ UP<CDMABUFFormatTable> formatTable;
dev_t mainDevice;
int mainDeviceFD = -1;
diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp
index 0bcf4a9c..ed412555 100644
--- a/src/protocols/MesaDRM.cpp
+++ b/src/protocols/MesaDRM.cpp
@@ -2,12 +2,11 @@
#include <algorithm>
#include <xf86drm.h>
#include "../Compositor.hpp"
-#include <wlr/render/drm_format_set.h>
#include "types/WLBuffer.hpp"
#define LOGM PROTO::mesaDRM->protoLog
-CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) {
+CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) {
LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes);
for (int i = 0; i < attrs_.planes; ++i) {
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i], attrs_.strides[i], attrs_.offsets[i]);
@@ -60,10 +59,27 @@ CMesaDRMResource::CMesaDRMResource(SP<CWlDrm> resource_) : resource(resource_) {
return;
}
- SDMABUFAttrs attrs;
+ uint64_t mod = DRM_FORMAT_MOD_INVALID;
+
+ auto fmts = g_pHyprOpenGL->getDRMFormats();
+ for (auto& f : fmts) {
+ if (f.drmFormat != fmt)
+ continue;
+
+ for (auto& m : f.modifiers) {
+ if (m == DRM_FORMAT_MOD_LINEAR)
+ continue;
+
+ mod = m;
+ break;
+ }
+ break;
+ }
+
+ Aquamarine::SDMABUFAttrs attrs;
attrs.success = true;
attrs.size = {w, h};
- attrs.modifier = DRM_FORMAT_MOD_INVALID;
+ attrs.modifier = mod;
attrs.planes = 1;
attrs.offsets[0] = off0;
attrs.strides[0] = str0;
@@ -87,7 +103,7 @@ CMesaDRMResource::CMesaDRMResource(SP<CWlDrm> resource_) : resource(resource_) {
auto fmts = g_pHyprOpenGL->getDRMFormats();
for (auto& fmt : fmts) {
- resource->sendFormat(fmt.format);
+ resource->sendFormat(fmt.drmFormat);
}
}
@@ -97,10 +113,10 @@ bool CMesaDRMResource::good() {
CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
drmDevice* dev = nullptr;
- int drmFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer);
+ int drmFD = g_pCompositor->m_iDRMFD;
if (drmGetDevice2(drmFD, 0, &dev) != 0) {
- LOGM(ERR, "Failed to get device");
- PROTO::mesaDRM.reset();
+ protoLog(ERR, "Failed to get device, disabling MesaDRM");
+ removeGlobal();
return;
}
@@ -108,7 +124,15 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co
nodeName = dev->nodes[DRM_NODE_RENDER];
} else {
ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY));
- LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]);
+
+ if (!dev->nodes[DRM_NODE_PRIMARY]) {
+ protoLog(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM");
+ drmFreeDevice(&dev);
+ removeGlobal();
+ return;
+ }
+
+ protoLog(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]);
nodeName = dev->nodes[DRM_NODE_PRIMARY];
}
drmFreeDevice(&dev);
diff --git a/src/protocols/MesaDRM.hpp b/src/protocols/MesaDRM.hpp
index ad31a182..46811d68 100644
--- a/src/protocols/MesaDRM.hpp
+++ b/src/protocols/MesaDRM.hpp
@@ -10,7 +10,7 @@
class CMesaDRMBufferResource {
public:
- CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs);
+ CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs);
~CMesaDRMBufferResource();
bool good();
diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp
index 68c50193..66f4c5f0 100644
--- a/src/protocols/OutputManagement.cpp
+++ b/src/protocols/OutputManagement.cpp
@@ -2,6 +2,8 @@
#include <algorithm>
#include "../Compositor.hpp"
+using namespace Aquamarine;
+
#define LOGM PROTO::outputManagement->protoLog
COutputManager::COutputManager(SP<CZwlrOutputManagerV1> resource_) : resource(resource_) {
@@ -123,8 +125,8 @@ void COutputHead::sendAllData() {
resource->sendName(pMonitor->szName.c_str());
resource->sendDescription(pMonitor->szDescription.c_str());
- if (pMonitor->output->phys_width > 0 && pMonitor->output->phys_height > 0)
- resource->sendPhysicalSize(pMonitor->output->phys_width, pMonitor->output->phys_height);
+ if (pMonitor->output->physicalSize.x > 0 && pMonitor->output->physicalSize.y > 0)
+ resource->sendPhysicalSize(pMonitor->output->physicalSize.x, pMonitor->output->physicalSize.y);
resource->sendEnabled(pMonitor->m_bEnabled);
if (pMonitor->m_bEnabled) {
@@ -133,12 +135,12 @@ void COutputHead::sendAllData() {
resource->sendScale(wl_fixed_from_double(pMonitor->scale));
}
- if (pMonitor->output->make && VERSION >= 2)
- resource->sendMake(pMonitor->output->make);
- if (pMonitor->output->model && VERSION >= 2)
- resource->sendModel(pMonitor->output->model);
- if (pMonitor->output->serial && VERSION >= 2)
- resource->sendSerialNumber(pMonitor->output->serial);
+ if (!pMonitor->output->make.empty() && VERSION >= 2)
+ resource->sendMake(pMonitor->output->make.c_str());
+ if (!pMonitor->output->model.empty() && VERSION >= 2)
+ resource->sendModel(pMonitor->output->model.c_str());
+ if (!pMonitor->output->serial.empty() && VERSION >= 2)
+ resource->sendSerialNumber(pMonitor->output->serial.c_str());
if (VERSION >= 4)
resource->sendAdaptiveSync(pMonitor->vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED);
@@ -146,12 +148,12 @@ void COutputHead::sendAllData() {
// send all available modes
if (modes.empty()) {
- if (!wl_list_empty(&pMonitor->output->modes)) {
- wlr_output_mode* mode;
-
- wl_list_for_each(mode, &pMonitor->output->modes, link) {
- makeAndSendNewMode(mode);
+ if (!pMonitor->output->modes.empty()) {
+ for (auto& m : pMonitor->output->modes) {
+ makeAndSendNewMode(m);
}
+ } else if (pMonitor->output->state->state().customMode) {
+ makeAndSendNewMode(pMonitor->output->state->state().customMode);
} else
makeAndSendNewMode(nullptr);
}
@@ -164,9 +166,9 @@ void COutputHead::sendAllData() {
if (!m)
continue;
- if (m->mode == pMonitor->currentMode) {
+ if (m->mode == pMonitor->output->state->state().mode) {
if (m->mode)
- LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh);
+ LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate);
else
LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName);
resource->sendCurrentMode(m->resource.get());
@@ -197,7 +199,7 @@ void COutputHead::updateMode() {
if (m->mode == pMonitor->currentMode) {
if (m->mode)
- LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh);
+ LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate);
else
LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName);
resource->sendCurrentMode(m->resource.get());
@@ -207,7 +209,7 @@ void COutputHead::updateMode() {
}
}
-void COutputHead::makeAndSendNewMode(wlr_output_mode* mode) {
+void COutputHead::makeAndSendNewMode(SP<Aquamarine::SOutputMode> mode) {
const auto RESOURCE = PROTO::outputManagement->m_vModes.emplace_back(makeShared<COutputMode>(makeShared<CZwlrOutputModeV1>(resource->client(), resource->version(), 0), mode));
if (!RESOURCE->good()) {
@@ -225,7 +227,7 @@ CMonitor* COutputHead::monitor() {
return pMonitor;
}
-COutputMode::COutputMode(SP<CZwlrOutputModeV1> resource_, wlr_output_mode* mode_) : resource(resource_), mode(mode_) {
+COutputMode::COutputMode(SP<CZwlrOutputModeV1> resource_, SP<Aquamarine::SOutputMode> mode_) : resource(resource_), mode(mode_) {
if (!good())
return;
@@ -237,11 +239,11 @@ void COutputMode::sendAllData() {
if (!mode)
return;
- LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->width, mode->height, mode->refresh, mode->preferred);
+ LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate, mode->preferred);
- resource->sendSize(mode->width, mode->height);
- if (mode->refresh > 0)
- resource->sendRefresh(mode->refresh);
+ resource->sendSize(mode->pixelSize.x, mode->pixelSize.y);
+ if (mode->refreshRate > 0)
+ resource->sendRefresh(mode->refreshRate);
if (mode->preferred)
resource->sendPreferred();
}
@@ -250,8 +252,8 @@ bool COutputMode::good() {
return resource->resource();
}
-wlr_output_mode* COutputMode::getMode() {
- return mode;
+SP<Aquamarine::SOutputMode> COutputMode::getMode() {
+ return mode.lock();
}
COutputConfiguration::COutputConfiguration(SP<CZwlrOutputConfigurationV1> resource_, SP<COutputManager> owner_) : resource(resource_), owner(owner_) {
@@ -364,8 +366,8 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {
newRule.disabled = false;
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
- newRule.resolution = {head->state.mode->getMode()->width, head->state.mode->getMode()->height};
- newRule.refreshRate = head->state.mode->getMode()->refresh / 1000.F;
+ newRule.resolution = head->state.mode->getMode()->pixelSize;
+ newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F;
} else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
newRule.resolution = head->state.customMode.size;
newRule.refreshRate = head->state.customMode.refresh / 1000.F;
@@ -425,7 +427,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
committedProperties |= OUTPUT_HEAD_COMMITTED_MODE;
state.mode = MODE;
- LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->width, MODE->getMode()->height, MODE->getMode()->refresh);
+ LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate);
});
resource->setSetCustomMode([this](CZwlrOutputConfigurationHeadV1* r, int32_t w, int32_t h, int32_t refresh) {
diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp
index 81ae9a71..36478d0b 100644
--- a/src/protocols/OutputManagement.hpp
+++ b/src/protocols/OutputManagement.hpp
@@ -6,6 +6,7 @@
#include "WaylandProtocol.hpp"
#include "wlr-output-management-unstable-v1.hpp"
#include "../helpers/signal/Signal.hpp"
+#include <aquamarine/output/Output.hpp>
class CMonitor;
@@ -34,15 +35,15 @@ class COutputManager {
class COutputMode {
public:
- COutputMode(SP<CZwlrOutputModeV1> resource_, wlr_output_mode* mode_);
+ COutputMode(SP<CZwlrOutputModeV1> resource_, SP<Aquamarine::SOutputMode> mode_);
- bool good();
- wlr_output_mode* getMode();
- void sendAllData();
+ bool good();
+ SP<Aquamarine::SOutputMode> getMode();
+ void sendAllData();
private:
- SP<CZwlrOutputModeV1> resource;
- wlr_output_mode* mode = nullptr;
+ SP<CZwlrOutputModeV1> resource;
+ WP<Aquamarine::SOutputMode> mode;
friend class COutputHead;
friend class COutputManagementProtocol;
@@ -61,7 +62,7 @@ class COutputHead {
SP<CZwlrOutputHeadV1> resource;
CMonitor* pMonitor = nullptr;
- void makeAndSendNewMode(wlr_output_mode* mode);
+ void makeAndSendNewMode(SP<Aquamarine::SOutputMode> mode);
void sendCurrentMode();
std::vector<WP<COutputMode>> modes;
diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp
index ef287cfa..597b9871 100644
--- a/src/protocols/OutputPower.cpp
+++ b/src/protocols/OutputPower.cpp
@@ -17,7 +17,7 @@ COutputPower::COutputPower(SP<CZwlrOutputPowerV1> resource_, CMonitor* pMonitor_
pMonitor->dpmsStatus = mode == ZWLR_OUTPUT_POWER_V1_MODE_ON;
- wlr_output_state_set_enabled(pMonitor->state.wlr(), pMonitor->dpmsStatus);
+ pMonitor->output->state->setEnabled(mode == ZWLR_OUTPUT_POWER_V1_MODE_ON);
if (!pMonitor->state.commit())
LOGM(ERR, "Couldn't set dpms to {} for {}", pMonitor->dpmsStatus, pMonitor->szName);
diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp
index 3907bf1e..e9472fc3 100644
--- a/src/protocols/PresentationTime.cpp
+++ b/src/protocols/PresentationTime.cpp
@@ -3,6 +3,8 @@
#include "../helpers/Monitor.hpp"
#include "../managers/HookSystemManager.hpp"
#include "core/Compositor.hpp"
+#include "core/Output.hpp"
+#include <aquamarine/output/Output.hpp>
#define LOGM PROTO::presentation->protoLog
@@ -41,13 +43,11 @@ bool CPresentationFeedback::good() {
}
void CPresentationFeedback::sendQueued(SP<CQueuedPresentationData> data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) {
- auto client = resource->client();
- wl_resource* res;
- wl_resource_for_each(res, &data->pMonitor->output->resources) {
- if (client == wl_resource_get_client(res)) {
- resource->sendSyncOutput(res);
- break;
- }
+ auto client = resource->client();
+
+ if (PROTO::outputs.contains(data->pMonitor->szName)) {
+ if (auto outputResource = PROTO::outputs.at(data->pMonitor->szName)->outputResourceFrom(client); outputResource)
+ resource->sendSyncOutput(outputResource->getResource()->resource());
}
uint32_t flags = 0;
@@ -55,9 +55,9 @@ void CPresentationFeedback::sendQueued(SP<CQueuedPresentationData> data, timespe
flags |= WP_PRESENTATION_FEEDBACK_KIND_VSYNC;
if (data->zeroCopy)
flags |= WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY;
- if (reportedFlags & WLR_OUTPUT_PRESENT_HW_CLOCK)
+ if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_CLOCK)
flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
- if (reportedFlags & WLR_OUTPUT_PRESENT_HW_COMPLETION)
+ if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION)
flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION;
if (data->wasPresented && when)
diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp
index 8a6285a1..5d1c9332 100644
--- a/src/protocols/Screencopy.cpp
+++ b/src/protocols/Screencopy.cpp
@@ -266,20 +266,17 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
return;
}
- if (PFRAME->pMonitor->output->allocator && (PFRAME->pMonitor->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) {
- PFRAME->dmabufFormat = PFRAME->pMonitor->output->render_format;
- } else {
- PFRAME->dmabufFormat = DRM_FORMAT_INVALID;
- }
+ PFRAME->dmabufFormat = PFRAME->pMonitor->output->state->state().drmFormat;
if (box.width == 0 && box.height == 0)
PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x), (int)(PFRAME->pMonitor->vecSize.y)};
else {
PFRAME->box = box;
}
- int ow, oh;
- wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh);
- PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), ow, oh).scale(PFRAME->pMonitor->scale).round();
+
+ PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), PFRAME->pMonitor->vecTransformedSize.x, PFRAME->pMonitor->vecTransformedSize.y)
+ .scale(PFRAME->pMonitor->scale)
+ .round();
PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
@@ -383,10 +380,10 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
g_pHyprRenderer->damageMonitor(PFRAME->pMonitor);
}
-void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
- m_pLastMonitorBackBuffer = e->state->buffer;
+void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor) {
+ m_pLastMonitorBackBuffer = pMonitor->output->state->state().buffer;
shareAllFrames(pMonitor);
- m_pLastMonitorBackBuffer = nullptr;
+ m_pLastMonitorBackBuffer.reset();
}
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) {
@@ -473,11 +470,7 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
}
bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
- wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer);
- if (!sourceTex)
- return false;
-
- auto TEXTURE = makeShared<CTexture>(sourceTex);
+ auto TEXTURE = makeShared<CTexture>(m_pLastMonitorBackBuffer);
auto shm = frame->buffer->shm();
auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm
@@ -487,10 +480,10 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
g_pHyprRenderer->makeEGLCurrent();
CFramebuffer fb;
- fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat);
+ fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->output->state->state().drmFormat);
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) {
- wlr_texture_destroy(sourceTex);
+ Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering");
return false;
}
@@ -509,8 +502,8 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format);
if (!PFORMAT) {
+ Debug::log(ERR, "Screencopy: can't copy: failed to find a pixel format");
g_pHyprRenderer->endRender();
- wlr_texture_destroy(sourceTex);
return false;
}
@@ -539,27 +532,24 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
- wlr_texture_destroy(sourceTex);
+ Debug::log(TRACE, "Screencopy: copied frame via shm");
return true;
}
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
- wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer);
- if (!sourceTex)
- return false;
-
- auto TEXTURE = makeShared<CTexture>(sourceTex);
+ auto TEXTURE = makeShared<CTexture>(m_pLastMonitorBackBuffer);
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
- if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true))
+ if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) {
+ Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering to dma frame");
return false;
+ }
- CBox monbox =
- CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}
- .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh.
- .transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->output->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y);
+ CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}
+ .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh.
+ .transform(wlTransformToHyprutils(invertTransform(frame->pMonitor->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y);
g_pHyprOpenGL->setMonitorTransformEnabled(true);
g_pHyprOpenGL->setRenderModifEnabled(false);
g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1);
@@ -569,7 +559,7 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
g_pHyprOpenGL->m_RenderData.blockScreenShader = true;
g_pHyprRenderer->endRender();
- wlr_texture_destroy(sourceTex);
+ Debug::log(TRACE, "Screencopy: copied frame via dma");
return true;
}
diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp
index be434285..4999773b 100644
--- a/src/protocols/Screencopy.hpp
+++ b/src/protocols/Screencopy.hpp
@@ -8,9 +8,10 @@
#include "../managers/HookSystemManager.hpp"
#include "../helpers/Timer.hpp"
#include "../managers/eventLoop/EventLoopTimer.hpp"
+#include <aquamarine/buffer/Buffer.hpp>
class CMonitor;
-class IWLBuffer;
+class IHLBuffer;
enum eClientOwners {
CLIENT_SCREENCOPY = 0,
@@ -56,7 +57,7 @@ struct SScreencopyFrame {
bool bufferDMA = false;
- WP<IWLBuffer> buffer;
+ WP<IHLBuffer> buffer;
CMonitor* pMonitor = nullptr;
PHLWINDOWREF pWindow;
@@ -79,7 +80,7 @@ class CScreencopyProtocolManager {
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
- void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
+ void onOutputCommit(CMonitor* pMonitor);
private:
wl_global* m_pGlobal = nullptr;
@@ -93,7 +94,7 @@ class CScreencopyProtocolManager {
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
- wlr_buffer* m_pLastMonitorBackBuffer = nullptr;
+ SP<Aquamarine::IBuffer> m_pLastMonitorBackBuffer;
void shareAllFrames(CMonitor* pMonitor);
void shareFrame(SScreencopyFrame* frame);
diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp
index 7b62f245..72c7cfde 100644
--- a/src/protocols/Tablet.cpp
+++ b/src/protocols/Tablet.cpp
@@ -5,6 +5,7 @@
#include "core/Seat.hpp"
#include "core/Compositor.hpp"
#include <algorithm>
+#include <cstring>
#define LOGM PROTO::tablet->protoLog
@@ -44,17 +45,17 @@ bool CTabletPadGroupV2Resource::good() {
return resource->resource();
}
-void CTabletPadGroupV2Resource::sendData(SP<CTabletPad> pad, wlr_tablet_pad_group* group) {
- resource->sendModes(group->mode_count);
+void CTabletPadGroupV2Resource::sendData(SP<CTabletPad> pad, SP<Aquamarine::ITabletPad::STabletPadGroup> group) {
+ resource->sendModes(group->modes);
wl_array buttonArr;
wl_array_init(&buttonArr);
- wl_array_add(&buttonArr, group->button_count * sizeof(int));
- memcpy(buttonArr.data, group->buttons, group->button_count * sizeof(int));
+ wl_array_add(&buttonArr, group->buttons.size() * sizeof(int));
+ memcpy(buttonArr.data, group->buttons.data(), group->buttons.size() * sizeof(int));
resource->sendButtons(&buttonArr);
wl_array_release(&buttonArr);
- for (size_t i = 0; i < group->strip_count; ++i) {
+ for (size_t i = 0; i < group->strips.size(); ++i) {
const auto RESOURCE =
PROTO::tablet->m_vStrips.emplace_back(makeShared<CTabletPadStripV2Resource>(makeShared<CZwpTabletPadStripV2>(resource->client(), resource->version(), 0), i));
@@ -67,7 +68,7 @@ void CTabletPadGroupV2Resource::sendData(SP<CTabletPad> pad, wlr_tablet_pad_grou
resource->sendStrip(RESOURCE->resource.get());
}
- for (size_t i = 0; i < group->ring_count; ++i) {
+ for (size_t i = 0; i < group->rings.size(); ++i) {
const auto RESOURCE =
PROTO::tablet->m_vRings.emplace_back(makeShared<CTabletPadRingV2Resource>(makeShared<CZwpTabletPadRingV2>(resource->client(), resource->version(), 0), i));
@@ -97,23 +98,20 @@ bool CTabletPadV2Resource::good() {
void CTabletPadV2Resource::sendData() {
// this is dodgy as fuck. I hate wl_array. it's expanded wl_array_for_each because C++ would complain about the implicit casts
- const char** path_ptr;
- for (path_ptr = (const char**)(&pad->wlr()->paths)->data; (const char*)path_ptr < ((const char*)(&pad->wlr()->paths)->data + (&pad->wlr()->paths)->size); (path_ptr)++) {
- resource->sendPath(*path_ptr);
+ for (auto& p : pad->aq()->paths) {
+ resource->sendPath(p.c_str());
}
- resource->sendButtons(pad->wlr()->button_count);
+ resource->sendButtons(pad->aq()->buttons);
- wlr_tablet_pad_group* group;
- size_t i = 0;
- wl_list_for_each(group, &pad->wlr()->groups, link) {
- createGroup(group, i++);
+ for (size_t i = 0; i < pad->aq()->groups.size(); ++i) {
+ createGroup(pad->aq()->groups.at(i), i);
}
resource->sendDone();
}
-void CTabletPadV2Resource::createGroup(wlr_tablet_pad_group* group, size_t idx) {
+void CTabletPadV2Resource::createGroup(SP<Aquamarine::ITabletPad::STabletPadGroup> group, size_t idx) {
const auto RESOURCE =
PROTO::tablet->m_vGroups.emplace_back(makeShared<CTabletPadGroupV2Resource>(makeShared<CZwpTabletPadGroupV2>(resource->client(), resource->version(), 0), idx));
@@ -142,13 +140,10 @@ bool CTabletV2Resource::good() {
void CTabletV2Resource::sendData() {
resource->sendName(tablet->deviceName.c_str());
- resource->sendId(tablet->wlr()->usb_vendor_id, tablet->wlr()->usb_product_id);
+ resource->sendId(tablet->aq()->usbVendorID, tablet->aq()->usbProductID);
- // this is dodgy as fuck. I hate wl_array. it's expanded wl_array_for_each because C++ would complain about the implicit casts
- const char** path_ptr;
- for (path_ptr = (const char**)(&tablet->wlr()->paths)->data; (const char*)path_ptr < ((const char*)(&tablet->wlr()->paths)->data + (&tablet->wlr()->paths)->size);
- (path_ptr)++) {
- resource->sendPath(*path_ptr);
+ for (auto& p : tablet->aq()->paths) {
+ resource->sendPath(p.c_str());
}
resource->sendDone();
@@ -179,23 +174,23 @@ bool CTabletToolV2Resource::good() {
}
void CTabletToolV2Resource::sendData() {
- static auto WLR_TYPE_TO_PROTO = [](uint32_t wlr) -> zwpTabletToolV2Type {
- switch (wlr) {
- case WLR_TABLET_TOOL_TYPE_PEN: return ZWP_TABLET_TOOL_V2_TYPE_PEN;
- case WLR_TABLET_TOOL_TYPE_ERASER: return ZWP_TABLET_TOOL_V2_TYPE_ERASER;
- case WLR_TABLET_TOOL_TYPE_BRUSH: return ZWP_TABLET_TOOL_V2_TYPE_BRUSH;
- case WLR_TABLET_TOOL_TYPE_PENCIL: return ZWP_TABLET_TOOL_V2_TYPE_PENCIL;
- case WLR_TABLET_TOOL_TYPE_AIRBRUSH: return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH;
- case WLR_TABLET_TOOL_TYPE_MOUSE: return ZWP_TABLET_TOOL_V2_TYPE_MOUSE;
- case WLR_TABLET_TOOL_TYPE_LENS: return ZWP_TABLET_TOOL_V2_TYPE_LENS;
+ static auto AQ_TYPE_TO_PROTO = [](uint32_t aq) -> zwpTabletToolV2Type {
+ switch (aq) {
+ case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_PEN: return ZWP_TABLET_TOOL_V2_TYPE_PEN;
+ case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_ERASER: return ZWP_TABLET_TOOL_V2_TYPE_ERASER;
+ case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_BRUSH: return ZWP_TABLET_TOOL_V2_TYPE_BRUSH;
+ case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_PENCIL: return ZWP_TABLET_TOOL_V2_TYPE_PENCIL;
+ case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_AIRBRUSH: return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH;
+ case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE: return ZWP_TABLET_TOOL_V2_TYPE_MOUSE;
+ case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_LENS: return ZWP_TABLET_TOOL_V2_TYPE_LENS;
default: ASSERT(false);
}
UNREACHABLE();
};
- resource->sendType(WLR_TYPE_TO_PROTO(tool->wlr()->type));
- resource->sendHardwareSerial(tool->wlr()->hardware_serial >> 32, tool->wlr()->hardware_serial & 0xFFFFFFFF);
- resource->sendHardwareIdWacom(tool->wlr()->hardware_wacom >> 32, tool->wlr()->hardware_wacom & 0xFFFFFFFF);
+ resource->sendType(AQ_TYPE_TO_PROTO(tool->aq()->type));
+ resource->sendHardwareSerial(tool->aq()->serial >> 32, tool->aq()->serial & 0xFFFFFFFF);
+ resource->sendHardwareIdWacom(tool->aq()->id >> 32, tool->aq()->id & 0xFFFFFFFF);
if (tool->toolCapabilities & CTabletTool::eTabletToolCapabilities::HID_TABLET_TOOL_CAPABILITY_DISTANCE)
resource->sendCapability(zwpTabletToolV2Capability::ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE);
if (tool->toolCapabilities & CTabletTool::eTabletToolCapabilities::HID_TABLET_TOOL_CAPABILITY_PRESSURE)
diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp
index 58f13c1a..1ebcb1e5 100644
--- a/src/protocols/Tablet.hpp
+++ b/src/protocols/Tablet.hpp
@@ -6,6 +6,7 @@
#include "WaylandProtocol.hpp"
#include "tablet-v2.hpp"
#include "../helpers/math/Math.hpp"
+#include <aquamarine/input/Input.hpp>
class CTablet;
class CTabletTool;
@@ -51,7 +52,7 @@ class CTabletPadGroupV2Resource {
CTabletPadGroupV2Resource(SP<CZwpTabletPadGroupV2> resource_, size_t idx);
bool good();
- void sendData(SP<CTabletPad> pad, wlr_tablet_pad_group* group);
+ void sendData(SP<CTabletPad> pad, SP<Aquamarine::ITabletPad::STabletPadGroup> group);
std::vector<WP<CTabletPadRingV2Resource>> rings;
std::vector<WP<CTabletPadStripV2Resource>> strips;
@@ -83,7 +84,7 @@ class CTabletPadV2Resource {
private:
SP<CZwpTabletPadV2> resource;
- void createGroup(wlr_tablet_pad_group* group, size_t idx);
+ void createGroup(SP<Aquamarine::ITabletPad::STabletPadGroup> group, size_t idx);
friend class CTabletSeat;
friend class CTabletV2Protocol;
diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp
index d4c66c3b..0e78e5f7 100644
--- a/src/protocols/ToplevelExport.cpp
+++ b/src/protocols/ToplevelExport.cpp
@@ -193,16 +193,11 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
return;
}
- if (PMONITOR->output->allocator && (PMONITOR->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) {
- PFRAME->dmabufFormat = PMONITOR->output->render_format;
- } else {
- PFRAME->dmabufFormat = DRM_FORMAT_INVALID;
- }
+ PFRAME->dmabufFormat = PMONITOR->output->state->state().drmFormat;
PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)};
- int ow, oh;
- wlr_output_effective_resolution(PMONITOR->output, &ow, &oh);
- PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), ow, oh).round();
+
+ PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round();
PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
@@ -289,12 +284,10 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
m_vFramesAwaitingWrite.emplace_back(PFRAME);
}
-void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
+void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor) {
if (m_vFramesAwaitingWrite.empty())
return; // nothing to share
- const auto PMONITOR = g_pCompositor->getMonitorFromOutput(e->output);
-
std::vector<SScreencopyFrame*> framesToRemove;
// share frame if correct output
@@ -306,7 +299,7 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp
continue;
}
- if (PMONITOR != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID))
+ if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID))
continue;
CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y};
@@ -370,7 +363,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
g_pHyprRenderer->makeEGLCurrent();
CFramebuffer outFB;
- outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->drmFormat);
+ outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->output->state->state().drmFormat);
if (frame->overlayCursor) {
g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock());
diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp
index f044a781..c3620d41 100644
--- a/src/protocols/ToplevelExport.hpp
+++ b/src/protocols/ToplevelExport.hpp
@@ -21,7 +21,7 @@ class CToplevelExportProtocolManager {
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage);
void displayDestroy();
void onWindowUnmap(PHLWINDOW pWindow);
- void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
+ void onOutputCommit(CMonitor* pMonitor);
private:
wl_global* m_pGlobal = nullptr;
diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp
index 8cb69dbe..03c5775e 100644
--- a/src/protocols/Viewporter.cpp
+++ b/src/protocols/Viewporter.cpp
@@ -52,6 +52,21 @@ CViewportResource::CViewportResource(SP<CWpViewport> resource_, SP<CWLSurfaceRes
surface->pending.viewport.hasSource = true;
surface->pending.viewport.source = {x, y, w, h};
});
+
+ listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) {
+ if (!surface || !surface->pending.buffer)
+ return;
+
+ if (surface->pending.viewport.hasSource) {
+ auto& src = surface->pending.viewport.source;
+
+ if (src.w + src.x > surface->pending.buffer->size.x || src.h + src.y > surface->pending.buffer->size.y) {
+ resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit");
+ surface->pending.rejected = true;
+ return;
+ }
+ }
+ });
}
CViewportResource::~CViewportResource() {
@@ -66,20 +81,6 @@ bool CViewportResource::good() {
return resource->resource();
}
-void CViewportResource::verify() {
- if (!surface)
- return;
-
- if (surface->pending.viewport.hasSource) {
- auto& src = surface->pending.viewport.source;
-
- if (src.w + src.x > surface->pending.size.x || src.h + src.y > surface->pending.size.y) {
- resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit");
- return;
- }
- }
-}
-
CViewporterResource::CViewporterResource(SP<CWpViewporter> resource_) : resource(resource_) {
if (!good())
return;
diff --git a/src/protocols/Viewporter.hpp b/src/protocols/Viewporter.hpp
index 01278203..3c2a4eef 100644
--- a/src/protocols/Viewporter.hpp
+++ b/src/protocols/Viewporter.hpp
@@ -15,11 +15,14 @@ class CViewportResource {
~CViewportResource();
bool good();
- void verify();
WP<CWLSurfaceResource> surface;
private:
SP<CWpViewport> resource;
+
+ struct {
+ CHyprSignalListener surfacePrecommit;
+ } listeners;
};
class CViewporterResource {
diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp
index 009c277c..2642ec11 100644
--- a/src/protocols/VirtualKeyboard.cpp
+++ b/src/protocols/VirtualKeyboard.cpp
@@ -1,12 +1,9 @@
#include "VirtualKeyboard.hpp"
#include <sys/mman.h>
+#include "../devices/IKeyboard.hpp"
#define LOGM PROTO::virtualKeyboard->protoLog
-static const struct wlr_keyboard_impl virtualKeyboardImpl = {
- .name = "virtual-keyboard",
-};
-
CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) {
if (!good())
return;
@@ -28,13 +25,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
return;
}
- wlr_keyboard_key_event event = {
- .time_msec = timeMs,
- .keycode = key,
- .update_state = false,
- .state = (wl_keyboard_key_state)state,
- };
- wlr_keyboard_notify_key(&keyboard, &event);
+ events.key.emit(IKeyboard::SKeyEvent{
+ .timeMs = timeMs,
+ .keycode = key,
+ .state = (wl_keyboard_key_state)state,
+ });
+
+ const bool CONTAINS = std::find(pressed.begin(), pressed.end(), key) != pressed.end();
+ if (state && !CONTAINS)
+ pressed.emplace_back(key);
+ else if (!state && CONTAINS)
+ std::erase(pressed, key);
});
resource->setModifiers([this](CZwpVirtualKeyboardV1* r, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) {
@@ -43,7 +44,12 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
return;
}
- wlr_keyboard_notify_modifiers(&keyboard, depressed, latched, locked, group);
+ events.modifiers.emit(IKeyboard::SModifiersEvent{
+ .depressed = depressed,
+ .latched = latched,
+ .locked = locked,
+ .group = group,
+ });
});
resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) {
@@ -75,7 +81,9 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
return;
}
- wlr_keyboard_set_keymap(&keyboard, xkbKeymap);
+ events.keymap.emit(IKeyboard::SKeymapEvent{
+ .keymap = xkbKeymap,
+ });
hasKeymap = true;
xkb_keymap_unref(xkbKeymap);
@@ -83,22 +91,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
close(fd);
});
- wlr_keyboard_init(&keyboard, &virtualKeyboardImpl, "CVirtualKeyboard");
+ name = "hl-virtual-keyboard";
}
CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() {
events.destroy.emit();
- wlr_keyboard_finish(&keyboard);
}
bool CVirtualKeyboardV1Resource::good() {
return resource->resource();
}
-wlr_keyboard* CVirtualKeyboardV1Resource::wlr() {
- return &keyboard;
-}
-
wl_client* CVirtualKeyboardV1Resource::client() {
return resource->resource() ? resource->client() : nullptr;
}
@@ -106,17 +109,16 @@ wl_client* CVirtualKeyboardV1Resource::client() {
void CVirtualKeyboardV1Resource::releasePressed() {
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
- size_t keycodesNum = keyboard.num_keycodes;
-
- for (size_t i = 0; i < keycodesNum; ++i) {
- struct wlr_keyboard_key_event event = {
- .time_msec = (now.tv_sec * 1000 + now.tv_nsec / 1000000),
- .keycode = keyboard.keycodes[keycodesNum - i - 1],
- .update_state = false,
- .state = WL_KEYBOARD_KEY_STATE_RELEASED,
- };
- wlr_keyboard_notify_key(&keyboard, &event); // updates num_keycodes
+
+ for (auto& p : pressed) {
+ events.key.emit(IKeyboard::SKeyEvent{
+ .timeMs = now.tv_sec * 1000 + now.tv_nsec / 1000000,
+ .keycode = p,
+ .state = WL_KEYBOARD_KEY_STATE_RELEASED,
+ });
}
+
+ pressed.clear();
}
CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp
index 447b5db9..93b63bb5 100644
--- a/src/protocols/VirtualKeyboard.hpp
+++ b/src/protocols/VirtualKeyboard.hpp
@@ -14,19 +14,24 @@ class CVirtualKeyboardV1Resource {
struct {
CSignal destroy;
+ CSignal key;
+ CSignal modifiers;
+ CSignal keymap;
} events;
- bool good();
- wlr_keyboard* wlr();
- wl_client* client();
+ bool good();
+ wl_client* client();
+
+ std::string name = "";
private:
SP<CZwpVirtualKeyboardV1> resource;
- wlr_keyboard keyboard;
void releasePressed();
bool hasKeymap = false;
+
+ std::vector<uint32_t> pressed;
};
class CVirtualKeyboardProtocol : public IWaylandProtocol {
diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp
index 1fb83888..bdeec32d 100644
--- a/src/protocols/VirtualPointer.cpp
+++ b/src/protocols/VirtualPointer.cpp
@@ -2,10 +2,6 @@
#define LOGM PROTO::virtualPointer->protoLog
-static const wlr_pointer_impl pointerImpl = {
- .name = "virtual-pointer-v1",
-};
-
CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> resource_) : resource(resource_) {
if (!good())
return;
@@ -19,41 +15,30 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
PROTO::virtualPointer->destroyResource(this);
});
- wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointerV1Resource");
-
resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) {
- wlr_pointer_motion_event event = {
- .pointer = &pointer,
- .time_msec = timeMs,
- .delta_x = wl_fixed_to_double(dx),
- .delta_y = wl_fixed_to_double(dy),
- .unaccel_dx = wl_fixed_to_double(dx),
- .unaccel_dy = wl_fixed_to_double(dy),
- };
- wl_signal_emit_mutable(&pointer.events.motion, &event);
+ events.move.emit(IPointer::SMotionEvent{
+ .timeMs = timeMs,
+ .delta = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)},
+ .unaccel = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)},
+ });
});
resource->setMotionAbsolute([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t x, uint32_t y, uint32_t xExtent, uint32_t yExtent) {
if (!xExtent || !yExtent)
return;
- wlr_pointer_motion_absolute_event event = {
- .pointer = &pointer,
- .time_msec = timeMs,
- .x = (double)x / xExtent,
- .y = (double)y / yExtent,
- };
- wl_signal_emit_mutable(&pointer.events.motion_absolute, &event);
+ events.warp.emit(IPointer::SMotionAbsoluteEvent{
+ .timeMs = timeMs,
+ .absolute = {(double)x / xExtent, (double)y / yExtent},
+ });
});
resource->setButton([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t button, uint32_t state) {
- struct wlr_pointer_button_event event = {
- .pointer = &pointer,
- .time_msec = timeMs,
- .button = button,
- .state = (wl_pointer_button_state)state,
- };
- wl_signal_emit_mutable(&pointer.events.button, &event);
+ events.button.emit(IPointer::SButtonEvent{
+ .timeMs = timeMs,
+ .button = button,
+ .state = (wl_pointer_button_state)state,
+ });
});
resource->setAxis([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value) {
@@ -63,18 +48,18 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
}
axis = axis_;
- axisEvents[axis] = wlr_pointer_axis_event{.pointer = &pointer, .time_msec = timeMs, .orientation = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)};
+ axisEvents[axis] = IPointer::SAxisEvent{.timeMs = timeMs, .axis = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)};
});
resource->setFrame([this](CZwlrVirtualPointerV1* r) {
for (auto& e : axisEvents) {
- if (!e.pointer)
+ if (!e.timeMs)
continue;
- wl_signal_emit_mutable(&pointer.events.axis, &e);
- e.pointer = nullptr;
+ events.axis.emit(e);
+ e.timeMs = 0;
}
- wl_signal_emit_mutable(&pointer.events.frame, &pointer);
+ events.frame.emit();
});
resource->setAxisSource([this](CZwlrVirtualPointerV1* r, uint32_t source) { axisEvents[axis].source = (wl_pointer_axis_source)source; });
@@ -85,12 +70,11 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
return;
}
- axis = axis_;
- axisEvents[axis].pointer = &pointer;
- axisEvents[axis].time_msec = timeMs;
- axisEvents[axis].orientation = (wl_pointer_axis)axis;
- axisEvents[axis].delta = 0;
- axisEvents[axis].delta_discrete = 0;
+ axis = axis_;
+ axisEvents[axis].timeMs = timeMs;
+ axisEvents[axis].axis = (wl_pointer_axis)axis;
+ axisEvents[axis].delta = 0;
+ axisEvents[axis].deltaDiscrete = 0;
});
resource->setAxisDiscrete([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value, int32_t discrete) {
@@ -99,17 +83,15 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
return;
}
- axis = axis_;
- axisEvents[axis].pointer = &pointer;
- axisEvents[axis].time_msec = timeMs;
- axisEvents[axis].orientation = (wl_pointer_axis)axis;
- axisEvents[axis].delta = wl_fixed_to_double(value);
- axisEvents[axis].delta_discrete = discrete * 120;
+ axis = axis_;
+ axisEvents[axis].timeMs = timeMs;
+ axisEvents[axis].axis = (wl_pointer_axis)axis;
+ axisEvents[axis].delta = wl_fixed_to_double(value);
+ axisEvents[axis].deltaDiscrete = discrete * 120;
});
}
CVirtualPointerV1Resource::~CVirtualPointerV1Resource() {
- wlr_pointer_finish(&pointer);
events.destroy.emit();
}
@@ -117,10 +99,6 @@ bool CVirtualPointerV1Resource::good() {
return resource->resource();
}
-wlr_pointer* CVirtualPointerV1Resource::wlr() {
- return &pointer;
-}
-
wl_client* CVirtualPointerV1Resource::client() {
return resource->client();
}
diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp
index 59a7e739..ee5ee7e2 100644
--- a/src/protocols/VirtualPointer.hpp
+++ b/src/protocols/VirtualPointer.hpp
@@ -7,6 +7,7 @@
#include "WaylandProtocol.hpp"
#include "wlr-virtual-pointer-unstable-v1.hpp"
#include "../helpers/signal/Signal.hpp"
+#include "../devices/IPointer.hpp"
class CVirtualPointerV1Resource {
public:
@@ -15,19 +16,35 @@ class CVirtualPointerV1Resource {
struct {
CSignal destroy;
+ CSignal move;
+ CSignal warp;
+ CSignal button;
+ CSignal axis;
+ CSignal frame;
+
+ CSignal swipeBegin;
+ CSignal swipeUpdate;
+ CSignal swipeEnd;
+
+ CSignal pinchBegin;
+ CSignal pinchUpdate;
+ CSignal pinchEnd;
+
+ CSignal holdBegin;
+ CSignal holdEnd;
} events;
- bool good();
- wlr_pointer* wlr();
- wl_client* client();
+ bool good();
+ wl_client* client();
+
+ std::string name;
private:
- SP<CZwlrVirtualPointerV1> resource;
- wlr_pointer pointer;
+ SP<CZwlrVirtualPointerV1> resource;
- uint32_t axis = 0;
+ uint32_t axis = 0;
- std::array<wlr_pointer_axis_event, 2> axisEvents;
+ std::array<IPointer::SAxisEvent, 2> axisEvents;
};
class CVirtualPointerProtocol : public IWaylandProtocol {
diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp
index 03e58956..073aa502 100644
--- a/src/protocols/XDGOutput.cpp
+++ b/src/protocols/XDGOutput.cpp
@@ -75,8 +75,8 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32
if (XDGVER >= OUTPUT_NAME_SINCE_VERSION)
pXDGOutput->resource->sendName(PMONITOR->szName.c_str());
- if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && PMONITOR->output->description)
- pXDGOutput->resource->sendDescription(PMONITOR->output->description);
+ if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && !PMONITOR->output->description.empty())
+ pXDGOutput->resource->sendDescription(PMONITOR->output->description.c_str());
pXDGOutput->sendDetails();
@@ -93,7 +93,7 @@ void CXDGOutputProtocol::updateAllOutputs() {
o->sendDetails();
- wlr_output_schedule_done(o->monitor->output);
+ o->monitor->scheduleDone();
}
}
diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp
index 9c56df93..8276ed55 100644
--- a/src/protocols/XDGShell.cpp
+++ b/src/protocols/XDGShell.cpp
@@ -4,6 +4,7 @@
#include "../managers/SeatManager.hpp"
#include "core/Seat.hpp"
#include "core/Compositor.hpp"
+#include <cstring>
#define LOGM PROTO::xdgShell->protoLog
diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp
index 691267b0..5cd6005a 100644
--- a/src/protocols/core/Compositor.cpp
+++ b/src/protocols/core/Compositor.cpp
@@ -6,6 +6,9 @@
#include "Subcompositor.hpp"
#include "../Viewporter.hpp"
#include "../../helpers/Monitor.hpp"
+#include "../PresentationTime.hpp"
+#include "../DRMSyncobj.hpp"
+#include "../../render/Renderer.hpp"
#define LOGM PROTO::compositor->protoLog
@@ -102,58 +105,14 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
pending.size = tfs / pending.scale;
}
- if (viewportResource)
- viewportResource->verify();
-
pending.damage.intersect(CBox{{}, pending.size});
- auto previousBuffer = current.buffer;
- CRegion previousBufferDamage = accumulateCurrentBufferDamage();
-
- current = pending;
- pending.damage.clear();
- pending.bufferDamage.clear();
-
- if (current.buffer && !bufferReleased) {
- // without previous dolphin et al are weird vvv
- //CRegion surfaceDamage =
- // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage);
- current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this.
-
- // release the buffer if it's synchronous as update() has done everything thats needed
- // so we can let the app know we're done.
- if (current.buffer->isSynchronous()) {
- current.buffer->sendRelease();
- bufferReleased = true;
- }
- }
-
- // TODO: we should _accumulate_ and not replace above if sync
- if (role->role() == SURFACE_ROLE_SUBSURFACE) {
- auto subsurface = (CWLSubsurfaceResource*)role.get();
- if (subsurface->sync)
- return;
-
- events.commit.emit();
- } else {
- // send commit to all synced surfaces in this tree.
- breadthfirst(
- [](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) {
- if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) {
- auto subsurface = (CWLSubsurfaceResource*)surf->role.get();
- if (!subsurface->sync)
- return;
- }
- surf->events.commit.emit();
- },
- nullptr);
- }
+ events.precommit.emit();
+ if (pending.rejected)
+ return;
- // for async buffers, we can only release the buffer once we are unrefing it from current.
- if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) {
- previousBuffer->sendRelease();
- bufferReleased = true;
- }
+ if (stateLocks <= 0)
+ commitPendingState();
});
resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.damage.add(CBox{x, y, w, h}); });
@@ -426,7 +385,97 @@ CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() {
Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size;
- return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(wlr_output_transform_invert(current.transform)), trc.x, trc.y).add(current.bufferDamage);
+ return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(invertTransform(current.transform)), trc.x, trc.y).add(current.bufferDamage);
+}
+
+void CWLSurfaceResource::lockPendingState() {
+ stateLocks++;
+}
+
+void CWLSurfaceResource::unlockPendingState() {
+ stateLocks--;
+ if (stateLocks <= 0)
+ commitPendingState();
+}
+
+void CWLSurfaceResource::commitPendingState() {
+ auto previousBuffer = current.buffer;
+ CRegion previousBufferDamage = accumulateCurrentBufferDamage();
+
+ current = pending;
+ pending.damage.clear();
+ pending.bufferDamage.clear();
+
+ if (current.buffer && !bufferReleased) {
+ // without previous dolphin et al are weird vvv
+ //CRegion surfaceDamage =
+ // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage);
+ current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this.
+
+ // release the buffer if it's synchronous as update() has done everything thats needed
+ // so we can let the app know we're done.
+ if (current.buffer->isSynchronous()) {
+ current.buffer->sendReleaseWithSurface(self.lock());
+ bufferReleased = true;
+ }
+ }
+
+ // TODO: we should _accumulate_ and not replace above if sync
+ if (role->role() == SURFACE_ROLE_SUBSURFACE) {
+ auto subsurface = (CWLSubsurfaceResource*)role.get();
+ if (subsurface->sync)
+ return;
+
+ events.commit.emit();
+ } else {
+ // send commit to all synced surfaces in this tree.
+ breadthfirst(
+ [](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) {
+ if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) {
+ auto subsurface = (CWLSubsurfaceResource*)surf->role.get();
+ if (!subsurface->sync)
+ return;
+ }
+ surf->events.commit.emit();
+ },
+ nullptr);
+ }
+
+ // for async buffers, we can only release the buffer once we are unrefing it from current.
+ if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) {
+ if (previousBuffer->lockedByBackend) {
+ previousBuffer->hlEvents.backendRelease = previousBuffer->events.backendRelease.registerListener([this, previousBuffer](std::any data) {
+ if (!self.expired()) // could be dead in the dtor
+ previousBuffer->sendReleaseWithSurface(self.lock());
+ else
+ previousBuffer->sendRelease();
+ previousBuffer->hlEvents.backendRelease.reset();
+ bufferReleased = true;
+ });
+ } else
+ previousBuffer->sendReleaseWithSurface(self.lock());
+
+ bufferReleased = true;
+ }
+}
+
+void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) {
+ frame(when);
+ auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock());
+ FEEDBACK->attachMonitor(pMonitor);
+ FEEDBACK->discarded();
+ PROTO::presentation->queueData(FEEDBACK);
+
+ if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync)
+ return;
+
+ // attach explicit sync
+ g_pHyprRenderer->explicitPresented.emplace_back(self.lock());
+
+ if (syncobj->acquirePoint > pMonitor->lastWaitPoint) {
+ Debug::log(TRACE, "presentFeedback lastWaitPoint {} -> {}", pMonitor->lastWaitPoint, syncobj->acquirePoint);
+ pMonitor->lastWaitPoint = syncobj->acquirePoint;
+ }
}
CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : resource(resource_) {
diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp
index 2f276719..5e6413c8 100644
--- a/src/protocols/core/Compositor.hpp
+++ b/src/protocols/core/Compositor.hpp
@@ -24,6 +24,7 @@ class CWLSurface;
class CWLSurfaceResource;
class CWLSubsurfaceResource;
class CViewportResource;
+class CDRMSyncobjSurfaceResource;
class CWLCallbackResource {
public:
@@ -74,6 +75,7 @@ class CWLSurfaceResource {
Vector2D sourceSize();
struct {
+ CSignal precommit;
CSignal commit;
CSignal map;
CSignal unmap;
@@ -81,11 +83,11 @@ class CWLSurfaceResource {
CSignal destroy;
} events;
- struct {
+ struct SState {
CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
int scale = 1;
- SP<IWLBuffer> buffer;
+ SP<IHLBuffer> buffer;
SP<CTexture> texture;
Vector2D offset;
Vector2D size;
@@ -95,6 +97,7 @@ class CWLSurfaceResource {
Vector2D destination;
CBox source;
} viewport;
+ bool rejected = false;
//
void reset() {
@@ -115,9 +118,13 @@ class CWLSurfaceResource {
std::vector<WP<CWLSubsurfaceResource>> subsurfaces;
WP<ISurfaceRole> role;
WP<CViewportResource> viewportResource;
+ WP<CDRMSyncobjSurfaceResource> syncobj; // may not be present
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
CRegion accumulateCurrentBufferDamage();
+ void presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync = false);
+ void lockPendingState();
+ void unlockPendingState();
// returns a pair: found surface (null if not found) and surface local coords.
// localCoords param is relative to 0,0 of this surface
@@ -130,7 +137,10 @@ class CWLSurfaceResource {
// tracks whether we should release the buffer
bool bufferReleased = false;
+ int stateLocks = 0;
+
void destroy();
+ void commitPendingState();
void bfHelper(std::vector<SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
};
diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp
index 10daa15e..4ba23cbe 100644
--- a/src/protocols/core/Output.cpp
+++ b/src/protocols/core/Output.cpp
@@ -21,8 +21,8 @@ CWLOutputResource::CWLOutputResource(SP<CWlOutput> resource_, SP<CMonitor> pMoni
PROTO::outputs.at(monitor->szName)->destroyResource(this);
});
- resource->sendGeometry(0, 0, monitor->output->phys_width, monitor->output->phys_height, monitor->output->subpixel, monitor->output->make ? monitor->output->make : "null",
- monitor->output->model ? monitor->output->model : "null", monitor->transform);
+ resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(),
+ monitor->output->model.c_str(), monitor->transform);
if (resource->version() >= 4) {
resource->sendName(monitor->szName.c_str());
resource->sendDescription(monitor->szDescription.c_str());
@@ -115,3 +115,9 @@ void CWLOutputProtocol::remove() {
bool CWLOutputProtocol::isDefunct() {
return defunct;
}
+
+void CWLOutputProtocol::sendDone() {
+ for (auto& r : m_vOutputs) {
+ r->resource->sendDone();
+ }
+}
diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp
index 46981635..46e4057b 100644
--- a/src/protocols/core/Output.hpp
+++ b/src/protocols/core/Output.hpp
@@ -26,6 +26,8 @@ class CWLOutputResource {
private:
SP<CWlOutput> resource;
wl_client* pClient = nullptr;
+
+ friend class CWLOutputProtocol;
};
class CWLOutputProtocol : public IWaylandProtocol {
@@ -35,6 +37,7 @@ class CWLOutputProtocol : public IWaylandProtocol {
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
SP<CWLOutputResource> outputResourceFrom(wl_client* client);
+ void sendDone();
WP<CMonitor> monitor;
diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp
index 464a901c..21a47575 100644
--- a/src/protocols/core/Seat.cpp
+++ b/src/protocols/core/Seat.cpp
@@ -254,8 +254,8 @@ void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) {
int fd;
uint32_t size;
if (keyboard) {
- fd = keyboard->wlr()->keymap_fd;
- size = keyboard->wlr()->keymap_size;
+ fd = keyboard->xkbKeymapFD;
+ size = keyboard->xkbKeymapString.length() + 1;
} else {
fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp
index 4088949f..75c2134a 100644
--- a/src/protocols/core/Shm.cpp
+++ b/src/protocols/core/Shm.cpp
@@ -41,20 +41,20 @@ CWLSHMBuffer::~CWLSHMBuffer() {
;
}
-eBufferCapability CWLSHMBuffer::caps() {
- return BUFFER_CAPABILITY_DATAPTR;
+Aquamarine::eBufferCapability CWLSHMBuffer::caps() {
+ return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
}
-eBufferType CWLSHMBuffer::type() {
- return BUFFER_TYPE_SHM;
+Aquamarine::eBufferType CWLSHMBuffer::type() {
+ return Aquamarine::eBufferType::BUFFER_TYPE_SHM;
}
bool CWLSHMBuffer::isSynchronous() {
return true;
}
-SSHMAttrs CWLSHMBuffer::shm() {
- SSHMAttrs attrs;
+Aquamarine::SSHMAttrs CWLSHMBuffer::shm() {
+ Aquamarine::SSHMAttrs attrs;
attrs.success = true;
attrs.fd = pool->fd;
attrs.format = FormatUtils::shmToDRM(fmt);
@@ -188,11 +188,18 @@ CWLSHMProtocol::CWLSHMProtocol(const wl_interface* iface, const int& ver, const
void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
if (shmFormats.empty()) {
- size_t len = 0;
- const uint32_t* formats = wlr_renderer_get_shm_texture_formats(g_pCompositor->m_sWLRRenderer, &len);
+ shmFormats.push_back(WL_SHM_FORMAT_ARGB8888);
+ shmFormats.push_back(WL_SHM_FORMAT_XRGB8888);
- for (size_t i = 0; i < len; ++i) {
- shmFormats.push_back(FormatUtils::drmToShm(formats[i]));
+ static const std::array<DRMFormat, 6> supportedShmFourccFormats = {
+ DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010,
+ };
+
+ for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) {
+ if (std::find(supportedShmFourccFormats.begin(), supportedShmFourccFormats.end(), fmt.drmFormat) == supportedShmFourccFormats.end())
+ continue;
+
+ shmFormats.push_back(fmt.drmFormat);
}
}
diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp
index 70a8b208..fab325fe 100644
--- a/src/protocols/core/Shm.hpp
+++ b/src/protocols/core/Shm.hpp
@@ -29,16 +29,16 @@ class CSHMPool {
void resize(size_t size);
};
-class CWLSHMBuffer : public IWLBuffer {
+class CWLSHMBuffer : public IHLBuffer {
public:
CWLSHMBuffer(SP<CWLSHMPoolResource> pool, uint32_t id, int32_t offset, const Vector2D& size, int32_t stride, uint32_t fmt);
virtual ~CWLSHMBuffer();
- virtual eBufferCapability caps();
- virtual eBufferType type();
+ virtual Aquamarine::eBufferCapability caps();
+ virtual Aquamarine::eBufferType type();
virtual void update(const CRegion& damage);
virtual bool isSynchronous();
- virtual SSHMAttrs shm();
+ virtual Aquamarine::SSHMAttrs shm();
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr();
diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp
index 5ed942e1..0217f7e2 100644
--- a/src/protocols/types/Buffer.cpp
+++ b/src/protocols/types/Buffer.cpp
@@ -1,41 +1,10 @@
#include "Buffer.hpp"
-#include "WLBuffer.hpp"
-SDMABUFAttrs IWLBuffer::dmabuf() {
- return SDMABUFAttrs{};
+void IHLBuffer::sendRelease() {
+ resource->sendRelease();
}
-SSHMAttrs IWLBuffer::shm() {
- return SSHMAttrs{};
-}
-
-std::tuple<uint8_t*, uint32_t, size_t> IWLBuffer::beginDataPtr(uint32_t flags) {
- return {nullptr, 0, 0};
-}
-
-void IWLBuffer::endDataPtr() {
- ; // empty
-}
-
-void IWLBuffer::sendRelease() {
- if (!resource || !resource->resource)
- return;
- resource->resource->sendRelease();
-}
-
-void IWLBuffer::lock() {
- locks++;
-}
-
-void IWLBuffer::unlock() {
- locks--;
-
- ASSERT(locks >= 0);
-
- if (locks <= 0)
- sendRelease();
-}
-
-bool IWLBuffer::locked() {
- return locks;
+void IHLBuffer::sendReleaseWithSurface(SP<CWLSurfaceResource> surf) {
+ if (resource && resource->good())
+ resource->sendReleaseWithSurface(surf);
}
diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp
index 9999a4e9..ba8278f3 100644
--- a/src/protocols/types/Buffer.hpp
+++ b/src/protocols/types/Buffer.hpp
@@ -1,75 +1,29 @@
#pragma once
#include "../../defines.hpp"
-#include "../../helpers/signal/Signal.hpp"
#include "../../render/Texture.hpp"
+#include "./WLBuffer.hpp"
-#include <array>
-#include <tuple>
+#include <aquamarine/buffer/Buffer.hpp>
-enum eBufferCapability {
- BUFFER_CAPABILITY_DATAPTR = (1 << 0),
-};
-
-enum eBufferType {
- BUFFER_TYPE_DMABUF = 0,
- BUFFER_TYPE_SHM,
- BUFFER_TYPE_MISC,
-};
-
-class CWLBufferResource;
-
-struct SDMABUFAttrs {
- bool success = false;
- Vector2D size;
- uint32_t format = 0; // fourcc
- uint64_t modifier = 0;
-
- int planes = 1;
- std::array<uint32_t, 4> offsets = {0};
- std::array<uint32_t, 4> strides = {0};
- std::array<int, 4> fds = {-1, -1, -1, -1};
-};
-
-struct SSHMAttrs {
- bool success = false;
- int fd = 0;
- uint32_t format = 0;
- Vector2D size;
- int stride = 0;
- int64_t offset = 0;
-};
-
-class IWLBuffer {
+class IHLBuffer : public Aquamarine::IBuffer {
public:
- virtual ~IWLBuffer() {
+ virtual ~IHLBuffer() {
;
- };
-
- virtual eBufferCapability caps() = 0;
- virtual eBufferType type() = 0;
- virtual void update(const CRegion& damage) = 0;
- virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
- virtual SDMABUFAttrs dmabuf();
- virtual SSHMAttrs shm();
- virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
- virtual void endDataPtr();
- virtual void sendRelease();
- virtual void lock();
- virtual void unlock();
- virtual bool locked();
-
- Vector2D size;
- bool opaque = false;
-
- SP<CWLBufferResource> resource;
-
- SP<CTexture> texture;
+ }
+ virtual Aquamarine::eBufferCapability caps() = 0;
+ virtual Aquamarine::eBufferType type() = 0;
+ virtual void update(const CRegion& damage) = 0;
+ virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
+ virtual bool good() = 0;
+ virtual void sendRelease();
+ virtual void sendReleaseWithSurface(SP<CWLSurfaceResource>);
+
+ SP<CTexture> texture;
+ bool opaque = false;
+ SP<CWLBufferResource> resource;
struct {
- CSignal destroy;
- } events;
-
- private:
- int locks = 0;
+ CHyprSignalListener backendRelease;
+ } hlEvents;
};
diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp
index 7c3a9886..63a26c76 100644
--- a/src/protocols/types/DMABuffer.cpp
+++ b/src/protocols/types/DMABuffer.cpp
@@ -3,7 +3,7 @@
#include "../../render/Renderer.hpp"
#include "../../helpers/Format.hpp"
-CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_) : attrs(attrs_) {
+CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : attrs(attrs_) {
g_pHyprRenderer->makeEGLCurrent();
listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) {
@@ -31,12 +31,12 @@ CDMABuffer::~CDMABuffer() {
closeFDs();
}
-eBufferCapability CDMABuffer::caps() {
- return BUFFER_CAPABILITY_DATAPTR;
+Aquamarine::eBufferCapability CDMABuffer::caps() {
+ return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
}
-eBufferType CDMABuffer::type() {
- return BUFFER_TYPE_DMABUF;
+Aquamarine::eBufferType CDMABuffer::type() {
+ return Aquamarine::eBufferType::BUFFER_TYPE_DMABUF;
}
void CDMABuffer::update(const CRegion& damage) {
@@ -47,7 +47,7 @@ bool CDMABuffer::isSynchronous() {
return false;
}
-SDMABUFAttrs CDMABuffer::dmabuf() {
+Aquamarine::SDMABUFAttrs CDMABuffer::dmabuf() {
return attrs;
}
diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp
index d07840b7..6977df4c 100644
--- a/src/protocols/types/DMABuffer.hpp
+++ b/src/protocols/types/DMABuffer.hpp
@@ -2,16 +2,16 @@
#include "Buffer.hpp"
-class CDMABuffer : public IWLBuffer {
+class CDMABuffer : public IHLBuffer {
public:
- CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_);
+ CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_);
virtual ~CDMABuffer();
- virtual eBufferCapability caps();
- virtual eBufferType type();
+ virtual Aquamarine::eBufferCapability caps();
+ virtual Aquamarine::eBufferType type();
virtual bool isSynchronous();
virtual void update(const CRegion& damage);
- virtual SDMABUFAttrs dmabuf();
+ virtual Aquamarine::SDMABUFAttrs dmabuf();
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr();
bool good();
@@ -21,7 +21,7 @@ class CDMABuffer : public IWLBuffer {
bool success = false;
private:
- SDMABUFAttrs attrs;
+ Aquamarine::SDMABUFAttrs attrs;
struct {
CHyprSignalListener resourceDestroy;
diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp
index e53538cb..d34a867d 100644
--- a/src/protocols/types/WLBuffer.cpp
+++ b/src/protocols/types/WLBuffer.cpp
@@ -1,5 +1,10 @@
#include "WLBuffer.hpp"
#include "Buffer.hpp"
+#include "../core/Compositor.hpp"
+#include "../DRMSyncobj.hpp"
+#include "../../helpers/sync/SyncTimeline.hpp"
+#include "../../Compositor.hpp"
+#include <xf86drm.h>
CWLBufferResource::CWLBufferResource(SP<CWlBuffer> resource_) : resource(resource_) {
if (!good())
@@ -27,6 +32,16 @@ void CWLBufferResource::sendRelease() {
resource->sendRelease();
}
+void CWLBufferResource::sendReleaseWithSurface(SP<CWLSurfaceResource> surf) {
+ sendRelease();
+
+ if (!surf || !surf->syncobj)
+ return;
+
+ if (drmSyncobjTimelineSignal(g_pCompositor->m_iDRMFD, &surf->syncobj->releaseTimeline->timeline->handle, &surf->syncobj->releasePoint, 1))
+ Debug::log(ERR, "sendReleaseWithSurface: drmSyncobjTimelineSignal failed");
+}
+
wl_resource* CWLBufferResource::getResource() {
return resource->resource();
}
diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp
index ac177965..59512128 100644
--- a/src/protocols/types/WLBuffer.hpp
+++ b/src/protocols/types/WLBuffer.hpp
@@ -7,7 +7,8 @@
#include "wayland.hpp"
#include "../../helpers/signal/Signal.hpp"
-class IWLBuffer;
+class IHLBuffer;
+class CWLSurfaceResource;
class CWLBufferResource {
public:
@@ -16,9 +17,10 @@ class CWLBufferResource {
bool good();
void sendRelease();
+ void sendReleaseWithSurface(SP<CWLSurfaceResource>);
wl_resource* getResource();
- WP<IWLBuffer> buffer;
+ WP<IHLBuffer> buffer;
WP<CWLBufferResource> self;
@@ -27,5 +29,5 @@ class CWLBufferResource {
SP<CWlBuffer> resource;
- friend class IWLBuffer;
+ friend class IHLBuffer;
};