From be2c484bb61ee32dd1dbce200d12cd03dfc84dad Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Jun 2024 18:50:57 +0300 Subject: [PATCH] LibWebView+WebContent: Move backing store allocation into WebContent In the upcoming changes, we are going to switch macOS to using an IOSurface for the backing store. This change will simplify the process of sharing an IOSurface between processes because we already have the MachPortServer running in the browser, and WebContent knows how to locate the corresponding server. --- Ladybird/WebContent/CMakeLists.txt | 1 + Userland/Libraries/LibWeb/Page/Page.h | 2 + .../LibWebView/ViewImplementation.cpp | 60 +++------------ .../Libraries/LibWebView/ViewImplementation.h | 9 +-- .../Libraries/LibWebView/WebContentClient.cpp | 6 ++ .../Libraries/LibWebView/WebContentClient.h | 1 + .../WebContent/BackingStoreManager.cpp | 75 +++++++++++++++++++ .../Services/WebContent/BackingStoreManager.h | 42 +++++++++++ .../WebContent/ConnectionFromClient.cpp | 6 -- .../WebContent/ConnectionFromClient.h | 1 - Userland/Services/WebContent/PageClient.cpp | 31 ++++---- Userland/Services/WebContent/PageClient.h | 14 ++-- .../Services/WebContent/WebContentClient.ipc | 1 + .../Services/WebContent/WebContentServer.ipc | 3 - 14 files changed, 158 insertions(+), 94 deletions(-) create mode 100644 Userland/Services/WebContent/BackingStoreManager.cpp create mode 100644 Userland/Services/WebContent/BackingStoreManager.h diff --git a/Ladybird/WebContent/CMakeLists.txt b/Ladybird/WebContent/CMakeLists.txt index bf3c07af417..a2606f7148b 100644 --- a/Ladybird/WebContent/CMakeLists.txt +++ b/Ladybird/WebContent/CMakeLists.txt @@ -6,6 +6,7 @@ set(WEBCONTENT_SOURCE_DIR ${LADYBIRD_SOURCE_DIR}/Userland/Services/WebContent/) set(WEBCONTENT_SOURCES ${WEBCONTENT_SOURCE_DIR}/ConnectionFromClient.cpp ${WEBCONTENT_SOURCE_DIR}/ConsoleGlobalEnvironmentExtensions.cpp + ${WEBCONTENT_SOURCE_DIR}/BackingStoreManager.cpp ${WEBCONTENT_SOURCE_DIR}/PageClient.cpp ${WEBCONTENT_SOURCE_DIR}/PageHost.cpp ${WEBCONTENT_SOURCE_DIR}/WebContentConsoleClient.cpp diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index db23de3a8f1..1a39cc7ba44 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -346,6 +347,7 @@ public: virtual void page_did_request_activate_tab() { } virtual void page_did_close_top_level_traversable() { } virtual void page_did_update_navigation_buttons_state([[maybe_unused]] bool back_enabled, [[maybe_unused]] bool forward_enabled) { } + virtual void page_did_allocate_backing_stores([[maybe_unused]] i32 front_bitmap_id, [[maybe_unused]] Gfx::ShareableBitmap front_bitmap, [[maybe_unused]] i32 back_bitmap_id, [[maybe_unused]] Gfx::ShareableBitmap back_bitmap) { } virtual void request_file(FileRequest) = 0; diff --git a/Userland/Libraries/LibWebView/ViewImplementation.cpp b/Userland/Libraries/LibWebView/ViewImplementation.cpp index 4d477541bc2..2b50476d6d5 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.cpp +++ b/Userland/Libraries/LibWebView/ViewImplementation.cpp @@ -16,10 +16,6 @@ namespace WebView { ViewImplementation::ViewImplementation() { - m_backing_store_shrink_timer = Core::Timer::create_single_shot(3000, [this] { - resize_backing_stores_if_needed(WindowResizeInProgress::No); - }); - m_repeated_crash_timer = Core::Timer::create_single_shot(1000, [this] { // Reset the "crashing a lot" counter after 1 second in case we just // happen to be visiting crashy websites a lot. @@ -386,62 +382,24 @@ void ViewImplementation::did_update_navigation_buttons_state(Badgerestart(); -} - -void ViewImplementation::resize_backing_stores_if_needed(WindowResizeInProgress window_resize_in_progress) +void ViewImplementation::did_allocate_backing_stores(Badge, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) { if (m_client_state.has_usable_bitmap) { // NOTE: We keep the outgoing front bitmap as a backup so we have something to paint until we get a new one. m_backup_bitmap = m_client_state.front_bitmap.bitmap; m_backup_bitmap_size = m_client_state.front_bitmap.last_painted_size; } - m_client_state.has_usable_bitmap = false; - auto viewport_size = this->viewport_size(); - if (viewport_size.is_empty()) - return; + m_client_state.front_bitmap.bitmap = front_bitmap.bitmap(); + m_client_state.front_bitmap.id = front_bitmap_id; + m_client_state.back_bitmap.bitmap = back_bitmap.bitmap(); + m_client_state.back_bitmap.id = back_bitmap_id; +} - Web::DevicePixelSize minimum_needed_size; - - if (window_resize_in_progress == WindowResizeInProgress::Yes) { - // Pad the minimum needed size so that we don't have to keep reallocating backing stores while the window is being resized. - minimum_needed_size = { viewport_size.width() + 256, viewport_size.height() + 256 }; - } else { - // If we're not in the middle of a resize, we can shrink the backing store size to match the viewport size. - minimum_needed_size = viewport_size; - m_client_state.front_bitmap = {}; - m_client_state.back_bitmap = {}; - } - - auto old_front_bitmap_id = m_client_state.front_bitmap.id; - auto old_back_bitmap_id = m_client_state.back_bitmap.id; - - auto reallocate_backing_store_if_needed = [&](SharedBitmap& backing_store) { - if (!backing_store.bitmap || !backing_store.bitmap->size().contains(minimum_needed_size.to_type())) { - if (auto new_bitmap_or_error = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, minimum_needed_size.to_type()); !new_bitmap_or_error.is_error()) { - backing_store.bitmap = new_bitmap_or_error.release_value(); - backing_store.id = m_client_state.next_bitmap_id++; - } - backing_store.last_painted_size = viewport_size; - } - }; - - reallocate_backing_store_if_needed(m_client_state.front_bitmap); - reallocate_backing_store_if_needed(m_client_state.back_bitmap); - - auto& front_bitmap = m_client_state.front_bitmap; - auto& back_bitmap = m_client_state.back_bitmap; - - if (front_bitmap.id != old_front_bitmap_id || back_bitmap.id != old_back_bitmap_id) { - client().async_add_backing_store(page_id(), front_bitmap.id, front_bitmap.bitmap->to_shareable_bitmap(), back_bitmap.id, - back_bitmap.bitmap->to_shareable_bitmap()); - client().async_set_viewport_size(page_id(), viewport_size); - } +void ViewImplementation::handle_resize() +{ + client().async_set_viewport_size(page_id(), this->viewport_size()); } void ViewImplementation::handle_web_content_process_crash() diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h index 22d2983a9c0..bd3bdf67cd8 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.h +++ b/Userland/Libraries/LibWebView/ViewImplementation.h @@ -117,6 +117,8 @@ public: void did_update_navigation_buttons_state(Badge, bool back_enabled, bool forward_enabled) const; + void did_allocate_backing_stores(Badge, i32 front_bitmap_id, Gfx::ShareableBitmap const&, i32 back_bitmap_id, Gfx::ShareableBitmap const&); + enum class ScreenshotType { Visible, Full, @@ -222,12 +224,6 @@ protected: u64 page_id() const; virtual void update_zoom() = 0; - enum class WindowResizeInProgress { - No, - Yes, - }; - void resize_backing_stores_if_needed(WindowResizeInProgress); - void handle_resize(); enum class CreateNewClient { @@ -250,7 +246,6 @@ protected: SharedBitmap front_bitmap; SharedBitmap back_bitmap; u64 page_index { 0 }; - i32 next_bitmap_id { 0 }; bool has_usable_bitmap { false }; } m_client_state; diff --git a/Userland/Libraries/LibWebView/WebContentClient.cpp b/Userland/Libraries/LibWebView/WebContentClient.cpp index c7d2da0a49c..ad3099c3507 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.cpp +++ b/Userland/Libraries/LibWebView/WebContentClient.cpp @@ -593,6 +593,12 @@ void WebContentClient::did_update_navigation_buttons_state(u64 page_id, bool bac view->did_update_navigation_buttons_state({}, back_enabled, forward_enabled); } +void WebContentClient::did_allocate_backing_stores(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) +{ + if (auto view = view_for_page_id(page_id); view.has_value()) + view->did_allocate_backing_stores({}, front_bitmap_id, front_bitmap, back_bitmap_id, back_bitmap); +} + void WebContentClient::inspector_did_load(u64 page_id) { if (auto view = view_for_page_id(page_id); view.has_value()) { diff --git a/Userland/Libraries/LibWebView/WebContentClient.h b/Userland/Libraries/LibWebView/WebContentClient.h index bdf172da81b..e771081f510 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.h +++ b/Userland/Libraries/LibWebView/WebContentClient.h @@ -100,6 +100,7 @@ private: virtual void did_insert_clipboard_entry(u64 page_id, String const& data, String const& presentation_style, String const& mime_type) override; virtual void did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState) override; virtual void did_update_navigation_buttons_state(u64 page_id, bool back_enabled, bool forward_enabled) override; + virtual void did_allocate_backing_stores(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const&, i32 back_bitmap_id, Gfx::ShareableBitmap const&) override; virtual void inspector_did_load(u64 page_id) override; virtual void inspector_did_select_dom_node(u64 page_id, i32 node_id, Optional const& pseudo_element) override; virtual void inspector_did_set_dom_node_text(u64 page_id, i32 node_id, String const& text) override; diff --git a/Userland/Services/WebContent/BackingStoreManager.cpp b/Userland/Services/WebContent/BackingStoreManager.cpp new file mode 100644 index 00000000000..71ec7ea0b2e --- /dev/null +++ b/Userland/Services/WebContent/BackingStoreManager.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace WebContent { + +BackingStoreManager::BackingStoreManager(PageClient& page_client) + : m_page_client(page_client) +{ + m_backing_store_shrink_timer = Core::Timer::create_single_shot(3000, [this] { + resize_backing_stores_if_needed(WindowResizingInProgress::No); + }); +} + +void BackingStoreManager::restart_resize_timer() +{ + m_backing_store_shrink_timer->restart(); +} + +void BackingStoreManager::resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress) +{ + auto css_pixels_viewport_rect = m_page_client.page().top_level_traversable()->viewport_rect(); + auto viewport_size = m_page_client.page().css_to_device_rect(css_pixels_viewport_rect).size(); + + if (viewport_size.is_empty()) + return; + + Web::DevicePixelSize minimum_needed_size; + if (window_resize_in_progress == WindowResizingInProgress::Yes) { + // Pad the minimum needed size so that we don't have to keep reallocating backing stores while the window is being resized. + minimum_needed_size = { viewport_size.width() + 256, viewport_size.height() + 256 }; + } else { + // If we're not in the middle of a resize, we can shrink the backing store size to match the viewport size. + minimum_needed_size = viewport_size; + m_front_bitmap.clear(); + m_back_bitmap.clear(); + } + + auto old_front_bitmap_id = m_front_bitmap_id; + auto old_back_bitmap_id = m_back_bitmap_id; + + auto reallocate_backing_store_if_needed = [&](RefPtr& bitmap, int& id) { + if (!bitmap || !bitmap->size().contains(minimum_needed_size.to_type())) { + if (auto new_bitmap_or_error = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, minimum_needed_size.to_type()); !new_bitmap_or_error.is_error()) { + bitmap = new_bitmap_or_error.release_value(); + id = m_next_bitmap_id++; + } + } + }; + + reallocate_backing_store_if_needed(m_front_bitmap, m_front_bitmap_id); + reallocate_backing_store_if_needed(m_back_bitmap, m_back_bitmap_id); + + auto& front_bitmap = m_front_bitmap; + auto& back_bitmap = m_back_bitmap; + + if (m_front_bitmap_id != old_front_bitmap_id || m_back_bitmap_id != old_back_bitmap_id) { + m_page_client.page_did_allocate_backing_stores(m_front_bitmap_id, front_bitmap->to_shareable_bitmap(), m_back_bitmap_id, back_bitmap->to_shareable_bitmap()); + } +} + +void BackingStoreManager::swap_back_and_front() +{ + swap(m_front_bitmap, m_back_bitmap); + swap(m_front_bitmap_id, m_back_bitmap_id); +} + +} diff --git a/Userland/Services/WebContent/BackingStoreManager.h b/Userland/Services/WebContent/BackingStoreManager.h new file mode 100644 index 00000000000..ffc2fecc873 --- /dev/null +++ b/Userland/Services/WebContent/BackingStoreManager.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace WebContent { + +class BackingStoreManager { +public: + enum class WindowResizingInProgress { + No, + Yes + }; + void resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress); + void restart_resize_timer(); + + RefPtr back_bitmap() { return m_back_bitmap; } + i32 front_id() const { return m_front_bitmap_id; } + + void swap_back_and_front(); + + BackingStoreManager(PageClient&); + +private: + PageClient& m_page_client; + + i32 m_front_bitmap_id { -1 }; + i32 m_back_bitmap_id { -1 }; + RefPtr m_front_bitmap; + RefPtr m_back_bitmap; + int m_next_bitmap_id { 0 }; + + RefPtr m_backing_store_shrink_timer; +}; + +} diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index f4d1671129b..cf94cca371f 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -155,12 +155,6 @@ void ConnectionFromClient::set_viewport_size(u64 page_id, Web::DevicePixelSize c page->set_viewport_size(size); } -void ConnectionFromClient::add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) -{ - if (auto page = this->page(page_id); page.has_value()) - page->add_backing_store(front_bitmap_id, front_bitmap, back_bitmap_id, back_bitmap); -} - void ConnectionFromClient::ready_to_paint(u64 page_id) { if (auto page = this->page(page_id); page.has_value()) diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 9f62af40325..3f9ac2be6e4 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -63,7 +63,6 @@ private: virtual void set_viewport_size(u64 page_id, Web::DevicePixelSize const) override; virtual void key_event(u64 page_id, Web::KeyEvent const&) override; virtual void mouse_event(u64 page_id, Web::MouseEvent const&) override; - virtual void add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) override; virtual void ready_to_paint(u64 page_id) override; virtual void debug_request(u64 page_id, ByteString const&, ByteString const&) override; virtual void get_source(u64 page_id) override; diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index a685f44c59a..a9dcb07141c 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -55,6 +55,7 @@ PageClient::PageClient(PageHost& owner, u64 id) : m_owner(owner) , m_page(Web::Page::create(Web::Bindings::main_thread_vm(), *this)) , m_id(id) + , m_backing_store_manager(*this) { setup_palette(); @@ -96,14 +97,6 @@ void PageClient::ready_to_paint() } } -void PageClient::add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) -{ - m_backing_stores.front_bitmap_id = front_bitmap_id; - m_backing_stores.back_bitmap_id = back_bitmap_id; - m_backing_stores.front_bitmap = *const_cast(front_bitmap).bitmap(); - m_backing_stores.back_bitmap = *const_cast(back_bitmap).bitmap(); -} - void PageClient::visit_edges(JS::Cell::Visitor& visitor) { Base::visit_edges(visitor); @@ -216,20 +209,17 @@ void PageClient::paint_next_frame() } } - if (!m_backing_stores.back_bitmap) { + auto back_bitmap = m_backing_store_manager.back_bitmap(); + if (!back_bitmap) return; - } - auto& back_bitmap = *m_backing_stores.back_bitmap; auto viewport_rect = page().css_to_device_rect(page().top_level_traversable()->viewport_rect()); - paint(viewport_rect, back_bitmap); + paint(viewport_rect, *back_bitmap); - auto& backing_stores = m_backing_stores; - swap(backing_stores.front_bitmap, backing_stores.back_bitmap); - swap(backing_stores.front_bitmap_id, backing_stores.back_bitmap_id); + m_backing_store_manager.swap_back_and_front(); m_paint_state = PaintState::WaitingForClient; - client().async_did_paint(m_id, viewport_rect.to_type(), backing_stores.front_bitmap_id); + client().async_did_paint(m_id, viewport_rect.to_type(), m_backing_store_manager.front_id()); } void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& target, Web::PaintOptions paint_options) @@ -245,6 +235,9 @@ void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& ta void PageClient::set_viewport_size(Web::DevicePixelSize const& size) { page().top_level_traversable()->set_viewport_size(page().device_to_css_size(size)); + + m_backing_store_manager.restart_resize_timer(); + m_backing_store_manager.resize_backing_stores_if_needed(BackingStoreManager::WindowResizingInProgress::Yes); } void PageClient::page_did_request_cursor_change(Gfx::StandardCursor cursor) @@ -596,6 +589,11 @@ void PageClient::page_did_change_audio_play_state(Web::HTML::AudioPlayState play client().async_did_change_audio_play_state(m_id, play_state); } +void PageClient::page_did_allocate_backing_stores(i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) +{ + client().async_did_allocate_backing_stores(m_id, front_bitmap_id, front_bitmap, back_bitmap_id, back_bitmap); +} + IPC::File PageClient::request_worker_agent() { auto response = client().send_sync_but_allow_failure(m_id); @@ -756,5 +754,4 @@ void PageClient::queue_screenshot_task(Optional node_id) m_screenshot_tasks.enqueue({ node_id }); page().top_level_traversable()->set_needs_display(); } - } diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index 063c836c94a..24bdda8b81c 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #ifdef HAS_ACCELERATED_GRAPHICS @@ -75,8 +76,6 @@ public: void ready_to_paint(); - void add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap); - void initialize_js_console(Web::DOM::Document& document); void destroy_js_console(Web::DOM::Document& document); void js_console_input(ByteString const& js_source); @@ -92,6 +91,8 @@ public: void queue_screenshot_task(Optional node_id); + friend class BackingStoreManager; + private: PageClient(PageHost&, u64 id); @@ -156,6 +157,7 @@ private: virtual void page_did_change_theme_color(Gfx::Color color) override; virtual void page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type) override; virtual void page_did_change_audio_play_state(Web::HTML::AudioPlayState) override; + virtual void page_did_allocate_backing_stores(i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) override; virtual IPC::File request_worker_agent() override; virtual void inspector_did_load() override; virtual void inspector_did_select_dom_node(i32 node_id, Optional const& pseudo_element) override; @@ -203,13 +205,7 @@ private: OwnPtr m_accelerated_graphics_context; #endif - struct BackingStores { - i32 front_bitmap_id { -1 }; - i32 back_bitmap_id { -1 }; - RefPtr front_bitmap; - RefPtr back_bitmap; - }; - BackingStores m_backing_stores; + BackingStoreManager m_backing_store_manager; // NOTE: These documents are not visited, but manually removed from the map on document finalization. HashMap, JS::NonnullGCPtr> m_console_clients; diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index 8bc6b078582..404475452ea 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -80,6 +80,7 @@ endpoint WebContentClient did_change_theme_color(u64 page_id, Gfx::Color color) =| did_insert_clipboard_entry(u64 page_id, String data, String presentation_style, String mime_type) =| did_update_navigation_buttons_state(u64 page_id, bool back_enabled, bool forward_enabled) =| + did_allocate_backing_stores(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) =| did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState play_state) =| diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index e9f3652648e..540e98de7d2 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -1,8 +1,6 @@ #include #include -#include #include -#include #include #include #include @@ -28,7 +26,6 @@ endpoint WebContentServer reload(u64 page_id) =| traverse_the_history_by_delta(u64 page_id, i32 delta) =| - add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) =| ready_to_paint(u64 page_id) =| set_viewport_size(u64 page_id, Web::DevicePixelSize size) =|