From 9f47021a307781a0c2cecffd3706d1a8f4cce505 Mon Sep 17 00:00:00 2001 From: Eduardo Hopperdietzel Date: Mon, 27 Jan 2025 18:08:47 -0300 Subject: [PATCH] Update version to 2.14.0-1 --- CHANGES | 9 +++++++++ README.md | 2 +- VERSION | 2 +- pkg/fedora/latest.spec | 12 +++--------- src/lib/core/LCompositor.cpp | 8 ++++---- src/lib/core/LOutput.cpp | 1 + src/lib/core/LOutput.h | 13 ++++++++++--- src/lib/core/private/LCompositorPrivate.cpp | 9 +++++++++ src/lib/core/private/LOutputPrivate.cpp | 8 ++++++++ src/lib/core/private/LSeatPrivate.cpp | 18 ++++++++++++++++++ 10 files changed, 64 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index a7d1e3fa..a2944cc5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ +Louvre (2.14.0-1) + + # API Additions + + - LOutput::repaintFilter(): Intercepts LOutput::repaint() calls, making it easier to retain the last rendered frame. Special thanks to @LeKinaSa and @jgroboredo for highlighting the need for this feature. + +-- Eduardo Hopperdietzel Mon, 27 Jan 2025 17:47:20 -0300 + + Louvre (2.13.0-1) # License diff --git a/README.md b/README.md index 944ef7ae..110818e6 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Louvre is released under the LGPLv2.1 license. - Current Louvre version. + Current Louvre version.

