aboutsummaryrefslogtreecommitdiffstats
path: root/components/compositing
diff options
context:
space:
mode:
Diffstat (limited to 'components/compositing')
-rw-r--r--components/compositing/compositor.rs81
-rw-r--r--components/compositing/webview_manager.rs8
-rw-r--r--components/compositing/webview_renderer.rs82
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)