LibWeb: Move backing store management into compositor thread
BackingStoreManager was owned by Navigable and allocated on the GC heap, which left backing-store sizing decisions on the main thread even though the compositor thread was already responsible for allocating the actual surfaces. That split ownership makes it harder to isolate the compositor behind a process boundary. Move the manager into LibWeb's compositor code and let CompositorThread thread data own it. The main thread now reports viewport size changes through a compositor command, and the compositor uses that message to decide when to resize and publish backing stores. The delayed shrink timer remains with the main-thread CompositorThread facade so it can use the Core event loop, but it now only sends another viewport-size update. This removes the GC edge from Navigable, drops stale WebContent includes and keeps the existing resize padding and delayed shrink behavior.
This commit is contained in:
parent
fabe966949
commit
fd823becd7
11 changed files with 155 additions and 157 deletions
|
|
@ -32,6 +32,7 @@ set(SOURCES
|
|||
Clipboard/SystemClipboard.cpp
|
||||
Compositor/AsyncScrollTree.cpp
|
||||
Compositor/AsyncScrollingState.cpp
|
||||
Compositor/BackingStoreManager.cpp
|
||||
Compositor/CompositorThread.cpp
|
||||
Compression/CompressionStream.cpp
|
||||
Compression/DecompressionStream.cpp
|
||||
|
|
@ -849,7 +850,6 @@ set(SOURCES
|
|||
Page/Page.cpp
|
||||
Painting/AccumulatedVisualContext.cpp
|
||||
Painting/BackgroundPainting.cpp
|
||||
Painting/BackingStoreManager.cpp
|
||||
Painting/Blending.cpp
|
||||
Painting/BorderPainting.cpp
|
||||
Painting/BorderRadiiData.cpp
|
||||
|
|
|
|||
41
Libraries/LibWeb/Compositor/BackingStoreManager.cpp
Normal file
41
Libraries/LibWeb/Compositor/BackingStoreManager.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Compositor/BackingStoreManager.h>
|
||||
#include <LibWeb/Compositor/CompositorThread.h>
|
||||
|
||||
namespace Web::Compositor {
|
||||
|
||||
Optional<BackingStoreManager::Allocation> BackingStoreManager::resize_backing_stores_if_needed(
|
||||
Gfx::IntSize viewport_size, bool is_top_level_traversable, WindowResizingInProgress window_resize_in_progress)
|
||||
{
|
||||
if (viewport_size.is_empty())
|
||||
return {};
|
||||
|
||||
auto minimum_needed_size = viewport_size;
|
||||
bool force_reallocate = false;
|
||||
if (window_resize_in_progress == WindowResizingInProgress::Yes && is_top_level_traversable) {
|
||||
// Pad the minimum needed size so that we don't have to keep reallocating backing stores while the window is being resized.
|
||||
minimum_needed_size = { viewport_size.width() + 256, viewport_size.height() + 256 };
|
||||
} 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;
|
||||
force_reallocate = m_allocated_size != minimum_needed_size;
|
||||
}
|
||||
|
||||
if (force_reallocate || m_allocated_size.is_empty() || !m_allocated_size.contains(minimum_needed_size)) {
|
||||
m_allocated_size = minimum_needed_size;
|
||||
return Allocation {
|
||||
.size = minimum_needed_size,
|
||||
.front_bitmap_id = m_next_bitmap_id++,
|
||||
.back_bitmap_id = m_next_bitmap_id++,
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
42
Libraries/LibWeb/Compositor/BackingStoreManager.h
Normal file
42
Libraries/LibWeb/Compositor/BackingStoreManager.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/Types.h>
|
||||
#include <LibGfx/Size.h>
|
||||
#include <LibWeb/Export.h>
|
||||
|
||||
namespace Web::Compositor {
|
||||
|
||||
enum class WindowResizingInProgress : u8;
|
||||
|
||||
class WEB_API BackingStoreManager {
|
||||
AK_MAKE_NONCOPYABLE(BackingStoreManager);
|
||||
AK_MAKE_NONMOVABLE(BackingStoreManager);
|
||||
|
||||
public:
|
||||
struct Allocation {
|
||||
Gfx::IntSize size;
|
||||
i32 front_bitmap_id { -1 };
|
||||
i32 back_bitmap_id { -1 };
|
||||
};
|
||||
|
||||
BackingStoreManager() = default;
|
||||
|
||||
Optional<Allocation> resize_backing_stores_if_needed(
|
||||
Gfx::IntSize viewport_size, bool is_top_level_traversable, WindowResizingInProgress);
|
||||
|
||||
private:
|
||||
int m_next_bitmap_id { 0 };
|
||||
|
||||
// Used to track if backing stores need reallocation
|
||||
Gfx::IntSize m_allocated_size;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibGfx/DecodedImageFrame.h>
|
||||
#include <LibGfx/PaintingSurface.h>
|
||||
#include <LibGfx/SharedImage.h>
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
#include <LibThreading/Thread.h>
|
||||
#include <LibWeb/Compositor/AsyncScrollTree.h>
|
||||
#include <LibWeb/Compositor/AsyncScrollingState.h>
|
||||
#include <LibWeb/Compositor/BackingStoreManager.h>
|
||||
#include <LibWeb/Compositor/CompositorThread.h>
|
||||
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
||||
#include <LibWeb/Page/InputEvent.h>
|
||||
|
|
@ -86,10 +88,10 @@ struct UpdateScrollStateCommand {
|
|||
Painting::ScrollStateSnapshot scroll_state_snapshot;
|
||||
};
|
||||
|
||||
struct UpdateBackingStoresCommand {
|
||||
Gfx::IntSize size;
|
||||
i32 front_bitmap_id;
|
||||
i32 back_bitmap_id;
|
||||
struct ViewportSizeUpdatedCommand {
|
||||
Gfx::IntSize viewport_size;
|
||||
bool is_top_level_traversable { false };
|
||||
WindowResizingInProgress window_resize_in_progress { WindowResizingInProgress::No };
|
||||
};
|
||||
|
||||
struct ScreenshotCommand {
|
||||
|
|
@ -97,7 +99,8 @@ struct ScreenshotCommand {
|
|||
Function<void()> callback;
|
||||
};
|
||||
|
||||
using CompositorCommand = Variant<UpdateDisplayListCommand, AsyncScrollByCommand, ViewportScrollbarDragCommand, UpdateScrollStateCommand, UpdateBackingStoresCommand, ScreenshotCommand>;
|
||||
using CompositorCommand = Variant<UpdateDisplayListCommand, AsyncScrollByCommand, ViewportScrollbarDragCommand,
|
||||
UpdateScrollStateCommand, ViewportSizeUpdatedCommand, ScreenshotCommand>;
|
||||
|
||||
static SkRect to_skia_rect(Gfx::IntRect const& rect)
|
||||
{
|
||||
|
|
@ -802,14 +805,19 @@ public:
|
|||
}
|
||||
}
|
||||
},
|
||||
[this](UpdateBackingStoresCommand& cmd) {
|
||||
[this](ViewportSizeUpdatedCommand& cmd) {
|
||||
auto allocation = m_backing_store_manager.resize_backing_stores_if_needed(
|
||||
cmd.viewport_size, cmd.is_top_level_traversable, cmd.window_resize_in_progress);
|
||||
if (!allocation.has_value())
|
||||
return;
|
||||
|
||||
if (m_has_async_scrolling_state) {
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] Compositor received backing stores front={} back={} size={}x{}",
|
||||
cmd.front_bitmap_id, cmd.back_bitmap_id, cmd.size.width(), cmd.size.height());
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] Compositor resizing backing stores front={} back={} size={}x{}",
|
||||
allocation->front_bitmap_id, allocation->back_bitmap_id, allocation->size.width(), allocation->size.height());
|
||||
}
|
||||
allocate_backing_stores(cmd);
|
||||
m_backing_stores.front_bitmap_id = cmd.front_bitmap_id;
|
||||
m_backing_stores.back_bitmap_id = cmd.back_bitmap_id;
|
||||
allocate_backing_stores(*allocation);
|
||||
m_backing_stores.front_bitmap_id = allocation->front_bitmap_id;
|
||||
m_backing_stores.back_bitmap_id = allocation->back_bitmap_id;
|
||||
},
|
||||
[this](ScreenshotCommand& cmd) {
|
||||
if (!m_cached_display_list)
|
||||
|
|
@ -1158,40 +1166,42 @@ private:
|
|||
m_skia_player = make<Painting::DisplayListPlayerSkia>(m_skia_backend_context);
|
||||
}
|
||||
|
||||
void publish_backing_store_pair(UpdateBackingStoresCommand& cmd, Gfx::SharedImage front_shared_image, Gfx::SharedImage back_shared_image)
|
||||
void publish_backing_store_pair(
|
||||
BackingStoreManager::Allocation const& allocation, Gfx::SharedImage front_shared_image, Gfx::SharedImage back_shared_image)
|
||||
{
|
||||
if (!m_presents_to_client)
|
||||
return;
|
||||
|
||||
VERIFY(CompositorThread::present_backing_stores_to_client(m_page_id, cmd.front_bitmap_id, move(front_shared_image), cmd.back_bitmap_id, move(back_shared_image)));
|
||||
VERIFY(CompositorThread::present_backing_stores_to_client(
|
||||
m_page_id, allocation.front_bitmap_id, move(front_shared_image), allocation.back_bitmap_id, move(back_shared_image)));
|
||||
}
|
||||
|
||||
void allocate_backing_stores(UpdateBackingStoresCommand& cmd)
|
||||
void allocate_backing_stores(BackingStoreManager::Allocation const& allocation)
|
||||
{
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
if (m_skia_backend_context && m_presents_to_client) {
|
||||
auto backing_stores = create_linear_dmabuf_backing_stores(cmd.size, *m_skia_backend_context);
|
||||
auto backing_stores = create_linear_dmabuf_backing_stores(allocation.size, *m_skia_backend_context);
|
||||
if (!backing_stores.is_error()) {
|
||||
auto backing_store_pair = backing_stores.release_value();
|
||||
m_backing_stores.front_store = move(backing_store_pair.front);
|
||||
m_backing_stores.back_store = move(backing_store_pair.back);
|
||||
publish_backing_store_pair(cmd, move(backing_store_pair.front_shared_image), move(backing_store_pair.back_shared_image));
|
||||
publish_backing_store_pair(allocation, move(backing_store_pair.front_shared_image), move(backing_store_pair.back_shared_image));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
auto front_buffer = Gfx::SharedImageBuffer::create(cmd.size);
|
||||
auto back_buffer = Gfx::SharedImageBuffer::create(cmd.size);
|
||||
auto front_buffer = Gfx::SharedImageBuffer::create(allocation.size);
|
||||
auto back_buffer = Gfx::SharedImageBuffer::create(allocation.size);
|
||||
auto front_shared_image = front_buffer.export_shared_image();
|
||||
auto back_shared_image = back_buffer.export_shared_image();
|
||||
auto backing_store_pair = create_shareable_bitmap_backing_stores(cmd.size, front_buffer, back_buffer, m_skia_backend_context);
|
||||
auto backing_store_pair = create_shareable_bitmap_backing_stores(allocation.size, front_buffer, back_buffer, m_skia_backend_context);
|
||||
m_backing_stores.front_store = move(backing_store_pair.front);
|
||||
m_backing_stores.back_store = move(backing_store_pair.back);
|
||||
publish_backing_store_pair(cmd, move(front_shared_image), move(back_shared_image));
|
||||
publish_backing_store_pair(allocation, move(front_shared_image), move(back_shared_image));
|
||||
if (m_has_async_scrolling_state) {
|
||||
dbgln_if(COMPOSITOR_DEBUG, "[Compositor] Allocated bitmap backing stores front={} back={} size={}x{}",
|
||||
cmd.front_bitmap_id, cmd.back_bitmap_id, cmd.size.width(), cmd.size.height());
|
||||
allocation.front_bitmap_id, allocation.back_bitmap_id, allocation.size.width(), allocation.size.height());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1228,6 +1238,7 @@ private:
|
|||
float m_viewport_scrollbar_thumb_grab_position { 0 };
|
||||
mutable Sync::Mutex m_async_scroll_tree_mutex;
|
||||
AsyncScrollTree m_async_scroll_tree;
|
||||
BackingStoreManager m_backing_store_manager;
|
||||
BackingStoreState m_backing_stores;
|
||||
CompositorThread::PresentationMode m_presentation_mode { CompositorThread::PresentToUI {} };
|
||||
|
||||
|
|
@ -1305,12 +1316,20 @@ static FramePresentationState& frame_presentation_state()
|
|||
CompositorThread::CompositorThread(u64 page_id, PagePresentationRegistration page_presentation_registration)
|
||||
: m_thread_data(adopt_ref(*new ThreadData(page_id, Core::EventLoop::current_weak(), page_presentation_registration)))
|
||||
{
|
||||
m_backing_store_shrink_timer = Core::Timer::create_single_shot(3000, [this] {
|
||||
enqueue_viewport_size_updated(m_last_viewport_size, m_last_viewport_size_is_top_level_traversable, WindowResizingInProgress::No);
|
||||
});
|
||||
|
||||
if (page_presentation_registration == PagePresentationRegistration::Yes)
|
||||
register_page_compositor(page_id, m_thread_data);
|
||||
}
|
||||
|
||||
CompositorThread::~CompositorThread()
|
||||
{
|
||||
m_backing_store_shrink_timer->on_timeout = {};
|
||||
m_backing_store_shrink_timer->stop();
|
||||
m_backing_store_shrink_timer.clear();
|
||||
|
||||
unregister_page_compositor(m_thread_data->page_id(), *m_thread_data);
|
||||
m_thread_data->exit();
|
||||
}
|
||||
|
|
@ -1573,9 +1592,21 @@ void CompositorThread::update_scroll_state(Painting::ScrollStateSnapshot&& scrol
|
|||
m_thread_data->enqueue_command(UpdateScrollStateCommand { move(scroll_state_snapshot) });
|
||||
}
|
||||
|
||||
void CompositorThread::update_backing_stores(Gfx::IntSize size, i32 front_id, i32 back_id)
|
||||
void CompositorThread::viewport_size_updated(
|
||||
Gfx::IntSize viewport_size, bool is_top_level_traversable, WindowResizingInProgress window_resize_in_progress)
|
||||
{
|
||||
m_thread_data->enqueue_command(UpdateBackingStoresCommand { size, front_id, back_id });
|
||||
m_last_viewport_size = viewport_size;
|
||||
m_last_viewport_size_is_top_level_traversable = is_top_level_traversable;
|
||||
if (window_resize_in_progress == WindowResizingInProgress::Yes)
|
||||
m_backing_store_shrink_timer->restart();
|
||||
enqueue_viewport_size_updated(viewport_size, is_top_level_traversable, window_resize_in_progress);
|
||||
}
|
||||
|
||||
void CompositorThread::enqueue_viewport_size_updated(
|
||||
Gfx::IntSize viewport_size, bool is_top_level_traversable, WindowResizingInProgress window_resize_in_progress)
|
||||
{
|
||||
m_thread_data->enqueue_command(
|
||||
ViewportSizeUpdatedCommand { viewport_size, is_top_level_traversable, window_resize_in_progress });
|
||||
}
|
||||
|
||||
u64 CompositorThread::present_frame(Gfx::IntRect viewport_rect)
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@
|
|||
#include <AK/Noncopyable.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibCore/Forward.h>
|
||||
#include <LibGfx/Point.h>
|
||||
#include <LibGfx/Rect.h>
|
||||
#include <LibGfx/SharedImage.h>
|
||||
#include <LibGfx/Size.h>
|
||||
#include <LibSync/ConditionVariable.h>
|
||||
#include <LibThreading/Forward.h>
|
||||
#include <LibWeb/Compositor/AsyncScrollingState.h>
|
||||
|
|
@ -25,6 +27,11 @@
|
|||
|
||||
namespace Web::Compositor {
|
||||
|
||||
enum class WindowResizingInProgress : u8 {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
class WEB_API CompositorThread {
|
||||
AK_MAKE_NONCOPYABLE(CompositorThread);
|
||||
AK_MAKE_NONMOVABLE(CompositorThread);
|
||||
|
|
@ -79,14 +86,19 @@ public:
|
|||
bool should_defer_async_scroll_offset_adoption() const;
|
||||
bool should_defer_main_thread_present_for_async_scroll() const;
|
||||
PendingAsyncScrollUpdates take_pending_async_scroll_updates();
|
||||
void update_backing_stores(Gfx::IntSize, i32 front_id, i32 back_id);
|
||||
void viewport_size_updated(Gfx::IntSize, bool is_top_level_traversable, WindowResizingInProgress);
|
||||
u64 present_frame(Gfx::IntRect);
|
||||
void wait_for_frame(u64 frame_id);
|
||||
void request_screenshot(NonnullRefPtr<Gfx::PaintingSurface>, Function<void()>&& callback);
|
||||
|
||||
private:
|
||||
void enqueue_viewport_size_updated(Gfx::IntSize, bool is_top_level_traversable, WindowResizingInProgress);
|
||||
|
||||
NonnullRefPtr<ThreadData> m_thread_data;
|
||||
RefPtr<Threading::Thread> m_thread;
|
||||
RefPtr<Core::Timer> m_backing_store_shrink_timer;
|
||||
Gfx::IntSize m_last_viewport_size;
|
||||
bool m_last_viewport_size_is_top_level_traversable { false };
|
||||
|
||||
static void register_page_compositor(u64 page_id, NonnullRefPtr<ThreadData>);
|
||||
static void unregister_page_compositor(u64 page_id, ThreadData&);
|
||||
|
|
|
|||
|
|
@ -281,7 +281,6 @@ Navigable::Navigable(
|
|||
: m_page(page)
|
||||
, m_event_handler({}, *this)
|
||||
, m_is_svg_page(is_svg_page)
|
||||
, m_backing_store_manager(heap().allocate<Painting::BackingStoreManager>(*this))
|
||||
, m_rendering_thread(
|
||||
is_svg_page ? 0 : page->client().id(),
|
||||
is_svg_page ? Compositor::CompositorThread::PagePresentationRegistration::No : page_presentation_registration)
|
||||
|
|
@ -324,7 +323,6 @@ void Navigable::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(m_parent);
|
||||
visitor.visit(m_active_document);
|
||||
visitor.visit(m_container);
|
||||
visitor.visit(m_backing_store_manager);
|
||||
m_event_handler.visit_edges(visitor);
|
||||
|
||||
for (auto& navigation_params : m_pending_navigations) {
|
||||
|
|
@ -2849,8 +2847,10 @@ void Navigable::set_viewport_size(CSSPixelSize size, InvalidateDisplayList inval
|
|||
m_viewport_size = size;
|
||||
|
||||
if (!m_is_svg_page) {
|
||||
m_backing_store_manager->restart_resize_timer();
|
||||
m_backing_store_manager->resize_backing_stores_if_needed(Web::Painting::BackingStoreManager::WindowResizingInProgress::Yes);
|
||||
m_rendering_thread.viewport_size_updated(
|
||||
page().css_to_device_rect(viewport_rect()).size().to_type<int>(),
|
||||
is_top_level_traversable(),
|
||||
Compositor::WindowResizingInProgress::Yes);
|
||||
m_pending_set_browser_zoom_request = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include <LibWeb/HTML/WindowType.h>
|
||||
#include <LibWeb/InvalidateDisplayList.h>
|
||||
#include <LibWeb/Page/EventHandler.h>
|
||||
#include <LibWeb/Painting/BackingStoreManager.h>
|
||||
#include <LibWeb/PixelUnits.h>
|
||||
#include <LibWeb/XHR/FormDataEntry.h>
|
||||
|
||||
|
|
@ -200,8 +199,6 @@ public:
|
|||
void wait_for_async_scroll_operation(Compositor::AsyncScrollOperationID, GC::Ref<WebIDL::Promise>);
|
||||
void clamp_viewport_scroll_offset();
|
||||
|
||||
Painting::BackingStoreManager& backing_store_manager() { return *m_backing_store_manager; }
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#rendering-opportunity
|
||||
[[nodiscard]] bool has_a_rendering_opportunity() const;
|
||||
|
||||
|
|
@ -333,7 +330,6 @@ private:
|
|||
bool m_pending_set_browser_zoom_request { false };
|
||||
bool m_should_show_line_box_borders { false };
|
||||
Optional<PaintConfig> m_rendering_thread_display_list_paint_config;
|
||||
GC::Ref<Painting::BackingStoreManager> m_backing_store_manager;
|
||||
Compositor::CompositorThread m_rendering_thread;
|
||||
RefPtr<Painting::ExternalContentSource> m_external_content_source;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||
#include <LibWeb/Painting/BackingStoreManager.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
GC_DEFINE_ALLOCATOR(BackingStoreManager);
|
||||
|
||||
BackingStoreManager::BackingStoreManager(HTML::Navigable& navigable)
|
||||
: m_navigable(navigable)
|
||||
{
|
||||
m_backing_store_shrink_timer = Core::Timer::create_single_shot(3000, [this] {
|
||||
resize_backing_stores_if_needed(WindowResizingInProgress::No);
|
||||
});
|
||||
}
|
||||
|
||||
void BackingStoreManager::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_navigable);
|
||||
}
|
||||
|
||||
void BackingStoreManager::finalize()
|
||||
{
|
||||
Base::finalize();
|
||||
m_backing_store_shrink_timer->on_timeout = {};
|
||||
m_backing_store_shrink_timer->stop();
|
||||
m_backing_store_shrink_timer.clear();
|
||||
}
|
||||
|
||||
void BackingStoreManager::restart_resize_timer()
|
||||
{
|
||||
m_backing_store_shrink_timer->restart();
|
||||
}
|
||||
|
||||
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_allocated_size = size;
|
||||
|
||||
m_navigable->rendering_thread().update_backing_stores(size, m_front_bitmap_id, m_back_bitmap_id);
|
||||
}
|
||||
|
||||
void BackingStoreManager::resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress)
|
||||
{
|
||||
if (m_navigable->is_svg_page())
|
||||
return;
|
||||
|
||||
auto viewport_size = m_navigable->page().css_to_device_rect(m_navigable->viewport_rect()).size();
|
||||
if (viewport_size.is_empty())
|
||||
return;
|
||||
|
||||
Web::DevicePixelSize minimum_needed_size;
|
||||
bool force_reallocate = false;
|
||||
if (window_resize_in_progress == WindowResizingInProgress::Yes && m_navigable->is_top_level_traversable()) {
|
||||
// Pad the minimum needed size so that we don't have to keep reallocating backing stores while the window is being resized.
|
||||
minimum_needed_size = { viewport_size.width() + 256, viewport_size.height() + 256 };
|
||||
} 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;
|
||||
force_reallocate = m_allocated_size != minimum_needed_size.to_type<int>();
|
||||
}
|
||||
|
||||
if (force_reallocate || m_allocated_size.is_empty() || !m_allocated_size.contains(minimum_needed_size.to_type<int>())) {
|
||||
reallocate_backing_stores(minimum_needed_size.to_type<int>());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Export.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
class WEB_API BackingStoreManager : public JS::Cell {
|
||||
GC_CELL(BackingStoreManager, JS::Cell);
|
||||
GC_DECLARE_ALLOCATOR(BackingStoreManager);
|
||||
|
||||
public:
|
||||
static constexpr bool OVERRIDES_FINALIZE = true;
|
||||
|
||||
enum class WindowResizingInProgress {
|
||||
No,
|
||||
Yes
|
||||
};
|
||||
void resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress);
|
||||
void reallocate_backing_stores(Gfx::IntSize);
|
||||
void restart_resize_timer();
|
||||
|
||||
virtual void finalize() override;
|
||||
virtual void visit_edges(Cell::Visitor& visitor) override;
|
||||
|
||||
BackingStoreManager(HTML::Navigable&);
|
||||
|
||||
private:
|
||||
GC::Ref<HTML::Navigable> m_navigable;
|
||||
|
||||
i32 m_front_bitmap_id { -1 };
|
||||
i32 m_back_bitmap_id { -1 };
|
||||
int m_next_bitmap_id { 0 };
|
||||
|
||||
// Used to track if backing stores need reallocation
|
||||
Gfx::IntSize m_allocated_size;
|
||||
|
||||
RefPtr<Core::Timer> m_backing_store_shrink_timer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@
|
|||
#include <LibWeb/HTML/AudioPlayState.h>
|
||||
#include <LibWeb/HTML/FileFilter.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
#include <LibWeb/Painting/BackingStoreManager.h>
|
||||
#include <LibWeb/PixelUnits.h>
|
||||
#include <LibWeb/StorageAPI/StorageEndpoint.h>
|
||||
#include <LibWebView/Forward.h>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <LibWeb/Loader/ContentFilter.h>
|
||||
#include <LibWeb/Loader/GeneratedPagesLoader.h>
|
||||
#include <LibWeb/Loader/ResourceLoader.h>
|
||||
#include <LibWeb/Painting/BackingStoreManager.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/Platform/FontPlugin.h>
|
||||
|
|
|
|||
Loading…
Reference in a new issue