diff options
author | Robin Burchell <robin+git@viroteck.net> | 2019-05-26 17:35:33 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-05-26 18:22:33 +0200 |
commit | 9b86eb9fadc98b1c32f0387cb788fe8de5d70d7c (patch) | |
tree | efe4cd83c3441e2ab8c1cdaf92dd1df53a23bb63 | |
parent | 8df3e2516fa416e1c778d20f7ad203d68fb6afa9 (diff) | |
download | serenity-9b86eb9fadc98b1c32f0387cb788fe8de5d70d7c.zip |
WSCompositor: Allow a compose to bypass the timer when it first happens
d66fa60fcf23fa7217a065479af6b1f5a851a506 introduced the use of a timer
to coalesce screen updates. This is OK, but it does introduce update
latency.
To help mitigate the impact of this, we now have a second (immediate)
timer. When a compose pass is first triggered, the immediate timer will
allow the compose to happen on the next spin of the event loop (so, only
coalescing updates across a single event loop pass). Any updates that
trigger while the delayed timer is running, though, will be delayed to
that (~60fps) timer.
This fixes #103.
-rw-r--r-- | Servers/WindowServer/WSCompositor.cpp | 33 | ||||
-rw-r--r-- | Servers/WindowServer/WSCompositor.h | 1 | ||||
-rw-r--r-- | SharedGraphics/DisjointRectSet.h | 1 |
3 files changed, 31 insertions, 4 deletions
diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 8c07d25623..77b7268317 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -30,12 +30,20 @@ WSCompositor::WSCompositor() m_compose_timer.on_timeout = [=]() { #if defined(COMPOSITOR_DEBUG) - dbgprintf("WSCompositor: frame callback\n"); + dbgprintf("WSCompositor: delayed frame callback: %d rects\n", m_dirty_rects.size()); #endif compose(); }; m_compose_timer.set_single_shot(true); m_compose_timer.set_interval(1000 / 60); + m_immediate_compose_timer.on_timeout = [=]() { +#if defined(COMPOSITOR_DEBUG) + dbgprintf("WSCompositor: immediate frame callback: %d rects\n", m_dirty_rects.size()); +#endif + compose(); + }; + m_immediate_compose_timer.set_single_shot(true); + m_immediate_compose_timer.set_interval(0); } void WSCompositor::compose() @@ -43,6 +51,12 @@ void WSCompositor::compose() auto& wm = WSWindowManager::the(); auto dirty_rects = move(m_dirty_rects); + + if (dirty_rects.size() == 0) { + // nothing dirtied since the last compose pass. + return; + } + dirty_rects.add(Rect::intersection(m_last_geometry_label_rect, WSScreen::the().rect())); dirty_rects.add(Rect::intersection(m_last_cursor_rect, WSScreen::the().rect())); dirty_rects.add(Rect::intersection(current_cursor_rect(), WSScreen::the().rect())); @@ -161,11 +175,22 @@ void WSCompositor::invalidate(const Rect& a_rect) if (rect.is_empty()) return; + m_dirty_rects.add(rect); + + // We delay composition by a timer interval, but to not affect latency too + // much, if a pending compose is not already scheduled, we also schedule an + // immediate compose the next spin of the event loop. + if (!m_compose_timer.is_active()) { #if defined(COMPOSITOR_DEBUG) - dbgprintf("Invalidated: %dx%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height()); + dbgprintf("Invalidated (starting immediate frame): %dx%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height()); #endif - m_dirty_rects.add(rect); - m_compose_timer.start(); + m_compose_timer.start(); + m_immediate_compose_timer.start(); + } else { +#if defined(COMPOSITOR_DEBUG) + dbgprintf("Invalidated (frame callback pending): %dx%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height()); +#endif + } } bool WSCompositor::set_wallpaper(const String& path, Function<void(bool)>&& callback) diff --git a/Servers/WindowServer/WSCompositor.h b/Servers/WindowServer/WSCompositor.h index 9fdbf5bc50..f0ea27bf14 100644 --- a/Servers/WindowServer/WSCompositor.h +++ b/Servers/WindowServer/WSCompositor.h @@ -40,6 +40,7 @@ private: unsigned m_compose_count { 0 }; unsigned m_flush_count { 0 }; CTimer m_compose_timer; + CTimer m_immediate_compose_timer; bool m_flash_flush { false }; bool m_buffers_are_flipped { false }; diff --git a/SharedGraphics/DisjointRectSet.h b/SharedGraphics/DisjointRectSet.h index 301c51d904..1c15eadbd9 100644 --- a/SharedGraphics/DisjointRectSet.h +++ b/SharedGraphics/DisjointRectSet.h @@ -12,6 +12,7 @@ public: void add(const Rect&); bool is_empty() const { return m_rects.is_empty(); } + int size() const { return m_rects.size(); } void clear() { m_rects.clear(); } void clear_with_capacity() { m_rects.clear_with_capacity(); } |