LibWeb+Compositor+WebContent: Simplify nested context composition

Nested navigables were represented through compositor surface ids owned
by the parent context. That forced CompositorState and ContextState to
maintain bidirectional attach/detach bookkeeping, publish child
snapshots into a surface map, and keep presentation mode variants just
to distinguish UI presentation from parent composition.

Record the child compositor context id directly in the display list and
let the compositor resolve it against the painting parent at playback
time. Child contexts now keep their parent context id and latest
rendered surface, while parents no longer track child maps or compositor
surface ids. UI presentation is represented separately from parent
composition, so closing a page only stops client presentation and nested
contexts keep using set_parent_context.
This commit is contained in:
Aliaksandr Kalenik 2026-06-18 06:10:37 +02:00 committed by Alexander Kalenik
parent 1b5bdb2b41
commit d96dc6535f
29 changed files with 224 additions and 319 deletions

View file

@ -21,9 +21,14 @@ CompositorContextHandle::~CompositorContextHandle()
m_host.destroy_context(m_context_id);
}
void CompositorContextHandle::set_presentation_mode(PresentationMode mode)
void CompositorContextHandle::set_parent_context(Optional<CompositorContextId> parent_context_id)
{
m_host.set_presentation_mode(m_context_id, move(mode));
m_host.set_parent_context(m_context_id, parent_context_id);
}
void CompositorContextHandle::stop_presenting_to_client()
{
m_host.stop_presenting_to_client(m_context_id);
}
void CompositorContextHandle::update_display_list(NonnullRefPtr<Painting::DisplayList> display_list, Painting::AccumulatedVisualContextTree visual_context_tree, Painting::DisplayListResourceTransaction&& resource_transaction, Painting::ScrollStateSnapshot&& scroll_state_snapshot)

View file

@ -32,7 +32,8 @@ public:
~CompositorContextHandle();
CompositorContextId id() const { return m_context_id; }
void set_presentation_mode(PresentationMode);
void set_parent_context(Optional<CompositorContextId>);
void stop_presenting_to_client();
void update_display_list(NonnullRefPtr<Painting::DisplayList>, Painting::AccumulatedVisualContextTree, Painting::DisplayListResourceTransaction&&, Painting::ScrollStateSnapshot&&);
void update_visual_context_tree(Painting::AccumulatedVisualContextTree);
@ -70,7 +71,8 @@ public:
virtual RefPtr<HTML::RemoteCanvas2DTransport> create_canvas_2d_transport() = 0;
virtual void destroy_context(CompositorContextId) = 0;
virtual void set_presentation_mode(CompositorContextId, PresentationMode) = 0;
virtual void set_parent_context(CompositorContextId, Optional<CompositorContextId>) = 0;
virtual void stop_presenting_to_client(CompositorContextId) = 0;
virtual void update_display_list(CompositorContextId, NonnullRefPtr<Painting::DisplayList>, Painting::AccumulatedVisualContextTree, Painting::DisplayListResourceTransaction&&, Painting::ScrollStateSnapshot&&) = 0;
virtual void update_visual_context_tree(CompositorContextId, Painting::AccumulatedVisualContextTree) = 0;

View file

@ -82,33 +82,4 @@ ErrorOr<Web::Compositor::AsyncScrollEnqueueResult> decode(Decoder& decoder)
};
}
template<>
ErrorOr<void> encode(Encoder& encoder, Web::Compositor::PublishToCompositorSurface const& mode)
{
TRY(encoder.encode(mode.target_context_id));
TRY(encoder.encode(mode.surface_id));
return {};
}
template<>
ErrorOr<Web::Compositor::PublishToCompositorSurface> decode(Decoder& decoder)
{
return Web::Compositor::PublishToCompositorSurface {
.target_context_id = TRY(decoder.decode<Web::Compositor::CompositorContextId>()),
.surface_id = TRY(decoder.decode<Web::Painting::CompositorSurfaceId>()),
};
}
template<>
ErrorOr<void> encode(Encoder&, Web::Compositor::PresentToClient const&)
{
return {};
}
template<>
ErrorOr<Web::Compositor::PresentToClient> decode(Decoder&)
{
return Web::Compositor::PresentToClient {};
}
}

View file

