Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
gmta committed Jan 29, 2025
1 parent 80c75c8 commit 247271e
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 101 deletions.
14 changes: 6 additions & 8 deletions Libraries/LibGfx/PaintingSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ struct PaintingSurface::Impl {
IntSize size;
sk_sp<SkSurface> surface;
RefPtr<Bitmap> bitmap;
RefPtr<SkiaBackendContext> context;
};

NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type)
Expand All @@ -37,12 +36,12 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBack
auto bitmap = Bitmap::create(color_type, alpha_type, size).value();
auto surface = SkSurfaces::WrapPixels(image_info, bitmap->begin(), bitmap->pitch());
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);
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)
Expand All @@ -52,7 +51,7 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_bitmap(Bitmap& bitmap)
auto size = bitmap.size();
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());
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
Expand All @@ -76,7 +75,7 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::wrap_iosurface(Core::IOSurfaceHa
VERIFY_NOT_REACHED();
}
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

Expand Down Expand Up @@ -138,9 +137,8 @@ sk_sp<SkImage> PaintingSurface::sk_image_snapshot() const

void PaintingSurface::flush() const
{
if (auto context = m_impl->context) {
context->flush_and_submit(m_impl->surface.get());
}
if (on_flush)
on_flush();
}

}
3 changes: 3 additions & 0 deletions Libraries/LibGfx/PaintingSurface.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include <AK/Function.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
Expand All @@ -29,6 +30,8 @@ class PaintingSurface : public RefCounted<PaintingSurface> {
BottomLeft,
};

Function<void()> on_flush;

static NonnullRefPtr<PaintingSurface> create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type);
static NonnullRefPtr<PaintingSurface> wrap_bitmap(Bitmap&);

Expand Down
1 change: 1 addition & 0 deletions Libraries/LibGfx/SkiaBackendContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <AK/NonnullOwnPtr.h>
#include <AK/RefPtr.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/SkiaBackendContext.h>

#include <core/SkSurface.h>
Expand Down
86 changes: 48 additions & 38 deletions Libraries/LibWeb/HTML/TraversableNavigable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ TraversableNavigable::TraversableNavigable(GC::Ref<Page> page)
, m_session_history_traversal_queue(vm().heap().allocate<SessionHistoryTraversalQueue>())
{
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_player = make<Painting::DisplayListPlayerSkia>(m_skia_backend_context);
} else {
m_skia_player = make<Painting::DisplayListPlayerSkia>();
}
}

TraversableNavigable::~TraversableNavigable() = default;
Expand Down Expand Up @@ -1384,16 +1388,53 @@ GC::Ptr<DOM::Node> TraversableNavigable::currently_focused_area()
return candidate;
}

NonnullRefPtr<Gfx::PaintingSurface> TraversableNavigable::painting_surface_for_backing_store(Painting::BackingStore& backing_store)
{
// Invalidate the surface cache if any provided backing store has a different size. This is a simple way to handle
// resizes of the navigable and prevents the cache from growing unbounded.
if (m_last_paint_size != backing_store.size()) {
m_backing_store_to_surface.clear();
m_last_paint_size = backing_store.size();
}

// auto cached_surface = m_backing_store_to_surface.find(&backing_store);
// if (cached_surface != m_backing_store_to_surface.end())
// return cached_surface->value;

RefPtr<Gfx::PaintingSurface> new_surface;
if (page().client().display_list_player_type() == DisplayListPlayerType::SkiaGPUIfAvailable) {
#ifdef USE_VULKAN
// Vulkan: Try to create an accelerated surface.
if (m_skia_backend_context) {
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 = backing_store.bitmap(), new_surface] { new_surface->read_into_bitmap(bitmap); };
}
#elif AK_OS_MACOS
// macOS: Wrap an IOSurface if available.
if (m_skia_backend_context && is<Painting::IOSurfaceBackingStore>(target)) {
auto& iosurface_backing_store = static_cast<Painting::IOSurfaceBackingStore&>(target);
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(backing_store.bitmap());

m_backing_store_to_surface.set(&backing_store, *new_surface);
return *new_surface;
}

void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::BackingStore& target, PaintOptions paint_options)
{
auto document = active_document();
if (!document)
return;

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();
}
}

DOM::Document::PaintConfig paint_config;
Expand All @@ -1402,43 +1443,12 @@ void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::
paint_config.has_focus = paint_options.has_focus;
paint_config.canvas_fill_rect = Gfx::IntRect { {}, content_rect.size() };
auto display_list = document->record_display_list(paint_config);
if (!display_list) {
if (!display_list)
return;
}

switch (page().client().display_list_player_type()) {
case DisplayListPlayerType::SkiaGPUIfAvailable: {
#ifdef USE_VULKAN
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();
}
auto painting_surface = painting_surface_for_backing_store(target);
m_skia_player->set_surface(painting_surface);
m_skia_player->execute(*display_list);
}

}
14 changes: 10 additions & 4 deletions Libraries/LibWeb/HTML/TraversableNavigable.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@
#include <LibWeb/Page/Page.h>
#include <LibWeb/Painting/DisplayListPlayerSkia.h>
#include <LibWeb/StorageAPI/StorageShed.h>

#ifdef USE_VULKAN
# include <LibGfx/VulkanContext.h>
#endif
#include <WebContent/BackingStoreManager.h>

#ifdef AK_OS_MACOS
# include <LibGfx/MetalContext.h>
#endif

