LibWeb+Compositor: Move backing-store shrink timer to service

The delayed backing-store shrink policy was still owned by the LibWeb
compositor context handle. That made the handle cache viewport state and
own a Core::Timer even though backing-store allocation now lives in the
compositor service.

Move the resize-completion timer into CompositorState::ContextState,
next to the viewport state and BackingStoreManager. The compositor
service still pads backing stores while a top-level resize is in
progress, then flips the context back to a non-resizing state after the
same delay so the stores can shrink. LibWeb now just forwards
viewport-size updates through CompositorHost.
This commit is contained in:
Aliaksandr Kalenik 2026-05-24 22:22:23 +02:00 committed by Alexander Kalenik
parent 399db4a213
commit 435c4d060c
4 changed files with 44 additions and 15 deletions

View file

@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/Timer.h>
#include <LibGfx/PaintingSurface.h>
#include <LibWeb/Compositor/CompositorHost.h>
#include <LibWeb/Painting/DisplayList.h>
@ -15,15 +14,10 @@ CompositorContextHandle::CompositorContextHandle(CompositorHost& host, Composito
: m_host(host)
, m_context_id(context_id)
{
m_backing_store_shrink_timer = Core::Timer::create_single_shot(3000, [this] {
m_host.viewport_size_updated(m_context_id, m_last_viewport_size, m_last_viewport_size_is_top_level_traversable, WindowResizingInProgress::No);
});
}
CompositorContextHandle::~CompositorContextHandle()
{
m_backing_store_shrink_timer->on_timeout = {};
m_backing_store_shrink_timer->stop();
m_host.destroy_context(m_context_id);
}
@ -90,10 +84,6 @@ PendingAsyncScrollUpdates CompositorContextHandle::take_pending_async_scroll_upd
void CompositorContextHandle::viewport_size_updated(Gfx::IntSize viewport_size, bool is_top_level_traversable, WindowResizingInProgress window_resize_in_progress)
{
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();
m_host.viewport_size_updated(m_context_id, viewport_size, is_top_level_traversable, window_resize_in_progress);
}

View file

@ -10,9 +10,7 @@
#include <AK/Noncopyable.h>
#include <AK/NonnullRefPtr.h>
#include <AK/OwnPtr.h>
#include <AK/RefPtr.h>
#include <AK/Types.h>
#include <LibCore/Forward.h>
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/SharedImage.h>
@ -60,9 +58,6 @@ private:
CompositorHost& m_host;
CompositorContextId m_context_id;
RefPtr<Core::Timer> m_backing_store_shrink_timer;
Gfx::IntSize m_last_viewport_size;
bool m_last_viewport_size_is_top_level_traversable { false };
};
class WEB_API CompositorHost {

View file

@ -6,6 +6,7 @@
#include <AK/StdLibExtras.h>
#include <Compositor/CompositorState.h>
#include <LibCore/Timer.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/Color.h>
#include <LibGfx/PainterSkia.h>
@ -150,6 +151,19 @@ CompositorState::CompositorState(RefPtr<Gfx::SkiaBackendContext> skia_backend_co
{
}
CompositorState::ContextState::~ContextState()
{
stop_backing_store_shrink_timer();
}
void CompositorState::ContextState::stop_backing_store_shrink_timer()
{
if (!backing_store_shrink_timer)
return;
backing_store_shrink_timer->on_timeout = {};
backing_store_shrink_timer->stop();
}
void CompositorState::set_client(CompositorStateClient& client)
{
m_client = &client;
@ -511,6 +525,8 @@ void CompositorState::viewport_size_updated(Web::Compositor::CompositorContextId
context->is_top_level_traversable = is_top_level_traversable;
context->window_resize_in_progress = window_resize_in_progress;
resize_backing_stores_if_needed(context_id, *context);
if (window_resize_in_progress == Web::Compositor::WindowResizingInProgress::Yes)
schedule_backing_store_shrink(context_id, *context);
}
void CompositorState::present_frame(Web::Compositor::CompositorContextId context_id, Gfx::IntRect viewport_rect)
@ -887,6 +903,26 @@ void CompositorState::resize_backing_stores_if_needed(Web::Compositor::Composito
}
}
void CompositorState::schedule_backing_store_shrink(Web::Compositor::CompositorContextId context_id, ContextState& context)
{
if (!context.backing_store_shrink_timer) {
context.backing_store_shrink_timer = Core::Timer::create_single_shot(3000, [this, context_id] {
shrink_backing_stores_after_resize(context_id);
});
}
context.backing_store_shrink_timer->restart();
}
void CompositorState::shrink_backing_stores_after_resize(Web::Compositor::CompositorContextId context_id)
{
auto* context = context_if_present(context_id);
if (!context)
return;
context->window_resize_in_progress = Web::Compositor::WindowResizingInProgress::No;
resize_backing_stores_if_needed(context_id, *context);
}
void CompositorState::present_current_frame(Web::Compositor::CompositorContextId context_id, ContextState& context)
{
// A queued frame already captures the newest viewport rect and will pick up

View file

@ -13,6 +13,7 @@
#include <AK/RefCounted.h>
#include <AK/Vector.h>
#include <Compositor/BackingStoreManager.h>
#include <LibCore/Forward.h>
#include <LibGfx/PaintingSurface.h>
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
@ -102,6 +103,8 @@ private:
};
struct ContextState {
~ContextState();
struct PublishedSurface {
Web::Compositor::CompositorContextId parent_context_id;
Web::Painting::CompositorSurfaceId surface_id;
@ -140,12 +143,15 @@ private:
Gfx::IntSize viewport_size;
bool is_top_level_traversable { false };
Web::Compositor::WindowResizingInProgress window_resize_in_progress { Web::Compositor::WindowResizingInProgress::No };
RefPtr<Core::Timer> backing_store_shrink_timer;
Optional<Gfx::IntRect> pending_present_frame;
Optional<Gfx::IntRect> presented_frame;
Optional<i32> presented_bitmap_id_awaiting_ack;
bool has_deferred_async_scroll_present { false };
Gfx::IntRect deferred_async_scroll_present_viewport_rect;
void stop_backing_store_shrink_timer();
};
ContextState* context_if_present(Web::Compositor::CompositorContextId);
@ -164,6 +170,8 @@ private:
bool apply_viewport_scrollbar_drag(Web::Compositor::CompositorContextId, ContextState&, size_t scrollbar_index, float primary_position, float thumb_grab_position);
void present_viewport_scrollbar_overlay(Web::Compositor::CompositorContextId, ContextState&);
bool paint_viewport_scrollbar_overlay(ContextState&, Gfx::PaintingSurface&);
void schedule_backing_store_shrink(Web::Compositor::CompositorContextId, ContextState&);
void shrink_backing_stores_after_resize(Web::Compositor::CompositorContextId);
void resize_backing_stores_if_needed(Web::Compositor::CompositorContextId, ContextState&);
void present_current_frame(Web::Compositor::CompositorContextId, ContextState&);
void publish_to_parent_surface(ContextState&, Web::Compositor::PublishToCompositorSurface const&);