Skip to content

Commit

Permalink
Wayland Backend: Fixed occasional flickering when no damage is genera…
Browse files Browse the repository at this point in the history
…ted within LOutput::paintGL()

LOutput::repaintFilter: Updated internal implementation to reduce CPU consumption and allow cursor plane updates when using the atomic DRM API

Updated SRM dependency to version >= 0.12.0
  • Loading branch information
ehopperdietzel committed Feb 8, 2025
1 parent 9f47021 commit daa0f9a
Show file tree
Hide file tree
Showing 16 changed files with 99 additions and 148 deletions.
16 changes: 15 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
Louvre (2.14.1-1)

# Bug Fixes

* Wayland Backend: Fixed occasional flickering when no damage is generated within LOutput::paintGL().
* LOutput::repaintFilter: Updated internal implementation to reduce CPU consumption and allow cursor plane updates when using the atomic DRM API.

# Dependencies

* Updated SRM dependency to version >= 0.12.0.

-- Eduardo Hopperdietzel <ehopperdietzel@gmail.com> Sat, 08 Feb 2025 08:27:14 -0300


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.
* 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 <ehopperdietzel@gmail.com> Mon, 27 Jan 2025 17:47:20 -0300

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<img src="https://img.shields.io/badge/license-LGPLv2.1-blue.svg" alt="Louvre is released under the LGPLv2.1 license." />
</a>
<a href="https://github.com/CuarzoSoftware/Louvre">
<img src="https://img.shields.io/badge/version-2.14.0-brightgreen" alt="Current Louvre version." />
<img src="https://img.shields.io/badge/version-2.14.1-brightgreen" alt="Current Louvre version." />
</a>
</p>

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.14.0
2.14.1
8 changes: 5 additions & 3 deletions pkg/fedora/latest.spec
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%global basever 2.14.0
%global basever 2.14.1
%global origrel 1
%global somajor 2

Expand Down Expand Up @@ -90,5 +90,7 @@ pushd repo/src
%{_libdir}/pkgconfig/Louvre.pc

%changelog
* Mon Jan 27 2025 Eduardo Hopperdietzel <ehopperdietzel@gmail.com> - %{basever}-%{origrel}

* Sat Feb 08 2025 Eduardo Hopperdietzel <ehopperdietzel@gmail.com> - %{basever}-%{origrel}
- Wayland Backend: Fixed occasional flickering when no damage is generated within LOutput::paintGL().
- LOutput::repaintFilter: Updated internal implementation to reduce CPU consumption and allow cursor plane updates when using the atomic DRM API.
- Updated SRM dependency to version >= 0.12.0.
11 changes: 9 additions & 2 deletions src/backends/graphic/DRM/LGraphicBackendDRM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,9 @@ bool LGraphicBackend::backendInitialize()

version = srmCoreGetVersion(bknd->core);

if (version->major == 0 && version->minor < 11)
if (version->major == 0 && version->minor < 12)
{
LLog::fatal("[%s] Using SRM v%d.%d.%d but version >= v0.11.0 is required.", BKND_NAME, version->major, version->minor, version->patch);
LLog::fatal("[%s] Using SRM v%d.%d.%d but version >= v0.12.0 is required.", BKND_NAME, version->major, version->minor, version->patch);
srmCoreDestroy(bknd->core);
goto fail;
}
Expand Down Expand Up @@ -897,6 +897,12 @@ LTexture *LGraphicBackend::outputGetBuffer(LOutput *output, UInt32 bufferIndex)
return tex;
}

void LGraphicBackend::outputLockCurrentBuffer(LOutput *output, bool locked)
{
Output *bkndOutput = (Output*)output->imp()->graphicBackendData;
srmConnectorSetCurrentBufferLocked(bkndOutput->conn, locked);
}

/* OUTPUT GAMMA */

UInt32 LGraphicBackend::outputGetGammaSize(LOutput *output)
Expand Down Expand Up @@ -1190,6 +1196,7 @@ extern "C" LGraphicBackendInterface *getAPI()
API.outputGetBuffersCount = &LGraphicBackend::outputGetBuffersCount;
API.outputGetCurrentBufferAge = &LGraphicBackend::outputGetCurrentBufferAge;
API.outputGetBuffer = &LGraphicBackend::outputGetBuffer;
API.outputLockCurrentBuffer = &LGraphicBackend::outputLockCurrentBuffer;

/* OUTPUT GAMMA */
API.outputGetGammaSize = &LGraphicBackend::outputGetGammaSize;
Expand Down
1 change: 1 addition & 0 deletions src/backends/graphic/LGraphicBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class Louvre::LGraphicBackend
static UInt32 outputGetCurrentBufferAge(LOutput *output);
static LTexture * outputGetBuffer(LOutput *output, UInt32 bufferIndex);
static void outputDestroyBuffers(std::vector<LTexture*> &textures);
static void outputLockCurrentBuffer(LOutput *output, bool locked);

