LibGfx+LibWeb: Reuse DisplayListPlayer and PaintingSurface when possible

Previously, we were reinstantiating the DisplayListPlayer and
PaintingSurface on every paint.
This commit is contained in:
Jelle Raaijmakers 2025-01-29 10:24:57 +01:00 committed by Alexander Kalenik
commit 342cb7addf
Notes: github-actions[bot] 2025-01-31 12:29:12 +00:00
12 changed files with 107 additions and 104 deletions

View file

@ -24,7 +24,6 @@ struct PaintingSurface::Impl {
IntSize size; IntSize size;
sk_sp<SkSurface> surface; sk_sp<SkSurface> surface;
RefPtr<Bitmap> bitmap; RefPtr<Bitmap> bitmap;
RefPtr<SkiaBackendContext> context;
}; };
NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type) NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type)
@ -37,12 +36,12 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBack
auto bitmap = Bitmap::create(color_type, alpha_type, size).value(); auto bitmap = Bitmap::create(color_type, alpha_type, size).value();
auto surface = SkSurfaces::WrapPixels(image_info, bitmap->begin(), bitmap->pitch()); auto surface = SkSurfaces::WrapPixels(image_info, bitmap->begin(), bitmap->pitch());
VERIFY(surface); VERIFY(surface);
return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, bitmap, context))); return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, bitmap)));
} }
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);
return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, nullptr, context))); return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, nullptr)));
} }
NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_bitmap(Bitmap& bitmap) NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_bitmap(Bitmap& bitmap)
@ -52,7 +51,7 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_bitmap(Bitmap& bitmap)
auto size = bitmap.size(); auto size = bitmap.size();
auto image_info = SkImageInfo::Make(bitmap.width(), bitmap.height(), color_type, alpha_type, SkColorSpace::MakeSRGB()); auto image_info = SkImageInfo::Make(bitmap.width(), bitmap.height(), color_type, alpha_type, SkColorSpace::MakeSRGB());
auto surface = SkSurfaces::WrapPixels(image_info, bitmap.begin(), bitmap.pitch()); auto surface = SkSurfaces::WrapPixels(image_info, bitmap.begin(), bitmap.pitch());
return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, bitmap, nullptr))); return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, bitmap)));
} }
#ifdef AK_OS_MACOS #ifdef AK_OS_MACOS
@ -76,7 +75,7 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_iosurface(Core::IOSurfaceHa
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
auto surface = SkSurfaces::WrapBackendRenderTarget(context->sk_context(), backend_render_target, sk_origin, kBGRA_8888_SkColorType, nullptr, nullptr); auto surface = SkSurfaces::WrapBackendRenderTarget(context->sk_context(), backend_render_target, sk_origin, kBGRA_8888_SkColorType, nullptr, nullptr);
return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, nullptr, context))); return adopt_ref(*new PaintingSurface(make<Impl>(size, surface, nullptr)));
} }
#endif #endif
@ -136,11 +135,10 @@ sk_sp<SkImage> PaintingSurface::sk_image_snapshot() const
return m_impl->surface->makeImageSnapshot(); return m_impl->surface->makeImageSnapshot();
} }
void PaintingSurface::flush() const void PaintingSurface::flush()
{ {
if (auto context = m_impl->context) { if (on_flush)
context->flush_and_submit(m_impl->surface.get()); on_flush(*this);
}
} }
} }

View file

@ -6,6 +6,7 @@
#pragma once #pragma once
#include <AK/Function.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/RefCounted.h> #include <AK/RefCounted.h>
#include <AK/RefPtr.h> #include <AK/RefPtr.h>
@ -29,6 +30,8 @@ public:
BottomLeft, BottomLeft,
}; };
Function<void(PaintingSurface&)> on_flush;
static NonnullRefPtr<PaintingSurface> create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type); static NonnullRefPtr<PaintingSurface> create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type);
static NonnullRefPtr<PaintingSurface> wrap_bitmap(Bitmap&); static NonnullRefPtr<PaintingSurface> wrap_bitmap(Bitmap&);
@ -50,7 +53,7 @@ public:
template<typename T> template<typename T>
T sk_image_snapshot() const; T sk_image_snapshot() const;
void flush() const; void flush();
~PaintingSurface(); ~PaintingSurface();

View file

@ -6,6 +6,7 @@
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/RefPtr.h> #include <AK/RefPtr.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/SkiaBackendContext.h> #include <LibGfx/SkiaBackendContext.h>
#include <core/SkSurface.h> #include <core/SkSurface.h>

