core/compositor: revert make wl_surface::frame follow pending states (#11896)

This reverts commit 17e77e0407.

Reverted due to severe performance degradation due to accumulating frame
callbacks
This commit is contained in:
Vaxry 2025-10-06 23:44:47 +01:00
parent 02cda6bebf
commit dc72259a54
No known key found for this signature in database
GPG key ID: 665806380871D640
5 changed files with 49 additions and 95 deletions

View file

@ -27,20 +27,16 @@ class CDefaultSurfaceRole : public ISurfaceRole {
} }
}; };
CWLCallbackResource::CWLCallbackResource(SP<CWlCallback>&& resource_) : m_resource(std::move(resource_)) { CWLCallbackResource::CWLCallbackResource(UP<CWlCallback>&& resource_) : m_resource(std::move(resource_)) {
; ;
} }
bool CWLCallbackResource::good() { bool CWLCallbackResource::good() {
return m_resource && m_resource->resource(); return m_resource->resource();
} }
void CWLCallbackResource::send(const Time::steady_tp& now) { void CWLCallbackResource::send(const Time::steady_tp& now) {
if (!good())
return;
m_resource->sendDone(Time::millis(now)); m_resource->sendDone(Time::millis(now));
m_resource.reset();
} }
CWLRegionResource::CWLRegionResource(SP<CWlRegion> resource_) : m_resource(resource_) { CWLRegionResource::CWLRegionResource(SP<CWlRegion> resource_) : m_resource(resource_) {
@ -131,16 +127,17 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
return; return;
} }
// null buffer attached if ((!m_pending.updated.bits.buffer) || // no new buffer attached
if (!m_pending.buffer && !m_pending.texture && m_pending.updated.bits.buffer) { (!m_pending.buffer && !m_pending.texture) // null buffer attached
) {
commitState(m_pending); commitState(m_pending);
// remove any pending states. if (!m_pending.buffer && !m_pending.texture) {
while (!m_pendingStates.empty()) { // null buffer attached, remove any pending states.
m_pendingStates.pop(); while (!m_pendingStates.empty()) {
m_pendingStates.pop();
}
} }
m_pendingWaiting = false;
m_pending.reset(); m_pending.reset();
return; return;
} }
@ -149,9 +146,36 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
const auto& state = m_pendingStates.emplace(makeUnique<SSurfaceState>(m_pending)); const auto& state = m_pendingStates.emplace(makeUnique<SSurfaceState>(m_pending));
m_pending.reset(); m_pending.reset();
if (!m_pendingWaiting) { auto whenReadable = [this, surf = m_self, state = WP<SSurfaceState>(m_pendingStates.back())] {
m_pendingWaiting = true; if (!surf || state.expired())
scheduleState(state); 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<CDMABuffer*>(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<CWlSurface> resource_) : m_resource(re
m_pending.opaque = RG->m_region; m_pending.opaque = RG->m_region;
}); });
m_resource->setFrame([this](CWlSurface* r, uint32_t id) { m_resource->setFrame([this](CWlSurface* r, uint32_t id) { m_callbacks.emplace_back(makeUnique<CWLCallbackResource>(makeUnique<CWlCallback>(m_client, 1, id))); });
m_pending.updated.bits.frame = true;
m_pending.callbacks.emplace_back(makeShared<CWLCallbackResource>(makeShared<CWlCallback>(m_client, 1, id)));
});
m_resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) { m_resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) {
m_pending.updated.bits.offset = true; m_pending.updated.bits.offset = true;
@ -319,14 +340,14 @@ void CWLSurfaceResource::sendPreferredScale(int32_t scale) {
} }
void CWLSurfaceResource::frame(const Time::steady_tp& now) { void CWLSurfaceResource::frame(const Time::steady_tp& now) {
if (m_current.callbacks.empty()) if (m_callbacks.empty())
return; return;
for (auto const& c : m_current.callbacks) { for (auto const& c : m_callbacks) {
c->send(now); c->send(now);
} }
m_current.callbacks.clear(); m_callbacks.clear();
} }
void CWLSurfaceResource::resetRole() { void CWLSurfaceResource::resetRole() {
@ -480,47 +501,6 @@ CBox CWLSurfaceResource::extends() {
return full.getExtents(); return full.getExtents();
} }
void CWLSurfaceResource::scheduleState(WP<SSurfaceState> 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<CDMABuffer*>(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) { void CWLSurfaceResource::commitState(SSurfaceState& state) {
auto lastTexture = m_current.texture; auto lastTexture = m_current.texture;
m_current.updateFrom(state); m_current.updateFrom(state);

View file

@ -35,21 +35,13 @@ class CContentType;
class CWLCallbackResource { class CWLCallbackResource {
public: public:
CWLCallbackResource(SP<CWlCallback>&& resource_); CWLCallbackResource(UP<CWlCallback>&& resource_);
~CWLCallbackResource() noexcept = default;
// disable copy
CWLCallbackResource(const CWLCallbackResource&) = delete;
CWLCallbackResource& operator=(const CWLCallbackResource&) = delete;
// allow move bool good();
CWLCallbackResource(CWLCallbackResource&&) noexcept = default; void send(const Time::steady_tp& now);
CWLCallbackResource& operator=(CWLCallbackResource&&) noexcept = default;
bool good();
void send(const Time::steady_tp& now);
private: private:
SP<CWlCallback> m_resource; UP<CWlCallback> m_resource;
}; };
class CWLRegionResource { class CWLRegionResource {
@ -102,8 +94,8 @@ class CWLSurfaceResource {
SSurfaceState m_current; SSurfaceState m_current;
SSurfaceState m_pending; SSurfaceState m_pending;
std::queue<UP<SSurfaceState>> m_pendingStates; std::queue<UP<SSurfaceState>> m_pendingStates;
bool m_pendingWaiting = false;
std::vector<UP<CWLCallbackResource>> m_callbacks;
WP<CWLSurfaceResource> m_self; WP<CWLSurfaceResource> m_self;
WP<CWLSurface> m_hlSurface; WP<CWLSurface> m_hlSurface;
std::vector<PHLMONITORREF> m_enteredOutputs; std::vector<PHLMONITORREF> m_enteredOutputs;
@ -118,7 +110,6 @@ class CWLSurfaceResource {
SP<CWLSurfaceResource> findFirstPreorder(std::function<bool(SP<CWLSurfaceResource>)> fn); SP<CWLSurfaceResource> findFirstPreorder(std::function<bool(SP<CWLSurfaceResource>)> fn);
SP<CWLSurfaceResource> findWithCM(); SP<CWLSurfaceResource> findWithCM();
void presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded = false); void presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded = false);
void scheduleState(WP<SSurfaceState> state);
void commitState(SSurfaceState& state); void commitState(SSurfaceState& state);
NColorManagement::SImageDescription getPreferredImageDescription(); NColorManagement::SImageDescription getPreferredImageDescription();
void sortSubsurfaces(); void sortSubsurfaces();

View file

@ -75,10 +75,6 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) {
if (ref.updated.bits.damage) { if (ref.updated.bits.damage) {
damage = ref.damage; damage = ref.damage;
bufferDamage = ref.bufferDamage; bufferDamage = ref.bufferDamage;
} else {
// damage is always relative to the current commit
damage.clear();
bufferDamage.clear();
} }
if (ref.updated.bits.input) if (ref.updated.bits.input)
@ -104,9 +100,4 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) {
if (ref.updated.bits.acked) if (ref.updated.bits.acked)
ackedSize = ref.ackedSize; 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();
}
} }

View file

@ -6,7 +6,6 @@
class CTexture; class CTexture;
class CDRMSyncPointState; class CDRMSyncPointState;
class CWLCallbackResource;
struct SSurfaceState { struct SSurfaceState {
union { union {
@ -22,7 +21,6 @@ struct SSurfaceState {
bool viewport : 1; bool viewport : 1;
bool acquire : 1; bool acquire : 1;
bool acked : 1; bool acked : 1;
bool frame : 1;
} bits; } bits;
} updated; } updated;
@ -43,9 +41,6 @@ struct SSurfaceState {
// for xdg_shell resizing // for xdg_shell resizing
Vector2D ackedSize; Vector2D ackedSize;
// for wl_surface::frame callbacks.
std::vector<SP<CWLCallbackResource>> callbacks;
// viewporter protocol surface state // viewporter protocol surface state
struct { struct {
bool hasDestination = false; bool hasDestination = false;

View file

@ -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) { void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) {
if (damage.empty())
return;
g_pHyprRenderer->makeEGLCurrent(); g_pHyprRenderer->makeEGLCurrent();
const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat); const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);