mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Simplify scheduling of post-message loop "update the rendering"
This commit is contained in:
parent
48e14be7ff
commit
bbad1f656a
2 changed files with 48 additions and 54 deletions
|
@ -3657,7 +3657,8 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether or not this [`Document`] needs a rendering update, due to changed
|
/// Whether or not this [`Document`] needs a rendering update, due to changed
|
||||||
/// contents or pending events.
|
/// contents or pending events. This is used to decide whether or not to schedule
|
||||||
|
/// a call to the "update the rendering" algorithm.
|
||||||
pub(crate) fn needs_rendering_update(&self) -> bool {
|
pub(crate) fn needs_rendering_update(&self) -> bool {
|
||||||
if !self.is_fully_active() {
|
if !self.is_fully_active() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1243,13 +1243,13 @@ impl ScriptThread {
|
||||||
///
|
///
|
||||||
/// Attempt to update the rendering and then do a microtask checkpoint if rendering was actually
|
/// Attempt to update the rendering and then do a microtask checkpoint if rendering was actually
|
||||||
/// updated.
|
/// updated.
|
||||||
pub(crate) fn update_the_rendering(&self, can_gc: CanGc) {
|
pub(crate) fn update_the_rendering(&self, can_gc: CanGc) -> bool {
|
||||||
self.last_render_opportunity_time.set(Some(Instant::now()));
|
self.last_render_opportunity_time.set(Some(Instant::now()));
|
||||||
self.cancel_scheduled_update_the_rendering();
|
self.cancel_scheduled_update_the_rendering();
|
||||||
self.needs_rendering_update.store(false, Ordering::Relaxed);
|
self.needs_rendering_update.store(false, Ordering::Relaxed);
|
||||||
|
|
||||||
if !self.can_continue_running_inner() {
|
if !self.can_continue_running_inner() {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: The specification says to filter out non-renderable documents,
|
// TODO: The specification says to filter out non-renderable documents,
|
||||||
|
@ -1371,68 +1371,62 @@ impl ScriptThread {
|
||||||
// Perform a microtask checkpoint as the specifications says that *update the rendering*
|
// Perform a microtask checkpoint as the specifications says that *update the rendering*
|
||||||
// should be run in a task and a microtask checkpoint is always done when running tasks.
|
// should be run in a task and a microtask checkpoint is always done when running tasks.
|
||||||
self.perform_a_microtask_checkpoint(can_gc);
|
self.perform_a_microtask_checkpoint(can_gc);
|
||||||
|
saw_any_reflows
|
||||||
self.maybe_schedule_rendering_opportunity_after_rendering_update(saw_any_reflows);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_schedule_rendering_opportunity_after_rendering_update(&self, saw_any_reflows: bool) {
|
fn maybe_schedule_rendering_opportunity_after_ipc_message(
|
||||||
// If there are any pending reflows and we are not having rendering opportunities
|
&self,
|
||||||
// immediately after running "update the rendering," run it one more time.
|
built_any_display_lists: bool,
|
||||||
if self.documents.borrow().iter().any(|(_, document)| {
|
) {
|
||||||
document.needs_rendering_update() ||
|
let needs_rendering_update = self
|
||||||
(saw_any_reflows && document.has_resize_observers())
|
.documents
|
||||||
}) {
|
.borrow()
|
||||||
self.cancel_scheduled_update_the_rendering();
|
.iter()
|
||||||
self.schedule_update_the_rendering_timer_if_necessary(Duration::ZERO);
|
.any(|(_, document)| document.needs_rendering_update());
|
||||||
}
|
let running_animations = self.documents.borrow().iter().any(|(_, document)| {
|
||||||
|
|
||||||
if !saw_any_reflows &&
|
|
||||||
self.documents.borrow().iter().any(|(_, document)| {
|
|
||||||
document.is_fully_active() &&
|
document.is_fully_active() &&
|
||||||
!document.window().throttled() &&
|
!document.window().throttled() &&
|
||||||
(document.animations().running_animation_count() != 0 ||
|
(document.animations().running_animation_count() != 0 ||
|
||||||
document.has_active_request_animation_frame_callbacks())
|
document.has_active_request_animation_frame_callbacks())
|
||||||
})
|
});
|
||||||
{
|
|
||||||
const SCRIPT_THREAD_ANIMATION_TICK_DELAY: Duration = Duration::from_millis(30);
|
|
||||||
self.schedule_update_the_rendering_timer_if_necessary(
|
|
||||||
SCRIPT_THREAD_ANIMATION_TICK_DELAY,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_schedule_rendering_opportunity_after_ipc_message(&self) {
|
// If we are not running animations and no rendering update is
|
||||||
// If no document needs a rendering update, exit early to avoid doing more work.
|
// necessary, just exit early and schedule the next rendering update
|
||||||
if !self
|
// when it becomes necessary.
|
||||||
.documents
|
if !needs_rendering_update && !running_animations {
|
||||||
.borrow()
|
|
||||||
.iter()
|
|
||||||
.any(|(_, document)| document.needs_rendering_update())
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait 20 milliseconds between frames triggered by the script thread itself. This
|
// If animations are running and a reflow in this event loop iteration
|
||||||
// should, in theory, allow compositor-based ticks to arrive sooner.
|
// produced a display list, rely on the renderer to inform us of the
|
||||||
const SCRIPT_THREAD_ANIMATION_TICK_DELAY: Duration = Duration::from_millis(20);
|
// next animation tick / rendering opportunity.
|
||||||
|
if running_animations && built_any_display_lists {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are two possibilities: rendering needs to be updated or we are
|
||||||
|
// scheduling a new animation tick because animations are running, but
|
||||||
|
// not changing the DOM. In the later case we can wait a bit longer
|
||||||
|
// until the next "update the rendering" call as it's more efficient to
|
||||||
|
// slow down rAFs that don't change the DOM.
|
||||||
|
let animation_delay = if running_animations && !needs_rendering_update {
|
||||||
|
Duration::from_millis(30)
|
||||||
|
} else {
|
||||||
|
// 20 milliseconds is used here in order to allow any renderer-based
|
||||||
|
// animation ticks to arrive first.
|
||||||
|
//
|
||||||
|
// TODO: Should this be faster to reduce update latency?
|
||||||
|
Duration::from_millis(20)
|
||||||
|
};
|
||||||
|
|
||||||
let time_since_last_rendering_opportunity = self
|
let time_since_last_rendering_opportunity = self
|
||||||
.last_render_opportunity_time
|
.last_render_opportunity_time
|
||||||
.get()
|
.get()
|
||||||
.map(|last_render_opportunity_time| Instant::now() - last_render_opportunity_time)
|
.map(|last_render_opportunity_time| Instant::now() - last_render_opportunity_time)
|
||||||
.unwrap_or(Duration::MAX)
|
.unwrap_or(Duration::MAX)
|
||||||
.min(SCRIPT_THREAD_ANIMATION_TICK_DELAY);
|
.min(animation_delay);
|
||||||
|
|
||||||
//eprintln!(" - scheduling update\n");
|
|
||||||
//// If it's been more than the time of a single frame the last rendering opportunity,
|
|
||||||
//// just run it now.
|
|
||||||
//if time_since_last_rendering_opportunity > SCRIPT_THREAD_ANIMATION_TICK_DELAY {
|
|
||||||
// println!(" - running immediately");
|
|
||||||
// self.update_the_rendering(can_gc);
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
self.schedule_update_the_rendering_timer_if_necessary(
|
self.schedule_update_the_rendering_timer_if_necessary(
|
||||||
SCRIPT_THREAD_ANIMATION_TICK_DELAY - time_since_last_rendering_opportunity,
|
animation_delay - time_since_last_rendering_opportunity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1667,12 +1661,11 @@ impl ScriptThread {
|
||||||
docs.clear();
|
docs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.needs_rendering_update.load(Ordering::Relaxed) {
|
let built_any_display_lists = self.needs_rendering_update.load(Ordering::Relaxed) &&
|
||||||
self.update_the_rendering(can_gc);
|
self.update_the_rendering(can_gc);
|
||||||
}
|
|
||||||
|
|
||||||
self.maybe_fulfill_font_ready_promises(can_gc);
|
self.maybe_fulfill_font_ready_promises(can_gc);
|
||||||
self.maybe_schedule_rendering_opportunity_after_ipc_message();
|
self.maybe_schedule_rendering_opportunity_after_ipc_message(built_any_display_lists);
|
||||||
self.maybe_send_document_state_messages();
|
self.maybe_send_document_state_messages();
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue