From b5d98c094566cc392d1249a5b9a862843e2895ce Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 16 Jan 2021 23:15:32 +0100 Subject: [PATCH] LibWeb+WebContent: Use anonymous files for OOPWV backing stores To support this, the GUI process and the WebContent service will now coordinate their backing store bitmaps. Each backing store can be referred to by a serial ID, and we don't need to keep resending it as a file descriptor. We should probably do something similar in WindowServer. :^) --- .../Libraries/LibWeb/OutOfProcessWebView.cpp | 27 +++++++++++---- .../Libraries/LibWeb/OutOfProcessWebView.h | 6 ++-- .../Libraries/LibWeb/WebContentClient.cpp | 5 +-- .../Services/WebContent/ClientConnection.cpp | 34 +++++++++---------- .../Services/WebContent/ClientConnection.h | 5 +++ .../Services/WebContent/WebContentClient.ipc | 2 +- .../Services/WebContent/WebContentServer.ipc | 5 ++- 7 files changed, 52 insertions(+), 32 deletions(-) diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp index 003571e2e8..ae3bfb7ecb 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp @@ -97,21 +97,33 @@ void OutOfProcessWebView::resize_event(GUI::ResizeEvent& event) client().post_message(Messages::WebContentServer::SetViewportRect(Gfx::IntRect({ horizontal_scrollbar().value(), vertical_scrollbar().value() }, available_size()))); - m_front_bitmap = nullptr; - m_back_bitmap = nullptr; + if (m_front_bitmap) { + m_front_bitmap = nullptr; + client().post_message(Messages::WebContentServer::RemoveBackingStore(m_front_bitmap_id)); + } + + if (m_back_bitmap) { + m_back_bitmap = nullptr; + client().post_message(Messages::WebContentServer::RemoveBackingStore(m_back_bitmap_id)); + } + + m_front_bitmap_id = -1; + m_back_bitmap_id = -1; m_has_usable_bitmap = false; if (available_size().is_empty()) return; if (auto new_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::RGB32, available_size())) { - new_bitmap->shared_buffer()->share_with(client().server_pid()); m_front_bitmap = move(new_bitmap); + m_front_bitmap_id = m_next_bitmap_id++; + client().post_message(Messages::WebContentServer::AddBackingStore(m_front_bitmap_id, m_front_bitmap->to_shareable_bitmap())); } if (auto new_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::RGB32, available_size())) { - new_bitmap->shared_buffer()->share_with(client().server_pid()); m_back_bitmap = move(new_bitmap); + m_back_bitmap_id = m_next_bitmap_id++; + client().post_message(Messages::WebContentServer::AddBackingStore(m_back_bitmap_id, m_back_bitmap->to_shareable_bitmap())); } request_repaint(); @@ -144,11 +156,12 @@ void OutOfProcessWebView::theme_change_event(GUI::ThemeChangeEvent& event) request_repaint(); } -void OutOfProcessWebView::notify_server_did_paint(Badge, i32 shbuf_id) +void OutOfProcessWebView::notify_server_did_paint(Badge, i32 bitmap_id) { - if (m_back_bitmap->shbuf_id() == shbuf_id) { + if (m_back_bitmap_id == bitmap_id) { m_has_usable_bitmap = true; swap(m_back_bitmap, m_front_bitmap); + swap(m_back_bitmap_id, m_front_bitmap_id); update(); } } @@ -246,7 +259,7 @@ void OutOfProcessWebView::request_repaint() // it won't have a back bitmap yet, so we can just skip repaint requests. if (!m_back_bitmap) return; - client().post_message(Messages::WebContentServer::Paint(m_back_bitmap->rect().translated(horizontal_scrollbar().value(), vertical_scrollbar().value()), m_back_bitmap->shbuf_id())); + client().post_message(Messages::WebContentServer::Paint(m_back_bitmap->rect().translated(horizontal_scrollbar().value(), vertical_scrollbar().value()), m_back_bitmap_id)); } WebContentClient& OutOfProcessWebView::client() diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.h b/Userland/Libraries/LibWeb/OutOfProcessWebView.h index a742a01af8..3a9167a06c 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.h +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.h @@ -50,7 +50,7 @@ public: void load_empty_document(); void notify_server_did_layout(Badge, const Gfx::IntSize& content_size); - void notify_server_did_paint(Badge, i32 shbuf_id); + void notify_server_did_paint(Badge, i32 bitmap_id); void notify_server_did_invalidate_content_rect(Badge, const Gfx::IntRect&); void notify_server_did_change_selection(Badge); void notify_server_did_change_title(Badge, const String&); @@ -89,7 +89,9 @@ private: RefPtr m_client; RefPtr m_front_bitmap; RefPtr m_back_bitmap; - + i32 m_front_bitmap_id { -1 }; + i32 m_back_bitmap_id { -1 }; + i32 m_next_bitmap_id { 0 }; bool m_has_usable_bitmap { false }; }; diff --git a/Userland/Libraries/LibWeb/WebContentClient.cpp b/Userland/Libraries/LibWeb/WebContentClient.cpp index c31420a56b..7032924600 100644 --- a/Userland/Libraries/LibWeb/WebContentClient.cpp +++ b/Userland/Libraries/LibWeb/WebContentClient.cpp @@ -45,10 +45,7 @@ void WebContentClient::handshake() void WebContentClient::handle(const Messages::WebContentClient::DidPaint& message) { -#ifdef DEBUG_SPAM - dbg() << "handle: WebContentClient::DidPaint! content_rect=" << message.content_rect() << ", shbuf_id=" << message.shbuf_id(); -#endif - m_view.notify_server_did_paint({}, message.shbuf_id()); + m_view.notify_server_did_paint({}, message.bitmap_id()); } void WebContentClient::handle([[maybe_unused]] const Messages::WebContentClient::DidFinishLoading& message) diff --git a/Userland/Services/WebContent/ClientConnection.cpp b/Userland/Services/WebContent/ClientConnection.cpp index 2f5b44f95a..43fabf1c6c 100644 --- a/Userland/Services/WebContent/ClientConnection.cpp +++ b/Userland/Services/WebContent/ClientConnection.cpp @@ -102,33 +102,33 @@ void ClientConnection::handle(const Messages::WebContentServer::SetViewportRect& m_page_host->set_viewport_rect(message.rect()); } +void ClientConnection::handle(const Messages::WebContentServer::AddBackingStore& message) +{ + m_backing_stores.set(message.backing_store_id(), *message.bitmap().bitmap()); +} + +void ClientConnection::handle(const Messages::WebContentServer::RemoveBackingStore& message) +{ + m_backing_stores.remove(message.backing_store_id()); +} + void ClientConnection::handle(const Messages::WebContentServer::Paint& message) { -#ifdef DEBUG_SPAM - 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()) { + if (pending_paint.bitmap_id == message.backing_store_id()) { pending_paint.content_rect = message.content_rect(); return; } } - auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id()); - if (!shared_buffer) { -#ifdef DEBUG_SPAM - dbgln("WebContentServer::Paint: SharedBuffer already gone! Ignoring :^)"); -#endif - return; - } - auto shared_bitmap = Gfx::Bitmap::create_with_shared_buffer(Gfx::BitmapFormat::RGB32, shared_buffer.release_nonnull(), message.content_rect().size()); - if (!shared_bitmap) { - did_misbehave("WebContentServer::Paint: Cannot create Gfx::Bitmap wrapper around SharedBuffer"); + auto it = m_backing_stores.find(message.backing_store_id()); + if (it == m_backing_stores.end()) { + did_misbehave("Client requested paint with backing store ID"); return; } - m_pending_paint_requests.append({ message.content_rect(), shared_bitmap.release_nonnull() }); + auto& bitmap = *it->value; + m_pending_paint_requests.append({ message.content_rect(), bitmap, message.backing_store_id() }); m_paint_flush_timer->start(); } @@ -136,7 +136,7 @@ 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())); + post_message(Messages::WebContentClient::DidPaint(pending_paint.content_rect, pending_paint.bitmap_id)); } m_pending_paint_requests.clear(); } diff --git a/Userland/Services/WebContent/ClientConnection.h b/Userland/Services/WebContent/ClientConnection.h index 42e2ab8313..34a13713f3 100644 --- a/Userland/Services/WebContent/ClientConnection.h +++ b/Userland/Services/WebContent/ClientConnection.h @@ -60,6 +60,8 @@ private: virtual void handle(const Messages::WebContentServer::MouseMove&) override; virtual void handle(const Messages::WebContentServer::MouseUp&) override; virtual void handle(const Messages::WebContentServer::KeyDown&) override; + virtual void handle(const Messages::WebContentServer::AddBackingStore&) override; + virtual void handle(const Messages::WebContentServer::RemoveBackingStore&) override; void flush_pending_paint_requests(); @@ -68,9 +70,12 @@ private: struct PaintRequest { Gfx::IntRect content_rect; NonnullRefPtr bitmap; + i32 bitmap_id { -1 }; }; Vector m_pending_paint_requests; RefPtr m_paint_flush_timer; + + HashMap> m_backing_stores; }; } diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index 10008a765c..2e2f63d831 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -2,7 +2,7 @@ endpoint WebContentClient = 90 { DidStartLoading(URL url) =| DidFinishLoading(URL url) =| - DidPaint(Gfx::IntRect content_rect, i32 shbuf_id) =| + DidPaint(Gfx::IntRect content_rect, i32 bitmap_id) =| DidInvalidateContentRect(Gfx::IntRect content_rect) =| DidChangeSelection() =| DidLayout(Gfx::IntSize content_size) =| diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index cb2ff26b85..e025e0b0cd 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -7,7 +7,10 @@ endpoint WebContentServer = 89 LoadURL(URL url) =| LoadHTML(String html, URL url) =| - Paint(Gfx::IntRect content_rect, i32 shbuf_id) =| + AddBackingStore(i32 backing_store_id, Gfx::ShareableBitmap bitmap) =| + RemoveBackingStore(i32 backing_store_id) =| + + Paint(Gfx::IntRect content_rect, i32 backing_store_id) =| SetViewportRect(Gfx::IntRect rect) =| MouseDown(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =|