diff --git a/debian/patches/sync.patch b/debian/patches/sync.patch index bb682de..736a7a5 100644 --- a/debian/patches/sync.patch +++ b/debian/patches/sync.patch @@ -1,7 +1,7 @@ From 46dbd22d987e5781ba7e6651f7e6be543009881f Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Tue, 18 Feb 2025 15:29:53 +0100 -Subject: [PATCH] syncobj: use eventfd instead of stalling fd checks +Subject: [PATCH 1/3] syncobj: use eventfd instead of stalling fd checks use eventfd and add it to the event loop and when it recieves a signal release the buffer, this means we dont stall entire compositor when @@ -430,5 +430,317 @@ index a5d3d7c001a..e6e03b99773 100644 return; } +From e156ace712a9dbe04b9a8759072c92f291507881 Mon Sep 17 00:00:00 2001 +From: Tom Englund +Date: Sat, 22 Feb 2025 19:52:49 +0100 +Subject: [PATCH 2/3] syncobj: lets optimize it further - \ No newline at end of file +lets use unique_pointers all over, add defaulted destructors and make +fromResource directly check existing timelines instead of C style +casting and return a WP from that. instead of moving the releasepoint +vector lets swap it. +--- + src/protocols/DRMSyncobj.cpp | 31 ++++++++++++++++++------------- + src/protocols/DRMSyncobj.hpp | 22 +++++++++++----------- + src/protocols/core/Compositor.cpp | 2 +- + 3 files changed, 30 insertions(+), 25 deletions(-) + +diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp +index 63f0946b58c..af2fadfaa7d 100644 +--- a/src/protocols/DRMSyncobj.cpp ++++ b/src/protocols/DRMSyncobj.cpp +@@ -8,7 +8,8 @@ + #include + using namespace Hyprutils::OS; + +-CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { ++CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(UP&& resource_, SP surface_) : ++ surface(surface_), resource(std::move(resource_)) { + if UNLIKELY (!good()) + return; + +@@ -107,7 +108,7 @@ bool CDRMSyncobjSurfaceResource::good() { + return resource->resource(); + } + +-CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, CFileDescriptor&& fd_) : fd(std::move(fd_)), resource(resource_) { ++CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(UP&& resource_, CFileDescriptor&& fd_) : fd(std::move(fd_)), resource(std::move(resource_)) { + if UNLIKELY (!good()) + return; + +@@ -124,16 +125,20 @@ CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP CDRMSyncobjTimelineResource::fromResource(wl_resource* res) { +- auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data()); +- return data ? data->self.lock() : nullptr; ++WP CDRMSyncobjTimelineResource::fromResource(wl_resource* res) { ++ for (const auto& t : PROTO::sync->m_vTimelines) { ++ if (t && t->resource && t->resource->resource() == res) ++ return t; ++ } ++ ++ return {}; + } + + bool CDRMSyncobjTimelineResource::good() { + return resource->resource(); + } + +-CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SP resource_) : resource(resource_) { ++CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(UP&& resource_) : resource(std::move(resource_)) { + if UNLIKELY (!good()) + return; + +@@ -157,28 +162,28 @@ CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SP(makeShared(resource->client(), resource->version(), id), SURF); ++ const auto& RESOURCE = PROTO::sync->m_vSurfaces.emplace_back( ++ makeUnique(makeUnique(resource->client(), resource->version(), id), SURF)); + if UNLIKELY (!RESOURCE->good()) { + resource->noMemory(); ++ PROTO::sync->m_vSurfaces.pop_back(); + 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(makeShared(resource->client(), resource->version(), id), CFileDescriptor{fd}); ++ const auto& RESOURCE = PROTO::sync->m_vTimelines.emplace_back( ++ makeUnique(makeUnique(resource->client(), resource->version(), id), CFileDescriptor{fd})); + if UNLIKELY (!RESOURCE->good()) { + resource->noMemory(); ++ PROTO::sync->m_vTimelines.pop_back(); + return; + } + +- PROTO::sync->m_vTimelines.emplace_back(RESOURCE); +- RESOURCE->self = RESOURCE; +- + LOGM(LOG, "New linux_drm_timeline at {:x}", (uintptr_t)RESOURCE.get()); + }); + } +@@ -192,7 +197,7 @@ CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& v + } + + void CDRMSyncobjProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { +- const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); ++ const auto& RESOURCE = m_vManagers.emplace_back(makeUnique(makeUnique(client, ver, id))); + + if UNLIKELY (!RESOURCE->good()) { + wl_client_post_no_memory(client); +diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp +index 06a3def2565..af4ee3567bd 100644 +--- a/src/protocols/DRMSyncobj.hpp ++++ b/src/protocols/DRMSyncobj.hpp +@@ -13,7 +13,7 @@ class CSyncTimeline; + + class CDRMSyncobjSurfaceResource { + public: +- CDRMSyncobjSurfaceResource(SP resource_, SP surface_); ++ CDRMSyncobjSurfaceResource(UP&& resource_, SP surface_); + ~CDRMSyncobjSurfaceResource(); + + bool good(); +@@ -34,7 +34,7 @@ class CDRMSyncobjSurfaceResource { + std::vector> releasePoints; + + private: +- SP resource; ++ UP resource; + bool acquireWaiting = false; + + struct { +@@ -45,33 +45,33 @@ class CDRMSyncobjSurfaceResource { + + class CDRMSyncobjTimelineResource { + public: +- CDRMSyncobjTimelineResource(SP resource_, Hyprutils::OS::CFileDescriptor&& fd_); ++ CDRMSyncobjTimelineResource(UP&& resource_, Hyprutils::OS::CFileDescriptor&& fd_); + ~CDRMSyncobjTimelineResource() = default; +- static SP fromResource(wl_resource*); ++ static WP fromResource(wl_resource*); + + bool good(); + +- WP self; + Hyprutils::OS::CFileDescriptor fd; + SP timeline; + + private: +- SP resource; ++ UP resource; + }; + + class CDRMSyncobjManagerResource { + public: +- CDRMSyncobjManagerResource(SP resource_); ++ CDRMSyncobjManagerResource(UP&& resource_); + + bool good(); + + private: +- SP resource; ++ UP resource; + }; + + class CDRMSyncobjProtocol : public IWaylandProtocol { + public: + CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name); ++ ~CDRMSyncobjProtocol() = default; + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + +@@ -81,9 +81,9 @@ class CDRMSyncobjProtocol : public IWaylandProtocol { + void destroyResource(CDRMSyncobjSurfaceResource* resource); + + // +- std::vector> m_vManagers; +- std::vector> m_vTimelines; +- std::vector> m_vSurfaces; ++ std::vector> m_vManagers; ++ std::vector> m_vTimelines; ++ std::vector> m_vSurfaces; + + // + int drmFD = -1; +diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp +index 87adaeae1be..0dddf8b42c1 100644 +--- a/src/protocols/core/Compositor.cpp ++++ b/src/protocols/core/Compositor.cpp +@@ -434,7 +434,7 @@ void CWLSurfaceResource::commitPendingState() { + events.roleCommit.emit(); + + if (syncobj && syncobj->release.resource && syncobj->release.resource->timeline && current.buffer && current.buffer->buffer) +- current.buffer->releaser = std::move(syncobj->releasePoints); ++ current.buffer->releaser.swap(syncobj->releasePoints); + + if (current.texture) + current.texture->m_eTransform = wlTransformToHyprutils(current.transform); + +From 40df1f771c281d11c0b67569bd7a061a3c102994 Mon Sep 17 00:00:00 2001 +From: Tom Englund +Date: Sat, 22 Feb 2025 20:36:03 +0100 +Subject: [PATCH 3/3] syncobj: remove early buffer release + +remove early buffer release config that previously tried to workaround +flickers while it was more of an syncobj issue, it also cant be used +since the buffer really is used for release point syncing in the +renderer later. and use std::move instead of std::exchange to avoid a +local temporar copy being created inside std::exchange. +--- + src/config/ConfigDescriptions.hpp | 6 ------ + src/config/ConfigManager.cpp | 1 - + src/protocols/DRMSyncobj.cpp | 12 ++++++++---- + src/protocols/core/Compositor.cpp | 17 +++-------------- + 4 files changed, 11 insertions(+), 25 deletions(-) + +diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp +index 4e591fa8107..f7e647b2b2f 100644 +--- a/src/config/ConfigDescriptions.hpp ++++ b/src/config/ConfigDescriptions.hpp +@@ -1348,12 +1348,6 @@ inline static const std::vector CONFIG_OPTIONS = { + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{2, 0, 2}, + }, +- SConfigOptionDescription{ +- .value = "render:allow_early_buffer_release", +- .description = "Allow early buffer release event. Fixes stuttering and missing frames for some apps. May cause graphical glitches and memory leaks in others", +- .type = CONFIG_OPTION_BOOL, +- .data = SConfigOptionDescription::SBoolData{true}, +- }, + + /* + * cursor: +diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp +index 9b547ffbb75..277098f5260 100644 +--- a/src/config/ConfigManager.cpp ++++ b/src/config/ConfigManager.cpp +@@ -664,7 +664,6 @@ CConfigManager::CConfigManager() { + m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1}); + m_pConfig->addConfigValue("render:xp_mode", Hyprlang::INT{0}); + m_pConfig->addConfigValue("render:ctm_animation", Hyprlang::INT{2}); +- m_pConfig->addConfigValue("render:allow_early_buffer_release", Hyprlang::INT{1}); + + m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0}); + m_pConfig->addConfigValue("ecosystem:no_donation_nag", Hyprlang::INT{0}); +diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp +index af2fadfaa7d..0e8b4cb47fe 100644 +--- a/src/protocols/DRMSyncobj.cpp ++++ b/src/protocols/DRMSyncobj.cpp +@@ -88,11 +88,15 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(UPevents.roleCommit.registerListener([this](std::any d) { +- if (pendingAcquire.resource) +- acquire = std::exchange(pendingAcquire, {}); ++ if (pendingAcquire.resource) { ++ acquire = std::move(pendingAcquire); ++ pendingAcquire = {}; ++ } + +- if (pendingRelease.resource) +- release = std::exchange(pendingRelease, {}); ++ if (pendingRelease.resource) { ++ release = std::move(pendingRelease); ++ pendingRelease = {}; ++ } + }); + } + +diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp +index 0dddf8b42c1..e3297da8a44 100644 +--- a/src/protocols/core/Compositor.cpp ++++ b/src/protocols/core/Compositor.cpp +@@ -11,7 +11,6 @@ + #include "../PresentationTime.hpp" + #include "../DRMSyncobj.hpp" + #include "../../render/Renderer.hpp" +-#include "config/ConfigValue.hpp" + #include + + class CDefaultSurfaceRole : public ISurfaceRole { +@@ -422,14 +421,12 @@ void CWLSurfaceResource::commitPendingState() { + if (stateLocked && syncobj) + return; + +- static auto PDROP = CConfigValue("render:allow_early_buffer_release"); +- auto const previousBuffer = current.buffer; +- current = pending; ++ auto const previousBuffer = current.buffer; ++ current = pending; + pending.damage.clear(); + pending.bufferDamage.clear(); + pending.newBuffer = false; +- if (!*PDROP) +- dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore ++ dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore + + events.roleCommit.emit(); + +@@ -447,14 +444,6 @@ void CWLSurfaceResource::commitPendingState() { + // TODO: don't update the entire texture + if (role->role() == SURFACE_ROLE_CURSOR && !DAMAGE.empty()) + updateCursorShm(DAMAGE); +- +- // release the buffer if it's synchronous as update() has done everything thats needed +- // so we can let the app know we're done. +- // Some clients aren't ready to receive a release this early. Should be fine to release it on the next commitPendingState. +- if (current.buffer->buffer->isSynchronous() && *PDROP) { +- dropCurrentBuffer(); +- dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore +- } + } + + // TODO: we should _accumulate_ and not replace above if sync + + + \ No newline at end of file