View file

@ -170,7 +170,7 @@ public:
CSSPixelPoint viewport_scroll_offset() const { return m_viewport_scroll_offset; } CSSPixelPoint viewport_scroll_offset() const { return m_viewport_scroll_offset; }
CSSPixelRect viewport_rect() const { return { m_viewport_scroll_offset, m_size }; } CSSPixelRect viewport_rect() const { return { m_viewport_scroll_offset, m_size }; }
void set_viewport_size(CSSPixelSize); virtual void set_viewport_size(CSSPixelSize);
void perform_scroll_of_viewport(CSSPixelPoint position); void perform_scroll_of_viewport(CSSPixelPoint position);
void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes); void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes);

View file

@ -53,8 +53,12 @@ TraversableNavigable::TraversableNavigable(GC::Ref<Page> page)
, m_session_history_traversal_queue(vm().heap().allocate<SessionHistoryTraversalQueue>()) , m_session_history_traversal_queue(vm().heap().allocate<SessionHistoryTraversalQueue>())
{ {
auto display_list_player_type = page->client().display_list_player_type(); auto display_list_player_type = page->client().display_list_player_type();
if (display_list_player_type == DisplayListPlayerType::SkiaGPUIfAvailable) if (display_list_player_type == DisplayListPlayerType::SkiaGPUIfAvailable) {
m_skia_backend_context = get_skia_backend_context(); m_skia_backend_context = get_skia_backend_context();
m_skia_player = make<Painting::DisplayListPlayerSkia>(m_skia_backend_context);
} else {
m_skia_player = make<Painting::DisplayListPlayerSkia>();
}
} }
TraversableNavigable::~TraversableNavigable() = default; TraversableNavigable::~TraversableNavigable() = default;
@ -1384,6 +1388,45 @@ GC::Ptr<DOM::Node> TraversableNavigable::currently_focused_area()
return candidate; return candidate;
} }
void TraversableNavigable::set_viewport_size(CSSPixelSize size)
{
Navigable::set_viewport_size(size);
// Invalidate the surface cache if the traversable changed size.
m_bitmap_to_surface.clear();
}
NonnullRefPtr<Gfx::PaintingSurface> TraversableNavigable::painting_surface_for_backing_store(Painting::BackingStore& backing_store)
{
auto& bitmap = backing_store.bitmap();
auto cached_surface = m_bitmap_to_surface.find(&bitmap);
if (cached_surface != m_bitmap_to_surface.end())
return cached_surface->value;
RefPtr<Gfx::PaintingSurface> new_surface;
if (page().client().display_list_player_type() == DisplayListPlayerType::SkiaGPUIfAvailable && m_skia_backend_context) {
#ifdef USE_VULKAN
// Vulkan: Try to create an accelerated surface.
new_surface = Gfx::PaintingSurface::create_with_size(m_skia_backend_context, backing_store.size(), Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
new_surface->on_flush = [&bitmap = bitmap](auto& surface) { surface.read_into_bitmap(bitmap); };
#endif
#ifdef AK_OS_MACOS
// macOS: Wrap an IOSurface if available.
if (is<Painting::IOSurfaceBackingStore>(backing_store)) {
auto& iosurface_backing_store = static_cast<Painting::IOSurfaceBackingStore&>(backing_store);
new_surface = Gfx::PaintingSurface::wrap_iosurface(iosurface_backing_store.iosurface_handle(), *m_skia_backend_context);
}
#endif
}
// CPU and fallback: wrap the backing store bitmap directly.
if (!new_surface)
new_surface = Gfx::PaintingSurface::wrap_bitmap(bitmap);
m_bitmap_to_surface.set(&bitmap, *new_surface);
return *new_surface;
}
void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::BackingStore& target, PaintOptions paint_options) void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::BackingStore& target, PaintOptions paint_options)
{ {
auto document = active_document(); auto document = active_document();
@ -1391,10 +1434,9 @@ void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::
return; return;
for (auto& navigable : all_navigables()) { for (auto& navigable : all_navigables()) {
if (auto active_document = navigable->active_document(); active_document && active_document->paintable()) { if (auto active_document = navigable->active_document(); active_document && active_document->paintable())
active_document->paintable()->refresh_scroll_state(); active_document->paintable()->refresh_scroll_state();
} }
}
DOM::Document::PaintConfig paint_config; DOM::Document::PaintConfig paint_config;
paint_config.paint_overlay = paint_options.paint_overlay == PaintOptions::PaintOverlay::Yes; paint_config.paint_overlay = paint_options.paint_overlay == PaintOptions::PaintOverlay::Yes;
@ -1402,43 +1444,12 @@ void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::
paint_config.has_focus = paint_options.has_focus; paint_config.has_focus = paint_options.has_focus;
paint_config.canvas_fill_rect = Gfx::IntRect { {}, content_rect.size() }; paint_config.canvas_fill_rect = Gfx::IntRect { {}, content_rect.size() };
auto display_list = document->record_display_list(paint_config); auto display_list = document->record_display_list(paint_config);
if (!display_list) { if (!display_list)
return; return;
}
switch (page().client().display_list_player_type()) { auto painting_surface = painting_surface_for_backing_store(target);
case DisplayListPlayerType::SkiaGPUIfAvailable: { m_skia_player->set_surface(painting_surface);
#ifdef USE_VULKAN m_skia_player->execute(*display_list);
if (m_skia_backend_context) {
Painting::DisplayListPlayerSkia player(*m_skia_backend_context, target.bitmap());
player.execute(*display_list);
return;
}
#endif
#ifdef AK_OS_MACOS
if (m_skia_backend_context && is<Painting::IOSurfaceBackingStore>(target)) {
auto& iosurface_backing_store = static_cast<Painting::IOSurfaceBackingStore&>(target);
auto painting_surface = Gfx::PaintingSurface::wrap_iosurface(iosurface_backing_store.iosurface_handle(), *m_skia_backend_context);
Painting::DisplayListPlayerSkia player(*m_skia_backend_context, painting_surface);
player.execute(*display_list);
return;
}
#endif
// Fallback to CPU backend if GPU is not available
Painting::DisplayListPlayerSkia player(target.bitmap());
player.execute(*display_list);
break;
}
case DisplayListPlayerType::SkiaCPU: {
Painting::DisplayListPlayerSkia player(target.bitmap());
player.execute(*display_list);
break;
}
default:
VERIFY_NOT_REACHED();
}
} }
} }

