Explorar o código

Everywhere: Pass backing store into Navigable::paint()

...instead of Gfx::Bitmap, which makes it possible to access and
directly paint into IOSurface on macOS.
Aliaksandr Kalenik hai 1 ano
pai
achega
c62cc915df

+ 5 - 0
Userland/Libraries/LibCore/IOSurface.cpp

@@ -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);

+ 2 - 0
Userland/Libraries/LibCore/IOSurface.h

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

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -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

+ 1 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -24,6 +24,7 @@ class XMLDocumentBuilder;
 }
 
 namespace Web::Painting {
+class BackingStore;
 class DisplayListRecorder;
 class SVGGradientPaintStyle;
 using PaintStyle = RefPtr<SVGGradientPaintStyle>;

+ 3 - 1
Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp

@@ -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);
 

+ 2 - 1
Userland/Libraries/LibWeb/HTML/TraversableNavigable.h

@@ -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>);

+ 1 - 1
Userland/Libraries/LibWeb/Page/Page.h

@@ -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 - 0
Userland/Libraries/LibWeb/Painting/BackingStore.cpp

@@ -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 - 0
Userland/Libraries/LibWeb/Painting/BackingStore.h

@@ -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
+
+}

+ 1 - 1
Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h

@@ -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; }
 

+ 4 - 2
Userland/Libraries/LibWebView/ViewImplementation.cpp

@@ -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;

+ 13 - 10
Userland/Services/WebContent/BackingStoreManager.cpp

@@ -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_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, m_front_bitmap->to_shareable_bitmap(), m_back_bitmap_id, m_back_bitmap->to_shareable_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);
 }
 

+ 4 - 3
Userland/Services/WebContent/BackingStoreManager.h

@@ -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;

+ 8 - 6
Userland/Services/WebContent/PageClient.cpp

@@ -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;

+ 1 - 1
Userland/Services/WebContent/PageClient.h

@@ -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&);

+ 8 - 2
Userland/Services/WebContent/WebDriverConnection.cpp

@@ -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));

+ 1 - 1
Userland/Services/WebWorker/PageHost.cpp

@@ -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)
 {
 }
 

+ 1 - 1
Userland/Services/WebWorker/PageHost.h

@@ -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; }