Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve decisions in compositor over when to draw a frame. #17398

Merged
merged 3 commits into from Jun 21, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Improve decisions in compositor over when to draw a frame.

This patch fixes a couple of issues in the compositor:

1) Remove the delayed composition code. Previously, this would schedule
   a composite for 12ms in the future. This doesn't really make any sense
   with WR. There's no point in doing a composite unless WR has provided
   a new frame to be drawn. This fixes issues in several benchmarks where
   we were doing multiple composite / renders per rAF, which is a waste
   of CPU time. This *does* make the framerate slower in some cases (such
   as a slow rAF callback) but it's more correct - otherwise we were just
   compositing the same frame multiple times for no real benefit.

2) Inform the window of the current animation state of the compositor.
   Specifically, if an animation (or rAF) is currently active, the
   window system switches to use event polling, and does not block on
   the OS-level event loop. In the case of active animation, we just
   assume that we want to be running as the vsync interval and not
   blocking. This means the compositor thread only sleeps on vsync
   during animation, which reduces OS scheduling and results in much
   smoother animation.
  • Loading branch information
gw3583 committed Jun 19, 2017
commit c8255922a98996c5aea7eff8eb837682d883aa63
@@ -6,7 +6,6 @@ use CompositionPipeline;
use SendableFrameTree;
use compositor_thread::{CompositorProxy, CompositorReceiver};
use compositor_thread::{InitialCompositorState, Msg, RenderListener};
use delayed_composition::DelayedCompositionTimerProxy;
use euclid::{Point2D, TypedPoint2D, TypedVector2D, TypedRect, ScaleFactor, TypedSize2D};
use gfx_traits::Epoch;
use gleam::gl;
@@ -131,9 +130,6 @@ pub struct IOCompositor<Window: WindowMethods> {

channel_to_self: CompositorProxy,

/// A handle to the delayed composition timer.
delayed_composition_timer: DelayedCompositionTimerProxy,

/// The type of composition to perform
composite_target: CompositeTarget,

@@ -207,7 +203,6 @@ struct ScrollZoomEvent {
#[derive(PartialEq, Debug)]
enum CompositionRequest {
NoCompositingNecessary,
DelayedComposite(u64),
CompositeNow(CompositingReason),
}

@@ -363,7 +358,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
scale: ScaleFactor::new(1.0),
scale_factor: scale_factor,
channel_to_self: state.sender.clone_compositor_proxy(),
delayed_composition_timer: DelayedCompositionTimerProxy::new(state.sender),
composition_request: CompositionRequest::NoCompositingNecessary,
touch_handler: TouchHandler::new(),
pending_scroll_zoom_events: Vec::new(),
@@ -437,8 +431,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
let _ = receiver.recv();
}

self.delayed_composition_timer.shutdown();

self.shutdown_state = ShutdownState::FinishedShuttingDown;
}

@@ -524,16 +516,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}

(Msg::DelayedCompositionTimeout(timestamp), ShutdownState::NotShuttingDown) => {
if let CompositionRequest::DelayedComposite(this_timestamp) =
self.composition_request {
if timestamp == this_timestamp {
self.composition_request = CompositionRequest::CompositeNow(
CompositingReason::DelayedCompositeTimeout)
}
}
}

(Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => {
self.composition_request = CompositionRequest::CompositeNow(reason)
}
@@ -753,18 +735,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}

fn schedule_delayed_composite_if_necessary(&mut self) {
match self.composition_request {
CompositionRequest::CompositeNow(_) => return,
CompositionRequest::DelayedComposite(_) |
CompositionRequest::NoCompositingNecessary => {}
}

let timestamp = precise_time_ns();
self.delayed_composition_timer.schedule_composite(timestamp);
self.composition_request = CompositionRequest::DelayedComposite(timestamp);
}

fn scroll_fragment_to_point(&mut self, id: ClipId, point: Point2D<f32>) {
self.webrender_api.scroll_node_with_id(LayoutPoint::from_untyped(&point), id,
ScrollClamping::ToContentBounds);
@@ -1235,13 +1205,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
pipeline_ids.push(*pipeline_id);
}
}
let animation_state = if pipeline_ids.is_empty() {
windowing::AnimationState::Idle
} else {
windowing::AnimationState::Animating
};
self.window.set_animation_state(animation_state);
for pipeline_id in &pipeline_ids {
self.tick_animations_for_pipeline(*pipeline_id)
}
}

