LibGfx: Make Skia surface construction/destruction thread-safe
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run

With this change we ensure that Skia surfaces are allowed to be created
or destroyed only by one thread at a time. Not enforcing this before
resulted in "Single owner failure." assertion crashes in debug mode on
pages with canvas elements.
This commit is contained in:
Aliaksandr Kalenik 2025-04-15 02:07:47 +02:00 committed by Alexander Kalenik
commit a4cc0703d1
Notes: github-actions[bot] 2025-04-15 00:34:33 +00:00

View file

@ -40,8 +40,10 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBack
return adopt_ref(*new PaintingSurface(make<Impl>(context, size, surface, bitmap))); return adopt_ref(*new PaintingSurface(make<Impl>(context, size, surface, bitmap)));
} }
context->lock();
auto surface = SkSurfaces::RenderTarget(context->sk_context(), skgpu::Budgeted::kNo, image_info); auto surface = SkSurfaces::RenderTarget(context->sk_context(), skgpu::Budgeted::kNo, image_info);
VERIFY(surface); VERIFY(surface);
context->unlock();
return adopt_ref(*new PaintingSurface(make<Impl>(context, size, surface, nullptr))); return adopt_ref(*new PaintingSurface(make<Impl>(context, size, surface, nullptr)));
} }
@ -58,6 +60,11 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_bitmap(Bitmap& bitmap)
#ifdef AK_OS_MACOS #ifdef AK_OS_MACOS
NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_iosurface(Core::IOSurfaceHandle const& iosurface_handle, RefPtr<SkiaBackendContext> context, Origin origin) NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_iosurface(Core::IOSurfaceHandle const& iosurface_handle, RefPtr<SkiaBackendContext> context, Origin origin)
{ {
context->lock();
ScopeGuard unlock_guard([&context] {
context->unlock();
});
auto metal_texture = context->metal_context().create_texture_from_iosurface(iosurface_handle); auto metal_texture = context->metal_context().create_texture_from_iosurface(iosurface_handle);
IntSize const size { metal_texture->width(), metal_texture->height() }; IntSize const size { metal_texture->width(), metal_texture->height() };
auto image_info = SkImageInfo::Make(size.width(), size.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB()); auto image_info = SkImageInfo::Make(size.width(), size.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
@ -85,7 +92,12 @@ PaintingSurface::PaintingSurface(NonnullOwnPtr<Impl>&& impl)
{ {
} }
PaintingSurface::~PaintingSurface() = default; PaintingSurface::~PaintingSurface()
{
lock_context();
m_impl->surface = nullptr;
unlock_context();
}
void PaintingSurface::read_into_bitmap(Bitmap& bitmap) void PaintingSurface::read_into_bitmap(Bitmap& bitmap)
{ {
@ -127,7 +139,9 @@ SkSurface& PaintingSurface::sk_surface() const
void PaintingSurface::notify_content_will_change() void PaintingSurface::notify_content_will_change()
{ {
lock_context();
m_impl->surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); m_impl->surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
unlock_context();
} }
template<> template<>