@ -10,12 +10,10 @@
#include <AK/DistinctNumeric.h>
#include <AK/Optional.h>
#include <AK/Types.h>
#include <AK/Variant.h>
#include <AK/Vector.h>
#include <LibIPC/Forward.h>
#include <LibWeb/Compositor/AsyncScrollingState.h>
#include <LibWeb/Export.h>
#include <LibWeb/Painting/DisplayListResourceIds.h>
namespace Web::Compositor {
@ -53,16 +51,6 @@ enum class AsyncScrollOperationTracking {
Yes,
};
struct PublishToCompositorSurface {
CompositorContextId target_context_id;
Painting::CompositorSurfaceId surface_id;
};
struct PresentToClient {
};
using PresentationMode = Variant<Empty, PresentToClient, PublishToCompositorSurface>;
}
namespace IPC {
@ -87,14 +75,4 @@ WEB_API ErrorOr<void> encode(Encoder&, Web::Compositor::AsyncScrollEnqueueResult
template<>
WEB_API ErrorOr<Web::Compositor::AsyncScrollEnqueueResult> decode(Decoder&);
template<>
WEB_API ErrorOr<void> encode(Encoder&, Web::Compositor::PublishToCompositorSurface const&);
template<>
WEB_API ErrorOr<Web::Compositor::PublishToCompositorSurface> decode(Decoder&);
template<>
WEB_API ErrorOr<void> encode(Encoder&, Web::Compositor::PresentToClient const&);
template<>
WEB_API ErrorOr<Web::Compositor::PresentToClient> decode(Decoder&);
}

View file

@ -513,11 +513,7 @@ void Navigable::initialize_navigable(NonnullRefPtr<DocumentState> document_state
m_should_show_caret_hit_test_debug_overlay = parent->m_should_show_caret_hit_test_debug_overlay;
}
if (parent && !m_is_svg_page && has_compositor_context() && parent->has_compositor_context()) {
m_compositor_surface_id = Painting::allocate_compositor_surface_id();
compositor_context().set_presentation_mode(Compositor::PublishToCompositorSurface {
.target_context_id = parent->compositor_context().id(),
.surface_id = *m_compositor_surface_id,
});
compositor_context().set_parent_context(parent->compositor_context().id());
}
// 6. Set the initial visibility state of documentState's document to navigable's traversable navigable's system visibility state.
@ -3766,24 +3762,15 @@ void Navigable::set_has_session_history_entry_and_ready_for_navigation()
process_pending_navigations();
}
Painting::CompositorSurfaceId Navigable::compositor_surface_id() const
void Navigable::clear_parent_compositor_context()
{
VERIFY(m_compositor_surface_id.has_value());
return *m_compositor_surface_id;
}
void Navigable::clear_compositor_surface()
{
if (!m_compositor_surface_id.has_value())
return;
if (has_compositor_context())
compositor_context().set_presentation_mode(Empty {});
m_compositor_surface_id.clear();
compositor_context().set_parent_context({});
}
void Navigable::destroy_compositor_context()
{
clear_compositor_surface();
clear_parent_compositor_context();
m_compositor_context.clear();
}
@ -3793,11 +3780,8 @@ void Navigable::repaint_after_compositor_process_reconnect()
if (has_compositor_context()) {
if (auto parent = this->parent();
parent && parent->has_compositor_context() && has_compositor_surface_id()) {
compositor_context().set_presentation_mode(Compositor::PublishToCompositorSurface {
.target_context_id = parent->compositor_context().id(),
.surface_id = *m_compositor_surface_id,
});
parent && parent->has_compositor_context()) {
compositor_context().set_parent_context(parent->compositor_context().id());
}
compositor_context().viewport_size_updated(
page().css_to_device_rect(viewport_rect()).size().to_type<int>(),
@ -3909,9 +3893,8 @@ void Navigable::paint_next_frame()
if (is_top_level_traversable()) {
paint_config.canvas_fill_rect = Gfx::IntRect { {}, viewport_rect.size() };
} else {
// Nested navigables publish transparent bitmaps to their preconfigured compositor surface instead of filling
// the canvas for the UI process.
if (!m_compositor_surface_id.has_value())
// Nested navigables paint transparent bitmaps for their parent compositor context.
if (!parent() || !parent()->has_compositor_context())
return;
}

View file

@ -271,11 +271,13 @@ public:
VERIFY(m_compositor_context);
return *m_compositor_context;
}
Compositor::CompositorContextHandle const& compositor_context() const
{
VERIFY(m_compositor_context);
return *m_compositor_context;
}
bool has_compositor_context() const { return m_compositor_context; }
Painting::CompositorSurfaceId compositor_surface_id() const;
bool has_compositor_surface_id() const { return m_compositor_surface_id.has_value(); }
void set_pending_set_browser_zoom_request(bool value) { m_pending_set_browser_zoom_request = value; }
bool pending_set_browser_zoom_request() const { return m_pending_set_browser_zoom_request; }
@ -319,7 +321,7 @@ private:
void reset_cursor_blink_cycle();
void scroll_offset_did_change();
void clear_compositor_surface();
void clear_parent_compositor_context();
void destroy_compositor_context();
void inform_the_navigation_api_about_aborting_navigation();
@ -389,7 +391,6 @@ private:
Painting::DisplayListResourceStorage m_display_list_resource_storage;
Painting::DisplayListResourceSet m_compositor_display_list_resources;
OwnPtr<Compositor::CompositorContextHandle> m_compositor_context;
Optional<Painting::CompositorSurfaceId> m_compositor_surface_id;
RefPtr<Core::Timer> m_async_scroll_hover_update_timer;
struct PendingAsyncScrollOperation {

View file

@ -40,7 +40,7 @@ void DrawRepeatedDecodedImageFrame::dump(StringBuilder& builder) const
builder.appendff(" dst_rect={} clip_rect={}", dst_rect, clip_rect);
}
void DrawCompositorSurface::dump(StringBuilder& builder) const
void DrawCompositedContext::dump(StringBuilder& builder) const
{
builder.appendff(" dst_rect={}", dst_rect);
}

View file

@ -24,6 +24,7 @@
#include <LibGfx/Rect.h>
#include <LibGfx/ScalingMode.h>
#include <LibGfx/Size.h>
#include <LibWeb/Compositor/Types.h>
#include <LibWeb/Forward.h>
#include <LibWeb/Painting/AccumulatedVisualContext.h>
#include <LibWeb/Painting/DisplayListResourceIds.h>
@ -38,7 +39,7 @@ class DisplayList;
V(FillRect, fill_rect) \
V(DrawScaledDecodedImageFrame, draw_scaled_decoded_image_frame) \
V(DrawRepeatedDecodedImageFrame, draw_repeated_decoded_image_frame) \
V(DrawCompositorSurface, draw_compositor_surface) \
V(DrawCompositedContext, draw_composited_context) \
V(DrawCanvas, draw_canvas) \
V(DrawVideoFrame, draw_video_frame) \
V(Save, save) \
@ -188,12 +189,12 @@ struct DrawRepeatedDecodedImageFrame {
void dump(StringBuilder&) const;
};
struct DrawCompositorSurface {
static constexpr StringView command_name = "DrawCompositorSurface"sv;
static constexpr DisplayListCommandType command_type = DisplayListCommandType::DrawCompositorSurface;
struct DrawCompositedContext {
static constexpr StringView command_name = "DrawCompositedContext"sv;
static constexpr DisplayListCommandType command_type = DisplayListCommandType::DrawCompositedContext;
Gfx::IntRect dst_rect;
CompositorSurfaceId surface_id;
Web::Compositor::CompositorContextId child_context_id;
Gfx::ScalingMode scaling_mode;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; }

View file

@ -65,9 +65,9 @@ void DisplayListPlayerSkia::execute(
ScrollStateSnapshot const& scroll_state_snapshot,
RefPtr<Gfx::PaintingSurface> surface,
CanvasSurfaceRegistry const* canvas_surface_registry,
CompositorSurfaceMap const* compositor_surfaces)
CompositedContextResolver const* composited_context_resolver)
{
TemporaryChange compositor_surfaces_change { m_compositor_surfaces, compositor_surfaces };
TemporaryChange composited_context_resolver_change { m_composited_context_resolver, composited_context_resolver };
DisplayListPlayer::execute(
display_list,
visual_context_tree,
@ -225,16 +225,16 @@ void DisplayListPlayerSkia::play_command(FillRect const& command)
canvas.drawRect(to_skia_rect(rect), paint);
}
void DisplayListPlayerSkia::play_command(DrawCompositorSurface const& command)
void DisplayListPlayerSkia::play_command(DrawCompositedContext const& command)
{
if (!m_compositor_surfaces)
if (!m_composited_context_resolver)
return;
auto compositor_surface = m_compositor_surfaces->get(command.surface_id);
if (!compositor_surface.has_value())
auto composited_context_surface = (*m_composited_context_resolver)(command.child_context_id);
if (!composited_context_surface)
return;
auto image = compositor_surface.value()->sk_image_snapshot<sk_sp<SkImage>>();
auto image = composited_context_surface->sk_image_snapshot<sk_sp<SkImage>>();
if (!image)
return;

View file

@ -7,7 +7,6 @@
#pragma once
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/NonnullRefPtr.h>
#include <AK/RefPtr.h>
#include <LibGfx/Forward.h>
@ -22,7 +21,7 @@ namespace Web::Painting {
class WEB_API DisplayListPlayerSkia final : public DisplayListPlayer {
public:
using CompositorSurfaceMap = HashMap<CompositorSurfaceId, NonnullRefPtr<Gfx::PaintingSurface>>;
using CompositedContextResolver = Function<RefPtr<Gfx::PaintingSurface>(Web::Compositor::CompositorContextId)>;
DisplayListPlayerSkia();
explicit DisplayListPlayerSkia(RefPtr<Gfx::SkiaBackendContext>);
@ -36,7 +35,7 @@ public:
ScrollStateSnapshot const&,
RefPtr<Gfx::PaintingSurface>,
CanvasSurfaceRegistry const*,
CompositorSurfaceMap const*);
CompositedContextResolver const*);
void flush(Gfx::PaintingSurface&) override;
void flush_async(Gfx::PaintingSurface&, Function<void()>&&);
@ -60,7 +59,7 @@ private:
ReadonlySpan<float> gradient_positions(DisplayListGradientColorStops) const;
RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
CompositorSurfaceMap const* m_compositor_surfaces { nullptr };
CompositedContextResolver const* m_composited_context_resolver { nullptr };
};
}

View file

@ -512,13 +512,13 @@ void DisplayListRecorder::draw_rect(Gfx::IntRect const& rect, Color color, bool
.rough = rough });
}
void DisplayListRecorder::draw_compositor_surface(Gfx::IntRect const& dst_rect, CompositorSurfaceId surface_id, Gfx::ScalingMode scaling_mode)
void DisplayListRecorder::draw_composited_context(Gfx::IntRect const& dst_rect, Web::Compositor::CompositorContextId child_context_id, Gfx::ScalingMode scaling_mode)
{
if (dst_rect.is_empty())
return;
append_command(DrawCompositorSurface {
append_command(DrawCompositedContext {
.dst_rect = dst_rect,
.surface_id = surface_id,
.child_context_id = child_context_id,
.scaling_mode = scaling_mode,
});
}

View file

@ -73,7 +73,7 @@ public:
void draw_rect(Gfx::IntRect const& rect, Color color, bool rough = false);
void draw_scaled_decoded_image_frame(Gfx::IntRect const& dst_rect, Gfx::DecodedImageFrame frame, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
void draw_compositor_surface(Gfx::IntRect const& dst_rect, CompositorSurfaceId, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
void draw_composited_context(Gfx::IntRect const& dst_rect, Web::Compositor::CompositorContextId, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
void draw_canvas(Gfx::IntRect const& dst_rect, CanvasId, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
void draw_video_frame(Gfx::IntRect const& dst_rect, VideoFrameResourceId, RefPtr<Media::VideoFrame const>, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);

View file

@ -16,7 +16,6 @@ AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, FontResourceId);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, ImageFrameResourceId);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, VideoFrameResourceId);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, DisplayListResourceId);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, CompositorSurfaceId);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, CanvasId);
inline VideoFrameResourceId allocate_video_frame_resource_id()
@ -25,10 +24,4 @@ inline VideoFrameResourceId allocate_video_frame_resource_id()
return VideoFrameResourceId { s_next_id.fetch_add(1, AK::MemoryOrder::memory_order_relaxed) };
}
inline CompositorSurfaceId allocate_compositor_surface_id()
{
static Atomic<u64> s_next_id { 1 };
return CompositorSurfaceId { s_next_id.fetch_add(1, AK::MemoryOrder::memory_order_relaxed) };
}
}

