diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2015-11-05 04:08:30 +0530 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2015-11-05 04:08:30 +0530 |
commit | c78da15abbffd223290300b6b985d65cd6f03d08 (patch) | |
tree | 7e074e6e1aac7fef676966ceb0ee4a367b1b002f /components | |
parent | 50e0c36eeb8cd52b90dba24b5b3692abc25d8d4d (diff) | |
parent | 19a1e57c9019d363a5391c5a93722b4206c95440 (diff) | |
download | servo-c78da15abbffd223290300b6b985d65cd6f03d08.tar.gz servo-c78da15abbffd223290300b6b985d65cd6f03d08.zip |
Auto merge of #8314 - jdm:timeoutinvestigations, r=metajack
Investigations for #7787
I'm just going to keep throwing stuff at try, because running directly on the builders isn't yielding results.
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8314)
<!-- Reviewable:end -->
Diffstat (limited to 'components')
-rw-r--r-- | components/compositing/compositor.rs | 75 | ||||
-rw-r--r-- | components/compositing/constellation.rs | 31 | ||||
-rw-r--r-- | components/util/opts.rs | 13 |
3 files changed, 93 insertions, 26 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index e8576e70e57..a0cc3059bc6 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -55,6 +55,24 @@ use util::opts; use util::print_tree::PrintTree; use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg}; +#[derive(Debug)] +enum UnableToComposite { + NoContext, + WindowUnprepared, + NotReadyToPaintImage(NotReadyToPaint), +} + +#[derive(Debug)] +enum NotReadyToPaint { + LayerHasOutstandingPaintMessages, + MissingRoot, + PendingSubpages(usize), + AnimationsRunning, + AnimationCallbacksRunning, + JustNotifiedConstellation, + WaitingOnConstellation, +} + const BUFFER_MAP_SIZE: usize = 10000000; // Default viewport constraints @@ -211,7 +229,7 @@ pub struct ScrollEvent { cursor: TypedPoint2D<DevicePixel, i32>, } -#[derive(PartialEq)] +#[derive(PartialEq, Debug)] enum CompositionRequest { NoCompositingNecessary, CompositeOnScrollTimeout(u64), @@ -579,8 +597,14 @@ impl<Window: WindowMethods> IOCompositor<Window> { assert!(self.ready_to_save_state == ReadyState::WaitingForConstellationReply); if is_ready { self.ready_to_save_state = ReadyState::ReadyToSaveImage; + if opts::get().is_running_problem_test { + println!("ready to save image!"); + } } else { self.ready_to_save_state = ReadyState::Unknown; + if opts::get().is_running_problem_test { + println!("resetting ready_to_save_state!"); + } } self.composite_if_necessary(CompositingReason::Headless); } @@ -1678,7 +1702,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { /// Query the constellation to see if the current compositor /// output matches the current frame tree output, and if the /// associated script tasks are idle. - fn is_ready_to_paint_image_output(&mut self) -> bool { + fn is_ready_to_paint_image_output(&mut self) -> Result<(), NotReadyToPaint> { match self.ready_to_save_state { ReadyState::Unknown => { // Unsure if the output image is stable. @@ -1689,17 +1713,17 @@ impl<Window: WindowMethods> IOCompositor<Window> { match self.scene.root { Some(ref root_layer) => { if self.does_layer_have_outstanding_paint_messages(root_layer) { - return false; + return Err(NotReadyToPaint::LayerHasOutstandingPaintMessages); } } None => { - return false; + return Err(NotReadyToPaint::MissingRoot); } } // Check if there are any pending frames. If so, the image is not stable yet. if self.pending_subpages.len() > 0 { - return false + return Err(NotReadyToPaint::PendingSubpages(self.pending_subpages.len())); } // Collect the currently painted epoch of each pipeline that is @@ -1710,8 +1734,11 @@ impl<Window: WindowMethods> IOCompositor<Window> { for (id, details) in &self.pipeline_details { // If animations are currently running, then don't bother checking // with the constellation if the output image is stable. - if details.animations_running || details.animation_callbacks_running { - return false; + if details.animations_running { + return Err(NotReadyToPaint::AnimationsRunning); + } + if details.animation_callbacks_running { + return Err(NotReadyToPaint::AnimationCallbacksRunning); } pipeline_epochs.insert(*id, details.current_epoch); @@ -1722,12 +1749,12 @@ impl<Window: WindowMethods> IOCompositor<Window> { let ConstellationChan(ref chan) = self.constellation_chan; chan.send(ConstellationMsg::IsReadyToSaveImage(pipeline_epochs)).unwrap(); self.ready_to_save_state = ReadyState::WaitingForConstellationReply; - false + Err(NotReadyToPaint::JustNotifiedConstellation) } ReadyState::WaitingForConstellationReply => { // If waiting on a reply from the constellation to the last // query if the image is stable, then assume not ready yet. - false + Err(NotReadyToPaint::WaitingOnConstellation) } ReadyState::ReadyToSaveImage => { // Constellation has replied at some point in the past @@ -1735,8 +1762,9 @@ impl<Window: WindowMethods> IOCompositor<Window> { // for saving. // Reset the flag so that we check again in the future // TODO: only reset this if we load a new document? + println!("was ready to save, resetting ready_to_save_state"); self.ready_to_save_state = ReadyState::Unknown; - true + Ok(()) } } } @@ -1746,8 +1774,10 @@ impl<Window: WindowMethods> IOCompositor<Window> { let composited = self.composite_specific_target(target); if composited.is_ok() && (opts::get().output_file.is_some() || opts::get().exit_after_load) { - debug!("Shutting down the Constellation after generating an output file or exit flag specified"); + println!("Shutting down the Constellation after generating an output file or exit flag specified"); self.start_shutting_down(); + } else if composited.is_err() && opts::get().is_running_problem_test { + println!("not ready to composite: {:?}", composited.err().unwrap()); } } @@ -1756,26 +1786,28 @@ impl<Window: WindowMethods> IOCompositor<Window> { /// for some reason. If CompositeTarget is Window or Png no image data is returned; /// in the latter case the image is written directly to a file. If CompositeTarget /// is WindowAndPng Ok(Some(png::Image)) is returned. - pub fn composite_specific_target(&mut self, target: CompositeTarget) -> Result<Option<Image>, ()> { + pub fn composite_specific_target(&mut self, target: CompositeTarget) -> Result<Option<Image>, UnableToComposite> { if !self.context.is_some() { - return Err(()) + return Err(UnableToComposite::NoContext) } let (width, height) = (self.window_size.width.get() as usize, self.window_size.height.get() as usize); if !self.window.prepare_for_composite(width, height) { - return Err(()) + return Err(UnableToComposite::WindowUnprepared) } match target { CompositeTarget::WindowAndPng | CompositeTarget::PngFile => { - if !self.is_ready_to_paint_image_output() { - return Err(()) + if let Err(result) = self.is_ready_to_paint_image_output() { + return Err(UnableToComposite::NotReadyToPaintImage(result)) } } CompositeTarget::Window => { - if opts::get().exit_after_load && !self.is_ready_to_paint_image_output() { - return Err(()) + if opts::get().exit_after_load { + if let Err(result) = self.is_ready_to_paint_image_output() { + return Err(UnableToComposite::NotReadyToPaintImage(result)) + } } } } @@ -1892,7 +1924,12 @@ impl<Window: WindowMethods> IOCompositor<Window> { fn composite_if_necessary(&mut self, reason: CompositingReason) { if self.composition_request == CompositionRequest::NoCompositingNecessary { + if opts::get().is_running_problem_test { + println!("updating composition_request ({:?})", reason); + } self.composition_request = CompositionRequest::CompositeNow(reason) + } else if opts::get().is_running_problem_test { + println!("composition_request is already {:?}", self.composition_request); } } @@ -2145,7 +2182,7 @@ impl<Window> CompositorEventListener for IOCompositor<Window> where Window: Wind } /// Why we performed a composite. This is used for debugging. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum CompositingReason { /// We hit the scroll timeout and are therefore drawing unrendered content. HitScrollTimeout, diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index d578fac7832..adfb9fb5b21 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -57,6 +57,16 @@ use util::geometry::PagePx; use util::task::spawn_named; use util::{opts, prefs}; +#[derive(Debug, PartialEq)] +enum ReadyToSave { + NoRootFrame, + WebFontNotLoaded, + DocumentLoading, + EpochMismatch, + PipelineUnknown, + Ready, +} + /// Maintains the pipelines and navigation context and grants permission to composite. /// /// It is parameterized over a `LayoutTaskFactory` and a @@ -516,7 +526,14 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { } ConstellationMsg::IsReadyToSaveImage(pipeline_states) => { let is_ready = self.handle_is_ready_to_save_image(pipeline_states); + if opts::get().is_running_problem_test { + println!("got ready to save image query, result is {:?}", is_ready); + } + let is_ready = is_ready == ReadyToSave::Ready; self.compositor_proxy.send(CompositorMsg::IsReadyToSaveImageReply(is_ready)); + if opts::get().is_running_problem_test { + println!("sent response"); + } } ConstellationMsg::RemoveIFrame(pipeline_id) => { debug!("constellation got remove iframe message"); @@ -1188,11 +1205,11 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { /// to check if the output image is "stable" and can be written as a screenshot /// for reftests. fn handle_is_ready_to_save_image(&mut self, - pipeline_states: HashMap<PipelineId, Epoch>) -> bool { + pipeline_states: HashMap<PipelineId, Epoch>) -> ReadyToSave { // If there is no root frame yet, the initial page has // not loaded, so there is nothing to save yet. if self.root_frame_id.is_none() { - return false; + return ReadyToSave::NoRootFrame; } // Step through the current frame tree, checking that the script @@ -1215,7 +1232,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { let msg = LayoutControlMsg::GetWebFontLoadState(sender); pipeline.layout_chan.0.send(msg).unwrap(); if receiver.recv().unwrap() { - return false; + return ReadyToSave::WebFontNotLoaded; } // Synchronously query the script task for this pipeline @@ -1225,7 +1242,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { pipeline.script_chan.send(msg).unwrap(); let result = receiver.recv().unwrap(); if result == ScriptState::DocumentLoading { - return false; + return ReadyToSave::DocumentLoading; } // Check the visible rectangle for this pipeline. If the constellation has received a @@ -1253,20 +1270,20 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { layout_chan.send(LayoutControlMsg::GetCurrentEpoch(sender)).unwrap(); let layout_task_epoch = receiver.recv().unwrap(); if layout_task_epoch != *compositor_epoch { - return false; + return ReadyToSave::EpochMismatch; } } None => { // The compositor doesn't know about this pipeline yet. // Assume it hasn't rendered yet. - return false; + return ReadyToSave::PipelineUnknown; } } } } // All script tasks are idle and layout epochs match compositor, so output image! - true + ReadyToSave::Ready } // Close a frame (and all children) diff --git a/components/util/opts.rs b/components/util/opts.rs index 31e3eb899ea..fb68c24964d 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -23,6 +23,8 @@ use url::{self, Url}; /// Global flags for Servo, currently set on the command line. #[derive(Clone)] pub struct Opts { + pub is_running_problem_test: bool, + /// The initial URL to load. pub url: Option<Url>, @@ -397,6 +399,7 @@ const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop; pub fn default_opts() -> Opts { Opts { + is_running_problem_test: false, url: Some(Url::parse("about:blank").unwrap()), paint_threads: 1, gpu_painting: false, @@ -518,6 +521,15 @@ pub fn from_cmdline_args(args: &[String]) { } else { homepage_pref.as_string() }; + let is_running_problem_test = + url_opt + .as_ref() + .map(|url| + url.starts_with("http://web-platform.test:8000/2dcontext/drawing-images-to-the-canvas/") || + url.starts_with("http://web-platform.test:8000/_mozilla/mozilla/canvas/") || + url.starts_with("http://web-platform.test:8000/_mozilla/css/canvas_over_area.html")) + .unwrap_or(false); + let url = match url_opt { Some(url_string) => { parse_url_or_filename(&cwd, url_string) @@ -605,6 +617,7 @@ pub fn from_cmdline_args(args: &[String]) { }).collect(); let opts = Opts { + is_running_problem_test: is_running_problem_test, url: Some(url), paint_threads: paint_threads, gpu_painting: gpu_painting, |