2026-05-22 11:02:42 -03:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2026, the Ladybird developers.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <WebContent/CompositorConnection.h>
|
|
|
|
|
|
2026-05-22 09:00:41 -03:00
|
|
|
#include <LibCore/EventLoop.h>
|
|
|
|
|
#include <LibGfx/Bitmap.h>
|
|
|
|
|
#include <LibGfx/PaintingSurface.h>
|
|
|
|
|
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
|
|
|
|
#include <WebContent/WebContentCompositorHost.h>
|
|
|
|
|
|
2026-05-22 11:02:42 -03:00
|
|
|
namespace WebContent {
|
|
|
|
|
|
|
|
|
|
CompositorConnection::CompositorConnection(NonnullOwnPtr<IPC::Transport> transport)
|
|
|
|
|
: IPC::ConnectionToServer<CompositorWebContentClientEndpoint, CompositorWebContentServerEndpoint>(*this, move(transport))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::die()
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
did_lose_compositor();
|
2026-05-22 09:00:41 -03:00
|
|
|
}
|
|
|
|
|
|
2026-06-18 01:10:37 -03:00
|
|
|
void CompositorConnection::set_parent_context(Web::Compositor::CompositorContextId context_id, Optional<Web::Compositor::CompositorContextId> parent_context_id)
|
2026-05-22 09:00:41 -03:00
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
2026-06-18 01:10:37 -03:00
|
|
|
async_set_parent_context(context_id, parent_context_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::stop_presenting_to_client(Web::Compositor::CompositorContextId context_id)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
async_stop_presenting_to_client(context_id);
|
2026-05-22 09:00:41 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::destroy_context(Web::Compositor::CompositorContextId context_id)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
2026-05-22 09:00:41 -03:00
|
|
|
async_destroy_context(context_id);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-27 12:51:03 -03:00
|
|
|
void CompositorConnection::update_display_list(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Web::Painting::DisplayList> const& display_list, Web::Painting::AccumulatedVisualContextTree const& visual_context_tree, Web::Painting::DisplayListResourceTransaction const& resource_transaction, Web::Painting::ScrollStateSnapshot const& scroll_state_snapshot)
|
2026-05-22 09:00:41 -03:00
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
|
2026-05-27 12:51:03 -03:00
|
|
|
auto encoded_message = MUST(Messages::CompositorWebContentServer::UpdateDisplayList::static_encode(context_id, display_list, visual_context_tree, resource_transaction, scroll_state_snapshot));
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (post_message(encoded_message).is_error())
|
|
|
|
|
did_lose_compositor();
|
2026-05-22 09:00:41 -03:00
|
|
|
}
|
|
|
|
|
|
2026-06-02 15:39:40 -03:00
|
|
|
void CompositorConnection::update_visual_context_tree(Web::Compositor::CompositorContextId context_id, Web::Painting::AccumulatedVisualContextTree const& visual_context_tree)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
async_update_visual_context_tree(context_id, visual_context_tree);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 09:00:41 -03:00
|
|
|
void CompositorConnection::update_scroll_state(Web::Compositor::CompositorContextId context_id, Web::Painting::ScrollStateSnapshot const& scroll_state_snapshot)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
2026-05-22 09:00:41 -03:00
|
|
|
async_update_scroll_state(context_id, scroll_state_snapshot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::update_video_frame(Web::Compositor::CompositorContextId context_id, Web::Painting::VideoFrameResourceId frame_id, NonnullRefPtr<Media::VideoFrame const> const& frame)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
|
2026-05-22 09:00:41 -03:00
|
|
|
auto encoded_message = MUST(Messages::CompositorWebContentServer::UpdateVideoFrame::static_encode(context_id, frame_id, frame));
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (post_message(encoded_message).is_error())
|
|
|
|
|
did_lose_compositor();
|
2026-05-22 09:00:41 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::clear_video_frame(Web::Compositor::CompositorContextId context_id, Web::Painting::VideoFrameResourceId frame_id)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
2026-05-22 09:00:41 -03:00
|
|
|
async_clear_video_frame(context_id, frame_id);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 14:29:43 -03:00
|
|
|
Optional<Web::Painting::CanvasId> CompositorConnection::create_canvas_2d_context(Gfx::IntSize size, bool alpha)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
auto response = send_sync<Messages::CompositorWebContentServer::CreateCanvas2dContext>(size, alpha);
|
|
|
|
|
if (!response->success())
|
|
|
|
|
return {};
|
|
|
|
|
return response->canvas_id();
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-18 18:12:08 -03:00
|
|
|
void CompositorConnection::update_canvas_2d_commands(Web::Painting::CanvasId canvas_id, Gfx::CanvasCommandList const& commands, bool commit)
|
2026-06-15 14:29:43 -03:00
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
|
2026-06-18 18:12:08 -03:00
|
|
|
auto encoded_message = MUST(Messages::CompositorWebContentServer::UpdateCanvas2dCommands::static_encode(canvas_id, commands, commit));
|
2026-06-15 14:29:43 -03:00
|
|
|
if (post_message(encoded_message).is_error())
|
|
|
|
|
did_lose_compositor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::destroy_canvas_context(Web::Painting::CanvasId canvas_id)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
async_destroy_canvas_context(canvas_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gfx::ShareableBitmap CompositorConnection::get_canvas_pixels(Web::Painting::CanvasId canvas_id, Gfx::IntRect rect)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
auto response = send_sync<Messages::CompositorWebContentServer::GetCanvasPixels>(canvas_id, rect);
|
|
|
|
|
return response->take_pixels();
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 09:00:41 -03:00
|
|
|
void CompositorConnection::invalidate_wheel_event_listener_state(Web::Compositor::CompositorContextId context_id, u64 generation)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
2026-05-22 09:00:41 -03:00
|
|
|
async_invalidate_wheel_event_listener_state(context_id, generation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Web::Compositor::AsyncScrollEnqueueResult CompositorConnection::async_scroll_by(Web::Compositor::CompositorContextId context_id, Web::UniqueNodeID document_id, Gfx::FloatPoint position, Gfx::FloatPoint delta, Gfx::IntRect viewport_rect, Web::Compositor::AsyncScrollOperationTracking operation_tracking)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
auto response = send_sync_but_allow_failure<Messages::CompositorWebContentServer::AsyncScrollBy>(context_id, document_id, position, delta, viewport_rect, operation_tracking);
|
|
|
|
|
if (!response) {
|
|
|
|
|
did_lose_compositor();
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2026-05-22 09:00:41 -03:00
|
|
|
return response->take_result();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CompositorConnection::should_defer_main_thread_present_for_async_scroll(Web::Compositor::CompositorContextId context_id)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto response = send_sync_but_allow_failure<Messages::CompositorWebContentServer::ShouldDeferMainThreadPresentForAsyncScroll>(context_id);
|
|
|
|
|
if (!response) {
|
|
|
|
|
did_lose_compositor();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-05-22 09:00:41 -03:00
|
|
|
return response->should_defer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Web::Compositor::PendingAsyncScrollUpdates CompositorConnection::take_pending_async_scroll_updates(Web::Compositor::CompositorContextId context_id)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
auto response = send_sync_but_allow_failure<Messages::CompositorWebContentServer::TakePendingAsyncScrollUpdates>(context_id);
|
|
|
|
|
if (!response) {
|
|
|
|
|
did_lose_compositor();
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2026-05-22 09:00:41 -03:00
|
|
|
return response->take_updates();
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-27 14:26:14 -03:00
|
|
|
void CompositorConnection::viewport_size_updated(Web::Compositor::CompositorContextId context_id, Gfx::IntSize viewport_size, Web::Compositor::WindowResizingInProgress window_resize_in_progress)
|
2026-05-22 09:00:41 -03:00
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
2026-05-27 14:26:14 -03:00
|
|
|
async_viewport_size_updated(context_id, viewport_size, window_resize_in_progress);
|
2026-05-22 09:00:41 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::present_frame(Web::Compositor::CompositorContextId context_id, Gfx::IntRect viewport_rect)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
2026-05-22 09:00:41 -03:00
|
|
|
async_present_frame(context_id, viewport_rect);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 14:29:43 -03:00
|
|
|
Optional<Web::Painting::CanvasId> CompositorConnection::create_webgl_context(Web::WebGL::WebGLVersion webgl_version, Gfx::IntSize size, bool depth, bool stencil, bool antialias, Vector<String>& out_supported_extensions)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
auto response = send_sync<Messages::CompositorWebContentServer::CreateWebglContext>(webgl_version, size, depth, stencil, antialias);
|
|
|
|
|
out_supported_extensions = response->take_supported_extensions();
|
|
|
|
|
if (!response->success())
|
|
|
|
|
return {};
|
|
|
|
|
return response->canvas_id();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::send_webgl_commands(Web::Painting::CanvasId canvas_id, ByteBuffer const& commands, Vector<Gfx::DecodedImageFrame> const& bitmaps)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto encoded_message = MUST(Messages::CompositorWebContentServer::WebglCommands::static_encode(canvas_id, commands, bitmaps));
|
|
|
|
|
if (post_message(encoded_message).is_error())
|
|
|
|
|
did_lose_compositor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::present_webgl_canvas(Web::Painting::CanvasId canvas_id, bool preserve_drawing_buffer)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
async_webgl_present_canvas(canvas_id, preserve_drawing_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ByteBuffer CompositorConnection::webgl_sync_call(Web::Painting::CanvasId canvas_id, ByteBuffer request)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
auto response = send_sync<Messages::CompositorWebContentServer::WebglSyncCall>(canvas_id, move(request));
|
|
|
|
|
return response->take_reply();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Web::WebGL::ReadPixelsResult CompositorConnection::read_webgl_pixels(Web::Painting::CanvasId canvas_id, 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 const& pixels)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
auto response = send_sync<Messages::CompositorWebContentServer::WebglReadPixels>(canvas_id, x, y, width, height, format, type, buf_size, pixels);
|
|
|
|
|
return {
|
|
|
|
|
.length = response->length(),
|
|
|
|
|
.columns = response->columns(),
|
|
|
|
|
.rows = response->rows(),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::read_webgl_buffer_sub_data(Web::Painting::CanvasId canvas_id, Web::WebGL::GLenum target, Web::WebGL::GLintptr offset, Web::WebGL::GLintptr size, Core::AnonymousBuffer const& data)
|
|
|
|
|
{
|
|
|
|
|
if (!can_send_message_to_compositor())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
(void)send_sync<Messages::CompositorWebContentServer::WebglReadBufferSubData>(canvas_id, target, offset, size, data);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 09:00:41 -03:00
|
|
|
void CompositorConnection::request_screenshot(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Gfx::PaintingSurface> target_surface, Function<void()>&& callback)
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!can_send_message_to_compositor()) {
|
|
|
|
|
if (callback)
|
|
|
|
|
callback();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 09:00:41 -03:00
|
|
|
auto target_bitmap = MUST(Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied, target_surface->size()));
|
|
|
|
|
auto shareable_bitmap = Gfx::ShareableBitmap { target_bitmap, Gfx::ShareableBitmap::ConstructWithKnownGoodBitmap };
|
|
|
|
|
auto request_id = Web::Compositor::ScreenshotRequestId { m_next_screenshot_request_id++ };
|
|
|
|
|
m_screenshots.set(request_id, PendingScreenshot { move(target_surface), move(target_bitmap), move(callback) });
|
|
|
|
|
async_request_screenshot(context_id, request_id, move(shareable_bitmap));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::mouse_event(u64 page_id, Web::MouseEvent event)
|
|
|
|
|
{
|
|
|
|
|
if (on_mouse_event)
|
|
|
|
|
on_mouse_event(page_id, move(event));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::request_rendering_update()
|
|
|
|
|
{
|
|
|
|
|
Web::HTML::main_thread_event_loop().queue_task_to_update_the_rendering();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::did_complete_screenshot(Web::Compositor::ScreenshotRequestId request_id)
|
|
|
|
|
{
|
|
|
|
|
auto pending_screenshot = take_screenshot(request_id);
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!pending_screenshot.has_value())
|
|
|
|
|
return;
|
2026-05-22 09:00:41 -03:00
|
|
|
|
|
|
|
|
pending_screenshot->target_surface->write_from_bitmap(*pending_screenshot->target_bitmap);
|
|
|
|
|
if (pending_screenshot->callback)
|
|
|
|
|
pending_screenshot->callback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::did_fail_screenshot(Web::Compositor::ScreenshotRequestId request_id)
|
|
|
|
|
{
|
|
|
|
|
auto pending_screenshot = take_screenshot(request_id);
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (!pending_screenshot.has_value())
|
|
|
|
|
return;
|
2026-05-22 09:00:41 -03:00
|
|
|
|
|
|
|
|
if (pending_screenshot->callback)
|
|
|
|
|
pending_screenshot->callback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CompositorConnection::did_lose_compositor()
|
|
|
|
|
{
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
if (m_has_lost_compositor)
|
|
|
|
|
return;
|
|
|
|
|
m_has_lost_compositor = true;
|
|
|
|
|
|
|
|
|
|
for (auto& entry : m_screenshots) {
|
|
|
|
|
if (entry.value.callback)
|
|
|
|
|
entry.value.callback();
|
|
|
|
|
}
|
|
|
|
|
m_screenshots.clear();
|
2026-06-15 13:53:42 -03:00
|
|
|
|
|
|
|
|
if (on_compositor_lost)
|
|
|
|
|
on_compositor_lost();
|
LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-23 22:36:24 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CompositorConnection::can_send_message_to_compositor() const
|
|
|
|
|
{
|
|
|
|
|
return !m_has_lost_compositor && is_open();
|
2026-05-22 11:02:42 -03:00
|
|
|
}
|
|
|
|
|
|
2026-05-22 09:00:41 -03:00
|
|
|
Optional<CompositorConnection::PendingScreenshot> CompositorConnection::take_screenshot(Web::Compositor::ScreenshotRequestId request_id)
|
2026-05-22 11:02:42 -03:00
|
|
|
{
|
2026-05-22 09:00:41 -03:00
|
|
|
return m_screenshots.take(request_id);
|
2026-05-22 11:02:42 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|