mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
Everywhere: Pass backing store into Navigable::paint()
...instead of Gfx::Bitmap, which makes it possible to access and directly paint into IOSurface on macOS.
This commit is contained in:
parent
c4e935aa97
commit
c62cc915df
Notes:
sideshowbarker
2024-07-17 02:56:25 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/c62cc915df Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/294
18 changed files with 145 additions and 30 deletions
|
@ -114,6 +114,11 @@ size_t IOSurfaceHandle::bytes_per_element() const
|
|||
return IOSurfaceGetBytesPerElement(m_ref_wrapper->ref);
|
||||
}
|
||||
|
||||
size_t IOSurfaceHandle::bytes_per_row() const
|
||||
{
|
||||
return IOSurfaceGetBytesPerRow(m_ref_wrapper->ref);
|
||||
}
|
||||
|
||||
void* IOSurfaceHandle::data() const
|
||||
{
|
||||
return IOSurfaceGetBaseAddress(m_ref_wrapper->ref);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <LibCore/MachPort.h>
|
||||
|
||||
namespace Core {
|
||||
|
@ -27,6 +28,7 @@ public:
|
|||
size_t width() const;
|
||||
size_t height() const;
|
||||
size_t bytes_per_element() const;
|
||||
size_t bytes_per_row() const;
|
||||
void* data() const;
|
||||
|
||||
~IOSurfaceHandle();
|
||||
|
|
|
@ -533,6 +533,7 @@ set(SOURCES
|
|||
Page/Page.cpp
|
||||
Painting/AudioPaintable.cpp
|
||||
Painting/BackgroundPainting.cpp
|
||||
Painting/BackingStore.cpp
|
||||
Painting/BorderRadiiData.cpp
|
||||
Painting/BorderPainting.cpp
|
||||
Painting/BorderRadiusCornerClipper.cpp
|
||||
|
|
|
@ -24,6 +24,7 @@ class XMLDocumentBuilder;
|
|||
}
|
||||
|
||||
namespace Web::Painting {
|
||||
class BackingStore;
|
||||
class DisplayListRecorder;
|
||||
class SVGGradientPaintStyle;
|
||||
using PaintStyle = RefPtr<SVGGradientPaintStyle>;
|
||||
|
|
|
@ -1174,8 +1174,10 @@ JS::GCPtr<DOM::Node> TraversableNavigable::currently_focused_area()
|
|||
return candidate;
|
||||
}
|
||||
|
||||
void TraversableNavigable::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& target, Web::PaintOptions paint_options)
|
||||
void TraversableNavigable::paint(Web::DevicePixelRect const& content_rect, Painting::BackingStore& backing_store, Web::PaintOptions paint_options)
|
||||
{
|
||||
auto& target = backing_store.bitmap();
|
||||
|
||||
Painting::DisplayList display_list;
|
||||
Painting::DisplayListRecorder display_list_recorder(display_list);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <LibWeb/HTML/SessionHistoryTraversalQueue.h>
|
||||
#include <LibWeb/HTML/VisibilityState.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
#include <WebContent/BackingStoreManager.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
|
@ -85,7 +86,7 @@ public:
|
|||
|
||||
[[nodiscard]] JS::GCPtr<DOM::Node> currently_focused_area();
|
||||
|
||||
void paint(Web::DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions);
|
||||
void paint(Web::DevicePixelRect const&, Painting::BackingStore&, Web::PaintOptions);
|
||||
|
||||
private:
|
||||
TraversableNavigable(JS::NonnullGCPtr<Page>);
|
||||
|
|
|
@ -304,7 +304,7 @@ public:
|
|||
virtual CSS::PreferredContrast preferred_contrast() const = 0;
|
||||
virtual CSS::PreferredMotion preferred_motion() const = 0;
|
||||
virtual void paint_next_frame() = 0;
|
||||
virtual void paint(DevicePixelRect const&, Gfx::Bitmap&, PaintOptions = {}) = 0;
|
||||
virtual void paint(DevicePixelRect const&, Painting::BackingStore&, PaintOptions = {}) = 0;
|
||||
virtual void page_did_change_title(ByteString const&) { }
|
||||
virtual void page_did_change_url(URL::URL const&) { }
|
||||
virtual void page_did_request_navigate_back() { }
|
||||
|
|
32
Userland/Libraries/LibWeb/Painting/BackingStore.cpp
Normal file
32
Userland/Libraries/LibWeb/Painting/BackingStore.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibWeb/Painting/BackingStore.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
BitmapBackingStore::BitmapBackingStore(RefPtr<Gfx::Bitmap> bitmap)
|
||||
: m_bitmap(move(bitmap))
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
IOSurfaceBackingStore::IOSurfaceBackingStore(Core::IOSurfaceHandle&& iosurface_handle)
|
||||
: m_iosurface_handle(move(iosurface_handle))
|
||||
{
|
||||
auto bytes_per_row = m_iosurface_handle.bytes_per_row();
|
||||
auto bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, size(), bytes_per_row, m_iosurface_handle.data());
|
||||
m_bitmap_wrapper = bitmap.release_value();
|
||||
}
|
||||
|
||||
Gfx::IntSize IOSurfaceBackingStore::size() const
|
||||
{
|
||||
return { m_iosurface_handle.width(), m_iosurface_handle.height() };
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
57
Userland/Libraries/LibWeb/Painting/BackingStore.h
Normal file
57
Userland/Libraries/LibWeb/Painting/BackingStore.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <LibGfx/Size.h>
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <LibCore/IOSurface.h>
|
||||
#endif
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
class BackingStore {
|
||||
AK_MAKE_NONCOPYABLE(BackingStore);
|
||||
|
||||
public:
|
||||
virtual Gfx::IntSize size() const = 0;
|
||||
virtual Gfx::Bitmap& bitmap() const = 0;
|
||||
|
||||
BackingStore() {};
|
||||
virtual ~BackingStore() {};
|
||||
};
|
||||
|
||||
class BitmapBackingStore final : public BackingStore {
|
||||
public:
|
||||
BitmapBackingStore(RefPtr<Gfx::Bitmap>);
|
||||
|
||||
Gfx::IntSize size() const override { return m_bitmap->size(); }
|
||||
Gfx::Bitmap& bitmap() const override { return *m_bitmap; }
|
||||
|
||||
private:
|
||||
RefPtr<Gfx::Bitmap> m_bitmap;
|
||||
};
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
class IOSurfaceBackingStore final : public BackingStore {
|
||||
public:
|
||||
IOSurfaceBackingStore(Core::IOSurfaceHandle&&);
|
||||
|
||||
Gfx::IntSize size() const override;
|
||||
|
||||
Core::IOSurfaceHandle& iosurface_handle() { return m_iosurface_handle; }
|
||||
Gfx::Bitmap& bitmap() const override { return *m_bitmap_wrapper; }
|
||||
|
||||
private:
|
||||
Core::IOSurfaceHandle m_iosurface_handle;
|
||||
RefPtr<Gfx::Bitmap> m_bitmap_wrapper;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
|
@ -76,7 +76,7 @@ public:
|
|||
virtual CSS::PreferredMotion preferred_motion() const override { return m_host_page->client().preferred_motion(); }
|
||||
virtual void request_file(FileRequest) override { }
|
||||
virtual void paint_next_frame() override { }
|
||||
virtual void paint(DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions = {}) override { }
|
||||
virtual void paint(DevicePixelRect const&, Painting::BackingStore&, Web::PaintOptions = {}) override { }
|
||||
virtual void schedule_repaint() override { }
|
||||
virtual bool is_ready_to_paint() const override { return true; }
|
||||
|
||||
|
|
|
@ -418,8 +418,10 @@ void ViewImplementation::did_allocate_iosurface_backing_stores(i32 front_id, Cor
|
|||
auto front_size = Gfx::IntSize { front_iosurface.width(), front_iosurface.height() };
|
||||
auto back_size = Gfx::IntSize { back_iosurface.width(), back_iosurface.height() };
|
||||
|
||||
auto front_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, front_size, front_size.width() * front_iosurface.bytes_per_element(), front_iosurface.data(), [handle = move(front_iosurface)] {});
|
||||
auto back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, back_size, back_size.width() * back_iosurface.bytes_per_element(), back_iosurface.data(), [handle = move(back_iosurface)] {});
|
||||
auto bytes_per_row = front_iosurface.bytes_per_row();
|
||||
|
||||
auto front_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, front_size, bytes_per_row, front_iosurface.data(), [handle = move(front_iosurface)] {});
|
||||
auto back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, back_size, bytes_per_row, back_iosurface.data(), [handle = move(back_iosurface)] {});
|
||||
|
||||
m_client_state.front_bitmap.bitmap = front_bitmap.release_value_but_fixme_should_propagate_errors();
|
||||
m_client_state.front_bitmap.id = front_id;
|
||||
|
|
|
@ -51,9 +51,6 @@ void BackingStoreManager::reallocate_backing_stores(Gfx::IntSize size)
|
|||
m_front_bitmap_id = m_next_bitmap_id++;
|
||||
m_back_bitmap_id = m_next_bitmap_id++;
|
||||
|
||||
m_front_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, size, size.width() * front_iosurface.bytes_per_element(), front_iosurface.data(), [handle = move(front_iosurface)] {}).release_value();
|
||||
m_back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, size, size.width() * back_iosurface.bytes_per_element(), back_iosurface.data(), [handle = move(back_iosurface)] {}).release_value();
|
||||
|
||||
Core::Platform::BackingStoreMetadata metadata;
|
||||
metadata.page_id = m_page_client.m_id;
|
||||
metadata.front_backing_store_id = m_front_bitmap_id;
|
||||
|
@ -86,6 +83,9 @@ void BackingStoreManager::reallocate_backing_stores(Gfx::IntSize size)
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
m_front_store = make<Web::Painting::IOSurfaceBackingStore>(move(front_iosurface));
|
||||
m_back_store = make<Web::Painting::IOSurfaceBackingStore>(move(back_iosurface));
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -93,10 +93,13 @@ void BackingStoreManager::reallocate_backing_stores(Gfx::IntSize size)
|
|||
m_front_bitmap_id = m_next_bitmap_id++;
|
||||
m_back_bitmap_id = m_next_bitmap_id++;
|
||||
|
||||
m_front_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, size).release_value();
|
||||
m_back_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, size).release_value();
|
||||
auto front_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, size).release_value();
|
||||
auto back_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, size).release_value();
|
||||
|
||||
m_page_client.page_did_allocate_backing_stores(m_front_bitmap_id, m_front_bitmap->to_shareable_bitmap(), m_back_bitmap_id, m_back_bitmap->to_shareable_bitmap());
|
||||
m_front_store = make<Web::Painting::BitmapBackingStore>(front_bitmap);
|
||||
m_back_store = make<Web::Painting::BitmapBackingStore>(back_bitmap);
|
||||
|
||||
m_page_client.page_did_allocate_backing_stores(m_front_bitmap_id, front_bitmap->to_shareable_bitmap(), m_back_bitmap_id, back_bitmap->to_shareable_bitmap());
|
||||
}
|
||||
|
||||
void BackingStoreManager::resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress)
|
||||
|
@ -114,18 +117,18 @@ void BackingStoreManager::resize_backing_stores_if_needed(WindowResizingInProgre
|
|||
} else {
|
||||
// If we're not in the middle of a resize, we can shrink the backing store size to match the viewport size.
|
||||
minimum_needed_size = viewport_size;
|
||||
m_front_bitmap.clear();
|
||||
m_back_bitmap.clear();
|
||||
m_front_store.clear();
|
||||
m_back_store.clear();
|
||||
}
|
||||
|
||||
if (!m_front_bitmap || !m_back_bitmap || !m_front_bitmap->size().contains(minimum_needed_size.to_type<int>())) {
|
||||
if (!m_front_store || !m_back_store || !m_front_store->size().contains(minimum_needed_size.to_type<int>())) {
|
||||
reallocate_backing_stores(minimum_needed_size.to_type<int>());
|
||||
}
|
||||
}
|
||||
|
||||
void BackingStoreManager::swap_back_and_front()
|
||||
{
|
||||
swap(m_front_bitmap, m_back_bitmap);
|
||||
swap(m_front_store, m_back_store);
|
||||
swap(m_front_bitmap_id, m_back_bitmap_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <LibCore/Forward.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
#include <LibWeb/Painting/BackingStore.h>
|
||||
#include <WebContent/Forward.h>
|
||||
|
||||
namespace WebContent {
|
||||
|
@ -26,7 +27,7 @@ public:
|
|||
void reallocate_backing_stores(Gfx::IntSize);
|
||||
void restart_resize_timer();
|
||||
|
||||
RefPtr<Gfx::Bitmap> back_bitmap() { return m_back_bitmap; }
|
||||
Web::Painting::BackingStore* back_store() { return m_back_store.ptr(); }
|
||||
i32 front_id() const { return m_front_bitmap_id; }
|
||||
|
||||
void swap_back_and_front();
|
||||
|
@ -38,8 +39,8 @@ private:
|
|||
|
||||
i32 m_front_bitmap_id { -1 };
|
||||
i32 m_back_bitmap_id { -1 };
|
||||
RefPtr<Gfx::Bitmap> m_front_bitmap;
|
||||
RefPtr<Gfx::Bitmap> m_back_bitmap;
|
||||
OwnPtr<Web::Painting::BackingStore> m_front_store;
|
||||
OwnPtr<Web::Painting::BackingStore> m_back_store;
|
||||
int m_next_bitmap_id { 0 };
|
||||
|
||||
RefPtr<Core::Timer> m_backing_store_shrink_timer;
|
||||
|
|
|
@ -199,22 +199,24 @@ void PageClient::paint_next_frame()
|
|||
}
|
||||
auto rect = page().enclosing_device_rect(dom_node->paintable_box()->absolute_border_box_rect());
|
||||
auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, rect.size().to_type<int>()).release_value_but_fixme_should_propagate_errors();
|
||||
paint(rect, *bitmap, { .paint_overlay = Web::PaintOptions::PaintOverlay::No });
|
||||
auto backing_store = Web::Painting::BitmapBackingStore(*bitmap);
|
||||
paint(rect, backing_store, { .paint_overlay = Web::PaintOptions::PaintOverlay::No });
|
||||
client().async_did_take_screenshot(m_id, bitmap->to_shareable_bitmap());
|
||||
} else {
|
||||
Web::DevicePixelRect rect { { 0, 0 }, content_size() };
|
||||
auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, rect.size().to_type<int>()).release_value_but_fixme_should_propagate_errors();
|
||||
paint(rect, *bitmap);
|
||||
auto backing_store = Web::Painting::BitmapBackingStore(*bitmap);
|
||||
paint(rect, backing_store);
|
||||
client().async_did_take_screenshot(m_id, bitmap->to_shareable_bitmap());
|
||||
}
|
||||
}
|
||||
|
||||
auto back_bitmap = m_backing_store_manager.back_bitmap();
|
||||
if (!back_bitmap)
|
||||
auto back_store = m_backing_store_manager.back_store();
|
||||
if (!back_store)
|
||||
return;
|
||||
|
||||
auto viewport_rect = page().css_to_device_rect(page().top_level_traversable()->viewport_rect());
|
||||
paint(viewport_rect, *back_bitmap);
|
||||
paint(viewport_rect, *back_store);
|
||||
|
||||
m_backing_store_manager.swap_back_and_front();
|
||||
|
||||
|
@ -222,7 +224,7 @@ void PageClient::paint_next_frame()
|
|||
client().async_did_paint(m_id, viewport_rect.to_type<int>(), m_backing_store_manager.front_id());
|
||||
}
|
||||
|
||||
void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& target, Web::PaintOptions paint_options)
|
||||
void PageClient::paint(Web::DevicePixelRect const& content_rect, Web::Painting::BackingStore& target, Web::PaintOptions paint_options)
|
||||
{
|
||||
paint_options.should_show_line_box_borders = m_should_show_line_box_borders;
|
||||
paint_options.has_focus = m_has_focus;
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
ErrorOr<void> connect_to_webdriver(ByteString const& webdriver_ipc_path);
|
||||
|
||||
virtual void paint_next_frame() override;
|
||||
virtual void paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap&, Web::PaintOptions = {}) override;
|
||||
virtual void paint(Web::DevicePixelRect const& content_rect, Web::Painting::BackingStore&, Web::PaintOptions = {}) override;
|
||||
|
||||
void set_palette_impl(Gfx::PaletteImpl&);
|
||||
void set_viewport_size(Web::DevicePixelSize const&);
|
||||
|
|
|
@ -1802,7 +1802,10 @@ Messages::WebDriverClient::TakeScreenshotResponse WebDriverConnection::take_scre
|
|||
auto root_rect = calculate_absolute_rect_of_element(m_page_client->page(), *document->document_element());
|
||||
|
||||
auto encoded_string = TRY(Web::WebDriver::capture_element_screenshot(
|
||||
[&](auto const& rect, auto& bitmap) { m_page_client->paint(rect.template to_type<Web::DevicePixels>(), bitmap); },
|
||||
[&](auto const& rect, auto& bitmap) {
|
||||
auto backing_store = Web::Painting::BitmapBackingStore(bitmap);
|
||||
m_page_client->paint(rect.template to_type<Web::DevicePixels>(), backing_store);
|
||||
},
|
||||
m_page_client->page(),
|
||||
*document->document_element(),
|
||||
root_rect));
|
||||
|
@ -1835,7 +1838,10 @@ Messages::WebDriverClient::TakeElementScreenshotResponse WebDriverConnection::ta
|
|||
auto element_rect = calculate_absolute_rect_of_element(m_page_client->page(), *element);
|
||||
|
||||
auto encoded_string = TRY(Web::WebDriver::capture_element_screenshot(
|
||||
[&](auto const& rect, auto& bitmap) { m_page_client->paint(rect.template to_type<Web::DevicePixels>(), bitmap); },
|
||||
[&](auto const& rect, auto& bitmap) {
|
||||
auto backing_store = Web::Painting::BitmapBackingStore(bitmap);
|
||||
m_page_client->paint(rect.template to_type<Web::DevicePixels>(), backing_store);
|
||||
},
|
||||
m_page_client->page(),
|
||||
*element,
|
||||
element_rect));
|
||||
|
|
|
@ -77,7 +77,7 @@ Web::CSS::PreferredMotion PageHost::preferred_motion() const
|
|||
return Web::CSS::PreferredMotion::Auto;
|
||||
}
|
||||
|
||||
void PageHost::paint(Web::DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions)
|
||||
void PageHost::paint(Web::DevicePixelRect const&, Web::Painting::BackingStore&, Web::PaintOptions)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
virtual Web::CSS::PreferredContrast preferred_contrast() const override;
|
||||
virtual Web::CSS::PreferredMotion preferred_motion() const override;
|
||||
virtual void paint_next_frame() override {};
|
||||
virtual void paint(Web::DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions = {}) override;
|
||||
virtual void paint(Web::DevicePixelRect const&, Web::Painting::BackingStore&, Web::PaintOptions = {}) override;
|
||||
virtual void request_file(Web::FileRequest) override;
|
||||
virtual void schedule_repaint() override {};
|
||||
virtual bool is_ready_to_paint() const override { return true; }
|
||||
|
|
Loading…
Reference in a new issue