LibWeb: Protect SkiaBackendContext with a mutex

The Skia Ganesh backend we currently use doesn't support painting from
multiple threads, which could happen before this change when the main
thread used Skia to paint on the HTML canvas while the rendering thread
was working on display list rasterization.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/4172
This commit is contained in:
Aliaksandr Kalenik 2025-04-01 20:18:15 +02:00 committed by Alexander Kalenik
commit fd147e6be0
Notes: github-actions[bot] 2025-04-01 21:40:01 +00:00
7 changed files with 98 additions and 29 deletions

View file

@ -36,6 +36,17 @@ static bool command_is_clip_or_mask(Command const& command)
}
void DisplayListPlayer::execute(DisplayList& display_list, RefPtr<Gfx::PaintingSurface> surface)
{
if (surface) {
surface->lock_context();
}
execute_impl(display_list, surface);
if (surface) {
surface->unlock_context();
}
}
void DisplayListPlayer::execute_impl(DisplayList& display_list, RefPtr<Gfx::PaintingSurface> surface)
{
if (surface)
m_surfaces.append(*surface);

View file

@ -30,6 +30,7 @@ public:
protected:
Gfx::PaintingSurface& surface() const { return m_surfaces.last(); }
void execute_impl(DisplayList&, RefPtr<Gfx::PaintingSurface>);
private:
virtual void flush() = 0;

View file

@ -972,7 +972,7 @@ void DisplayListPlayerSkia::add_mask(AddMask const& command)
auto mask_surface = Gfx::PaintingSurface::create_with_size(m_context, rect.size(), Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
execute(*command.display_list, mask_surface);
execute_impl(*command.display_list, mask_surface);
SkMatrix mask_matrix;
mask_matrix.setTranslate(rect.x(), rect.y());
@ -985,7 +985,7 @@ void DisplayListPlayerSkia::paint_nested_display_list(PaintNestedDisplayList con
{
auto& canvas = surface().canvas();
canvas.translate(command.rect.x(), command.rect.y());
execute(*command.display_list, {});
execute_impl(*command.display_list, {});
}
void DisplayListPlayerSkia::paint_scrollbar(PaintScrollBar const& command)