Skip to content

Commit 5409477

Browse files
committed
Keep WAAPI state outside document footprint (#699)
1 parent a2bc2e7 commit 5409477

3 files changed

Lines changed: 51 additions & 59 deletions

File tree

‎experiments/WebScene.NativeEngine.Probe/native/webscene_native_dom.h‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2614,11 +2614,15 @@ class native_document final {
26142614
// vector here would add its full implementation-specific footprint to
26152615
// every document, including documents that never run an animation.
26162616
std::unique_ptr<std::vector<animation_event_record>> animation_events_;
2617-
std::unique_ptr<std::vector<web_animation_event_record>>
2618-
web_animation_events_;
26192617
static constexpr size_t maximum_live_web_animations = 1024U;
2620-
std::unique_ptr<std::unordered_map<uint32_t, uint32_t>>
2621-
web_animation_nodes_;
2618+
struct web_animation_auxiliary_storage final {
2619+
std::vector<web_animation_event_record> events;
2620+
std::unordered_map<uint32_t, uint32_t> nodes;
2621+
};
2622+
// Script-created animations are opt-in. Keep their event queue and direct
2623+
// ID index behind one lazy allocation so ordinary documents pay neither
2624+
// heap storage nor another pointer in the native document shell.
2625+
std::unique_ptr<web_animation_auxiliary_storage> web_animation_auxiliary_;
26222626
webscene_text_measure_callback text_measure_callback_{nullptr};
26232627
void* text_measure_user_data_{nullptr};
26242628
mutable std::unordered_map<

‎experiments/WebScene.NativeEngine.Probe/native/webscene_native_dom_animations.inc‎

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,12 @@ bool fills_after(node_style::animation_data::fill_kind fill) noexcept
7373
}
7474

7575
void discard_web_animation_events(
76-
std::unique_ptr<std::vector<native_document::web_animation_event_record>>& events,
76+
std::vector<native_document::web_animation_event_record>& events,
7777
uint32_t animation_id)
7878
{
79-
if (!events) return;
80-
std::erase_if(*events, [animation_id](const auto& event) {
79+
std::erase_if(events, [animation_id](const auto& event) {
8180
return event.animation_id == animation_id;
8281
});
83-
if (events->empty()) events.reset();
8482
}
8583
} // namespace
8684

@@ -102,9 +100,11 @@ bool native_document::create_web_animation(
102100
node.style.animations().keyframe_animations.end(),
103101
[](const auto& track) { return !track.signature.empty(); });
104102
if (id == 0U
105-
|| (web_animation_nodes_
106-
&& web_animation_nodes_->size() >= maximum_live_web_animations)
107-
|| (web_animation_nodes_ && web_animation_nodes_->contains(id))
103+
|| (web_animation_auxiliary_
104+
&& web_animation_auxiliary_->nodes.size()
105+
>= maximum_live_web_animations)
106+
|| (web_animation_auxiliary_
107+
&& web_animation_auxiliary_->nodes.contains(id))
108108
|| css_track_count + animation.web_animations.size()
109109
>= node_style::animation_data::max_keyframe_animation_tracks
110110
|| std::any_of(
@@ -130,11 +130,11 @@ bool native_document::create_web_animation(
130130
record.runtime.painted_scale_y = node.style.transform_scale_y;
131131
record.runtime.painted_rotation_degrees = node.style.transform_rotate_degrees;
132132
animation.web_animations.push_back(std::move(record));
133-
if (!web_animation_nodes_) {
134-
web_animation_nodes_ =
135-
std::make_unique<std::unordered_map<uint32_t, uint32_t>>();
133+
if (!web_animation_auxiliary_) {
134+
web_animation_auxiliary_ =
135+
std::make_unique<web_animation_auxiliary_storage>();
136136
}
137-
web_animation_nodes_->emplace(id, node.id);
137+
web_animation_auxiliary_->nodes.emplace(id, node.id);
138138
active_animation_demand_cache_valid_ = false;
139139
last_animation_advance_timestamp_ms_ =
140140
std::numeric_limits<double>::quiet_NaN();
@@ -148,9 +148,9 @@ bool native_document::control_web_animation(
148148
web_animation_command command,
149149
double seek_time_ms)
150150
{
151-
if (!web_animation_nodes_) return false;
152-
const auto owner = web_animation_nodes_->find(id);
153-
if (owner == web_animation_nodes_->end()) return false;
151+
if (!web_animation_auxiliary_) return false;
152+
const auto owner = web_animation_auxiliary_->nodes.find(id);
153+
if (owner == web_animation_auxiliary_->nodes.end()) return false;
154154
auto* node = find_by_native_id(owner->second);
155155
if (node == nullptr || node->animation_runtime() == nullptr) return false;
156156
auto* animation = node->animation_runtime();
@@ -163,7 +163,8 @@ bool native_document::control_web_animation(
163163
switch (command) {
164164
case web_animation_command::play:
165165
if (record.finished) {
166-
discard_web_animation_events(web_animation_events_, id);
166+
discard_web_animation_events(
167+
web_animation_auxiliary_->events, id);
167168
runtime.started_ms = animation_frame_timestamp_ms_;
168169
runtime.active = true;
169170
runtime.filled = false;
@@ -182,14 +183,11 @@ bool native_document::control_web_animation(
182183
}
183184
break;
184185
case web_animation_command::cancel:
185-
discard_web_animation_events(web_animation_events_, id);
186-
if (!web_animation_events_) {
187-
web_animation_events_ =
188-
std::make_unique<std::vector<web_animation_event_record>>();
189-
}
190-
web_animation_events_->push_back({node->id, id, true});
186+
discard_web_animation_events(
187+
web_animation_auxiliary_->events, id);
188+
web_animation_auxiliary_->events.push_back({node->id, id, true});
191189
animation->web_animations.erase(found);
192-
web_animation_nodes_->erase(id);
190+
web_animation_auxiliary_->nodes.erase(id);
193191
break;
194192
case web_animation_command::finish: {
195193
const auto active_duration = keyframe_active_duration_ms(record.effect);
@@ -203,7 +201,8 @@ bool native_document::control_web_animation(
203201
}
204202
case web_animation_command::seek:
205203
if (!std::isfinite(seek_time_ms)) return false;
206-
discard_web_animation_events(web_animation_events_, id);
204+
discard_web_animation_events(
205+
web_animation_auxiliary_->events, id);
207206
runtime.started_ms = (runtime.paused
208207
? runtime.paused_at_ms : animation_frame_timestamp_ms_)
209208
- seek_time_ms;
@@ -224,9 +223,9 @@ bool native_document::control_web_animation(
224223
std::optional<native_document::web_animation_state>
225224
native_document::web_animation_status(uint32_t id) const
226225
{
227-
if (!web_animation_nodes_) return std::nullopt;
228-
const auto owner = web_animation_nodes_->find(id);
229-
if (owner == web_animation_nodes_->end()
226+
if (!web_animation_auxiliary_) return std::nullopt;
227+
const auto owner = web_animation_auxiliary_->nodes.find(id);
228+
if (owner == web_animation_auxiliary_->nodes.end()
230229
|| owner->second == 0U || owner->second > native_id_index_.size()) {
231230
return std::nullopt;
232231
}
@@ -271,13 +270,11 @@ void native_document::cancel_web_animations(
271270
auto* animation = node.animation_runtime();
272271
if (animation == nullptr || animation->web_animations.empty()) return;
273272
for (const auto& record : animation->web_animations) {
274-
discard_web_animation_events(web_animation_events_, record.id);
275-
if (!web_animation_events_) {
276-
web_animation_events_ = std::make_unique<
277-
std::vector<web_animation_event_record>>();
278-
}
279-
web_animation_events_->push_back({node.id, record.id, true});
280-
if (web_animation_nodes_) web_animation_nodes_->erase(record.id);
273+
discard_web_animation_events(
274+
web_animation_auxiliary_->events, record.id);
275+
web_animation_auxiliary_->events.push_back(
276+
{node.id, record.id, true});
277+
web_animation_auxiliary_->nodes.erase(record.id);
281278
}
282279
animation->web_animations.clear();
283280
canceled = true;
@@ -506,16 +503,12 @@ void native_document::update_style_animations(dom_node& node)
506503
for (size_t index = web_capacity;
507504
index < animation.web_animations.size(); ++index) {
508505
discard_web_animation_events(
509-
web_animation_events_, animation.web_animations[index].id);
510-
if (!web_animation_events_) {
511-
web_animation_events_ = std::make_unique<
512-
std::vector<web_animation_event_record>>();
513-
}
514-
web_animation_events_->push_back(
506+
web_animation_auxiliary_->events,
507+
animation.web_animations[index].id);
508+
web_animation_auxiliary_->events.push_back(
515509
{node.id, animation.web_animations[index].id, true});
516-
if (web_animation_nodes_) {
517-
web_animation_nodes_->erase(animation.web_animations[index].id);
518-
}
510+
web_animation_auxiliary_->nodes.erase(
511+
animation.web_animations[index].id);
519512
}
520513
animation.web_animations.resize(web_capacity);
521514
}
@@ -1860,11 +1853,8 @@ bool native_document::advance_animations() noexcept
18601853
}
18611854
advanced = advanced || (contributes && keyframe_paint_visible);
18621855
if (completed && !runtime.end_event_sent) {
1863-
if (!web_animation_events_) {
1864-
web_animation_events_ = std::make_unique<
1865-
std::vector<web_animation_event_record>>();
1866-
}
1867-
web_animation_events_->push_back({node.id, record.id, false});
1856+
web_animation_auxiliary_->events.push_back(
1857+
{node.id, record.id, false});
18681858
runtime.end_event_sent = true;
18691859
}
18701860
}
@@ -2237,8 +2227,8 @@ native_document::take_animation_events()
22372227
std::vector<native_document::web_animation_event_record>
22382228
native_document::take_web_animation_events()
22392229
{
2240-
if (!web_animation_events_) return {};
2241-
auto events = std::move(*web_animation_events_);
2242-
web_animation_events_.reset();
2230+
if (!web_animation_auxiliary_) return {};
2231+
auto events = std::move(web_animation_auxiliary_->events);
2232+
web_animation_auxiliary_->events.clear();
22432233
return events;
22442234
}

‎experiments/WebScene.NativeEngine.Probe/native/webscene_native_dom_tree.inc‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -628,13 +628,12 @@ size_t native_document::erase_detached_subtrees(
628628
});
629629
if (animation_events_->empty()) animation_events_.reset();
630630
}
631-
if (web_animation_nodes_) {
632-
std::erase_if(*web_animation_nodes_, [&](const auto& entry) {
631+
if (web_animation_auxiliary_) {
632+
std::erase_if(web_animation_auxiliary_->nodes, [&](const auto& entry) {
633633
return entry.second == 0U
634634
|| entry.second > native_id_index_.size()
635635
|| native_id_index_[entry.second - 1U] == nullptr;
636636
});
637-
if (web_animation_nodes_->empty()) web_animation_nodes_.reset();
638637
}
639638
if (shadow_dom_storage_ != nullptr) {
640639
for (const auto* node : removed) {
@@ -990,8 +989,7 @@ void native_document::clear()
990989
node_pool_.release();
991990
transition_events_.clear();
992991
animation_events_.reset();
993-
web_animation_events_.reset();
994-
web_animation_nodes_.reset();
992+
web_animation_auxiliary_.reset();
995993
last_animation_advance_timestamp_ms_ =
996994
std::numeric_limits<double>::quiet_NaN();
997995
next_node_id_ = 1;

0 commit comments

Comments
 (0)