/* OUTPUT GAMMA */
static UInt32 outputGetGammaSize(LOutput *output);
Expand Down
41 changes: 32 additions & 9 deletions src/backends/graphic/Wayland/LGraphicBackendWayland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class Louvre::LGraphicBackend
inline static EGLContext windowEGLContext { EGL_NO_CONTEXT };
inline static PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC eglSwapBuffersWithDamageKHR { nullptr };
inline static LRegion damage;
inline static bool bufferIsLocked { false };
inline static EGLConfig eglConfig { EGL_NO_CONFIG_KHR };
inline static EGLSurface eglSurface { EGL_NO_SURFACE };
inline static std::thread renderThread;
Expand Down Expand Up @@ -527,12 +528,17 @@ class Louvre::LGraphicBackend
else
wl_display_cancel_read(display);

paintGLChangedBufferIsLocked:

if (bufferIsLocked)
repaint = false;

if (output->state() == LOutput::Initialized && repaint)
{
eglSwapInterval(eglDisplay, vSync);

repaint = false;

eglSwapInterval(eglDisplay, vSync);

if (wl_surface_get_version(surface) >= 3)
wl_surface_set_buffer_scale(surface, pendingBufferScale);

Expand All @@ -551,13 +557,20 @@ class Louvre::LGraphicBackend
}

output->imp()->backendPaintGL();

if (bufferIsLocked)
goto paintGLChangedBufferIsLocked;

wl_surface_set_opaque_region(surface, opaqueRegion);

if (damage.empty())
wl_surface_commit(surface);
else
if (eglSwapBuffersWithDamageKHR)
{
if (eglSwapBuffersWithDamageKHR)
if (damage.empty())
{
constexpr GLint dummyBox[4] { -100, -100, 1, 1 };
eglSwapBuffersWithDamageKHR(eglDisplay, eglSurface, dummyBox, 1);
}
else
{
Int32 n;
const LBox *boxes { damage.boxes(&n) };
Expand All @@ -577,12 +590,17 @@ class Louvre::LGraphicBackend
eglSwapBuffersWithDamageKHR(eglDisplay, eglSurface, rects, n);
delete []rects;
}
}
else
{
if (damage.empty())
wl_surface_commit(surface);
else
eglSwapBuffers(eglDisplay, eglSurface);

damage.clear();
}

damage.clear();

if (!vSync && refreshRateLimit >= 0)
{
Int64 diff {LTime::us() - lastFrameUsec};
Expand All @@ -605,7 +623,6 @@ class Louvre::LGraphicBackend
output->imp()->presentationTime.period = 0;
clock_gettime(CLOCK_MONOTONIC, &output->imp()->presentationTime.time);
output->imp()->backendPageFlipped();

}
else if (output->state() == LOutput::PendingInitialize)
output->imp()->backendInitializeGL();
Expand Down Expand Up @@ -1071,6 +1088,11 @@ class Louvre::LGraphicBackend
return nullptr;
}

static void outputLockCurrentBuffer(LOutput */*output*/, bool locked)
{
bufferIsLocked = locked;
}

static UInt32 outputGetGammaSize(LOutput */*output*/)
{
return 0;
Expand Down Expand Up @@ -1385,6 +1407,7 @@ extern "C" LGraphicBackendInterface *getAPI()
API.outputGetBuffersCount = &LGraphicBackend::outputGetBuffersCount;
API.outputGetCurrentBufferAge = &LGraphicBackend::outputGetCurrentBufferAge;
API.outputGetBuffer = &LGraphicBackend::outputGetBuffer;
API.outputLockCurrentBuffer = &LGraphicBackend::outputLockCurrentBuffer;

/* OUTPUT GAMMA */
API.outputGetGammaSize = &LGraphicBackend::outputGetGammaSize;
Expand Down
21 changes: 8 additions & 13 deletions src/lib/core/LCompositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,6 @@ Int32 LCompositor::processLoop(Int32 msTimeout)
imp()->handleDestroyedClients();
}

imp()->handleOutputRepaintRequests();

