LibWebView+WebContent: Add feature-gated Compositor process backend
We are moving toward an architecture where the browser owns a single
process that holds the GPU context, so Skia resources can be shared
across every renderer and WebContent processes can be sandboxed away
from direct GPU access. A dedicated Compositor helper process is the
first step. The earlier commits laid the foundation; this one turns the
helper on as a selectable backend, gated behind
--enable-compositor-process so the existing in-process path stays the
shipping default.
Default topology -- one compositor per WebContent, in-process:
+---------+
| Browser |
+---------+
/ | \
v v v
+---+ +---+ +---+ each WebContent runs its own
|WC | |WC | |WC | CompositorThread on a dedicated
|+C+| |+C+| |+C+| thread, with its own GPU context.
+---+ +---+ +---+
Opt-in topology -- one single-threaded Compositor, shared by all WCs:
+---------+ control +-------------------+
| Browser |<----------->| Compositor |
+---------+ | (single thread, |
/ | \ | single GPU ctx, |
v v v data | shared by all |
[WC] [WC] [WC] ---------->| connected WCs) |
+-------------------+
Three IPC channels carry the work in the opt-in topology. The
existing Browser<->WebContent channel gains context allocation.
A new Browser<->Compositor channel carries context lifetime,
viewport, UI input, and presentation acks plus backing-store and
frame upcalls. A new WebContent<->Compositor channel carries
display lists, scroll state, video, compositor surfaces, async
scrolling, presentation, and screenshots, with upcalls for
delegated input and compositor loss.
This commit is contained in:
parent
3eae2c0f3e
commit
9479bc8d7f
18 changed files with 306 additions and 48 deletions
|
|
@ -20,6 +20,7 @@
|
|||
#include <LibImageDecoderClient/Client.h>
|
||||
#include <LibWeb/CSS/PropertyID.h>
|
||||
#include <LibWeb/Loader/UserAgent.h>
|
||||
#include <LibWeb/Page/InputEvent.h>
|
||||
#include <LibWebView/Application.h>
|
||||
#include <LibWebView/CompositorClient.h>
|
||||
#include <LibWebView/CookieJar.h>
|
||||
|
|
@ -532,13 +533,43 @@ void Application::register_compositor_context(WebContentClient& web_content_clie
|
|||
m_compositor_client->create_context(context_id, page_id, page_presentation_registration, *web_content_connection_id);
|
||||
}
|
||||
|
||||
void Application::destroy_compositor_context(Web::Compositor::CompositorContextId context_id)
|
||||
void Application::update_compositor_viewport(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress window_resize_in_progress)
|
||||
{
|
||||
if (should_skip_compositor_process_ipc(m_compositor_client))
|
||||
return;
|
||||
VERIFY(m_compositor_client);
|
||||
|
||||
m_compositor_client->async_destroy_context(context_id);
|
||||
m_compositor_client->async_viewport_size_updated(context_id, viewport_size, true, window_resize_in_progress);
|
||||
}
|
||||
|
||||
bool Application::send_async_scroll_to_compositor(Web::Compositor::CompositorContextId context_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels)
|
||||
{
|
||||
VERIFY(m_compositor_client);
|
||||
return m_compositor_client->async_scroll_by(context_id, position, delta_in_device_pixels);
|
||||
}
|
||||
|
||||
bool Application::handle_mouse_event_in_compositor(Web::Compositor::CompositorContextId context_id, Web::MouseEvent const& event)
|
||||
{
|
||||
VERIFY(m_compositor_client);
|
||||
return m_compositor_client->handle_mouse_event(context_id, event.clone_without_browser_data());
|
||||
}
|
||||
|
||||
void Application::dispatch_mouse_event_to_web_content(Web::Compositor::CompositorContextId context_id, Web::MouseEvent const& event)
|
||||
{
|
||||
if (should_skip_compositor_process_ipc(m_compositor_client))
|
||||
return;
|
||||
VERIFY(m_compositor_client);
|
||||
|
||||
m_compositor_client->async_dispatch_mouse_event_to_web_content(context_id, event.clone_without_browser_data());
|
||||
}
|
||||
|
||||
void Application::notify_compositor_presented_bitmap_ready_to_paint(Web::Compositor::CompositorContextId context_id, i32 bitmap_id)
|
||||
{
|
||||
if (should_skip_compositor_process_ipc(m_compositor_client))
|
||||
return;
|
||||
VERIFY(m_compositor_client);
|
||||
|
||||
m_compositor_client->async_presented_bitmap_ready_to_paint(context_id, bitmap_id);
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<WebContentClient>> Application::launch_web_content_process(ViewImplementation& view)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include <LibDatabase/Forward.h>
|
||||
#include <LibDevTools/DevToolsDelegate.h>
|
||||
#include <LibDevTools/Forward.h>
|
||||
#include <LibGfx/Point.h>
|
||||
#include <LibGfx/Size.h>
|
||||
#include <LibIPC/Forward.h>
|
||||
#include <LibImageDecoderClient/Client.h>
|
||||
#include <LibMain/Main.h>
|
||||
|
|
@ -40,6 +42,12 @@
|
|||
# include <LibIPC/TransportBootstrapMach.h>
|
||||
#endif
|
||||
|
||||
namespace Web {
|
||||
|
||||
struct MouseEvent;
|
||||
|
||||
}
|
||||
|
||||
namespace WebView {
|
||||
|
||||
struct ApplicationSettingsObserver;
|
||||
|
|
@ -85,7 +93,11 @@ public:
|
|||
ErrorOr<NonnullRefPtr<WebContentClient>> launch_web_content_process(ViewImplementation&);
|
||||
ErrorOr<void> connect_web_content_to_compositor(WebContentClient&);
|
||||
void register_compositor_context(WebContentClient&, Web::Compositor::CompositorContextId, Optional<u64> page_id, Web::Compositor::PagePresentationRegistration);
|
||||
void destroy_compositor_context(Web::Compositor::CompositorContextId);
|
||||
void update_compositor_viewport(Web::Compositor::CompositorContextId, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress = Web::Compositor::WindowResizingInProgress::No);
|
||||
bool send_async_scroll_to_compositor(Web::Compositor::CompositorContextId, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels);
|
||||
bool handle_mouse_event_in_compositor(Web::Compositor::CompositorContextId, Web::MouseEvent const&);
|
||||
void dispatch_mouse_event_to_web_content(Web::Compositor::CompositorContextId, Web::MouseEvent const&);
|
||||
void notify_compositor_presented_bitmap_ready_to_paint(Web::Compositor::CompositorContextId, i32 bitmap_id);
|
||||
|
||||
virtual Optional<ViewImplementation&> active_web_view() const { return {}; }
|
||||
virtual Optional<ViewImplementation&> open_blank_new_tab(Web::HTML::ActivateTab) const { return {}; }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <LibWebView/CompositorClient.h>
|
||||
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibWebView/WebContentClient.h>
|
||||
|
||||
namespace WebView {
|
||||
|
||||
|
|
@ -24,12 +25,29 @@ void CompositorClient::die()
|
|||
}
|
||||
}
|
||||
|
||||
void CompositorClient::did_allocate_backing_stores(Web::Compositor::CompositorContextId, i32, Gfx::SharedImage, i32, Gfx::SharedImage)
|
||||
void CompositorClient::did_allocate_backing_stores(Web::Compositor::CompositorContextId context_id, i32 front_bitmap_id, Gfx::SharedImage front_backing_store, i32 back_bitmap_id, Gfx::SharedImage back_backing_store)
|
||||
{
|
||||
auto web_content_client = WebContentClient::client_for_compositor_context_id(context_id);
|
||||
if (!web_content_client.has_value())
|
||||
return;
|
||||
|
||||
auto page_id = web_content_client->page_id_for_compositor_context_id(context_id);
|
||||
VERIFY(page_id.has_value());
|
||||
|
||||
web_content_client->did_present_backing_stores(*page_id, front_bitmap_id, move(front_backing_store), back_bitmap_id, move(back_backing_store));
|
||||
}
|
||||
|
||||
void CompositorClient::did_present_frame(Web::Compositor::CompositorContextId, Gfx::IntRect, i32)
|
||||
void CompositorClient::did_present_frame(Web::Compositor::CompositorContextId context_id, Gfx::IntRect content_rect, i32 bitmap_id)
|
||||
{
|
||||
auto web_content_client = WebContentClient::client_for_compositor_context_id(context_id);
|
||||
if (web_content_client.has_value()) {
|
||||
auto page_id = web_content_client->page_id_for_compositor_context_id(context_id);
|
||||
VERIFY(page_id.has_value());
|
||||
web_content_client->did_present_bitmap(*page_id, content_rect, bitmap_id);
|
||||
return;
|
||||
}
|
||||
|
||||
async_presented_bitmap_ready_to_paint(context_id, bitmap_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ HeadlessWebView::HeadlessWebView(Core::AnonymousBuffer theme, Web::DevicePixelSi
|
|||
m_viewport_size = size.template to_type<Web::DevicePixels>();
|
||||
|
||||
client().async_set_window_size(m_client_state.page_index, m_viewport_size);
|
||||
client().async_set_viewport(m_client_state.page_index, m_viewport_size, m_device_pixel_ratio, Web::ViewportIsFullscreen::No);
|
||||
handle_resize();
|
||||
|
||||
client().async_did_update_window_rect(m_client_state.page_index);
|
||||
};
|
||||
|
|
@ -79,7 +79,7 @@ HeadlessWebView::HeadlessWebView(Core::AnonymousBuffer theme, Web::DevicePixelSi
|
|||
|
||||
client().async_set_window_position(m_client_state.page_index, screen_rect.location());
|
||||
client().async_set_window_size(m_client_state.page_index, screen_rect.size());
|
||||
client().async_set_viewport(m_client_state.page_index, screen_rect.size(), m_device_pixel_ratio, m_is_fullscreen);
|
||||
handle_resize();
|
||||
|
||||
client().async_did_update_window_rect(m_client_state.page_index);
|
||||
};
|
||||
|
|
@ -91,7 +91,7 @@ HeadlessWebView::HeadlessWebView(Core::AnonymousBuffer theme, Web::DevicePixelSi
|
|||
|
||||
client().async_set_window_position(m_client_state.page_index, screen_rect.location());
|
||||
client().async_set_window_size(m_client_state.page_index, screen_rect.size());
|
||||
client().async_set_viewport(m_client_state.page_index, screen_rect.size(), m_device_pixel_ratio, Web::ViewportIsFullscreen::Yes);
|
||||
handle_resize();
|
||||
|
||||
client().async_did_update_window_rect(m_client_state.page_index);
|
||||
};
|
||||
|
|
@ -102,7 +102,7 @@ HeadlessWebView::HeadlessWebView(Core::AnonymousBuffer theme, Web::DevicePixelSi
|
|||
|
||||
client().async_set_window_position(m_client_state.page_index, m_previous_dimensions.location());
|
||||
client().async_set_window_size(m_client_state.page_index, m_previous_dimensions.size());
|
||||
client().async_set_viewport(m_client_state.page_index, m_previous_dimensions.size(), m_device_pixel_ratio, Web::ViewportIsFullscreen::No);
|
||||
handle_resize();
|
||||
|
||||
client().async_did_update_window_rect(m_client_state.page_index);
|
||||
};
|
||||
|
|
@ -171,7 +171,7 @@ void HeadlessWebView::initialize_client(CreateNewClient create_new_client)
|
|||
ViewImplementation::initialize_client(create_new_client);
|
||||
|
||||
client().async_update_system_theme(m_client_state.page_index, m_theme);
|
||||
client().async_set_viewport(m_client_state.page_index, viewport_size(), m_device_pixel_ratio, m_is_fullscreen);
|
||||
handle_resize();
|
||||
client().async_set_window_size(m_client_state.page_index, viewport_size());
|
||||
client().async_update_screen_rects(m_client_state.page_index, { { screen_rect } }, 0);
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ void HeadlessWebView::reset_viewport_size(Web::DevicePixelSize size)
|
|||
m_viewport_size = size;
|
||||
|
||||
client().async_set_window_size(m_client_state.page_index, m_viewport_size);
|
||||
client().async_set_viewport(m_client_state.page_index, m_viewport_size, m_device_pixel_ratio, m_is_fullscreen);
|
||||
handle_resize();
|
||||
|
||||
client().async_did_update_window_rect(m_client_state.page_index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ static ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_proc
|
|||
arguments.append("--disable-scrollbar-painting"sv);
|
||||
if (web_content_options.enable_async_scrolling == EnableAsyncScrolling::No)
|
||||
arguments.append("--disable-async-scrolling"sv);
|
||||
if (browser_options.enable_compositor_process == EnableCompositorProcess::Yes)
|
||||
arguments.append("--enable-compositor-process"sv);
|
||||
if (web_content_options.file_scheme_urls_have_tuple_origins == FileSchemeUrlsHaveTupleOrigins::Yes)
|
||||
arguments.append("--tuple-file-origins"sv);
|
||||
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ void ViewImplementation::enqueue_input_event(Web::InputEvent event)
|
|||
mouse_event->async_scroll_performed_default_action = true;
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] UI compositor wheel bypass result for page {}: {}",
|
||||
m_client_state.page_index, mouse_event->async_scroll_performed_default_action ? "accepted"sv : "rejected"sv);
|
||||
} else if (client().send_mouse_event_to_compositor(m_client_state.page_index, *mouse_event)) {
|
||||
} else if (client().handle_mouse_event_in_compositor(m_client_state.page_index, *mouse_event)) {
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] UI compositor handled mouse event for page {} at {},{}",
|
||||
m_client_state.page_index, mouse_event->position.x().value(), mouse_event->position.y().value());
|
||||
return;
|
||||
|
|
@ -309,7 +309,7 @@ void ViewImplementation::enqueue_input_event(Web::InputEvent event)
|
|||
client().async_key_event(m_client_state.page_index, event.clone_without_browser_data());
|
||||
},
|
||||
[this](Web::MouseEvent const& event) {
|
||||
client().async_mouse_event(m_client_state.page_index, event.clone_without_browser_data());
|
||||
client().dispatch_mouse_event_to_web_content(m_client_state.page_index, event);
|
||||
},
|
||||
[this](Web::DragEvent& event) {
|
||||
auto cloned_event = event.clone_without_browser_data();
|
||||
|
|
@ -720,6 +720,8 @@ void ViewImplementation::apply_zoom_for_current_host()
|
|||
void ViewImplementation::handle_resize()
|
||||
{
|
||||
client().async_set_viewport(page_id(), viewport_size(), m_device_pixel_ratio, m_is_fullscreen);
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::Yes)
|
||||
Application::the().update_compositor_viewport(client().compositor_context_id_for_page(page_id()), viewport_size().to_type<int>());
|
||||
}
|
||||
|
||||
void ViewImplementation::initialize_client(CreateNewClient create_new_client)
|
||||
|
|
@ -739,6 +741,10 @@ void ViewImplementation::initialize_client(CreateNewClient create_new_client)
|
|||
client().async_set_viewport(m_client_state.page_index, viewport_size(), m_device_pixel_ratio, m_is_fullscreen);
|
||||
client().async_set_maximum_frames_per_second(m_client_state.page_index, m_maximum_frames_per_second);
|
||||
client().async_set_system_visibility_state(m_client_state.page_index, m_system_visibility_state);
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::Yes) {
|
||||
auto compositor_context_id = client().compositor_context_id_for_page(m_client_state.page_index);
|
||||
Application::the().update_compositor_viewport(compositor_context_id, viewport_size().to_type<int>());
|
||||
}
|
||||
client().async_set_document_cookie_version_buffer(m_client_state.page_index, m_document_cookie_version_buffer);
|
||||
|
||||
if (auto webdriver_endpoint = Application::browser_options().webdriver_endpoint; webdriver_endpoint.has_value())
|
||||
|
|
|
|||
|
|
@ -101,14 +101,16 @@ WebContentClient::WebContentClient(NonnullOwnPtr<IPC::Transport> transport, View
|
|||
{
|
||||
s_clients.set(this);
|
||||
m_views.set(0, view);
|
||||
initialize_compositor_connection(*this);
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::No)
|
||||
initialize_compositor_connection(*this);
|
||||
}
|
||||
|
||||
WebContentClient::WebContentClient(NonnullOwnPtr<IPC::Transport> transport)
|
||||
: IPC::ConnectionToServer<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(transport))
|
||||
{
|
||||
s_clients.set(this);
|
||||
initialize_compositor_connection(*this);
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::No)
|
||||
initialize_compositor_connection(*this);
|
||||
}
|
||||
|
||||
WebContentClient::~WebContentClient()
|
||||
|
|
@ -167,11 +169,9 @@ Messages::WebContentClient::AllocateCompositorContextIdResponse WebContentClient
|
|||
return context_id;
|
||||
}
|
||||
|
||||
void WebContentClient::destroy_compositor_context(Web::Compositor::CompositorContextId context_id)
|
||||
void WebContentClient::did_destroy_compositor_context(Web::Compositor::CompositorContextId context_id)
|
||||
{
|
||||
if (!forget_compositor_context(context_id))
|
||||
return;
|
||||
Application::the().destroy_compositor_context(context_id);
|
||||
forget_compositor_context(context_id);
|
||||
}
|
||||
|
||||
bool WebContentClient::forget_compositor_context(Web::Compositor::CompositorContextId context_id)
|
||||
|
|
@ -249,32 +249,63 @@ void WebContentClient::notify_all_views_of_crash()
|
|||
|
||||
bool WebContentClient::send_async_scroll_to_compositor(u64 page_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels)
|
||||
{
|
||||
auto connection = compositor_connections().get(this);
|
||||
VERIFY(connection.has_value());
|
||||
VERIFY(connection.value()->is_open());
|
||||
|
||||
auto timer = Core::ElapsedTimer::start_new(Core::TimerType::Precise);
|
||||
auto handled = connection.value()->async_scroll_by(page_id, position, delta_in_device_pixels);
|
||||
|
||||
bool handled = false;
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::Yes) {
|
||||
handled = Application::the().send_async_scroll_to_compositor(compositor_context_id_for_page(page_id), position, delta_in_device_pixels);
|
||||
} else {
|
||||
auto connection = compositor_connections().get(this);
|
||||
VERIFY(connection.has_value());
|
||||
VERIFY(connection.value()->is_open());
|
||||
handled = connection.value()->async_scroll_by(page_id, position, delta_in_device_pixels);
|
||||
}
|
||||
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] UI compositor IPC async_scroll_by page {} returned {} in {} us",
|
||||
page_id, handled, timer.elapsed_time().to_microseconds());
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool WebContentClient::send_mouse_event_to_compositor(u64 page_id, Web::MouseEvent const& event)
|
||||
bool WebContentClient::handle_mouse_event_in_compositor(u64 page_id, Web::MouseEvent const& event)
|
||||
{
|
||||
auto connection = compositor_connections().get(this);
|
||||
VERIFY(connection.has_value());
|
||||
VERIFY(connection.value()->is_open());
|
||||
|
||||
auto timer = Core::ElapsedTimer::start_new(Core::TimerType::Precise);
|
||||
auto handled = connection.value()->mouse_event(page_id, event.clone_without_browser_data());
|
||||
|
||||
bool handled = false;
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::Yes) {
|
||||
handled = Application::the().handle_mouse_event_in_compositor(compositor_context_id_for_page(page_id), event);
|
||||
} else {
|
||||
auto connection = compositor_connections().get(this);
|
||||
VERIFY(connection.has_value());
|
||||
VERIFY(connection.value()->is_open());
|
||||
handled = connection.value()->mouse_event(page_id, event.clone_without_browser_data());
|
||||
}
|
||||
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] UI compositor IPC mouse_event page {} returned {} in {} us",
|
||||
page_id, handled, timer.elapsed_time().to_microseconds());
|
||||
return handled;
|
||||
}
|
||||
|
||||
void WebContentClient::dispatch_mouse_event_to_web_content(u64 page_id, Web::MouseEvent const& event)
|
||||
{
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::Yes) {
|
||||
Application::the().dispatch_mouse_event_to_web_content(compositor_context_id_for_page(page_id), event);
|
||||
return;
|
||||
}
|
||||
|
||||
async_mouse_event(page_id, event.clone_without_browser_data());
|
||||
}
|
||||
|
||||
void WebContentClient::notify_presented_bitmap_ready_to_paint(u64 page_id, i32 bitmap_id)
|
||||
{
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::Yes) {
|
||||
auto context_id = m_page_compositor_context_ids.get(page_id);
|
||||
if (!context_id.has_value())
|
||||
return;
|
||||
|
||||
Application::the().notify_compositor_presented_bitmap_ready_to_paint(*context_id, bitmap_id);
|
||||
return;
|
||||
}
|
||||
|
||||
VERIFY(try_notify_presented_bitmap_ready_to_paint(*this, page_id, bitmap_id));
|
||||
}
|
||||
|
||||
|
|
@ -287,7 +318,10 @@ void WebContentClient::did_present_bitmap(u64 page_id, Gfx::IntRect rect, i32 bi
|
|||
} else {
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] UI dropping did_paint for page {} bitmap {}: no view",
|
||||
page_id, bitmap_id);
|
||||
try_notify_presented_bitmap_ready_to_paint(*this, page_id, bitmap_id);
|
||||
if (Application::browser_options().enable_compositor_process == EnableCompositorProcess::Yes)
|
||||
notify_presented_bitmap_ready_to_paint(page_id, bitmap_id);
|
||||
else
|
||||
try_notify_presented_bitmap_ready_to_paint(*this, page_id, bitmap_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ public:
|
|||
Web::Compositor::CompositorContextId compositor_context_id_for_page(u64 page_id);
|
||||
Optional<u64> page_id_for_compositor_context_id(Web::Compositor::CompositorContextId) const;
|
||||
bool send_async_scroll_to_compositor(u64 page_id, Gfx::FloatPoint position, Gfx::FloatPoint delta_in_device_pixels);
|
||||
bool send_mouse_event_to_compositor(u64 page_id, Web::MouseEvent const&);
|
||||
bool handle_mouse_event_in_compositor(u64 page_id, Web::MouseEvent const&);
|
||||
void dispatch_mouse_event_to_web_content(u64 page_id, Web::MouseEvent const&);
|
||||
void notify_presented_bitmap_ready_to_paint(u64 page_id, i32 bitmap_id);
|
||||
void did_present_backing_stores(u64 page_id, i32 front_bitmap_id, Gfx::SharedImage front_backing_store, i32 back_bitmap_id, Gfx::SharedImage back_backing_store);
|
||||
void did_present_bitmap(u64 page_id, Gfx::IntRect, i32 bitmap_id);
|
||||
|
|
@ -85,7 +86,7 @@ private:
|
|||
virtual void die() override;
|
||||
|
||||
virtual Messages::WebContentClient::AllocateCompositorContextIdResponse allocate_compositor_context_id(u64 page_id, Web::Compositor::PagePresentationRegistration) override;
|
||||
virtual void destroy_compositor_context(Web::Compositor::CompositorContextId) override;
|
||||
virtual void did_destroy_compositor_context(Web::Compositor::CompositorContextId) override;
|
||||
virtual void did_request_new_process_for_navigation(u64 page_id, URL::URL url) override;
|
||||
virtual void did_finish_loading(u64 page_id, URL::URL) override;
|
||||
virtual void did_request_refresh(u64 page_id) override;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ endpoint CompositorControlServer
|
|||
connect_web_content() => (IPC::TransportHandle handle, i32 web_content_connection_id)
|
||||
|
||||
create_context(Web::Compositor::CompositorContextId context_id, Optional<u64> page_id, Web::Compositor::PagePresentationRegistration page_presentation_registration, i32 web_content_connection_id) => ()
|
||||
destroy_context(Web::Compositor::CompositorContextId context_id) =|
|
||||
|
||||
viewport_size_updated(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, bool is_top_level_traversable, Web::Compositor::WindowResizingInProgress window_resize_in_progress) =|
|
||||
|
||||
|
|
|
|||
|
|
@ -69,11 +69,6 @@ void ConnectionFromClient::create_context(Web::Compositor::CompositorContextId c
|
|||
m_compositor_state->create_context(context_id, page_id, page_presentation_registration, *connection);
|
||||
}
|
||||
|
||||
void ConnectionFromClient::destroy_context(Web::Compositor::CompositorContextId context_id)
|
||||
{
|
||||
m_compositor_state->destroy_context(context_id);
|
||||
}
|
||||
|
||||
void ConnectionFromClient::viewport_size_updated(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, bool is_top_level_traversable, Web::Compositor::WindowResizingInProgress window_resize_in_progress)
|
||||
{
|
||||
m_compositor_state->viewport_size_updated(context_id, viewport_size, is_top_level_traversable, window_resize_in_progress);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ private:
|
|||
virtual Messages::CompositorControlServer::InitTransportResponse init_transport(int peer_pid) override;
|
||||
virtual Messages::CompositorControlServer::ConnectWebContentResponse connect_web_content() override;
|
||||
virtual void create_context(Web::Compositor::CompositorContextId, Optional<u64> page_id, Web::Compositor::PagePresentationRegistration, i32 web_content_connection_id) override;
|
||||
virtual void destroy_context(Web::Compositor::CompositorContextId) override;
|
||||
virtual void viewport_size_updated(Web::Compositor::CompositorContextId, Gfx::IntSize, bool is_top_level_traversable, Web::Compositor::WindowResizingInProgress) override;
|
||||
virtual Messages::CompositorControlServer::HandleMouseEventResponse handle_mouse_event(Web::Compositor::CompositorContextId, Web::MouseEvent) override;
|
||||
virtual void dispatch_mouse_event_to_web_content(Web::Compositor::CompositorContextId, Web::MouseEvent) override;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
#include <WebContent/PageClient.h>
|
||||
#include <WebContent/PageHost.h>
|
||||
#include <WebContent/WebContentClientEndpoint.h>
|
||||
#include <WebContent/WebContentCompositorHost.h>
|
||||
|
||||
namespace WebContent {
|
||||
|
||||
|
|
@ -77,6 +78,18 @@ ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<IPC::Transport> transpo
|
|||
|
||||
ConnectionFromClient::~ConnectionFromClient() = default;
|
||||
|
||||
CompositorConnection& ConnectionFromClient::compositor_process_connection() const
|
||||
{
|
||||
VERIFY(m_compositor_connection);
|
||||
VERIFY(m_compositor_connection->is_open());
|
||||
return *m_compositor_connection;
|
||||
}
|
||||
|
||||
void ConnectionFromClient::did_destroy_compositor_context(Web::Compositor::CompositorContextId context_id)
|
||||
{
|
||||
async_did_destroy_compositor_context(context_id);
|
||||
}
|
||||
|
||||
void ConnectionFromClient::die()
|
||||
{
|
||||
_exit(0);
|
||||
|
|
@ -158,7 +171,11 @@ void ConnectionFromClient::connect_to_compositor(IPC::TransportHandle handle)
|
|||
|
||||
void ConnectionFromClient::connect_to_compositor_process(IPC::TransportHandle handle)
|
||||
{
|
||||
(void)handle;
|
||||
auto transport = MUST(handle.create_transport());
|
||||
m_compositor_connection = adopt_ref(*new CompositorConnection(move(transport)));
|
||||
m_compositor_connection->on_mouse_event = [this](u64 page_id, Web::MouseEvent event) {
|
||||
mouse_event(page_id, move(event));
|
||||
};
|
||||
}
|
||||
|
||||
void ConnectionFromClient::connect_to_request_server(IPC::TransportHandle handle)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <LibWeb/CSS/PreferredColorScheme.h>
|
||||
#include <LibWeb/CSS/PreferredContrast.h>
|
||||
#include <LibWeb/CSS/PreferredMotion.h>
|
||||
#include <LibWeb/Compositor/Types.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/Loader/FileRequest.h>
|
||||
#include <LibWeb/Page/EventResult.h>
|
||||
|
|
@ -48,6 +49,8 @@ public:
|
|||
|
||||
PageHost& page_host() { return *m_page_host; }
|
||||
PageHost const& page_host() const { return *m_page_host; }
|
||||
CompositorConnection& compositor_process_connection() const;
|
||||
void did_destroy_compositor_context(Web::Compositor::CompositorContextId);
|
||||
|
||||
Function<void(IPC::TransportHandle const&)> on_request_server_connection;
|
||||
Function<void(IPC::TransportHandle const&)> on_image_decoder_connection;
|
||||
|
|
@ -179,6 +182,7 @@ private:
|
|||
|
||||
virtual void exit_fullscreen(u64 page_id) override;
|
||||
|
||||
RefPtr<CompositorConnection> m_compositor_connection;
|
||||
NonnullOwnPtr<PageHost> m_page_host;
|
||||
|
||||
HashMap<int, Web::FileRequest> m_requested_files {};
|
||||
|
|
@ -187,7 +191,6 @@ private:
|
|||
void enqueue_input_event(Web::QueuedInputEvent);
|
||||
|
||||
Queue<Web::QueuedInputEvent> m_input_event_queue;
|
||||
RefPtr<CompositorConnection> m_compositor_connection;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ void PageHost::ensure_compositor_host(Web::DisplayListPlayerType display_list_pl
|
|||
{
|
||||
if (m_compositor_host)
|
||||
return;
|
||||
m_compositor_host = create_web_content_compositor_host();
|
||||
m_compositor_host = create_web_content_compositor_host(m_client);
|
||||
m_compositor_host->start(display_list_player_type);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
endpoint WebContentClient
|
||||
{
|
||||
allocate_compositor_context_id(u64 page_id, Web::Compositor::PagePresentationRegistration page_presentation_registration) => (Web::Compositor::CompositorContextId context_id)
|
||||
destroy_compositor_context(Web::Compositor::CompositorContextId context_id) =|
|
||||
did_destroy_compositor_context(Web::Compositor::CompositorContextId context_id) =|
|
||||
|
||||
did_request_new_process_for_navigation(u64 page_id, URL::URL url) =|
|
||||
did_start_loading(u64 page_id, URL::URL url, bool is_redirect) =|
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/Debug.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
|
|
@ -20,13 +21,26 @@
|
|||
#include <LibWeb/Painting/DisplayList.h>
|
||||
#include <LibWeb/Painting/DisplayListResourceStorage.h>
|
||||
#include <WebContent/CompositorClientEndpoint.h>
|
||||
#include <WebContent/CompositorConnection.h>
|
||||
#include <WebContent/CompositorServerEndpoint.h>
|
||||
#include <WebContent/ConnectionFromClient.h>
|
||||
#include <WebContent/WebContentCompositorClientEndpoint.h>
|
||||
#include <WebContent/WebContentCompositorHost.h>
|
||||
#include <WebContent/WebContentCompositorServerEndpoint.h>
|
||||
|
||||
namespace WebContent {
|
||||
|
||||
static bool& should_use_compositor_process()
|
||||
{
|
||||
static bool flag = false;
|
||||
return flag;
|
||||
}
|
||||
|
||||
void set_should_use_compositor_process(bool enabled)
|
||||
{
|
||||
should_use_compositor_process() = enabled;
|
||||
}
|
||||
|
||||
class WebContentCompositorActor;
|
||||
|
||||
class WebContentCompositorConnectionToServer final
|
||||
|
|
@ -388,7 +402,7 @@ void CompositorConnectionFromClient::ready_to_paint(u64 page_id, i32 bitmap_id)
|
|||
m_actor.presented_bitmap_ready_to_paint(page_id, bitmap_id);
|
||||
}
|
||||
|
||||
class WebContentCompositorHost final : public Web::Compositor::CompositorHost {
|
||||
class LocalWebContentCompositorHost final : public Web::Compositor::CompositorHost {
|
||||
public:
|
||||
virtual void start(Web::DisplayListPlayerType display_list_player_type) override
|
||||
{
|
||||
|
|
@ -525,9 +539,128 @@ private:
|
|||
RefPtr<Threading::Thread> m_actor_thread;
|
||||
};
|
||||
|
||||
NonnullOwnPtr<Web::Compositor::CompositorHost> create_web_content_compositor_host()
|
||||
class ProcessWebContentCompositorHost final : public Web::Compositor::CompositorHost {
|
||||
public:
|
||||
explicit ProcessWebContentCompositorHost(ConnectionFromClient& client)
|
||||
: m_client(client)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void start(Web::DisplayListPlayerType) override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void register_context(Web::Compositor::CompositorContextId context_id, Optional<u64> page_id, Web::Compositor::PagePresentationRegistration page_presentation_registration) override
|
||||
{
|
||||
if (page_presentation_registration == Web::Compositor::PagePresentationRegistration::Yes) {
|
||||
VERIFY(page_id.has_value());
|
||||
} else {
|
||||
VERIFY(!page_id.has_value());
|
||||
VERIFY(!Web::Compositor::is_page_presenting_compositor_context_id(context_id));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void destroy_context(Web::Compositor::CompositorContextId context_id) override
|
||||
{
|
||||
connection().destroy_context(context_id);
|
||||
m_client.did_destroy_compositor_context(context_id);
|
||||
}
|
||||
|
||||
virtual void stop_presenting_to_client(Web::Compositor::CompositorContextId context_id) override
|
||||
{
|
||||
connection().stop_presenting_to_client(context_id);
|
||||
}
|
||||
|
||||
virtual void set_presentation_mode(Web::Compositor::CompositorContextId context_id, Web::Compositor::PresentationMode mode) override
|
||||
{
|
||||
connection().set_presentation_mode(context_id, mode);
|
||||
}
|
||||
|
||||
virtual void update_display_list(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Web::Painting::DisplayList> display_list, Web::Painting::DisplayListResourceTransaction&& resource_transaction, Web::Painting::ScrollStateSnapshot&& scroll_state_snapshot) override
|
||||
{
|
||||
connection().update_display_list(context_id, display_list, resource_transaction, scroll_state_snapshot);
|
||||
}
|
||||
|
||||
virtual void update_video_frame(Web::Compositor::CompositorContextId context_id, Web::Painting::VideoFrameResourceId frame_id, NonnullRefPtr<Media::VideoFrame const> frame) override
|
||||
{
|
||||
connection().update_video_frame(context_id, frame_id, frame);
|
||||
}
|
||||
|
||||
virtual void clear_video_frame(Web::Compositor::CompositorContextId context_id, Web::Painting::VideoFrameResourceId frame_id) override
|
||||
{
|
||||
connection().clear_video_frame(context_id, frame_id);
|
||||
}
|
||||
|
||||
virtual void update_compositor_surface(Web::Compositor::CompositorContextId context_id, Web::Painting::CompositorSurfaceId surface_id, Gfx::SharedImage&& shared_image) override
|
||||
{
|
||||
connection().update_compositor_surface(context_id, surface_id, shared_image);
|
||||
}
|
||||
|
||||
virtual void clear_compositor_surface(Web::Compositor::CompositorContextId context_id, Web::Painting::CompositorSurfaceId surface_id) override
|
||||
{
|
||||
connection().clear_compositor_surface(context_id, surface_id);
|
||||
}
|
||||
|
||||
virtual void update_scroll_state(Web::Compositor::CompositorContextId context_id, Web::Painting::ScrollStateSnapshot&& scroll_state_snapshot) override
|
||||
{
|
||||
connection().update_scroll_state(context_id, scroll_state_snapshot);
|
||||
}
|
||||
|
||||
virtual void invalidate_wheel_event_listener_state(Web::Compositor::CompositorContextId context_id, u64 generation) override
|
||||
{
|
||||
connection().invalidate_wheel_event_listener_state(context_id, generation);
|
||||
}
|
||||
|
||||
virtual Web::Compositor::AsyncScrollEnqueueResult async_scroll_by(Web::Compositor::CompositorContextId context_id, Web::UniqueNodeID expected_document_id, Gfx::FloatPoint position,
|
||||
Gfx::FloatPoint delta_in_device_pixels, Gfx::IntRect viewport_rect, Web::Compositor::AsyncScrollOperationTracking operation_tracking) override
|
||||
{
|
||||
return connection().async_scroll_by(context_id, expected_document_id, position, delta_in_device_pixels, viewport_rect, operation_tracking);
|
||||
}
|
||||
|
||||
virtual bool should_defer_async_scroll_offset_adoption(Web::Compositor::CompositorContextId) const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool should_defer_main_thread_present_for_async_scroll(Web::Compositor::CompositorContextId context_id) const override
|
||||
{
|
||||
return connection().should_defer_main_thread_present_for_async_scroll(context_id);
|
||||
}
|
||||
|
||||
virtual Web::Compositor::PendingAsyncScrollUpdates take_pending_async_scroll_updates(Web::Compositor::CompositorContextId context_id) override
|
||||
{
|
||||
return connection().take_pending_async_scroll_updates(context_id);
|
||||
}
|
||||
|
||||
virtual void viewport_size_updated(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, bool is_top_level_traversable, Web::Compositor::WindowResizingInProgress window_resize_in_progress) override
|
||||
{
|
||||
connection().viewport_size_updated(context_id, viewport_size, is_top_level_traversable, window_resize_in_progress);
|
||||
}
|
||||
|
||||
virtual void present_frame(Web::Compositor::CompositorContextId context_id, Gfx::IntRect viewport_rect) override
|
||||
{
|
||||
connection().present_frame(context_id, viewport_rect);
|
||||
}
|
||||
|
||||
virtual void request_screenshot(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Gfx::PaintingSurface> target_surface, Function<void()>&& callback) override
|
||||
{
|
||||
connection().request_screenshot(context_id, move(target_surface), move(callback));
|
||||
}
|
||||
|
||||
CompositorConnection& connection() const
|
||||
{
|
||||
return m_client.compositor_process_connection();
|
||||
}
|
||||
|
||||
ConnectionFromClient& m_client;
|
||||
};
|
||||
|
||||
NonnullOwnPtr<Web::Compositor::CompositorHost> create_web_content_compositor_host(ConnectionFromClient& client)
|
||||
{
|
||||
return make<WebContentCompositorHost>();
|
||||
if (should_use_compositor_process())
|
||||
return make<ProcessWebContentCompositorHost>(client);
|
||||
return make<LocalWebContentCompositorHost>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibWeb/Compositor/CompositorHost.h>
|
||||
#include <WebContent/Forward.h>
|
||||
|
||||
namespace WebContent {
|
||||
|
||||
NonnullOwnPtr<Web::Compositor::CompositorHost> create_web_content_compositor_host();
|
||||
NonnullOwnPtr<Web::Compositor::CompositorHost> create_web_content_compositor_host(ConnectionFromClient&);
|
||||
void set_should_use_compositor_process(bool);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include <LibWebView/Utilities.h>
|
||||
#include <WebContent/ConnectionFromClient.h>
|
||||
#include <WebContent/PageClient.h>
|
||||
#include <WebContent/WebContentCompositorHost.h>
|
||||
#include <WebContent/WebDriverConnection.h>
|
||||
|
||||
#include <openssl/thread.h>
|
||||
|
|
@ -149,6 +150,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
bool is_headless = false;
|
||||
bool disable_scrollbar_painting = false;
|
||||
bool disable_async_scrolling = false;
|
||||
bool enable_compositor_process = false;
|
||||
StringView echo_server_port_string_view {};
|
||||
StringView default_time_zone {};
|
||||
StringView style_invalidation_counter_dump_interval {};
|
||||
|
|
@ -171,6 +173,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
args_parser.add_option(collect_garbage_on_every_allocation, "Collect garbage after every JS heap allocation", "collect-garbage-on-every-allocation");
|
||||
args_parser.add_option(disable_scrollbar_painting, "Don't paint horizontal or vertical viewport scrollbars", "disable-scrollbar-painting");
|
||||
args_parser.add_option(disable_async_scrolling, "Disable async scrolling", "disable-async-scrolling");
|
||||
args_parser.add_option(enable_compositor_process, "Use the Compositor helper process", "enable-compositor-process");
|
||||
args_parser.add_option(echo_server_port_string_view, "Echo server port used in test internals", "echo-server-port", 0, "echo_server_port");
|
||||
args_parser.add_option(is_headless, "Report that the browser is running in headless mode", "headless");
|
||||
args_parser.add_option(default_time_zone, "Default time zone", "default-time-zone", 0, "time-zone-id");
|
||||
|
|
@ -222,6 +225,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
|
||||
Web::Painting::set_paint_viewport_scrollbars(!disable_scrollbar_painting);
|
||||
WebContent::PageClient::set_async_scrolling_enabled(!disable_async_scrolling);
|
||||
WebContent::set_should_use_compositor_process(enable_compositor_process);
|
||||
|
||||
if (!echo_server_port_string_view.is_empty()) {
|
||||
if (auto maybe_echo_server_port = echo_server_port_string_view.to_number<u16>(); maybe_echo_server_port.has_value())
|
||||
|
|
|
|||
Loading…
Reference in a new issue