Introduce a dedicated Compositor IPC channel between the UI process and WebContent. Use it for backing-store setup, presented bitmap delivery, and bitmap-specific ready_to_paint acknowledgements. This makes CompositorThread the single owner of frame presentation bookkeeping before async scrolling starts producing frames without the main thread. Remove old paint and backing-store messages from WebContentClient and PageClient so the UI process no longer observes two presentation protocols.
76 lines
2.5 KiB
C++
76 lines
2.5 KiB
C++
/*
|
|
* 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>());
|
|
}
|
|
}
|
|
|
|
}
|