View file

@ -14,15 +14,16 @@
#include <LibWeb/Page/Page.h> #include <LibWeb/Page/Page.h>
#include <LibWeb/Painting/DisplayListPlayerSkia.h> #include <LibWeb/Painting/DisplayListPlayerSkia.h>
#include <LibWeb/StorageAPI/StorageShed.h> #include <LibWeb/StorageAPI/StorageShed.h>
#include <WebContent/BackingStoreManager.h>
#ifdef USE_VULKAN
# include <LibGfx/VulkanContext.h>
#endif
#ifdef AK_OS_MACOS #ifdef AK_OS_MACOS
# include <LibGfx/MetalContext.h> # include <LibGfx/MetalContext.h>
#endif #endif
#ifdef USE_VULKAN
# include <LibGfx/VulkanContext.h>
#endif
namespace Web::HTML { namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/document-sequences.html#traversable-navigable // https://html.spec.whatwg.org/multipage/document-sequences.html#traversable-navigable
@ -110,6 +111,8 @@ public:
StorageAPI::StorageShed& storage_shed() { return m_storage_shed; } StorageAPI::StorageShed& storage_shed() { return m_storage_shed; }
StorageAPI::StorageShed const& storage_shed() const { return m_storage_shed; } StorageAPI::StorageShed const& storage_shed() const { return m_storage_shed; }
void set_viewport_size(CSSPixelSize) override;
private: private:
TraversableNavigable(GC::Ref<Page>); TraversableNavigable(GC::Ref<Page>);
@ -131,6 +134,8 @@ private:
[[nodiscard]] bool can_go_forward() const; [[nodiscard]] bool can_go_forward() const;
NonnullRefPtr<Gfx::PaintingSurface> painting_surface_for_backing_store(Painting::BackingStore&);
// https://html.spec.whatwg.org/multipage/document-sequences.html#tn-current-session-history-step // https://html.spec.whatwg.org/multipage/document-sequences.html#tn-current-session-history-step
int m_current_session_history_step { 0 }; int m_current_session_history_step { 0 };
@ -154,6 +159,8 @@ private:
String m_window_handle; String m_window_handle;
RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context; RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
OwnPtr<Painting::DisplayListPlayerSkia> m_skia_player;
HashMap<Gfx::Bitmap*, NonnullRefPtr<Gfx::PaintingSurface>> m_bitmap_to_surface;
}; };
struct BrowsingContextAndDocument { struct BrowsingContextAndDocument {

View file

@ -41,6 +41,8 @@ void DisplayListPlayer::execute(DisplayList& display_list)
auto const& scroll_state = display_list.scroll_state(); auto const& scroll_state = display_list.scroll_state();
auto device_pixels_per_css_pixel = display_list.device_pixels_per_css_pixel(); auto device_pixels_per_css_pixel = display_list.device_pixels_per_css_pixel();
VERIFY(m_surface);
size_t next_command_index = 0; size_t next_command_index = 0;
while (next_command_index < commands.size()) { while (next_command_index < commands.size()) {
auto scroll_frame_id = commands[next_command_index].scroll_frame_id; auto scroll_frame_id = commands[next_command_index].scroll_frame_id;
@ -128,6 +130,8 @@ void DisplayListPlayer::execute(DisplayList& display_list)
else VERIFY_NOT_REACHED(); else VERIFY_NOT_REACHED();
// clang-format on // clang-format on
} }
flush();
} }
} }

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com> * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -25,9 +26,14 @@ class DisplayListPlayer {
public: public:
virtual ~DisplayListPlayer() = default; virtual ~DisplayListPlayer() = default;
void execute(DisplayList& display_list); void execute(DisplayList&);
void set_surface(NonnullRefPtr<Gfx::PaintingSurface> surface) { m_surface = surface; }
protected:
Gfx::PaintingSurface& surface() const { return *m_surface; }
private: private:
virtual void flush() = 0;
virtual void draw_glyph_run(DrawGlyphRun const&) = 0; virtual void draw_glyph_run(DrawGlyphRun const&) = 0;
virtual void fill_rect(FillRect const&) = 0; virtual void fill_rect(FillRect const&) = 0;
virtual void draw_painting_surface(DrawPaintingSurface const&) = 0; virtual void draw_painting_surface(DrawPaintingSurface const&) = 0;
@ -65,6 +71,8 @@ private:
virtual void apply_transform(ApplyTransform const&) = 0; virtual void apply_transform(ApplyTransform const&) = 0;
virtual void apply_mask_bitmap(ApplyMaskBitmap const&) = 0; virtual void apply_mask_bitmap(ApplyMaskBitmap const&) = 0;
virtual bool would_be_fully_clipped_by_painter(Gfx::IntRect) const = 0; virtual bool would_be_fully_clipped_by_painter(Gfx::IntRect) const = 0;
RefPtr<Gfx::PaintingSurface> m_surface;
}; };
class DisplayList : public RefCounted<DisplayList> { class DisplayList : public RefCounted<DisplayList> {

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com> * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -29,36 +30,13 @@
namespace Web::Painting { namespace Web::Painting {
#ifdef USE_VULKAN DisplayListPlayerSkia::DisplayListPlayerSkia(RefPtr<Gfx::SkiaBackendContext> context)
DisplayListPlayerSkia::DisplayListPlayerSkia(Gfx::SkiaBackendContext& context, Gfx::Bitmap& bitmap)
: m_context(context) : m_context(context)
{ {
m_surface = Gfx::PaintingSurface::create_with_size(m_context, bitmap.size(), Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
m_flush_context = [&bitmap, surface = m_surface] mutable {
surface->read_into_bitmap(bitmap);
};
}
#endif
#ifdef AK_OS_MACOS
DisplayListPlayerSkia::DisplayListPlayerSkia(Gfx::SkiaBackendContext& context, NonnullRefPtr<Gfx::PaintingSurface> surface)
: m_context(context)
, m_surface(move(surface))
{
}
#endif
DisplayListPlayerSkia::DisplayListPlayerSkia(Gfx::Bitmap& bitmap)
{
m_surface = Gfx::PaintingSurface::wrap_bitmap(bitmap);
} }
DisplayListPlayerSkia::~DisplayListPlayerSkia() DisplayListPlayerSkia::DisplayListPlayerSkia()
{ {
m_surface->flush();
if (m_flush_context) {
m_flush_context();
}
} }
static SkRRect to_skia_rrect(auto const& rect, CornerRadii const& corner_radii) static SkRRect to_skia_rrect(auto const& rect, CornerRadii const& corner_radii)
@ -88,9 +66,11 @@ static SkMatrix to_skia_matrix(Gfx::AffineTransform const& affine_transform)
return matrix; return matrix;
} }
Gfx::PaintingSurface& DisplayListPlayerSkia::surface() const void DisplayListPlayerSkia::flush()
{ {
return *m_surface; if (m_context)
m_context->flush_and_submit(&surface().sk_surface());
surface().flush();
} }
void DisplayListPlayerSkia::draw_glyph_run(DrawGlyphRun const& command) void DisplayListPlayerSkia::draw_glyph_run(DrawGlyphRun const& command)
@ -850,10 +830,10 @@ 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); auto mask_surface = Gfx::PaintingSurface::create_with_size(m_context, rect.size(), Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
auto previous_surface = move(m_surface); NonnullRefPtr old_surface = surface();
m_surface = mask_surface; set_surface(mask_surface);
execute(*command.display_list); execute(*command.display_list);
m_surface = move(previous_surface); set_surface(old_surface);
SkMatrix mask_matrix; SkMatrix mask_matrix;
mask_matrix.setTranslate(rect.x(), rect.y()); mask_matrix.setTranslate(rect.x(), rect.y());

View file

@ -14,21 +14,13 @@ class GrDirectContext;
namespace Web::Painting { namespace Web::Painting {
class DisplayListPlayerSkia : public DisplayListPlayer { class DisplayListPlayerSkia final : public DisplayListPlayer {
public: public:
DisplayListPlayerSkia(Gfx::Bitmap&); DisplayListPlayerSkia(RefPtr<Gfx::SkiaBackendContext>);
DisplayListPlayerSkia();
#ifdef USE_VULKAN
DisplayListPlayerSkia(Gfx::SkiaBackendContext&, Gfx::Bitmap&);
#endif
#ifdef AK_OS_MACOS
DisplayListPlayerSkia(Gfx::SkiaBackendContext&, NonnullRefPtr<Gfx::PaintingSurface>);
#endif
virtual ~DisplayListPlayerSkia() override;
private: private:
void flush() override;
void draw_glyph_run(DrawGlyphRun const&) override; void draw_glyph_run(DrawGlyphRun const&) override;
void fill_rect(FillRect const&) override; void fill_rect(FillRect const&) override;
void draw_painting_surface(DrawPaintingSurface const&) override; void draw_painting_surface(DrawPaintingSurface const&) override;
@ -68,12 +60,7 @@ private:
bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override; bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override;
Gfx::PaintingSurface& surface() const; RefPtr<Gfx::SkiaBackendContext> m_context;
RefPtr<Gfx::SkiaBackendContext> m_context {};
RefPtr<Gfx::PaintingSurface> m_surface {};
Function<void()> m_flush_context;
}; };
} }

View file

@ -90,7 +90,9 @@ RefPtr<Gfx::ImmutableBitmap> SVGMaskable::calculate_mask_of_svg(PaintContext& co
paint_context.set_svg_transform(graphics_element.get_transform()); paint_context.set_svg_transform(graphics_element.get_transform());
paint_context.set_draw_svg_geometry_for_clip_path(is<SVGClipPaintable>(paintable)); paint_context.set_draw_svg_geometry_for_clip_path(is<SVGClipPaintable>(paintable));
StackingContext::paint_svg(paint_context, paintable, PaintPhase::Foreground); StackingContext::paint_svg(paint_context, paintable, PaintPhase::Foreground);
DisplayListPlayerSkia display_list_player { *mask_bitmap }; auto painting_surface = Gfx::PaintingSurface::wrap_bitmap(*mask_bitmap);
DisplayListPlayerSkia display_list_player;
display_list_player.set_surface(painting_surface);
display_list_player.execute(display_list); display_list_player.execute(display_list);
return mask_bitmap; return mask_bitmap;
}; };

View file

@ -103,7 +103,9 @@ RefPtr<Gfx::Bitmap> SVGDecodedImageData::render(Gfx::IntSize size) const
switch (painting_command_executor_type) { switch (painting_command_executor_type) {
case DisplayListPlayerType::SkiaGPUIfAvailable: case DisplayListPlayerType::SkiaGPUIfAvailable:
case DisplayListPlayerType::SkiaCPU: { case DisplayListPlayerType::SkiaCPU: {
Painting::DisplayListPlayerSkia display_list_player { *bitmap }; auto painting_surface = Gfx::PaintingSurface::wrap_bitmap(*bitmap);
Painting::DisplayListPlayerSkia display_list_player;
display_list_player.set_surface(painting_surface);
display_list_player.execute(*display_list); display_list_player.execute(*display_list);
break; break;
} }