diff options
author | Andreas Kling <kling@serenityos.org> | 2020-07-05 16:26:15 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-05 16:26:15 +0200 |
commit | 668fe61b1de666ba583fa43a317d47d269e0bb70 (patch) | |
tree | 5100a1fb27bbf4b4aaa712223b8c2f1b65eba7a7 | |
parent | ddbdd0e68617f7e09d5b07496de216d120630bf8 (diff) | |
download | serenity-668fe61b1de666ba583fa43a317d47d269e0bb70.zip |
WebContent: Coalesce pending paint events to reduce overdraw
Instead of painting synchronously whenever a Paint request comes in,
the WebContent process will now buffer pending paints and coalesce
them and defer the actual paint using a zero-timer.
This significantly reduces flickering already, without doing any
double-buffering in the WebContentView widget.
-rw-r--r-- | Services/WebContent/ClientConnection.cpp | 22 | ||||
-rw-r--r-- | Services/WebContent/ClientConnection.h | 9 |
2 files changed, 29 insertions, 2 deletions
diff --git a/Services/WebContent/ClientConnection.cpp b/Services/WebContent/ClientConnection.cpp index 00bf8d7e31..f818fa5538 100644 --- a/Services/WebContent/ClientConnection.cpp +++ b/Services/WebContent/ClientConnection.cpp @@ -41,6 +41,7 @@ ClientConnection::ClientConnection(Core::LocalSocket& socket, int client_id) , m_page_host(PageHost::create(*this)) { s_connections.set(client_id, *this); + m_paint_flush_timer = Core::Timer::create_single_shot(0, [this] { flush_pending_paint_requests(); }); } ClientConnection::~ClientConnection() @@ -102,6 +103,13 @@ void ClientConnection::handle(const Messages::WebContentServer::Paint& message) dbg() << "handle: WebContentServer::Paint: content_rect=" << message.content_rect() << ", shbuf_id=" << message.shbuf_id(); #endif + for (auto& pending_paint : m_pending_paint_requests) { + if (pending_paint.bitmap->shbuf_id() == message.shbuf_id()) { + pending_paint.content_rect = message.content_rect(); + return; + } + } + auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id()); if (!shared_buffer) { dbg() << "WebContentServer::Paint: SharedBuffer already gone! Ignoring :^)"; @@ -112,8 +120,18 @@ void ClientConnection::handle(const Messages::WebContentServer::Paint& message) did_misbehave("WebContentServer::Paint: Cannot create Gfx::Bitmap wrapper around SharedBuffer"); return; } - m_page_host->paint(message.content_rect(), *shared_bitmap); - post_message(Messages::WebContentClient::DidPaint(message.content_rect(), message.shbuf_id())); + + m_pending_paint_requests.append({ message.content_rect(), shared_bitmap.release_nonnull() }); + m_paint_flush_timer->start(); +} + +void ClientConnection::flush_pending_paint_requests() +{ + for (auto& pending_paint : m_pending_paint_requests) { + m_page_host->paint(pending_paint.content_rect, *pending_paint.bitmap); + post_message(Messages::WebContentClient::DidPaint(pending_paint.content_rect, pending_paint.bitmap->shbuf_id())); + } + m_pending_paint_requests.clear(); } void ClientConnection::handle(const Messages::WebContentServer::MouseDown& message) diff --git a/Services/WebContent/ClientConnection.h b/Services/WebContent/ClientConnection.h index 5ee492132a..b2981e6be5 100644 --- a/Services/WebContent/ClientConnection.h +++ b/Services/WebContent/ClientConnection.h @@ -58,7 +58,16 @@ private: virtual void handle(const Messages::WebContentServer::MouseMove&) override; virtual void handle(const Messages::WebContentServer::MouseUp&) override; + void flush_pending_paint_requests(); + NonnullOwnPtr<PageHost> m_page_host; + + struct PaintRequest { + Gfx::IntRect content_rect; + NonnullRefPtr<Gfx::Bitmap> bitmap; + }; + Vector<PaintRequest> m_pending_paint_requests; + RefPtr<Core::Timer> m_paint_flush_timer; }; } |