summaryrefslogtreecommitdiff
path: root/src/protocols/core
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/core
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/core')
-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
7 files changed, 145 insertions, 70 deletions
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();