mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +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
|
||||
/// 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 {
|
||||
if !self.is_fully_active() {
|
||||
return false;
|
||||
|
|
|
@ -1243,13 +1243,13 @@ impl ScriptThread {
|
|||
///
|
||||
/// Attempt to update the rendering and then do a microtask checkpoint if rendering was actually
|
||||
/// 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.cancel_scheduled_update_the_rendering();
|
||||
self.needs_rendering_update.store(false, Ordering::Relaxed);
|
||||
|
||||
if !self.can_continue_running_inner() {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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*
|
||||
// should be run in a task and a microtask checkpoint is always done when running tasks.
|
||||
self.perform_a_microtask_checkpoint(can_gc);
|
||||
|
||||
self.maybe_schedule_rendering_opportunity_after_rendering_update(saw_any_reflows);
|
||||
saw_any_reflows
|
||||
}
|
||||
|
||||
fn maybe_schedule_rendering_opportunity_after_rendering_update(&self, saw_any_reflows: bool) {
|
||||
// If there are any pending reflows and we are not having rendering opportunities
|
||||
// immediately after running "update the rendering," run it one more time.
|
||||
if self.documents.borrow().iter().any(|(_, document)| {
|
||||
document.needs_rendering_update() ||
|
||||
(saw_any_reflows && document.has_resize_observers())
|
||||
}) {
|
||||
self.cancel_scheduled_update_the_rendering();
|
||||
self.schedule_update_the_rendering_timer_if_necessary(Duration::ZERO);
|
||||
}
|
||||
|
||||
if !saw_any_reflows &&
|
||||
self.documents.borrow().iter().any(|(_, document)| {
|
||||
document.is_fully_active() &&
|
||||
!document.window().throttled() &&
|
||||
(document.animations().running_animation_count() != 0 ||
|
||||
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 no document needs a rendering update, exit early to avoid doing more work.
|
||||
if !self
|
||||
fn maybe_schedule_rendering_opportunity_after_ipc_message(
|
||||
&self,
|
||||
built_any_display_lists: bool,
|
||||
) {
|
||||
let needs_rendering_update = self
|
||||
.documents
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|(_, document)| document.needs_rendering_update())
|
||||
{
|
||||
.any(|(_, document)| document.needs_rendering_update());
|
||||
let running_animations = self.documents.borrow().iter().any(|(_, document)| {
|
||||
document.is_fully_active() &&
|
||||
!document.window().throttled() &&
|
||||
(document.animations().running_animation_count() != 0 ||
|
||||
document.has_active_request_animation_frame_callbacks())
|
||||
});
|
||||
|
||||
// If we are not running animations and no rendering update is
|
||||
// necessary, just exit early and schedule the next rendering update
|
||||
// when it becomes necessary.
|
||||
if !needs_rendering_update && !running_animations {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait 20 milliseconds between frames triggered by the script thread itself. This
|
||||
// should, in theory, allow compositor-based ticks to arrive sooner.
|
||||
const SCRIPT_THREAD_ANIMATION_TICK_DELAY: Duration = Duration::from_millis(20);
|
||||
// If animations are running and a reflow in this event loop iteration
|
||||
// produced a display list, rely on the renderer to inform us of the
|
||||
// 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
|
||||
.last_render_opportunity_time
|
||||
.get()
|
||||
.map(|last_render_opportunity_time| Instant::now() - last_render_opportunity_time)
|
||||
.unwrap_or(Duration::MAX)
|
||||
.min(SCRIPT_THREAD_ANIMATION_TICK_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;
|
||||
//}
|
||||
|
||||
.min(animation_delay);
|
||||
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();
|
||||
}
|
||||
|
||||
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.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();
|
||||
|
||||
true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue