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. :^)
This commit is contained in:
Andreas Kling 2021-01-16 23:15:32 +01:00
parent 04b2aeef33
commit b5d98c0945
Notes: sideshowbarker 2024-07-18 23:09:40 +09:00
7 changed files with 52 additions and 32 deletions

View file

@ -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<WebContentClient>, i32 shbuf_id)
void OutOfProcessWebView::notify_server_did_paint(Badge<WebContentClient>, 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()

View file

@ -50,7 +50,7 @@ public:
void load_empty_document();
void notify_server_did_layout(Badge<WebContentClient>, const Gfx::IntSize& content_size);
void notify_server_did_paint(Badge<WebContentClient>, i32 shbuf_id);
void notify_server_did_paint(Badge<WebContentClient>, i32 bitmap_id);
void notify_server_did_invalidate_content_rect(Badge<WebContentClient>, const Gfx::IntRect&);
void notify_server_did_change_selection(Badge<WebContentClient>);
void notify_server_did_change_title(Badge<WebContentClient>, const String&);
@ -89,7 +89,9 @@ private:
RefPtr<WebContentClient> m_client;
RefPtr<Gfx::Bitmap> m_front_bitmap;
RefPtr<Gfx::Bitmap> 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 };
};

View file

@ -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)

View file

@ -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();
}

View file

@ -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<Gfx::Bitmap> bitmap;
i32 bitmap_id { -1 };
};
Vector<PaintRequest> m_pending_paint_requests;
RefPtr<Core::Timer> m_paint_flush_timer;
HashMap<i32, NonnullRefPtr<Gfx::Bitmap>> m_backing_stores;
};
}

View file

@ -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) =|

View file

@ -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) =|