diff --git a/VERSION b/VERSION index fb2c0766..edcfe40d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.13.0 +2.14.0 diff --git a/pkg/fedora/latest.spec b/pkg/fedora/latest.spec index df78c789..084f1389 100644 --- a/pkg/fedora/latest.spec +++ b/pkg/fedora/latest.spec @@ -1,4 +1,4 @@ -%global basever 2.13.0 +%global basever 2.14.0 %global origrel 1 %global somajor 2 @@ -90,11 +90,5 @@ pushd repo/src %{_libdir}/pkgconfig/Louvre.pc %changelog -* Sun Dec 08 2024 Eduardo Hopperdietzel - %{basever}-%{origrel} -- Updated license to LGPLv2.1. -- LTexture::write(Begin/Update/End): An alternative to LTexture::updateRect() that allows multiple texture updates without issuing an immediate internal synchronization. -- LOutput::currentBufferAge: Retrieves the age of the current buffer according to the [EGL_EXT_buffer_age](https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_buffer_age.txt) extension specification. -- Added damage tracking support. -- LPainter::bindProgram() now fully synchronizes all uniforms and GL state, instead of just binding its GL program. This resolves issues encountered when integrating external shaders. -- Replaced LScene index-based damage tracking with buffer age. -- Updated SRM dependency to >= 0.11.0. +* Mon Jan 27 2025 Eduardo Hopperdietzel - %{basever}-%{origrel} + diff --git a/src/lib/core/LCompositor.cpp b/src/lib/core/LCompositor.cpp index e5f3ec96..6f0554b1 100644 --- a/src/lib/core/LCompositor.cpp +++ b/src/lib/core/LCompositor.cpp @@ -236,9 +236,6 @@ bool LCompositor::start() goto fail; } - imp()->state = CompositorState::Initialized; - initialized(); - imp()->events[LEV_UNLOCK].events = EPOLLIN; imp()->events[LEV_UNLOCK].data.fd = eventfd(0, EFD_NONBLOCK); @@ -247,6 +244,8 @@ bool LCompositor::start() compositor()->imp()->events[LEV_UNLOCK].data.fd, &compositor()->imp()->events[LEV_UNLOCK]); + imp()->state = CompositorState::Initialized; + initialized(); return true; fail: @@ -340,9 +339,10 @@ Int32 LCompositor::processLoop(Int32 msTimeout) imp()->destroyPendingRenderBuffers(nullptr); imp()->handleDestroyedClients(); - imp()->handleOutputRepaintRequests(); } + imp()->handleOutputRepaintRequests(); + if (state() == CompositorState::Uninitializing) { uninitialized(); diff --git a/src/lib/core/LOutput.cpp b/src/lib/core/LOutput.cpp index 5d5c4530..86ca239e 100644 --- a/src/lib/core/LOutput.cpp +++ b/src/lib/core/LOutput.cpp @@ -351,6 +351,7 @@ Float32 LOutput::scale() const noexcept void LOutput::repaint() noexcept { + // Check LCompositor::processLoop() -> LCompositorPrivate::handleOutputRepaintRequests() imp()->stateFlags.add(LOutputPrivate::PendingRepaint); compositor()->imp()->unlockPoll(); } diff --git a/src/lib/core/LOutput.h b/src/lib/core/LOutput.h index fbd9d11c..09701897 100644 --- a/src/lib/core/LOutput.h +++ b/src/lib/core/LOutput.h @@ -1019,10 +1019,17 @@ class Louvre::LOutput : public LFactoryObject virtual void availableGeometryChanged(); /** - * @brief Selectively disables repaint calls. + * @brief Temporarily disables repaint calls for this output. * - * This method can be used to intercept repaint() calls and keep the last rendered frame. - * If `false` is returned, the repaint() call is ignored, preventing paintGL() from being triggered. + * An output locks its rendering thread until repaint() is called. However, many objects and implementations + * within the compositor may automatically trigger repaints to reflect changes, making it difficult to + * prevent unwanted repaints. + * + * This method intercepts repaint() calls and preserves the last rendered frame. When `false` is returned, + * the repaint() calls are ignored, and paintGL() is not triggered. + * + * @note During initialization, uninitialization, or mode changes, the rendering thread is forcefully + * unlocked and the filter is ignored to prevent deadlocks. * * #### Default Implementation * diff --git a/src/lib/core/private/LCompositorPrivate.cpp b/src/lib/core/private/LCompositorPrivate.cpp index 533b93d3..7b40694d 100644 --- a/src/lib/core/private/LCompositorPrivate.cpp +++ b/src/lib/core/private/LCompositorPrivate.cpp @@ -1069,6 +1069,15 @@ void LCompositor::LCompositorPrivate::handleOutputRepaintRequests() noexcept for (LOutput *o : outputs) { + if (!seat->enabled()) + { + if (o->imp()->stateFlags.check(LOutput::LOutputPrivate::RepaintLocked)) + { + o->imp()->stateFlags.remove(LOutput::LOutputPrivate::RepaintLocked); + o->imp()->repaintFilterMutex.unlock(); + } + } + if (!o->imp()->stateFlags.check(LOutput::LOutputPrivate::PendingRepaint)) continue; diff --git a/src/lib/core/private/LOutputPrivate.cpp b/src/lib/core/private/LOutputPrivate.cpp index c3d856b0..d908957a 100644 --- a/src/lib/core/private/LOutputPrivate.cpp +++ b/src/lib/core/private/LOutputPrivate.cpp @@ -266,11 +266,17 @@ void LOutput::LOutputPrivate::backendPaintGL() { compositor()->imp()->lock(); + // This means LOutput::repaintFilter() returned false if (stateFlags.check(RepaintLocked)) { + // Unlock other threads (let the main loop update the RepaintLocked state) compositor()->imp()->unlock(); + + // Wait until LOutput::repaintFilter() returns true repaintFilterMutex.lock(); repaintFilterMutex.unlock(); + + // Continue rendering... compositor()->imp()->lock(); compositor()->imp()->unlockPoll(); } @@ -381,6 +387,8 @@ void LOutput::LOutputPrivate::backendPaintGL() /* Destroy render buffers created from this thread and marked as destroyed by the user */ compositor()->imp()->destroyPendingRenderBuffers(&output->imp()->threadId); + + /* Handle LOutput::repaint() calls from this thread */ compositor()->imp()->handleOutputRepaintRequests(); if (callLock) diff --git a/src/lib/core/private/LSeatPrivate.cpp b/src/lib/core/private/LSeatPrivate.cpp index a2857b62..0221ec1e 100644 --- a/src/lib/core/private/LSeatPrivate.cpp +++ b/src/lib/core/private/LSeatPrivate.cpp @@ -23,6 +23,15 @@ void LSeat::LSeatPrivate::seatEnabled(libseat *seat, void *data) compositor()->imp()->unlock(); + for (LOutput *o : compositor()->outputs()) + { + if (o->imp()->stateFlags.check(LOutput::LOutputPrivate::RepaintLocked)) + { + o->imp()->stateFlags.remove(LOutput::LOutputPrivate::RepaintLocked); + o->imp()->repaintFilterMutex.unlock(); + } + } + if (compositor()->isGraphicBackendInitialized()) compositor()->imp()->graphicBackend->backendResume(); @@ -75,6 +84,15 @@ void LSeat::LSeatPrivate::seatDisabled(libseat *seat, void *data) compositor()->imp()->unlock(); + for (LOutput *o : compositor()->outputs()) + { + if (o->imp()->stateFlags.check(LOutput::LOutputPrivate::RepaintLocked)) + { + o->imp()->stateFlags.remove(LOutput::LOutputPrivate::RepaintLocked); + o->imp()->repaintFilterMutex.unlock(); + } + } + if (compositor()->isGraphicBackendInitialized()) compositor()->imp()->graphicBackend->backendSuspend();