fn tick_animations_for_pipeline(&mut self, pipeline_id: PipelineId) {
self.schedule_delayed_composite_if_necessary();
let animation_callbacks_running = self.pipeline_details(pipeline_id).animation_callbacks_running;
if animation_callbacks_running {
let msg = ConstellationMsg::TickAnimation(pipeline_id, AnimationTickType::Script);
@@ -1635,14 +1610,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
_ => compositor_messages.push(msg),
}
}
if found_recomposite_msg {
compositor_messages.retain(|msg| {
match *msg {
Msg::DelayedCompositionTimeout(_) => false,
_ => true,
}
})
}
for msg in compositor_messages {
if !self.handle_browser_message(msg) {
break
@@ -1664,8 +1631,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}

match self.composition_request {
CompositionRequest::NoCompositingNecessary |
CompositionRequest::DelayedComposite(_) => {}
CompositionRequest::NoCompositingNecessary => {}
CompositionRequest::CompositeNow(_) => {
self.composite()
}
@@ -100,8 +100,6 @@ pub enum Msg {
HistoryChanged(Vec<LoadData>, usize),
/// Wether or not to follow a link
AllowNavigation(ServoUrl, IpcSender<bool>),
/// We hit the delayed composition timeout. (See `delayed_composition.rs`.)
DelayedCompositionTimeout(u64),
/// Composite.
Recomposite(CompositingReason),
/// Sends an unconsumed key event back to the compositor.
@@ -160,7 +158,6 @@ impl Debug for Msg {
Msg::AllowNavigation(..) => write!(f, "AllowNavigation"),
Msg::LoadStart => write!(f, "LoadStart"),
Msg::HistoryChanged(..) => write!(f, "HistoryChanged"),
Msg::DelayedCompositionTimeout(..) => write!(f, "DelayedCompositionTimeout"),
Msg::Recomposite(..) => write!(f, "Recomposite"),
Msg::KeyEvent(..) => write!(f, "KeyEvent"),
Msg::TouchEventProcessed(..) => write!(f, "TouchEventProcessed"),

This file was deleted.

@@ -35,7 +35,6 @@ use style_traits::CSSPixel;

mod compositor;
pub mod compositor_thread;
mod delayed_composition;
mod touch;
pub mod windowing;

@@ -102,6 +102,12 @@ impl Debug for WindowEvent {
}
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum AnimationState {
Idle,
Animating,
}

pub trait WindowMethods {
/// Returns the rendering area size in hardware pixels.
fn framebuffer_size(&self) -> TypedSize2D<u32, DevicePixel>;
@@ -163,4 +169,10 @@ pub trait WindowMethods {

/// Return the GL function pointer trait.
fn gl(&self) -> Rc<gl::Gl>;

/// Set whether the application is currently animating.
/// Typically, when animations are active, the window
/// will want to avoid blocking on UI events, and just
/// run the event loop at the vsync interval.
fn set_animation_state(&self, _state: AnimationState) {}
}
@@ -6,7 +6,7 @@

use NestedEventLoopListener;
use compositing::compositor_thread::EventLoopWaker;
use compositing::windowing::{MouseWindowEvent, WindowNavigateMsg};
use compositing::windowing::{AnimationState, MouseWindowEvent, WindowNavigateMsg};
use compositing::windowing::{WindowEvent, WindowMethods};
use euclid::{Point2D, Size2D, TypedPoint2D, TypedVector2D, TypedRect, ScaleFactor, TypedSize2D};
#[cfg(target_os = "windows")]
@@ -196,6 +196,8 @@ pub struct Window {
#[cfg(not(target_os = "windows"))]
pressed_key_map: RefCell<Vec<(ScanCode, char)>>,

animation_state: Cell<AnimationState>,

gl: Rc<gl::Gl>,
}

@@ -316,6 +318,7 @@ impl Window {
#[cfg(target_os = "windows")]
last_pressed_key: Cell::new(None),
gl: gl.clone(),
animation_state: Cell::new(AnimationState::Idle),
};

window.present();
@@ -655,10 +658,14 @@ impl Window {
let mut events = mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new());
let mut close_event = false;

let poll = self.animation_state.get() == AnimationState::Animating ||
opts::get().output_file.is_some() ||
opts::get().exit_after_load ||
opts::get().headless;
// When writing to a file then exiting, use event
// polling so that we don't block on a GUI event
// such as mouse click.
if opts::get().output_file.is_some() || opts::get().exit_after_load || opts::get().headless {
if poll {
match self.kind {
WindowKind::Window(ref window) => {
while let Some(event) = window.poll_events().next() {
@@ -1005,6 +1012,10 @@ impl WindowMethods for Window {

}

fn set_animation_state(&self, state: AnimationState) {
self.animation_state.set(state);
}

fn set_inner_size(&self, size: Size2D<u32>) {
match self.kind {
WindowKind::Window(ref window) => {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.