From dc72259a5443116e892c49e37552ca5f82525ca6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 6 Oct 2025 23:44:47 +0100 Subject: [PATCH] core/compositor: revert make wl_surface::frame follow pending states (#11896) This reverts commit 17e77e0407bebd5d24521012ee1d04b156d6b9f4. Reverted due to severe performance degradation due to accumulating frame callbacks --- src/protocols/core/Compositor.cpp | 108 +++++++++++---------------- src/protocols/core/Compositor.hpp | 19 ++--- src/protocols/types/SurfaceState.cpp | 9 --- src/protocols/types/SurfaceState.hpp | 5 -- src/render/Texture.cpp | 3 - 5 files changed, 49 insertions(+), 95 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 955ba5ca..484df21f 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -27,20 +27,16 @@ class CDefaultSurfaceRole : public ISurfaceRole { } }; -CWLCallbackResource::CWLCallbackResource(SP&& resource_) : m_resource(std::move(resource_)) { +CWLCallbackResource::CWLCallbackResource(UP&& resource_) : m_resource(std::move(resource_)) { ; } bool CWLCallbackResource::good() { - return m_resource && m_resource->resource(); + return m_resource->resource(); } void CWLCallbackResource::send(const Time::steady_tp& now) { - if (!good()) - return; - m_resource->sendDone(Time::millis(now)); - m_resource.reset(); } CWLRegionResource::CWLRegionResource(SP resource_) : m_resource(resource_) { @@ -131,16 +127,17 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re return; } - // null buffer attached - if (!m_pending.buffer && !m_pending.texture && m_pending.updated.bits.buffer) { + if ((!m_pending.updated.bits.buffer) || // no new buffer attached + (!m_pending.buffer && !m_pending.texture) // null buffer attached + ) { commitState(m_pending); - // remove any pending states. - while (!m_pendingStates.empty()) { - m_pendingStates.pop(); + if (!m_pending.buffer && !m_pending.texture) { + // null buffer attached, remove any pending states. + while (!m_pendingStates.empty()) { + m_pendingStates.pop(); + } } - - m_pendingWaiting = false; m_pending.reset(); return; } @@ -149,9 +146,36 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re const auto& state = m_pendingStates.emplace(makeUnique(m_pending)); m_pending.reset(); - if (!m_pendingWaiting) { - m_pendingWaiting = true; - scheduleState(state); + auto whenReadable = [this, surf = m_self, state = WP(m_pendingStates.back())] { + if (!surf || state.expired()) + return; + + while (!m_pendingStates.empty() && m_pendingStates.front() != state) { + commitState(*m_pendingStates.front()); + m_pendingStates.pop(); + } + + commitState(*m_pendingStates.front()); + m_pendingStates.pop(); + }; + + if (state->updated.bits.acquire) { + // wait on acquire point for this surface, from explicit sync protocol + state->acquire.addWaiter(std::move(whenReadable)); + } else if (state->buffer->isSynchronous()) { + // synchronous (shm) buffers can be read immediately + whenReadable(); + } else if (state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success) { + // async buffer and is dmabuf, then we can wait on implicit fences + auto syncFd = dc(state->buffer.m_buffer.get())->exportSyncFile(); + + if (syncFd.isValid()) + g_pEventLoopManager->doOnReadable(std::move(syncFd), std::move(whenReadable)); + else + whenReadable(); + } else { + Debug::log(ERR, "BUG THIS: wl_surface.commit: no acquire, non-dmabuf, async buffer, needs wait... this shouldn't happen"); + whenReadable(); } }); @@ -215,10 +239,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re m_pending.opaque = RG->m_region; }); - m_resource->setFrame([this](CWlSurface* r, uint32_t id) { - m_pending.updated.bits.frame = true; - m_pending.callbacks.emplace_back(makeShared(makeShared(m_client, 1, id))); - }); + m_resource->setFrame([this](CWlSurface* r, uint32_t id) { m_callbacks.emplace_back(makeUnique(makeUnique(m_client, 1, id))); }); m_resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) { m_pending.updated.bits.offset = true; @@ -319,14 +340,14 @@ void CWLSurfaceResource::sendPreferredScale(int32_t scale) { } void CWLSurfaceResource::frame(const Time::steady_tp& now) { - if (m_current.callbacks.empty()) + if (m_callbacks.empty()) return; - for (auto const& c : m_current.callbacks) { + for (auto const& c : m_callbacks) { c->send(now); } - m_current.callbacks.clear(); + m_callbacks.clear(); } void CWLSurfaceResource::resetRole() { @@ -480,47 +501,6 @@ CBox CWLSurfaceResource::extends() { return full.getExtents(); } -void CWLSurfaceResource::scheduleState(WP state) { - auto whenReadable = [this, surf = m_self, state] { - if (!surf || state.expired() || m_pendingStates.empty()) - return; - - while (!m_pendingStates.empty() && m_pendingStates.front() != state) { - commitState(*m_pendingStates.front()); - m_pendingStates.pop(); - } - - commitState(*m_pendingStates.front()); - m_pendingStates.pop(); - - // If more states are queued, schedule next state - if (!m_pendingStates.empty()) { - scheduleState(m_pendingStates.front()); - } else { - m_pendingWaiting = false; - } - }; - - if (state->updated.bits.acquire) { - // wait on acquire point for this surface, from explicit sync protocol - state->acquire.addWaiter(std::move(whenReadable)); - } else if (state->buffer && state->buffer->isSynchronous()) { - // synchronous (shm) buffers can be read immediately - whenReadable(); - } else if (state->buffer && state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success) { - // async buffer and is dmabuf, then we can wait on implicit fences - auto syncFd = dc(state->buffer.m_buffer.get())->exportSyncFile(); - - if (syncFd.isValid()) - g_pEventLoopManager->doOnReadable(std::move(syncFd), std::move(whenReadable)); - else - whenReadable(); - } else { - // state commit without a buffer. - whenReadable(); - } -} - void CWLSurfaceResource::commitState(SSurfaceState& state) { auto lastTexture = m_current.texture; m_current.updateFrom(state); diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index dc61917d..0eff3f08 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -35,21 +35,13 @@ class CContentType; class CWLCallbackResource { public: - CWLCallbackResource(SP&& resource_); - ~CWLCallbackResource() noexcept = default; - // disable copy - CWLCallbackResource(const CWLCallbackResource&) = delete; - CWLCallbackResource& operator=(const CWLCallbackResource&) = delete; + CWLCallbackResource(UP&& resource_); - // allow move - CWLCallbackResource(CWLCallbackResource&&) noexcept = default; - CWLCallbackResource& operator=(CWLCallbackResource&&) noexcept = default; - - bool good(); - void send(const Time::steady_tp& now); + bool good(); + void send(const Time::steady_tp& now); private: - SP m_resource; + UP m_resource; }; class CWLRegionResource { @@ -102,8 +94,8 @@ class CWLSurfaceResource { SSurfaceState m_current; SSurfaceState m_pending; std::queue> m_pendingStates; - bool m_pendingWaiting = false; + std::vector> m_callbacks; WP m_self; WP m_hlSurface; std::vector m_enteredOutputs; @@ -118,7 +110,6 @@ class CWLSurfaceResource { SP findFirstPreorder(std::function)> fn); SP findWithCM(); void presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded = false); - void scheduleState(WP state); void commitState(SSurfaceState& state); NColorManagement::SImageDescription getPreferredImageDescription(); void sortSubsurfaces(); diff --git a/src/protocols/types/SurfaceState.cpp b/src/protocols/types/SurfaceState.cpp index 50e59049..a8838170 100644 --- a/src/protocols/types/SurfaceState.cpp +++ b/src/protocols/types/SurfaceState.cpp @@ -75,10 +75,6 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) { if (ref.updated.bits.damage) { damage = ref.damage; bufferDamage = ref.bufferDamage; - } else { - // damage is always relative to the current commit - damage.clear(); - bufferDamage.clear(); } if (ref.updated.bits.input) @@ -104,9 +100,4 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) { if (ref.updated.bits.acked) ackedSize = ref.ackedSize; - - if (ref.updated.bits.frame) { - callbacks.insert(callbacks.end(), std::make_move_iterator(ref.callbacks.begin()), std::make_move_iterator(ref.callbacks.end())); - ref.callbacks.clear(); - } } diff --git a/src/protocols/types/SurfaceState.hpp b/src/protocols/types/SurfaceState.hpp index e6764eda..eb50a988 100644 --- a/src/protocols/types/SurfaceState.hpp +++ b/src/protocols/types/SurfaceState.hpp @@ -6,7 +6,6 @@ class CTexture; class CDRMSyncPointState; -class CWLCallbackResource; struct SSurfaceState { union { @@ -22,7 +21,6 @@ struct SSurfaceState { bool viewport : 1; bool acquire : 1; bool acked : 1; - bool frame : 1; } bits; } updated; @@ -43,9 +41,6 @@ struct SSurfaceState { // for xdg_shell resizing Vector2D ackedSize; - // for wl_surface::frame callbacks. - std::vector> callbacks; - // viewporter protocol surface state struct { bool hasDestination = false; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 17c416c7..b9797751 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -111,9 +111,6 @@ void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) } void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) { - if (damage.empty()) - return; - g_pHyprRenderer->makeEGLCurrent(); const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);