Преглед изворни кода

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.
Andreas Kling пре 5 година
родитељ
комит
668fe61b1d
2 измењених фајлова са 29 додато и 2 уклоњено
  1. 20 2
      Services/WebContent/ClientConnection.cpp
  2. 9 0
      Services/WebContent/ClientConnection.h

+ 20 - 2
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)

+ 9 - 0
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;
 };
 
 }