#ifdef USE_VULKAN
# include <LibGfx/VulkanContext.h>
#endif

namespace Web::HTML {

// https://html.spec.whatwg.org/multipage/document-sequences.html#traversable-navigable
Expand Down Expand Up @@ -131,6 +132,8 @@ class TraversableNavigable final : public Navigable {

[[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
int m_current_session_history_step { 0 };

Expand All @@ -154,6 +157,9 @@ class TraversableNavigable final : public Navigable {
String m_window_handle;

RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
OwnPtr<Painting::DisplayListPlayerSkia> m_skia_player;
HashMap<Painting::BackingStore*, NonnullRefPtr<Gfx::PaintingSurface>> m_backing_store_to_surface;
Gfx::IntSize m_last_paint_size;
};

struct BrowsingContextAndDocument {
Expand Down
4 changes: 4 additions & 0 deletions Libraries/LibWeb/Painting/DisplayList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ void DisplayListPlayer::execute(DisplayList& display_list)
auto const& scroll_state = display_list.scroll_state();
auto device_pixels_per_css_pixel = display_list.device_pixels_per_css_pixel();

VERIFY(m_surface);

size_t next_command_index = 0;
while (next_command_index < commands.size()) {
auto scroll_frame_id = commands[next_command_index].scroll_frame_id;
Expand Down Expand Up @@ -128,6 +130,8 @@ void DisplayListPlayer::execute(DisplayList& display_list)
else VERIFY_NOT_REACHED();
// clang-format on
}

flush();
}

}
10 changes: 9 additions & 1 deletion Libraries/LibWeb/Painting/DisplayList.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
Expand All @@ -25,9 +26,14 @@ class DisplayListPlayer {
public:
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:
virtual void flush() = 0;
virtual void draw_glyph_run(DrawGlyphRun const&) = 0;
virtual void fill_rect(FillRect const&) = 0;
virtual void draw_painting_surface(DrawPaintingSurface const&) = 0;
Expand Down Expand Up @@ -65,6 +71,8 @@ class DisplayListPlayer {
virtual void apply_transform(ApplyTransform const&) = 0;
virtual void apply_mask_bitmap(ApplyMaskBitmap const&) = 0;
virtual bool would_be_fully_clipped_by_painter(Gfx::IntRect) const = 0;

RefPtr<Gfx::PaintingSurface> m_surface;
};

class DisplayList : public RefCounted<DisplayList> {
Expand Down
40 changes: 10 additions & 30 deletions Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
Expand Down Expand Up @@ -32,36 +33,13 @@

namespace Web::Painting {

#ifdef USE_VULKAN
DisplayListPlayerSkia::DisplayListPlayerSkia(Gfx::SkiaBackendContext& context, Gfx::Bitmap& bitmap)
DisplayListPlayerSkia::DisplayListPlayerSkia(RefPtr<Gfx::SkiaBackendContext> 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)
DisplayListPlayerSkia::DisplayListPlayerSkia()
{
m_surface = Gfx::PaintingSurface::wrap_bitmap(bitmap);
}

DisplayListPlayerSkia::~DisplayListPlayerSkia()
{
m_surface->flush();
if (m_flush_context) {
m_flush_context();
}
}

static SkRRect to_skia_rrect(auto const& rect, CornerRadii const& corner_radii)
Expand Down Expand Up @@ -91,9 +69,11 @@ static SkMatrix to_skia_matrix(Gfx::AffineTransform const& affine_transform)
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)
Expand Down Expand Up @@ -853,10 +833,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 previous_surface = move(m_surface);
m_surface = mask_surface;
NonnullRefPtr old_surface = surface();
set_surface(mask_surface);
execute(*command.display_list);
m_surface = move(previous_surface);
set_surface(old_surface);

SkMatrix mask_matrix;
mask_matrix.setTranslate(rect.x(), rect.y());
Expand Down
23 changes: 5 additions & 18 deletions Libraries/LibWeb/Painting/DisplayListPlayerSkia.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,13 @@ class GrDirectContext;

namespace Web::Painting {

class DisplayListPlayerSkia : public DisplayListPlayer {
class DisplayListPlayerSkia final : public DisplayListPlayer {
public:
DisplayListPlayerSkia(Gfx::Bitmap&);

#ifdef USE_VULKAN
DisplayListPlayerSkia(Gfx::SkiaBackendContext&, Gfx::Bitmap&);
#endif

#ifdef AK_OS_MACOS
DisplayListPlayerSkia(Gfx::SkiaBackendContext&, NonnullRefPtr<Gfx::PaintingSurface>);
#endif

virtual ~DisplayListPlayerSkia() override;
DisplayListPlayerSkia(RefPtr<Gfx::SkiaBackendContext>);
DisplayListPlayerSkia();

private:
void flush() override;
void draw_glyph_run(DrawGlyphRun const&) override;
void fill_rect(FillRect const&) override;
void draw_painting_surface(DrawPaintingSurface const&) override;
Expand Down Expand Up @@ -68,12 +60,7 @@ class DisplayListPlayerSkia : public DisplayListPlayer {

bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override;

Gfx::PaintingSurface& surface() const;

RefPtr<Gfx::SkiaBackendContext> m_context {};
RefPtr<Gfx::PaintingSurface> m_surface {};

Function<void()> m_flush_context;
RefPtr<Gfx::SkiaBackendContext> m_context;
};

}
Loading

0 comments on commit 247271e

Please sign in to comment.