if (state() == CompositorState::Uninitializing)
{
uninitialized();
Expand Down Expand Up @@ -491,7 +489,7 @@ bool LCompositor::addOutput(LOutput *output)

void LCompositor::removeOutput(LOutput *output)
{
if (!isGraphicBackendInitialized() || std::this_thread::get_id() != mainThreadId())
if (!isGraphicBackendInitialized())
return;

// Loop to check if output was added (initialized)
Expand All @@ -500,20 +498,17 @@ void LCompositor::removeOutput(LOutput *output)
// Was initialized
if (o == output)
{
output->imp()->state = LOutput::PendingUninitialize;
// Uninitializing outputs from their own thread is not allowed
if (output->threadId() == std::this_thread::get_id())
return;

output->imp()->callLockACK.store(false);
output->imp()->callLock.store(false);

if (o->imp()->stateFlags.check(LOutput::LOutputPrivate::RepaintLocked))
{
o->imp()->stateFlags.remove(LOutput::LOutputPrivate::RepaintLocked);
o->imp()->repaintFilterMutex.unlock();
}

imp()->graphicBackend->outputRepaint(output);
output->repaint();
output->imp()->state = LOutput::PendingUninitialize;
imp()->unlock();

Int32 waitLimit = 0;
Int32 waitLimit { 0 };

while (!output->imp()->callLockACK.load() && waitLimit < 1000)
{
Expand Down
16 changes: 7 additions & 9 deletions src/lib/core/LOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,6 @@ void LOutput::setMode(const LOutputMode *mode) noexcept
imp()->callLockACK.store(false);
imp()->callLock.store(false);

if (imp()->stateFlags.check(LOutputPrivate::RepaintLocked))
{
imp()->stateFlags.remove(LOutputPrivate::RepaintLocked);
imp()->repaintFilterMutex.unlock();
}

compositor()->imp()->unlock();

Int32 waitLimit = 0;
Expand Down Expand Up @@ -351,9 +345,13 @@ Float32 LOutput::scale() const noexcept

void LOutput::repaint() noexcept
{
// Check LCompositor::processLoop() -> LCompositorPrivate::handleOutputRepaintRequests()
imp()->stateFlags.add(LOutputPrivate::PendingRepaint);
compositor()->imp()->unlockPoll();
if (imp()->stateFlags.check(LOutputPrivate::IsInRepaintFilter))
return;

compositor()->imp()->graphicBackend->outputLockCurrentBuffer(this, !imp()->repaintFilter());

if (compositor()->imp()->graphicBackend->outputRepaint(this))
imp()->stateFlags.add(LOutputPrivate::PendingRepaint);
}

Int32 LOutput::dpi() noexcept
Expand Down
1 change: 1 addition & 0 deletions src/lib/core/private/LBackendPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace Louvre
UInt32 (*outputGetBuffersCount)(LOutput *output);
UInt32 (*outputGetCurrentBufferAge)(LOutput *output);
LTexture * (*outputGetBuffer)(LOutput *output, UInt32 bufferIndex);
void (*outputLockCurrentBuffer)(LOutput *output, bool locked);

/* OUTPUT GAMMA */
UInt32 (*outputGetGammaSize)(LOutput *output);
Expand Down
58 changes: 0 additions & 58 deletions src/lib/core/private/LCompositorPrivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1045,61 +1045,3 @@ void LCompositor::LCompositorPrivate::unitDRMLeaseGlobals()
if (gpu->m_leaseGlobal)
compositor()->removeGlobal(gpu->m_leaseGlobal);
}

void LCompositor::LCompositorPrivate::handleOutputRepaintRequests() noexcept
{
bool repaint;

if (std::this_thread::get_id() != compositor()->mainThreadId())
{
for (LOutput *o : outputs)
{
if (!o->imp()->stateFlags.check(LOutput::LOutputPrivate::PendingRepaint) || o->imp()->stateFlags.check(LOutput::LOutputPrivate::RepaintLocked))
continue;

repaint = o->repaintFilter();

if (repaint)
graphicBackend->outputRepaint(o);
}

return;
}


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;

repaint = o->repaintFilter();

if (repaint)
{
if (o->imp()->stateFlags.check(LOutput::LOutputPrivate::RepaintLocked))
{
o->imp()->stateFlags.remove(LOutput::LOutputPrivate::RepaintLocked);
o->imp()->repaintFilterMutex.unlock();
}
}
else
{
if (!o->imp()->stateFlags.check(LOutput::LOutputPrivate::RepaintLocked))
{
o->imp()->stateFlags.add(LOutput::LOutputPrivate::RepaintLocked);
o->imp()->repaintFilterMutex.lock();
}
}

graphicBackend->outputRepaint(o);
}
}
1 change: 0 additions & 1 deletion src/lib/core/private/LCompositorPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ LPRIVATE_CLASS(LCompositor)

bool runningAnimations();
void processAnimations();
void handleOutputRepaintRequests() noexcept;

// Thread specific data
struct ThreadData
Expand Down
Loading

0 comments on commit daa0f9a

Please sign in to comment.