summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-07-05 16:26:15 +0200
committerAndreas Kling <kling@serenityos.org>2020-07-05 16:26:15 +0200
commit668fe61b1de666ba583fa43a317d47d269e0bb70 (patch)
tree5100a1fb27bbf4b4aaa712223b8c2f1b65eba7a7
parentddbdd0e68617f7e09d5b07496de216d120630bf8 (diff)
downloadserenity-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.cpp22
-rw-r--r--Services/WebContent/ClientConnection.h9
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;
};
}