ladybird/Libraries/LibWeb/Painting/CanvasPaintable.cpp
Aliaksandr Kalenik 93bbdf1f55 LibWeb: Use compositor surface IDs for embedded content
Display lists kept canvas and nested navigable content alive through
ExternalContentSource objects. That made the resource graph depend on
process-local object identity instead of a stable surface handle, which
blocks compositor process isolation and made teardown-sensitive embedded
content harder to reason about.

Allocate CompositorSurfaceId values for canvases and child navigables,
publish their backing stores to the owning compositor, and paint them
with DrawCompositorSurface. Child navigables now publish to parent
compositors by CompositorContextId instead of raw object pointers, so
the in-process path uses the same stable addressing model required by a
remote compositor.

Clear and skip stale child surfaces during teardown, preserve Skia
canvas state while drawing compositor surfaces, and add display-list
coverage for canvas and iframe compositor surfaces. The nested navigable
async-scrolling baseline now expects DrawCompositorSurface.
2026-05-18 15:27:59 +02:00

46 lines
1.6 KiB
C++

/*
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
#include <LibWeb/Painting/CanvasPaintable.h>
#include <LibWeb/Painting/DisplayListRecorder.h>
namespace Web::Painting {
NonnullRefPtr<CanvasPaintable> CanvasPaintable::create(Layout::CanvasBox const& layout_box)
{
return adopt_ref(*new CanvasPaintable(layout_box));
}
CanvasPaintable::CanvasPaintable(Layout::CanvasBox const& layout_box)
: PaintableBox(layout_box)
{
}
void CanvasPaintable::paint(DisplayListRecordingContext& context, PaintPhase phase) const
{
if (!is_visible())
return;
PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) {
auto canvas_rect = context.rounded_device_rect(absolute_rect());
ScopedCornerRadiusClip corner_clip { context, canvas_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) };
auto& canvas_element = as<HTML::HTMLCanvasElement>(*dom_node());
if (auto surface = canvas_element.surface()) {
auto canvas_int_rect = canvas_rect.to_type<int>();
auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(),
surface->size(), canvas_int_rect.size());
auto& mutable_canvas_element = const_cast<HTML::HTMLCanvasElement&>(canvas_element);
context.display_list_recorder().draw_compositor_surface(canvas_int_rect,
mutable_canvas_element.ensure_compositor_surface_id(), scaling_mode);
}
}
}
}