summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Burchell <robin+git@viroteck.net>2019-05-26 17:35:33 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-26 18:22:33 +0200
commit9b86eb9fadc98b1c32f0387cb788fe8de5d70d7c (patch)
treeefe4cd83c3441e2ab8c1cdaf92dd1df53a23bb63
parent8df3e2516fa416e1c778d20f7ad203d68fb6afa9 (diff)
downloadserenity-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.cpp33
-rw-r--r--Servers/WindowServer/WSCompositor.h1
-rw-r--r--SharedGraphics/DisjointRectSet.h1
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(); }