libservo: Remove Servo::animating() (#40799)

Instead of relying on `Sevo::animating()` in servoshell to drive the
event loop, it is sufficient to just let the `RefreshDriver` wake it up
when it is time to re-render.

This allows us to remove `Servo::animating()` completely. It is a bit
odd that there is a global API to track this, rather than per-`WebView`
or window, so this change just removes it entirely.

Testing: This should make the main loop of headless servoshell more
efficient,
but I do not think this difference is going to be observable in any way.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson
2025-11-21 18:35:45 +01:00
committed by GitHub
parent 1ffd3ad761
commit 39676a6f60
11 changed files with 4 additions and 90 deletions

View File

@@ -208,8 +208,6 @@ pub struct Servo {
/// and deinitialization of the JS Engine. Multiprocess Servo instances have their
/// own instance that exists in the content process instead.
_js_engine_setup: Option<JSEngineSetup>,
/// Whether or not any WebView in this instance is animating or WebXR is enabled.
animating: Cell<bool>,
}
impl Servo {
@@ -324,7 +322,6 @@ impl Servo {
webviews: Default::default(),
servo_errors: ServoErrorChannel::default(),
_js_engine_setup: js_engine_setup,
animating: Cell::new(false),
}
}
@@ -336,15 +333,6 @@ impl Servo {
*self.delegate.borrow_mut() = delegate;
}
/// Whether or not any [`WebView`] of this Servo instance has animating content, such as a CSS
/// animation or transition or is running `requestAnimationFrame` callbacks. In addition, this
/// returns true if WebXR content is running. This indicates that the embedding application
/// should be spinning the Servo event loop on regular intervals in order to trigger animation
/// updates.
pub fn animating(&self) -> bool {
self.animating.get()
}
/// **EXPERIMENTAL:** Intialize GL accelerated media playback. This currently only works on a limited number
/// of platforms. This should be run *before* calling [`Servo::new`] and creating the first [`WebView`].
pub fn initialize_gl_accelerated_media(display: NativeDisplay, api: GlApi, context: GlContext) {
@@ -394,7 +382,6 @@ impl Servo {
self.compositor.borrow_mut().perform_updates();
self.send_new_frame_ready_messages();
self.send_animating_changed_messages();
self.handle_delegate_errors();
self.clean_up_destroyed_webview_handles();
@@ -416,19 +403,6 @@ impl Servo {
}
}
fn send_animating_changed_messages(&self) {
let animating = self.compositor.borrow().webxr_running() ||
self.webviews
.borrow()
.values()
.filter_map(WebView::from_weak_handle)
.any(|webview| webview.animating());
if animating != self.animating.get() {
self.animating.set(animating);
self.delegate().notify_animating_changed(animating);
}
}
fn handle_delegate_errors(&self) {
while let Some(error) = self.servo_errors.try_recv() {
self.delegate().notify_error(self, error);

View File

@@ -15,7 +15,8 @@ mod common;
use common::ServoTest;
#[test]
fn test_simple_servo_is_not_animating_by_default() {
fn test_simple_start_and_stop_servo() {
let servo_test = ServoTest::new();
assert!(!servo_test.servo().animating());
servo_test.servo().start_shutting_down();
while servo_test.servo().spin_event_loop() {}
}

View File

@@ -175,14 +175,6 @@ impl App {
self.state = AppState::Running(running_state);
}
pub(crate) fn animating(&self) -> bool {
match self.state {
AppState::Initializing => false,
AppState::Running(ref running_app_state) => running_app_state.servo().animating(),
AppState::ShuttingDown => false,
}
}
/// Handle all servo events with headless mode. Return true if the application should
/// continue.
pub fn handle_events_with_headless(&mut self) -> bool {

View File

@@ -102,9 +102,7 @@ impl EventsLoop {
if !app.handle_events_with_headless() {
break;
}
if !app.animating() {
*flag.lock().unwrap() = false;
}
*flag.lock().unwrap() = false;
}
},
}

View File

@@ -679,19 +679,6 @@ impl HostTrait for HostCallbacks {
.unwrap();
}
fn on_animating_changed(&self, animating: bool) {
debug!("on_animating_changed");
let mut env = self.jvm.get_env().unwrap();
let animating = JValue::Bool(animating as jboolean);
env.call_method(
self.callbacks.as_obj(),
"onAnimatingChanged",
"(Z)V",
&[animating],
)
.unwrap();
}
fn on_ime_show(&self, _: InputMethodControl) {
let mut env = self.jvm.get_env().unwrap();
env.call_method(self.callbacks.as_obj(), "onImeShow", "()V", &[])

View File

@@ -443,12 +443,6 @@ impl RunningAppState {
if !should_continue {
self.callbacks.host_callbacks.on_shutdown_complete();
}
if self.inner().animating_state_changed.get() {
self.inner().animating_state_changed.set(false);
self.callbacks
.host_callbacks
.on_animating_changed(self.servo().animating());
}
}
/// Load an URL.

View File

@@ -37,22 +37,6 @@ pub trait HostTrait {
/// Back/forward state has changed.
/// Back/forward buttons need to be disabled/enabled.
fn on_history_changed(&self, can_go_back: bool, can_go_forward: bool);
/// Page animation state has changed. If animating, it's recommended
/// that the embedder doesn't wait for the wake function to be called
/// to call perform_updates. Usually, it means doing:
/// ```rust
/// while true {
/// servo.perform_updates();
/// servo.present_if_needed();
/// }
/// ```
/// . This will end up calling flush
/// which will call swap_buffer which will be blocking long enough to limit
/// drawing at 60 FPS.
/// If not animating, call perform_updates only when needed (when the embedder
/// has events for Servo, or Servo has woken up the embedder event loop via
/// EventLoopWaker).
fn on_animating_changed(&self, animating: bool);
/// Servo finished shutting down.
fn on_shutdown_complete(&self);
/// A text input is focused.

View File

@@ -980,10 +980,6 @@ impl HostTrait for HostCallbacks {
fn on_history_changed(&self, can_go_back: bool, can_go_forward: bool) {}
fn on_animating_changed(&self, animating: bool) {
// todo: should we tell the vsync thread that it should perform updates?
}
fn on_shutdown_complete(&self) {
if let Some(terminate_fn) = TERMINATE_CALLBACK.get() {
terminate_fn.call((), ThreadsafeFunctionCallMode::Blocking);

View File

@@ -100,8 +100,6 @@ public class JNIServo {
void onAlert(String message);
void onAnimatingChanged(boolean animating);
void onLoadStarted();
void onLoadEnded();

View File

@@ -211,8 +211,6 @@ public class Servo {
public interface GfxCallbacks {
void flushGLBuffers();
void animationStateChanged(boolean animating);
void makeCurrent();
}
@@ -262,10 +260,6 @@ public class Servo {
mRunCallback.inUIThread(() -> mClient.onImeHide());
}
public void onAnimatingChanged(boolean animating) {
mRunCallback.inGLThread(() -> mGfxCb.animationStateChanged(animating));
}
public boolean onAllowNavigation(String url) {
return mClient.onAllowNavigation(url);
}

View File

@@ -105,10 +105,6 @@ public class ServoView extends SurfaceView
}
@Override
public void animationStateChanged(boolean animating) {
}
@Override
public void makeCurrent() {
}