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

Investigations for #7787 #8314

Merged
merged 1 commit into from Nov 5, 2015
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -54,6 +54,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
@@ -206,7 +224,7 @@ pub struct ScrollEvent {
cursor: TypedPoint2D<DevicePixel, i32>,
}

#[derive(PartialEq)]
#[derive(PartialEq, Debug)]
enum CompositionRequest {
NoCompositingNecessary,
CompositeOnScrollTimeout(u64),
@@ -570,8 +588,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);
}
@@ -1612,7 +1636,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.
@@ -1623,17 +1647,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
@@ -1644,8 +1668,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);
@@ -1656,21 +1683,22 @@ 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
// that the current output image is stable and ready
// 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(())
}
}
}
@@ -1680,8 +1708,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());
}
}

@@ -1690,26 +1720,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))
}
}
}
}
@@ -1826,7 +1858,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);
}
}

@@ -2079,7 +2116,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,
@@ -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)
@@ -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>,

@@ -403,6 +405,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,
@@ -524,6 +527,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)
@@ -611,6 +623,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,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.