View file

@ -47,14 +47,14 @@ void NavigableContainerViewportPaintable::paint(DisplayListRecordingContext& con
auto content_navigable = navigable_container.content_navigable();
VERIFY(content_navigable);
if (content_navigable->has_been_destroyed() || !content_navigable->has_compositor_surface_id())
if (content_navigable->has_been_destroyed() || !content_navigable->has_compositor_context())
return;
context.display_list_recorder().save();
context.display_list_recorder().add_clip_rect(clip_rect.to_type<int>());
context.display_list_recorder().draw_compositor_surface(
context.display_list_recorder().draw_composited_context(
context.enclosing_device_rect(absolute_rect).to_type<int>(),
content_navigable->compositor_surface_id(),
content_navigable->compositor_context().id(),
Gfx::ScalingMode::NearestNeighbor);
context.display_list_recorder().restore();

View file

@ -164,6 +164,11 @@ bool BackingStoreManager::is_valid() const
return m_backing_stores.is_valid();
}
RefPtr<Gfx::PaintingSurface> BackingStoreManager::front_store_if_present() const
{
return m_backing_stores.front_store;
}
Gfx::PaintingSurface& BackingStoreManager::front_store()
{
VERIFY(m_backing_stores.front_store);

View file

@ -41,6 +41,7 @@ public:
Optional<Publication> allocate_backing_stores(Allocation const&, RefPtr<Gfx::SkiaBackendContext> const&, bool should_publish);
bool is_valid() const;
RefPtr<Gfx::PaintingSurface> front_store_if_present() const;
Gfx::PaintingSurface& front_store();
Gfx::PaintingSurface& back_store();
i32 back_bitmap_id() const;

View file

@ -81,39 +81,50 @@ void CompositorState::destroy_context(Web::Compositor::CompositorContextId conte
VERIFY(context);
cancel_pending_async_presents_for_context(context_id);
detach_from_parent_surface(context_id, *context);
for (auto& child_context_entry : context->child_contexts()) {
auto* child_context = context_if_present(child_context_entry.child_context_id);
VERIFY(child_context);
child_context->did_detach_from_parent_surface(context_id, child_context_entry.surface_id);
clear_parent_context(*context);
for (auto& context_entry : m_contexts) {
if (context_entry.key == context_id)
continue;
auto& possible_child_context = *context_entry.value;
auto parent_context_id = possible_child_context.parent_context_id();
if (parent_context_id.has_value() && *parent_context_id == context_id)
possible_child_context.set_parent_context({});
}
m_contexts.remove(context_id);
}
void CompositorState::set_presentation_mode(Web::Compositor::CompositorContextId context_id, Web::Compositor::PresentationMode presentation_mode)
void CompositorState::set_parent_context(Web::Compositor::CompositorContextId context_id, Optional<Web::Compositor::CompositorContextId> parent_context_id)
{
auto* context = context_if_present(context_id);
VERIFY(context);
auto& context_state = *context;
auto was_presenting_to_client = context_state.presents_to_client();
auto will_present_to_client = ContextState::presentation_mode_presents_to_client(presentation_mode);
detach_from_parent_surface(context_id, context_state);
if (parent_context_id.has_value()) {
VERIFY(!context->presents_to_client());
VERIFY(*parent_context_id != context_id);
VERIFY(context_if_present(*parent_context_id));
}
presentation_mode.visit(
[](Empty const&) {},
[](Web::Compositor::PresentToClient const&) {},
[&](Web::Compositor::PublishToCompositorSurface const& mode) {
auto* parent_context = context_if_present(mode.target_context_id);
VERIFY(parent_context);
parent_context->attach_child_surface(mode.surface_id, context_id);
context_state.set_published_surface({
.parent_context_id = mode.target_context_id,
.surface_id = mode.surface_id,
});
});
context_state.set_presentation_mode(move(presentation_mode));
context_state.did_stop_presenting_to_client_if_needed(was_presenting_to_client, will_present_to_client);
auto current_parent_context_id = context->parent_context_id();
if (current_parent_context_id.has_value() == parent_context_id.has_value()
&& (!current_parent_context_id.has_value() || *current_parent_context_id == *parent_context_id))
return;
clear_parent_context(*context);
context->set_parent_context(parent_context_id);
if (!parent_context_id.has_value() || !context->latest_rendered_surface())
return;
auto* parent_context = context_if_present(*parent_context_id);
VERIFY(parent_context);
present_current_frame(*parent_context_id, *parent_context);
}
void CompositorState::stop_presenting_to_client(Web::Compositor::CompositorContextId context_id)
{
auto* context = context_if_present(context_id);
VERIFY(context);
context->stop_presenting_to_client();
}
void CompositorState::update_display_list(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Web::Painting::DisplayList> display_list, Web::Painting::AccumulatedVisualContextTree visual_context_tree, Web::Painting::DisplayListResourceTransaction&& resource_transaction, Web::Painting::ScrollStateSnapshot&& scroll_state_snapshot)
@ -269,7 +280,8 @@ void CompositorState::present_frame(Web::Compositor::CompositorContextId context
void CompositorState::present_frame(Web::Compositor::CompositorContextId context_id, ContextState& context, Gfx::IntRect viewport_rect)
{
auto prepared_frame = context.prepare_frame(*m_display_list_player, viewport_rect);
auto composited_context_resolver = resolver_for(context_id);
auto prepared_frame = context.prepare_frame(*m_display_list_player, viewport_rect, &composited_context_resolver);
if (!prepared_frame.has_value())
return;
@ -339,8 +351,11 @@ void CompositorState::flush_descendant_surfaces_for_screenshot(Web::Compositor::
// present synchronously (deepest-first) — to capture a complete frame instead of a stale/blank iframe.
auto* context = context_if_present(context_id);
VERIFY(context);
for (auto& child : context->child_contexts())
present_subtree_for_screenshot(child.child_context_id);
for (auto& context_entry : m_contexts) {
auto parent_context_id = context_entry.value->parent_context_id();
if (parent_context_id.has_value() && *parent_context_id == context_id)
present_subtree_for_screenshot(context_entry.key);
}
}
bool CompositorState::present_subtree_for_screenshot(Web::Compositor::CompositorContextId context_id)
@ -349,23 +364,24 @@ bool CompositorState::present_subtree_for_screenshot(Web::Compositor::Compositor
VERIFY(context);
bool needs_present = context->needs_synchronous_present_for_screenshot();
for (auto& child : context->child_contexts()) {
if (present_subtree_for_screenshot(child.child_context_id))
for (auto& context_entry : m_contexts) {
auto parent_context_id = context_entry.value->parent_context_id();
if (parent_context_id.has_value()
&& *parent_context_id == context_id
&& present_subtree_for_screenshot(context_entry.key))
needs_present = true;
}
if (!needs_present || !context->publishes_to_parent_surface())
if (!needs_present)
return false;
present_context_synchronously(*context);
return true;
return present_context_synchronously(context_id, *context);
}
void CompositorState::present_context_synchronously(ContextState& context)
bool CompositorState::present_context_synchronously(Web::Compositor::CompositorContextId context_id, ContextState& context)
{
auto publish_mode = context.present_synchronously(*m_display_list_player);
if (publish_mode.has_value())
publish_to_parent_surface(context, *publish_mode);
auto composited_context_resolver = resolver_for(context_id);
return context.present_synchronously(*m_display_list_player, &composited_context_resolver);
}
bool CompositorState::request_screenshot(Web::Compositor::CompositorContextId context_id, Gfx::ShareableBitmap& target_bitmap)
@ -377,7 +393,8 @@ bool CompositorState::request_screenshot(Web::Compositor::CompositorContextId co
return false;
flush_descendant_surfaces_for_screenshot(context_id);
context->paint_screenshot(*m_display_list_player, target_bitmap);
auto composited_context_resolver = resolver_for(context_id);
context->paint_screenshot(*m_display_list_player, target_bitmap, &composited_context_resolver);
return true;
}
@ -417,15 +434,15 @@ void CompositorState::did_finish_async_present(PendingAsyncPresent& pending_pres
VERIFY(context);
context->did_finish_gpu_present(bitmap_id);
context->presentation_mode().visit(
[](Empty const&) {},
[&](Web::Compositor::PresentToClient const&) {
VERIFY(m_client);
m_client->did_present_frame(context_id, viewport_rect, bitmap_id);
},
[&](Web::Compositor::PublishToCompositorSurface const& mode) {
publish_to_parent_surface(*context, mode);
});
if (context->presents_to_client()) {
VERIFY(m_client);
m_client->did_present_frame(context_id, viewport_rect, bitmap_id);
}
if (auto parent_context_id = context->parent_context_id(); parent_context_id.has_value()) {
auto* parent_context = context_if_present(*parent_context_id);
VERIFY(parent_context);
present_current_frame(*parent_context_id, *parent_context);
}
schedule_pending_present_frame_if_unblocked(context_id, *context);
}
@ -484,19 +501,35 @@ ContextState const* CompositorState::context_if_present(Web::Compositor::Composi
return it->value.ptr();
}
void CompositorState::detach_from_parent_surface(Web::Compositor::CompositorContextId context_id, ContextState& context)
void CompositorState::clear_parent_context(ContextState& context)
{
auto published_surface = context.take_published_surface();
if (!published_surface.has_value())
auto parent_context_id = context.parent_context_id();
if (!parent_context_id.has_value())
return;
auto* parent_context = context_if_present(published_surface->parent_context_id);
VERIFY(parent_context);
auto removed_child_context_id = parent_context->take_child_context_for_surface(published_surface->surface_id);
VERIFY(removed_child_context_id.has_value());
VERIFY(*removed_child_context_id == context_id);
parent_context->clear_compositor_surface(published_surface->surface_id);
present_current_frame(published_surface->parent_context_id, *parent_context);
context.set_parent_context({});
auto* parent_context = context_if_present(*parent_context_id);
if (!parent_context)
return;
present_current_frame(*parent_context_id, *parent_context);
}
CompositedContextResolver CompositorState::resolver_for(Web::Compositor::CompositorContextId parent_context_id)
{
return [this, parent_context_id](Web::Compositor::CompositorContextId child_context_id) {
return resolve_composited_context(parent_context_id, child_context_id);
};
}
RefPtr<Gfx::PaintingSurface> CompositorState::resolve_composited_context(Web::Compositor::CompositorContextId parent_context_id, Web::Compositor::CompositorContextId child_context_id)
{
auto* child_context = context_if_present(child_context_id);
if (!child_context)
return nullptr;
auto child_parent_context_id = child_context->parent_context_id();
if (!child_parent_context_id.has_value() || *child_parent_context_id != parent_context_id)
return nullptr;
return child_context->latest_rendered_surface();
}
void CompositorState::resize_backing_stores_if_needed(Web::Compositor::CompositorContextId context_id, ContextState& context)
@ -533,15 +566,6 @@ void CompositorState::present_current_frame(Web::Compositor::CompositorContextId
schedule_present_frame(context_id, context, *frame_to_present);
}
void CompositorState::publish_to_parent_surface(ContextState& context, Web::Compositor::PublishToCompositorSurface const& mode)
{
auto* parent_context = context_if_present(mode.target_context_id);
VERIFY(parent_context);
parent_context->update_compositor_surface(mode.surface_id, context.snapshot_front_store());
present_current_frame(mode.target_context_id, *parent_context);
}
bool CompositorState::apply_context_update_result(
Web::Compositor::CompositorContextId context_id,
ContextState& context,

View file

@ -77,7 +77,7 @@ public:
void create_context(Web::Compositor::CompositorContextId, Optional<u64> page_id, CompositorStateWebContentClient&);
void destroy_context(Web::Compositor::CompositorContextId);
void set_presentation_mode(Web::Compositor::CompositorContextId, Web::Compositor::PresentationMode);
void set_parent_context(Web::Compositor::CompositorContextId, Optional<Web::Compositor::CompositorContextId> parent_context_id);
void stop_presenting_to_client(Web::Compositor::CompositorContextId);
void update_display_list(Web::Compositor::CompositorContextId, NonnullRefPtr<Web::Painting::DisplayList>, Web::Painting::AccumulatedVisualContextTree, Web::Painting::DisplayListResourceTransaction&&, Web::Painting::ScrollStateSnapshot&&);
void update_visual_context_tree(Web::Compositor::CompositorContextId, Web::Painting::AccumulatedVisualContextTree);
@ -117,12 +117,13 @@ private:
ContextState* context_if_present(Web::Compositor::CompositorContextId);
ContextState const* context_if_present(Web::Compositor::CompositorContextId) const;
void detach_from_parent_surface(Web::Compositor::CompositorContextId, ContextState&);
void clear_parent_context(ContextState&);
CompositedContextResolver resolver_for(Web::Compositor::CompositorContextId parent_context_id);
RefPtr<Gfx::PaintingSurface> resolve_composited_context(Web::Compositor::CompositorContextId parent_context_id, Web::Compositor::CompositorContextId child_context_id);
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&);
bool apply_context_update_result(
Web::Compositor::CompositorContextId,
ContextState&,
@ -135,7 +136,7 @@ private:
void present_pending_frames_on_vsync(Optional<u64> display_id);
void flush_descendant_surfaces_for_screenshot(Web::Compositor::CompositorContextId);
bool present_subtree_for_screenshot(Web::Compositor::CompositorContextId);
void present_context_synchronously(ContextState&);
bool present_context_synchronously(Web::Compositor::CompositorContextId, ContextState&);
void publish_backing_stores(Web::Compositor::CompositorContextId, ContextState&, BackingStoreManager::Publication&&);
void did_finish_async_present(PendingAsyncPresent&);
void cancel_pending_async_presents_for_context(Web::Compositor::CompositorContextId);

View file

@ -1,4 +1,5 @@
#include <AK/NonnullRefPtr.h>
#include <AK/Optional.h>
#include <LibCore/AnonymousBuffer.h>
#include <LibGfx/CanvasCommandList.h>
#include <LibGfx/DecodedImageFrame.h>
@ -19,7 +20,8 @@ endpoint CompositorWebContentServer
{
init_transport(int peer_pid) => (int compositor_pid)
set_presentation_mode(Web::Compositor::CompositorContextId context_id, Web::Compositor::PresentationMode presentation_mode) =|
set_parent_context(Web::Compositor::CompositorContextId context_id, Optional<Web::Compositor::CompositorContextId> parent_context_id) =|
stop_presenting_to_client(Web::Compositor::CompositorContextId context_id) =|
destroy_context(Web::Compositor::CompositorContextId context_id) =|
update_display_list(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Web::Painting::DisplayList> display_list, Web::Painting::AccumulatedVisualContextTree visual_context_tree, Web::Painting::DisplayListResourceTransaction resource_transaction, Web::Painting::ScrollStateSnapshot scroll_state_snapshot) =|

View file

@ -64,10 +64,16 @@ void ConnectionFromWebContent::verify_context_is_owned_by_this_connection(Web::C
VERIFY_NOT_REACHED();
}
void ConnectionFromWebContent::set_presentation_mode(Web::Compositor::CompositorContextId context_id, Web::Compositor::PresentationMode presentation_mode)
void ConnectionFromWebContent::set_parent_context(Web::Compositor::CompositorContextId context_id, Optional<Web::Compositor::CompositorContextId> parent_context_id)
{
verify_context_is_owned_by_this_connection(context_id);
m_compositor_state->set_presentation_mode(context_id, move(presentation_mode));
m_compositor_state->set_parent_context(context_id, parent_context_id);
}
void ConnectionFromWebContent::stop_presenting_to_client(Web::Compositor::CompositorContextId context_id)
{
verify_context_is_owned_by_this_connection(context_id);
m_compositor_state->stop_presenting_to_client(context_id);
}
void ConnectionFromWebContent::destroy_context(Web::Compositor::CompositorContextId context_id)

View file

@ -37,7 +37,8 @@ private:
virtual void die() override;
virtual Messages::CompositorWebContentServer::InitTransportResponse init_transport(int peer_pid) override;
virtual void set_presentation_mode(Web::Compositor::CompositorContextId, Web::Compositor::PresentationMode) override;
virtual void set_parent_context(Web::Compositor::CompositorContextId, Optional<Web::Compositor::CompositorContextId>) override;
virtual void stop_presenting_to_client(Web::Compositor::CompositorContextId) override;
virtual void destroy_context(Web::Compositor::CompositorContextId) override;
virtual void update_display_list(Web::Compositor::CompositorContextId, NonnullRefPtr<Web::Painting::DisplayList>, Web::Painting::AccumulatedVisualContextTree, Web::Painting::DisplayListResourceTransaction, Web::Painting::ScrollStateSnapshot) override;
virtual void update_visual_context_tree(Web::Compositor::CompositorContextId, Web::Painting::AccumulatedVisualContextTree) override;

View file

@ -13,7 +13,6 @@
#include <LibGfx/Color.h>
#include <LibGfx/PainterSkia.h>
#include <LibGfx/PaintingSurface.h>
#include <LibGfx/SharedImageBuffer.h>
#include <LibWeb/Page/InputEvent.h>
#include <LibWeb/Painting/DisplayListPlayerSkia.h>
@ -88,7 +87,7 @@ ContextState::ContextState(Optional<u64> page_id, CompositorStateWebContentClien
, m_async_scrolling_enabled(async_scrolling_enabled)
{
if (page_id.has_value())
m_presentation_mode = Web::Compositor::PresentToClient {};
m_presents_to_client = true;
}
ContextState::~ContextState()
@ -96,11 +95,6 @@ ContextState::~ContextState()
stop_backing_store_shrink_timer();
}
bool ContextState::presentation_mode_presents_to_client(Web::Compositor::PresentationMode const& presentation_mode)
{
return presentation_mode.has<Web::Compositor::PresentToClient>();
}
bool ContextState::is_owned_by(CompositorStateWebContentClient const& web_content_client) const
{
return &m_web_content_client == &web_content_client;
@ -117,11 +111,11 @@ void ContextState::dispatch_mouse_event_to_web_content(Web::MouseEvent const& ev
m_web_content_client.dispatch_mouse_event_to_web_content(*m_page_id, event);
}
void ContextState::set_presentation_mode(Web::Compositor::PresentationMode presentation_mode)
void ContextState::stop_presenting_to_client()
{
if (presentation_mode_presents_to_client(presentation_mode))
VERIFY(m_page_id.has_value());
m_presentation_mode = move(presentation_mode);
auto was_presenting_to_client = m_presents_to_client;
m_presents_to_client = false;
did_stop_presenting_to_client_if_needed(was_presenting_to_client, m_presents_to_client);
}
void ContextState::did_stop_presenting_to_client_if_needed(bool was_presenting_to_client, bool will_present_to_client)
@ -132,44 +126,9 @@ void ContextState::did_stop_presenting_to_client_if_needed(bool was_presenting_t
m_presented_bitmap_id_awaiting_ack.clear();
}
void ContextState::set_published_surface(PublishedSurface published_surface)
void ContextState::set_parent_context(Optional<Web::Compositor::CompositorContextId> parent_context_id)
{
m_published_surface = published_surface;
}
Optional<ContextState::PublishedSurface> ContextState::take_published_surface()
{
if (!m_published_surface.has_value())
return {};
return m_published_surface.release_value();
}
void ContextState::did_detach_from_parent_surface(Web::Compositor::CompositorContextId parent_context_id, Web::Painting::CompositorSurfaceId surface_id)
{
VERIFY(m_published_surface.has_value());
VERIFY(m_published_surface->parent_context_id == parent_context_id);
VERIFY(m_published_surface->surface_id == surface_id);
m_published_surface.clear();
m_presentation_mode = Empty {};
}
void ContextState::attach_child_surface(Web::Painting::CompositorSurfaceId surface_id, Web::Compositor::CompositorContextId child_context_id)
{
m_child_contexts_by_surface_id.set(surface_id, child_context_id);
}
Optional<Web::Compositor::CompositorContextId> ContextState::take_child_context_for_surface(Web::Painting::CompositorSurfaceId surface_id)
{
return m_child_contexts_by_surface_id.take(surface_id);
}
Vector<ContextState::ChildSurface> ContextState::child_contexts() const
{
Vector<ChildSurface> child_contexts;
child_contexts.ensure_capacity(m_child_contexts_by_surface_id.size());
for (auto& child_context : m_child_contexts_by_surface_id)
child_contexts.unchecked_append({ child_context.key, child_context.value });
return child_contexts;
m_parent_context_id = parent_context_id;
}
void ContextState::apply_display_list_resource_transaction(Web::Painting::DisplayListResourceTransaction&& resource_transaction)
@ -259,22 +218,6 @@ void ContextState::clear_video_frame(Web::Painting::VideoFrameResourceId frame_i
m_display_list_resource_storage.clear_video_frame(frame_id);
}
void ContextState::update_compositor_surface(Web::Painting::CompositorSurfaceId surface_id, Gfx::SharedImage&& shared_image)
{
auto shared_image_buffer = Gfx::SharedImageBuffer::import_from_shared_image(move(shared_image));
m_compositor_surfaces.set(surface_id, Gfx::PaintingSurface::wrap_bitmap(*shared_image_buffer.bitmap()));
}
void ContextState::clear_compositor_surface(Web::Painting::CompositorSurfaceId surface_id)
{
m_compositor_surfaces.remove(surface_id);
}
Gfx::SharedImage ContextState::snapshot_front_store()
{
return m_backing_store_manager.front_store().snapshot_into_shared_image();
}
void ContextState::invalidate_wheel_event_listener_state(u64 generation)
{
m_wheel_event_listener_state_generation = max(m_wheel_event_listener_state_generation, generation);
@ -618,7 +561,7 @@ Optional<Gfx::IntRect> ContextState::current_frame_rect_to_present() const
return m_presented_frame;
}
Optional<ContextState::PreparedFrame> ContextState::prepare_frame(Web::Painting::DisplayListPlayerSkia& display_list_player, Gfx::IntRect viewport_rect)
Optional<ContextState::PreparedFrame> ContextState::prepare_frame(Web::Painting::DisplayListPlayerSkia& display_list_player, Gfx::IntRect viewport_rect, CompositedContextResolver const* composited_context_resolver)
{
if (is_present_blocked()) {
m_pending_present_frame = viewport_rect;
@ -631,14 +574,11 @@ Optional<ContextState::PreparedFrame> ContextState::prepare_frame(Web::Painting:
}
auto& back_store = m_backing_store_manager.back_store();
m_presentation_mode.visit(
[](Empty const&) {},
[](Web::Compositor::PresentToClient const&) {},
[&](Web::Compositor::PublishToCompositorSurface const&) {
Gfx::PainterSkia painter { NonnullRefPtr<Gfx::PaintingSurface> { back_store } };
painter.clear_rect(back_store.rect().to_type<float>(), Gfx::Color::Transparent);
});
paint_current_display_list(display_list_player, back_store);
if (!presents_to_client()) {
Gfx::PainterSkia painter { NonnullRefPtr<Gfx::PaintingSurface> { back_store } };
painter.clear_rect(back_store.rect().to_type<float>(), Gfx::Color::Transparent);
}
paint_current_display_list(display_list_player, back_store, composited_context_resolver);
auto rendered_bitmap_id = m_backing_store_manager.back_bitmap_id();
m_gpu_present_bitmap_id_awaiting_completion = rendered_bitmap_id;
@ -656,34 +596,33 @@ void ContextState::did_submit_prepared_frame(Gfx::IntRect viewport_rect)
m_presented_frame = viewport_rect;
}
Optional<Web::Compositor::PublishToCompositorSurface> ContextState::present_synchronously(Web::Painting::DisplayListPlayerSkia& display_list_player)
bool ContextState::present_synchronously(Web::Painting::DisplayListPlayerSkia& display_list_player, CompositedContextResolver const* composited_context_resolver)
{
auto* publish_mode = m_presentation_mode.get_pointer<Web::Compositor::PublishToCompositorSurface>();
VERIFY(publish_mode);
if (!can_render_frame())
return {};
// Don't race an async present already in flight for this context; its own completion will publish.
return false;
// Don't race an async present already in flight for this context; its own completion will update the output.
if (is_present_blocked())
return {};
return false;
auto viewport_rect = m_pending_present_frame;
if (!viewport_rect.has_value())
viewport_rect = m_presented_frame;
if (!viewport_rect.has_value())
return {};
return false;
auto& back_store = m_backing_store_manager.back_store();
{
if (!presents_to_client()) {
Gfx::PainterSkia painter { NonnullRefPtr<Gfx::PaintingSurface> { back_store } };
painter.clear_rect(back_store.rect().to_type<float>(), Gfx::Color::Transparent);
}
paint_current_display_list(display_list_player, back_store);
paint_current_display_list(display_list_player, back_store, composited_context_resolver);
display_list_player.flush(back_store);
m_backing_store_manager.swap();
m_latest_rendered_surface = m_backing_store_manager.front_store_if_present();
m_presented_frame = viewport_rect;
m_pending_present_frame.clear();
m_pending_present_frame_scheduled = false;
return *publish_mode;
return true;
}
bool ContextState::can_paint_screenshot(Gfx::ShareableBitmap& target_bitmap) const
@ -691,12 +630,12 @@ bool ContextState::can_paint_screenshot(Gfx::ShareableBitmap& target_bitmap) con
return m_display_list && target_bitmap.is_valid() && target_bitmap.bitmap();
}
void ContextState::paint_screenshot(Web::Painting::DisplayListPlayerSkia& display_list_player, Gfx::ShareableBitmap& target_bitmap)
void ContextState::paint_screenshot(Web::Painting::DisplayListPlayerSkia& display_list_player, Gfx::ShareableBitmap& target_bitmap, CompositedContextResolver const* composited_context_resolver)
{
VERIFY(can_paint_screenshot(target_bitmap));
auto target_surface = Gfx::PaintingSurface::wrap_bitmap(*target_bitmap.bitmap());
paint_current_display_list(display_list_player, *target_surface);
paint_current_display_list(display_list_player, *target_surface, composited_context_resolver);
display_list_player.flush(*target_surface);
}
@ -713,6 +652,7 @@ void ContextState::did_finish_gpu_present(i32 bitmap_id)
{
VERIFY(m_gpu_present_bitmap_id_awaiting_completion == bitmap_id);
m_gpu_present_bitmap_id_awaiting_completion.clear();
m_latest_rendered_surface = m_backing_store_manager.front_store_if_present();
}
void ContextState::stop_backing_store_shrink_timer()
@ -878,7 +818,7 @@ Web::Painting::AccumulatedVisualContextTree const& ContextState::visual_context_
return *m_visual_context_tree_for_compositing;
}
void ContextState::paint_current_display_list(Web::Painting::DisplayListPlayerSkia& display_list_player, Gfx::PaintingSurface& surface)
void ContextState::paint_current_display_list(Web::Painting::DisplayListPlayerSkia& display_list_player, Gfx::PaintingSurface& surface, CompositedContextResolver const* composited_context_resolver)
{
VERIFY(m_display_list);
display_list_player.execute(
@ -888,7 +828,7 @@ void ContextState::paint_current_display_list(Web::Painting::DisplayListPlayerSk
m_scroll_state_snapshot,
surface,
&m_canvas_surface_registry,
&m_compositor_surfaces);
composited_context_resolver);
m_viewport_scrollbar_controller.paint(surface, display_list_player, m_scroll_state_snapshot);
}

View file

@ -7,7 +7,6 @@
#pragma once
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/Noncopyable.h>
#include <AK/NonnullRefPtr.h>
#include <AK/Optional.h>
@ -20,7 +19,6 @@
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/ShareableBitmap.h>
#include <LibGfx/SharedImage.h>
#include <LibGfx/Size.h>
#include <LibWeb/Compositor/AsyncScrollTree.h>
#include <LibWeb/Compositor/AsyncScrollingState.h>
@ -53,22 +51,13 @@ class DisplayListPlayerSkia;
namespace Compositor {
class CompositorStateWebContentClient;
using CompositedContextResolver = Function<RefPtr<Gfx::PaintingSurface>(Web::Compositor::CompositorContextId)>;
class ContextState {
AK_MAKE_NONCOPYABLE(ContextState);
AK_MAKE_NONMOVABLE(ContextState);
public:
struct PublishedSurface {
Web::Compositor::CompositorContextId parent_context_id;
Web::Painting::CompositorSurfaceId surface_id;
};
struct ChildSurface {
Web::Painting::CompositorSurfaceId surface_id;
Web::Compositor::CompositorContextId child_context_id;
};
struct AsyncScrollResult {
Web::Compositor::AsyncScrollEnqueueResult enqueue_result;
Optional<Gfx::IntRect> frame_to_present;
@ -88,24 +77,17 @@ public:
ContextState(Optional<u64> page_id, CompositorStateWebContentClient&, Web::Painting::CanvasSurfaceRegistry const&, bool async_scrolling_enabled);
~ContextState();
static bool presentation_mode_presents_to_client(Web::Compositor::PresentationMode const&);
bool is_owned_by(CompositorStateWebContentClient const&) const;
void request_rendering_update();
void dispatch_mouse_event_to_web_content(Web::MouseEvent const&);
bool presents_to_client() const { return presentation_mode_presents_to_client(m_presentation_mode); }
bool publishes_to_parent_surface() const { return m_presentation_mode.has<Web::Compositor::PublishToCompositorSurface>(); }
Web::Compositor::PresentationMode const& presentation_mode() const { return m_presentation_mode; }
void set_presentation_mode(Web::Compositor::PresentationMode);
bool presents_to_client() const { return m_presents_to_client; }
void stop_presenting_to_client();
void did_stop_presenting_to_client_if_needed(bool was_presenting_to_client, bool will_present_to_client);
void set_published_surface(PublishedSurface);
Optional<PublishedSurface> take_published_surface();
void did_detach_from_parent_surface(Web::Compositor::CompositorContextId parent_context_id, Web::Painting::CompositorSurfaceId);
void attach_child_surface(Web::Painting::CompositorSurfaceId, Web::Compositor::CompositorContextId child_context_id);
Optional<Web::Compositor::CompositorContextId> take_child_context_for_surface(Web::Painting::CompositorSurfaceId);
Vector<ChildSurface> child_contexts() const;
void set_parent_context(Optional<Web::Compositor::CompositorContextId>);
Optional<Web::Compositor::CompositorContextId> parent_context_id() const { return m_parent_context_id; }
RefPtr<Gfx::PaintingSurface> latest_rendered_surface() const { return m_latest_rendered_surface; }
void apply_display_list_resource_transaction(Web::Painting::DisplayListResourceTransaction&&);
void install_display_list_update(
@ -116,9 +98,6 @@ public:
void update_scroll_state(Web::Painting::ScrollStateSnapshot&&);
void update_video_frame(Web::Painting::VideoFrameResourceId, NonnullRefPtr<Media::VideoFrame const>);
void clear_video_frame(Web::Painting::VideoFrameResourceId);
void update_compositor_surface(Web::Painting::CompositorSurfaceId, Gfx::SharedImage&&);
void clear_compositor_surface(Web::Painting::CompositorSurfaceId);
Gfx::SharedImage snapshot_front_store();
void invalidate_wheel_event_listener_state(u64 generation);
ContextUpdateResult handle_mouse_event(Web::MouseEvent const&);
@ -150,11 +129,11 @@ public:
Optional<Gfx::IntRect> take_pending_present_frame_if_unblocked();
bool needs_synchronous_present_for_screenshot() const;
Optional<Gfx::IntRect> current_frame_rect_to_present() const;
Optional<PreparedFrame> prepare_frame(Web::Painting::DisplayListPlayerSkia&, Gfx::IntRect);
Optional<PreparedFrame> prepare_frame(Web::Painting::DisplayListPlayerSkia&, Gfx::IntRect, CompositedContextResolver const*);
void did_submit_prepared_frame(Gfx::IntRect);
Optional<Web::Compositor::PublishToCompositorSurface> present_synchronously(Web::Painting::DisplayListPlayerSkia&);
bool present_synchronously(Web::Painting::DisplayListPlayerSkia&, CompositedContextResolver const*);
bool can_paint_screenshot(Gfx::ShareableBitmap&) const;
void paint_screenshot(Web::Painting::DisplayListPlayerSkia&, Gfx::ShareableBitmap&);
void paint_screenshot(Web::Painting::DisplayListPlayerSkia&, Gfx::ShareableBitmap&, CompositedContextResolver const*);
bool acknowledge_presented_bitmap(i32 bitmap_id);
void did_finish_gpu_present(i32 bitmap_id);
@ -176,24 +155,23 @@ private:
bool is_present_blocked() const;
bool can_render_frame() const;
Web::Painting::AccumulatedVisualContextTree const& visual_context_tree_for_compositing() const;
void paint_current_display_list(Web::Painting::DisplayListPlayerSkia&, Gfx::PaintingSurface&);
void paint_current_display_list(Web::Painting::DisplayListPlayerSkia&, Gfx::PaintingSurface&, CompositedContextResolver const*);
CompositorStateWebContentClient& m_web_content_client;
Web::Painting::CanvasSurfaceRegistry const& m_canvas_surface_registry;
Optional<u64> m_page_id;
bool const m_async_scrolling_enabled { true };
Web::Compositor::PresentationMode m_presentation_mode { Empty {} };
Optional<PublishedSurface> m_published_surface;
HashMap<Web::Painting::CompositorSurfaceId, Web::Compositor::CompositorContextId> m_child_contexts_by_surface_id;
bool m_presents_to_client { false };
Optional<Web::Compositor::CompositorContextId> m_parent_context_id;
RefPtr<Web::Painting::DisplayList const> m_display_list;
Optional<Web::Painting::AccumulatedVisualContextTree> m_visual_context_tree;
mutable Optional<Web::Painting::AccumulatedVisualContextTree> m_visual_context_tree_for_compositing;
Web::Painting::DisplayListResourceStorage m_display_list_resource_storage;
HashMap<Web::Painting::CompositorSurfaceId, NonnullRefPtr<Gfx::PaintingSurface>> m_compositor_surfaces;
Web::Painting::ScrollStateSnapshot m_scroll_state_snapshot;
BackingStoreManager m_backing_store_manager;
RefPtr<Gfx::PaintingSurface> m_latest_rendered_surface;
Web::Compositor::AsyncScrollTree m_async_scroll_tree;
ViewportScrollbarController m_viewport_scrollbar_controller;

View file

@ -24,11 +24,18 @@ void CompositorConnection::die()
did_lose_compositor();
}
void CompositorConnection::set_presentation_mode(Web::Compositor::CompositorContextId context_id, Web::Compositor::PresentationMode const& presentation_mode)
void CompositorConnection::set_parent_context(Web::Compositor::CompositorContextId context_id, Optional<Web::Compositor::CompositorContextId> parent_context_id)
{
if (!can_send_message_to_compositor())
return;
async_set_presentation_mode(context_id, presentation_mode);
async_set_parent_context(context_id, parent_context_id);
}
void CompositorConnection::stop_presenting_to_client(Web::Compositor::CompositorContextId context_id)
{
if (!can_send_message_to_compositor())
return;
async_stop_presenting_to_client(context_id);
}
void CompositorConnection::destroy_context(Web::Compositor::CompositorContextId context_id)

View file

@ -37,7 +37,8 @@ class CompositorConnection final
public:
explicit CompositorConnection(NonnullOwnPtr<IPC::Transport>);
void set_presentation_mode(Web::Compositor::CompositorContextId, Web::Compositor::PresentationMode const&);
void set_parent_context(Web::Compositor::CompositorContextId, Optional<Web::Compositor::CompositorContextId>);
void stop_presenting_to_client(Web::Compositor::CompositorContextId);
void destroy_context(Web::Compositor::CompositorContextId);
void update_display_list(Web::Compositor::CompositorContextId, NonnullRefPtr<Web::Painting::DisplayList> const&, Web::Painting::AccumulatedVisualContextTree const&, Web::Painting::DisplayListResourceTransaction const&, Web::Painting::ScrollStateSnapshot const&);
void update_visual_context_tree(Web::Compositor::CompositorContextId, Web::Painting::AccumulatedVisualContextTree const&);

View file

@ -818,7 +818,7 @@ void PageClient::page_did_request_activate_tab()
void PageClient::page_did_close_top_level_traversable()
{
page().top_level_traversable()->compositor_context().set_presentation_mode(Empty {});
page().top_level_traversable()->compositor_context().stop_presenting_to_client();
if (m_webdriver)
m_webdriver->page_did_close_window({}, page().top_level_traversable()->window_handle());

View file

@ -178,10 +178,16 @@ private:
m_client.did_destroy_compositor_context(context_id);
}
virtual void set_presentation_mode(Web::Compositor::CompositorContextId context_id, Web::Compositor::PresentationMode mode) override
virtual void set_parent_context(Web::Compositor::CompositorContextId context_id, Optional<Web::Compositor::CompositorContextId> parent_context_id) override
{
if (auto* connection = compositor_connection())
connection->set_presentation_mode(context_id, mode);
connection->set_parent_context(context_id, parent_context_id);
}
virtual void stop_presenting_to_client(Web::Compositor::CompositorContextId context_id) override
{
if (auto* connection = compositor_connection())
connection->stop_presenting_to_client(context_id);
}
virtual void update_display_list(Web::Compositor::CompositorContextId context_id, NonnullRefPtr<Web::Painting::DisplayList> display_list, Web::Painting::AccumulatedVisualContextTree visual_context_tree, Web::Painting::DisplayListResourceTransaction&& resource_transaction, Web::Painting::ScrollStateSnapshot&& scroll_state_snapshot) override

View file

@ -17,6 +17,6 @@ SaveLayer@0
CompositorMainThreadWheelEventRegion@1 rect=[40,40 160x120]
Save@1
AddClipRect@1 rect=[40,40 160x120]
DrawCompositorSurface@1 dst_rect=[40,40 160x120]
DrawCompositedContext@1 dst_rect=[40,40 160x120]
Restore@1
Restore@0

View file

@ -12,6 +12,6 @@ SaveLayer@0
CompositorMainThreadWheelEventRegion@1 rect=[0,0 120x80]
Save@1
AddClipRect@1 rect=[0,0 120x80]
DrawCompositorSurface@1 dst_rect=[0,0 120x80]
DrawCompositedContext@1 dst_rect=[0,0 120x80]
Restore@1
Restore@0