mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-06-19 08:11:58 +00:00
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.
53 lines
1.8 KiB
C++
53 lines
1.8 KiB
C++
/*
|
|
* Copyright (c) 2026, the Ladybird developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWebView/CompositorClient.h>
|
|
|
|
#include <LibCore/EventLoop.h>
|
|
#include <LibWebView/WebContentClient.h>
|
|
|
|
namespace WebView {
|
|
|
|
CompositorClient::CompositorClient(NonnullOwnPtr<IPC::Transport> transport)
|
|
: IPC::ConnectionToServer<CompositorControlClientEndpoint, CompositorControlServerEndpoint>(*this, move(transport))
|
|
{
|
|
}
|
|
|
|
void CompositorClient::die()
|
|
{
|
|
if (auto callback = move(on_death)) {
|
|
Core::deferred_invoke([callback = move(callback)]() mutable {
|
|
callback();
|
|
});
|
|
}
|
|
}
|
|
|
|
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 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);
|
|
}
|
|
|
|
}
|