ladybird/Services/WebContent/WebContentCompositorHost.cpp

287 lines
11 KiB
C++
Raw Permalink Normal View History

/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/NonnullOwnPtr.h>
#include <AK/Optional.h>
#include <LibGfx/CanvasCommandList.h>
#include <LibGfx/PaintingSurface.h>
#include <LibMedia/VideoFrame.h>
#include <LibWeb/Compositor/CompositorHost.h>
#include <LibWeb/HTML/Canvas/RemoteCanvas2DTransport.h>
#include <LibWeb/WebGL/RemoteWebGLTransport.h>
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.
2026-05-22 11:17:27 -03:00
#include <WebContent/CompositorConnection.h>
#include <WebContent/ConnectionFromClient.h>
#include <WebContent/WebContentCompositorHost.h>
namespace WebContent {
class WebContentRemoteWebGLTransport final : public Web::WebGL::RemoteWebGLTransport {
public:
explicit WebContentRemoteWebGLTransport(NonnullRefPtr<CompositorConnection> connection)
: m_connection(move(connection))
{
}
private:
virtual CreateResult create_context(Web::WebGL::WebGLVersion webgl_version, Gfx::IntSize initial_size, bool depth, bool stencil, bool antialias) override
{
VERIFY(!m_canvas_id.has_value());
CreateResult result;
auto canvas_id = m_connection->create_webgl_context(webgl_version, initial_size, depth, stencil, antialias, result.supported_extensions);
if (canvas_id.has_value()) {
result.success = true;
m_canvas_id = *canvas_id;
}
return result;
}
virtual Optional<Web::Painting::CanvasId> canvas_id() const override
{
return m_canvas_id;
}
virtual void destroy_context() override
{
if (!m_canvas_id.has_value())
return;
m_connection->destroy_canvas_context(*m_canvas_id);
m_canvas_id.clear();
}
virtual void send_commands(ByteBuffer const& commands, Vector<Gfx::DecodedImageFrame> const& bitmaps) override
{
if (!m_canvas_id.has_value())
return;
m_connection->send_webgl_commands(*m_canvas_id, commands, bitmaps);
}
virtual void present_canvas(bool preserve_drawing_buffer) override
{
if (!m_canvas_id.has_value())
return;
m_connection->present_webgl_canvas(*m_canvas_id, preserve_drawing_buffer);
}
virtual ByteBuffer sync_call(ByteBuffer request) override
{
if (!m_canvas_id.has_value())
return {};
return m_connection->webgl_sync_call(*m_canvas_id, move(request));
}
virtual Web::WebGL::ReadPixelsResult read_pixels_robust_angle(Web::WebGL::GLint x, Web::WebGL::GLint y, Web::WebGL::GLsizei width, Web::WebGL::GLsizei height, Web::WebGL::GLenum format, Web::WebGL::GLenum type, Web::WebGL::GLsizei buf_size, Core::AnonymousBuffer pixels) override
{
if (!m_canvas_id.has_value())
return {};
return m_connection->read_webgl_pixels(*m_canvas_id, x, y, width, height, format, type, buf_size, pixels);
}
virtual void read_buffer_sub_data(Web::WebGL::GLenum target, Web::WebGL::GLintptr offset, Web::WebGL::GLintptr size, Core::AnonymousBuffer data) override
{
if (!m_canvas_id.has_value())
return;
m_connection->read_webgl_buffer_sub_data(*m_canvas_id, target, offset, size, data);
}
virtual Gfx::ShareableBitmap read_back_drawing_buffer(Gfx::IntRect const& rect) override
{
if (!m_canvas_id.has_value())
return {};
return m_connection->get_canvas_pixels(*m_canvas_id, rect);
}
NonnullRefPtr<CompositorConnection> m_connection;
Optional<Web::Painting::CanvasId> m_canvas_id;
};
class WebContentRemoteCanvas2DTransport final : public Web::HTML::RemoteCanvas2DTransport {
public:
explicit WebContentRemoteCanvas2DTransport(NonnullRefPtr<CompositorConnection> connection)
: m_connection(move(connection))
{
}
private:
virtual bool create_context(Gfx::IntSize size, bool alpha) override
{
VERIFY(!m_canvas_id.has_value());
auto canvas_id = m_connection->create_canvas_2d_context(size, alpha);
if (!canvas_id.has_value())
return false;
m_canvas_id = *canvas_id;
return true;
}
virtual Optional<Web::Painting::CanvasId> canvas_id() const override
{
return m_canvas_id;
}
virtual void destroy_context() override
{
if (!m_canvas_id.has_value())
return;
m_connection->destroy_canvas_context(*m_canvas_id);
m_canvas_id.clear();
}
virtual void update_commands(Gfx::CanvasCommandList const& commands, bool commit) override
{
if (!m_canvas_id.has_value())
return;
m_connection->update_canvas_2d_commands(*m_canvas_id, commands, commit);
}
virtual RefPtr<Gfx::Bitmap> read_back_pixels(Gfx::IntRect const& rect) override
{
if (!m_canvas_id.has_value())
return nullptr;
auto shareable_bitmap = m_connection->get_canvas_pixels(*m_canvas_id, rect);
if (!shareable_bitmap.is_valid())
return nullptr;
return shareable_bitmap.bitmap();
}
NonnullRefPtr<CompositorConnection> m_connection;
Optional<Web::Painting::CanvasId> m_canvas_id;
};
class WebContentCompositorHost final : public Web::Compositor::CompositorHost {
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.
2026-05-22 11:17:27 -03:00
public:
explicit WebContentCompositorHost(ConnectionFromClient& client)
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.
2026-05-22 11:17:27 -03:00
: m_client(client)
{
}
private:
virtual RefPtr<Web::WebGL::RemoteWebGLTransport> create_webgl_transport() override
{
if (auto* connection = compositor_connection())
return adopt_ref(*new WebContentRemoteWebGLTransport(*connection));
return nullptr;
}
virtual RefPtr<Web::HTML::RemoteCanvas2DTransport> create_canvas_2d_transport() override
{
if (auto* connection = compositor_connection())
return adopt_ref(*new WebContentRemoteCanvas2DTransport(*connection));
return nullptr;
}
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.
2026-05-22 11:17:27 -03:00
virtual void destroy_context(Web::Compositor::CompositorContextId context_id) override
{
if (auto* connection = compositor_connection())
connection->destroy_context(context_id);
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.
2026-05-22 11:17:27 -03:00
m_client.did_destroy_compositor_context(context_id);
}
virtual void set_parent_context(Web::Compositor::CompositorContextId context_id, Optional<Web::Compositor::CompositorContextId> parent_context_id) override
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.
2026-05-22 11:17:27 -03:00
{
if (auto* connection = compositor_connection())
connection->set_parent_context(context_id, parent_context_id);
}
virtual void stop_presenting_to_client(Web::Compositor::CompositorContextId context_id) override
{
if (auto* connection = compositor_connection())
connection->stop_presenting_to_client(context_id);
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.
2026-05-22 11:17:27 -03:00
}
virtual void update_display_list(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Web::Painting::DisplayList> display_list, Web::Painting::AccumulatedVisualContextTree visual_context_tree, Web::Painting::DisplayListResourceTransaction&& resource_transaction, Web::Painting::ScrollStateSnapshot&& scroll_state_snapshot) override
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.
2026-05-22 11:17:27 -03:00
{
if (auto* connection = compositor_connection())
connection->update_display_list(context_id, display_list, visual_context_tree, resource_transaction, scroll_state_snapshot);
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.
2026-05-22 11:17:27 -03:00
}
virtual void update_visual_context_tree(Web::Compositor::CompositorContextId context_id, Web::Painting::AccumulatedVisualContextTree visual_context_tree) override
{
if (auto* connection = compositor_connection())
connection->update_visual_context_tree(context_id, visual_context_tree);
}
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.
2026-05-22 11:17:27 -03:00
virtual void update_video_frame(Web::Compositor::CompositorContextId context_id, Web::Painting::VideoFrameResourceId frame_id, NonnullRefPtr<Media::VideoFrame const> frame) override
{
if (auto* connection = compositor_connection())
connection->update_video_frame(context_id, frame_id, frame);
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.
2026-05-22 11:17:27 -03:00
}
virtual void clear_video_frame(Web::Compositor::CompositorContextId context_id, Web::Painting::VideoFrameResourceId frame_id) override
{
if (auto* connection = compositor_connection())
connection->clear_video_frame(context_id, frame_id);
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.
2026-05-22 11:17:27 -03:00
}
virtual void update_scroll_state(Web::Compositor::CompositorContextId context_id, Web::Painting::ScrollStateSnapshot&& scroll_state_snapshot) override
{
if (auto* connection = compositor_connection())
connection->update_scroll_state(context_id, scroll_state_snapshot);
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.
2026-05-22 11:17:27 -03:00
}
virtual void invalidate_wheel_event_listener_state(Web::Compositor::CompositorContextId context_id, u64 generation) override
{
if (auto* connection = compositor_connection())
connection->invalidate_wheel_event_listener_state(context_id, generation);
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.
2026-05-22 11:17:27 -03:00
}
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
{
if (auto* connection = compositor_connection())
return connection->async_scroll_by(context_id, expected_document_id, position, delta_in_device_pixels, viewport_rect, operation_tracking);
return {};
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.
2026-05-22 11:17:27 -03:00
}
virtual bool should_defer_main_thread_present_for_async_scroll(Web::Compositor::CompositorContextId context_id) const override
{
if (auto* connection = compositor_connection())
return connection->should_defer_main_thread_present_for_async_scroll(context_id);
return false;
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.
2026-05-22 11:17:27 -03:00
}
virtual Web::Compositor::PendingAsyncScrollUpdates take_pending_async_scroll_updates(Web::Compositor::CompositorContextId context_id) override
{
if (auto* connection = compositor_connection())
return connection->take_pending_async_scroll_updates(context_id);
return {};
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.
2026-05-22 11:17:27 -03:00
}
virtual void viewport_size_updated(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress window_resize_in_progress) override
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.
2026-05-22 11:17:27 -03:00
{
if (auto* connection = compositor_connection())
connection->viewport_size_updated(context_id, viewport_size, window_resize_in_progress);
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.
2026-05-22 11:17:27 -03:00
}
virtual void present_frame(Web::Compositor::CompositorContextId context_id, Gfx::IntRect viewport_rect) override
{
if (auto* connection = compositor_connection())
connection->present_frame(context_id, viewport_rect);
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.
2026-05-22 11:17:27 -03:00
}
virtual void request_screenshot(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Gfx::PaintingSurface> target_surface, Function<void()>&& callback) override
{
if (auto* connection = compositor_connection()) {
connection->request_screenshot(context_id, move(target_surface), move(callback));
return;
}
if (callback)
callback();
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.
2026-05-22 11:17:27 -03:00
}
CompositorConnection* compositor_connection() const
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.
2026-05-22 11:17:27 -03:00
{
return m_client.compositor_process_connection();
}
ConnectionFromClient& m_client;
};
NonnullOwnPtr<Web::Compositor::CompositorHost> create_web_content_compositor_host(ConnectionFromClient& client)
{
return make<WebContentCompositorHost>(client);
}
}