diff options
Diffstat (limited to 'components/compositing')
-rw-r--r-- | components/compositing/compositor.rs | 81 | ||||
-rw-r--r-- | components/compositing/webview_manager.rs | 8 | ||||
-rw-r--r-- | components/compositing/webview_renderer.rs | 82 |
3 files changed, 77 insertions, 94 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 4550188a7fa..41286a2760a 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -21,12 +21,12 @@ use compositing_traits::rendering_context::RenderingContext; use compositing_traits::{ CompositionPipeline, CompositorMsg, ImageUpdate, SendableFrameTree, WebViewTrait, }; -use constellation_traits::{AnimationTickType, EmbedderToConstellationMessage, PaintMetricEvent}; +use constellation_traits::{EmbedderToConstellationMessage, PaintMetricEvent}; use crossbeam_channel::{Receiver, Sender}; use dpi::PhysicalSize; use embedder_traits::{ - AnimationState, CompositorHitTestResult, Cursor, InputEvent, MouseButtonEvent, MouseMoveEvent, - ShutdownState, TouchEventType, UntrustedNodeAddress, ViewportDetails, + CompositorHitTestResult, Cursor, InputEvent, MouseButtonEvent, MouseMoveEvent, ShutdownState, + TouchEventType, UntrustedNodeAddress, ViewportDetails, }; use euclid::{Point2D, Rect, Scale, Size2D, Transform3D}; use fnv::FnvHashMap; @@ -197,9 +197,6 @@ pub(crate) struct PipelineDetails { /// The pipeline associated with this PipelineDetails object. pub pipeline: Option<CompositionPipeline>, - /// The [`PipelineId`] of this pipeline. - pub id: PipelineId, - /// The id of the parent pipeline, if any. pub parent_pipeline_id: Option<PipelineId>, @@ -243,32 +240,12 @@ impl PipelineDetails { pub(crate) fn animating(&self) -> bool { !self.throttled && (self.animation_callbacks_running || self.animations_running) } - - pub(crate) fn tick_animations(&self, compositor: &IOCompositor) { - if !self.animating() { - return; - } - - let mut tick_type = AnimationTickType::empty(); - if self.animations_running { - tick_type.insert(AnimationTickType::CSS_ANIMATIONS_AND_TRANSITIONS); - } - if self.animation_callbacks_running { - tick_type.insert(AnimationTickType::REQUEST_ANIMATION_FRAME); - } - - let msg = EmbedderToConstellationMessage::TickAnimation(self.id, tick_type); - if let Err(e) = compositor.global.borrow().constellation_sender.send(msg) { - warn!("Sending tick to constellation failed ({:?}).", e); - } - } } impl PipelineDetails { - pub(crate) fn new(id: PipelineId) -> PipelineDetails { + pub(crate) fn new() -> PipelineDetails { PipelineDetails { pipeline: None, - id, parent_pipeline_id: None, most_recent_display_list_epoch: None, animations_running: false, @@ -543,22 +520,14 @@ impl IOCompositor { pipeline_id, animation_state, ) => { - let mut throttled = true; if let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) { - throttled = webview_renderer - .change_running_animations_state(pipeline_id, animation_state); - } - - // These operations should eventually happen per-WebView, but they are global now as rendering - // is still global to all WebViews. - if !throttled && animation_state == AnimationState::AnimationsPresent { - self.set_needs_repaint(RepaintReason::ChangedAnimationState); - } - - if !throttled && animation_state == AnimationState::AnimationCallbacksPresent { - // We need to fetch the WebView again in order to avoid a double borrow. - if let Some(webview_renderer) = self.webview_renderers.get(webview_id) { - webview_renderer.tick_animations_for_pipeline(pipeline_id, self); + if webview_renderer + .change_pipeline_running_animations_state(pipeline_id, animation_state) && + webview_renderer.animating() + { + // These operations should eventually happen per-WebView, but they are + // global now as rendering is still global to all WebViews. + self.process_animations(true); } } }, @@ -605,8 +574,13 @@ impl IOCompositor { CompositorMsg::SetThrottled(webview_id, pipeline_id, throttled) => { if let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) { - webview_renderer.set_throttled(pipeline_id, throttled); - self.process_animations(true); + if webview_renderer.set_throttled(pipeline_id, throttled) && + webview_renderer.animating() + { + // These operations should eventually happen per-WebView, but they are + // global now as rendering is still global to all WebViews. + self.process_animations(true); + } } }, @@ -1283,8 +1257,23 @@ impl IOCompositor { } self.last_animation_tick = Instant::now(); - for webview_renderer in self.webview_renderers.iter() { - webview_renderer.tick_all_animations(self); + let animating_webviews: Vec<_> = self + .webview_renderers + .iter() + .filter_map(|webview_renderer| { + if webview_renderer.animating() { + Some(webview_renderer.id) + } else { + None + } + }) + .collect(); + if !animating_webviews.is_empty() { + if let Err(error) = self.global.borrow().constellation_sender.send( + EmbedderToConstellationMessage::TickAnimation(animating_webviews), + ) { + warn!("Sending tick to constellation failed ({error:?})."); + } } } diff --git a/components/compositing/webview_manager.rs b/components/compositing/webview_manager.rs index 42e9bfe1cb7..201f9d1c5c5 100644 --- a/components/compositing/webview_manager.rs +++ b/components/compositing/webview_manager.rs @@ -111,11 +111,7 @@ impl<WebView> WebViewManager<WebView> { #[cfg(test)] mod test { - use std::num::NonZeroU32; - - use base::id::{ - BrowsingContextId, BrowsingContextIndex, PipelineNamespace, PipelineNamespaceId, WebViewId, - }; + use base::id::{BrowsingContextId, Index, PipelineNamespace, PipelineNamespaceId, WebViewId}; use crate::webview_manager::WebViewManager; use crate::webview_renderer::UnknownWebView; @@ -123,7 +119,7 @@ mod test { fn top_level_id(namespace_id: u32, index: u32) -> WebViewId { WebViewId(BrowsingContextId { namespace_id: PipelineNamespaceId(namespace_id), - index: BrowsingContextIndex(NonZeroU32::new(index).unwrap()), + index: Index::new(index).unwrap(), }) } diff --git a/components/compositing/webview_renderer.rs b/components/compositing/webview_renderer.rs index 6ad77d46043..614ef0ff4c3 100644 --- a/components/compositing/webview_renderer.rs +++ b/components/compositing/webview_renderer.rs @@ -86,6 +86,9 @@ pub(crate) struct WebViewRenderer { /// The HiDPI scale factor for the `WebView` associated with this renderer. This is controlled /// by the embedding layer. hidpi_scale_factor: Scale<f32, DeviceIndependentPixel, DevicePixel>, + /// Whether or not this [`WebViewRenderer`] isn't throttled and has a pipeline with + /// active animations or animation frame callbacks. + animating: bool, } impl Drop for WebViewRenderer { @@ -119,6 +122,7 @@ impl WebViewRenderer { min_viewport_zoom: Some(PinchZoomFactor::new(1.0)), max_viewport_zoom: None, hidpi_scale_factor: Scale::new(hidpi_scale_factor.0), + animating: false, } } @@ -138,6 +142,10 @@ impl WebViewRenderer { self.pipelines.keys() } + pub(crate) fn animating(&self) -> bool { + self.animating + } + /// Returns the [`PipelineDetails`] for the given [`PipelineId`], creating it if needed. pub(crate) fn ensure_pipeline_details( &mut self, @@ -148,14 +156,10 @@ impl WebViewRenderer { .borrow_mut() .pipeline_to_webview_map .insert(pipeline_id, self.id); - PipelineDetails::new(pipeline_id) + PipelineDetails::new() }) } - pub(crate) fn set_throttled(&mut self, pipeline_id: PipelineId, throttled: bool) { - self.ensure_pipeline_details(pipeline_id).throttled = throttled; - } - pub(crate) fn remove_pipeline(&mut self, pipeline_id: PipelineId) { self.global .borrow_mut() @@ -245,51 +249,45 @@ impl WebViewRenderer { }) } - /// Sets or unsets the animations-running flag for the given pipeline. Returns true if - /// the pipeline is throttled. - pub(crate) fn change_running_animations_state( + /// Sets or unsets the animations-running flag for the given pipeline. Returns + /// true if the [`WebViewRenderer`]'s overall animating state changed. + pub(crate) fn change_pipeline_running_animations_state( &mut self, pipeline_id: PipelineId, animation_state: AnimationState, ) -> bool { - let throttled = { - let pipeline_details = self.ensure_pipeline_details(pipeline_id); - match animation_state { - AnimationState::AnimationsPresent => { - pipeline_details.animations_running = true; - }, - AnimationState::AnimationCallbacksPresent => { - pipeline_details.animation_callbacks_running = true; - }, - AnimationState::NoAnimationsPresent => { - pipeline_details.animations_running = false; - }, - AnimationState::NoAnimationCallbacksPresent => { - pipeline_details.animation_callbacks_running = false; - }, - } - pipeline_details.throttled - }; - - let animating = self.pipelines.values().any(PipelineDetails::animating); - self.webview.set_animating(animating); - throttled + let pipeline_details = self.ensure_pipeline_details(pipeline_id); + match animation_state { + AnimationState::AnimationsPresent => { + pipeline_details.animations_running = true; + }, + AnimationState::AnimationCallbacksPresent => { + pipeline_details.animation_callbacks_running = true; + }, + AnimationState::NoAnimationsPresent => { + pipeline_details.animations_running = false; + }, + AnimationState::NoAnimationCallbacksPresent => { + pipeline_details.animation_callbacks_running = false; + }, + } + self.update_animation_state() } - pub(crate) fn tick_all_animations(&self, compositor: &IOCompositor) { - for pipeline_details in self.pipelines.values() { - pipeline_details.tick_animations(compositor) - } + /// Sets or unsets the throttled flag for the given pipeline. Returns + /// true if the [`WebViewRenderer`]'s overall animating state changed. + pub(crate) fn set_throttled(&mut self, pipeline_id: PipelineId, throttled: bool) -> bool { + self.ensure_pipeline_details(pipeline_id).throttled = throttled; + + // Throttling a pipeline can cause it to be taken into the "not-animating" state. + self.update_animation_state() } - pub(crate) fn tick_animations_for_pipeline( - &self, - pipeline_id: PipelineId, - compositor: &IOCompositor, - ) { - if let Some(pipeline_details) = self.pipelines.get(&pipeline_id) { - pipeline_details.tick_animations(compositor); - } + pub(crate) fn update_animation_state(&mut self) -> bool { + let animating = self.pipelines.values().any(PipelineDetails::animating); + let old_animating = std::mem::replace(&mut self.animating, animating); + self.webview.set_animating(self.animating); + old_animating != self.animating } /// On a Window refresh tick (e.g. vsync) |