servo: Merge #13848 - Remove concept of Layers from Servo (from mrobinson:remove-layers); r=glennw
authorMartin Robinson <mrobinson@igalia.com>
Fri, 21 Oct 2016 01:43:25 -0500
changeset 339966 121c429a753fc41eed792d85c7c2106c1fc0ce01
parent 339965 f778d6fee54c191e640717baf5780c30d3a61849
child 339967 66dea736a35d7870cd314b460e9e140d1919a8a4
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglennw
servo: Merge #13848 - Remove concept of Layers from Servo (from mrobinson:remove-layers); r=glennw <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because this PR should not change behavior. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Layers were a feature of the legacy drawing path. If we re-add them at some point, it probably makes more sense to make them a product of display list inspection. This change also remove a bunch of dead painting code. Source-Repo: https://github.com/servo/servo Source-Revision: bb271ef4afea02b6b1b5d207e773d1fedccd2906
servo/components/compositing/compositor.rs
servo/components/compositing/compositor_thread.rs
servo/components/compositing/scrolling.md
servo/components/constellation/constellation.rs
servo/components/gfx/display_list/mod.rs
servo/components/gfx_traits/lib.rs
servo/components/layout/block.rs
servo/components/layout/context.rs
servo/components/layout/display_list_builder.rs
servo/components/layout/flow.rs
servo/components/layout/fragment.rs
servo/components/layout/query.rs
servo/components/layout/webrender_helpers.rs
servo/components/layout_thread/lib.rs
servo/components/script/dom/window.rs
servo/components/script/script_thread.rs
servo/components/script_layout_interface/message.rs
servo/components/script_layout_interface/rpc.rs
servo/components/script_layout_interface/wrapper_traits.rs
servo/components/script_traits/lib.rs
servo/components/script_traits/script_msg.rs
--- a/servo/components/compositing/compositor.rs
+++ b/servo/components/compositing/compositor.rs
@@ -7,17 +7,17 @@ use SendableFrameTree;
 use compositor_thread::{CompositorProxy, CompositorReceiver};
 use compositor_thread::{InitialCompositorState, Msg, RenderListener};
 use delayed_composition::DelayedCompositionTimerProxy;
 use euclid::{Point2D, Size2D};
 use euclid::point::TypedPoint2D;
 use euclid::scale_factor::ScaleFactor;
 use euclid::size::TypedSize2D;
 use gfx_traits::{DevicePixel, LayerPixel, StackingContextId};
-use gfx_traits::{Epoch, FrameTreeId, FragmentType, LayerId};
+use gfx_traits::{Epoch, FrameTreeId, FragmentType};
 use gleam::gl;
 use gleam::gl::types::{GLint, GLsizei};
 use image::{DynamicImage, ImageFormat, RgbImage};
 use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
 use ipc_channel::router::ROUTER;
 use msg::constellation_msg::{Image, PixelFormat, Key, KeyModifiers, KeyState};
 use msg::constellation_msg::{LoadData, TraversalDirection, PipelineId};
 use msg::constellation_msg::{PipelineIndex, PipelineNamespaceId, WindowSizeType};
@@ -518,19 +518,19 @@ impl<Window: WindowMethods> IOCompositor
 
             (Msg::SetFrameTree(frame_tree, response_chan),
              ShutdownState::NotShuttingDown) => {
                 self.set_frame_tree(&frame_tree, response_chan);
                 self.send_viewport_rects();
                 self.title_for_main_frame();
             }
 
-            (Msg::ScrollFragmentPoint(pipeline_id, layer_id, point, _),
+            (Msg::ScrollFragmentPoint(pipeline_id, point, _),
              ShutdownState::NotShuttingDown) => {
-                self.scroll_fragment_to_point(pipeline_id, layer_id, point);
+                self.scroll_fragment_to_point(pipeline_id, point);
             }
 
             (Msg::MoveTo(point),
              ShutdownState::NotShuttingDown) => {
                 self.window.set_position(point);
             }
 
             (Msg::ResizeTo(size),
@@ -791,17 +791,16 @@ impl<Window: WindowMethods> IOCompositor
 
         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,
                                 _pipeline_id: PipelineId,
-                                _layer_id: LayerId,
                                 _point: Point2D<f32>) {
         println!("TODO: Support scroll_fragment_to_point again");
     }
 
     fn handle_window_message(&mut self, event: WindowEvent) {
         match event {
             WindowEvent::Idle => {}
 
--- a/servo/components/compositing/compositor_thread.rs
+++ b/servo/components/compositing/compositor_thread.rs
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Communication with the compositor thread.
 
 use SendableFrameTree;
 use compositor::CompositingReason;
 use euclid::point::Point2D;
 use euclid::size::Size2D;
-use gfx_traits::LayerId;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState, PipelineId};
 use profile_traits::mem;
 use profile_traits::time;
 use script_traits::{AnimationState, ConstellationMsg, EventResult};
 use std::fmt::{Debug, Error, Formatter};
 use std::sync::mpsc::{Receiver, Sender};
 use style_traits::cursor::Cursor;
@@ -67,17 +66,17 @@ pub enum Msg {
     Exit,
 
     /// Informs the compositor that the constellation has completed shutdown.
     /// Required because the constellation can have pending calls to make
     /// (e.g. SetFrameTree) at the time that we send it an ExitMsg.
     ShutdownComplete,
 
     /// Scroll a page in a window
-    ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>, bool),
+    ScrollFragmentPoint(PipelineId, Point2D<f32>, bool),
     /// Alerts the compositor that the current page has changed its title.
     ChangePageTitle(PipelineId, Option<String>),
     /// Alerts the compositor that the current page has changed its URL.
     ChangePageUrl(PipelineId, Url),
     /// Alerts the compositor that the given pipeline has changed whether it is running animations.
     ChangeRunningAnimationsState(PipelineId, AnimationState),
     /// Replaces the current frame tree, typically called during main frame navigation.
     SetFrameTree(SendableFrameTree, IpcSender<()>),
deleted file mode 100644
--- a/servo/components/compositing/scrolling.md
+++ /dev/null
@@ -1,57 +0,0 @@
-Scrolling
-=========
-
-Scrolling is implemented by the compositor. Compositor layers that opt in to
-scroll events via the `wants_scroll_events` flag can scroll their contents.
-These will be referred "scrolling roots." Scrolling roots serve as a viewport
-into their content, which is stored in descendant layers. In order for
-scrolling roots to be able to scroll their content, they need to be smaller
-than that content. If the content was smaller than the scrolling root, it would
-not be able to move around inside the scrolling root. Imagine a browser window
-that is larger than the content that it contains. The size of each layer is
-defined by the window size (the root layer) or the block size for iframes and
-elements with `overflow:scroll`.
-
-Since the compositor allows layers to exist independently of their parents,
-child layers can overflow or fail to intersect their parents completely. To
-prevent this, scrolling roots use the `masks_to_bounds` flag, which is a signal
-to the compositor that it should not paint the parts of descendant layers that
-lie outside the boundaries of the scrolling root.
-
-Below is an ASCII art diagram showing a scrolling root with three content
-layers (a, b, and c), scrolled down a few ticks. `masks_to_bounds` has not been
-applied in the diagram.
-
-<pre>
-+-----------------------+
-|                       |
-=========================
-|                       |  scrolling
-|           &lt;-------------+root
-|                       |
-|             +-------+ |
-=========================
-|             |  b    | |
-++-------+    +--^----+ |
-||       |       |      |
-||       |       |      |  content
-||   c &lt;---------+---------+layers
-|+-------+    /         |
-|          a &lt;          |
-|                       |
-+-----------------------+
-</pre>
-
-Everything above and below the set of `====` bars would be hidden by
-`masks_to_bounds`, so the composited scene will just be the viewport defined by
-the scrolling root with the content layers a and b visible.
-
-<pre>
-=========================
-|                       |
-|                       |
-|                       |
-|             +-------+ |
-=========================
-</pre>
-
--- a/servo/components/constellation/constellation.rs
+++ b/servo/components/constellation/constellation.rs
@@ -928,21 +928,20 @@ impl<Message, LTF, STF> Constellation<Me
                 debug!("constellation got SetDocumentState message");
                 self.document_states.insert(pipeline_id, state);
             }
             FromScriptMsg::Alert(pipeline_id, message, sender) => {
                 debug!("constellation got Alert message");
                 self.handle_alert(pipeline_id, message, sender);
             }
 
-            FromScriptMsg::ScrollFragmentPoint(pipeline_id, layer_id, point, smooth) => {
+            FromScriptMsg::ScrollFragmentPoint(pipeline_id, point, smooth) => {
                 self.compositor_proxy.send(ToCompositorMsg::ScrollFragmentPoint(pipeline_id,
-                                                               layer_id,
-                                                               point,
-                                                               smooth));
+                                                                                point,
+                                                                                smooth));
             }
 
             FromScriptMsg::GetClientWindow(send) => {
                 self.compositor_proxy.send(ToCompositorMsg::GetClientWindow(send));
             }
 
             FromScriptMsg::MoveTo(point) => {
                 self.compositor_proxy.send(ToCompositorMsg::MoveTo(point));
--- a/servo/components/gfx/display_list/mod.rs
+++ b/servo/components/gfx/display_list/mod.rs
@@ -10,90 +10,49 @@
 //! (although this benefit does not apply to GPU-based painting).
 //!
 //! Display items describe relatively high-level drawing operations (for example, entire borders
 //! and shadows instead of lines and blur operations), to reduce the amount of allocation required.
 //! They are therefore not exactly analogous to constructs like Skia pictures, which consist of
 //! low-level drawing primitives.
 
 use app_units::Au;
-use azure::azure::AzFloat;
 use azure::azure_hl::Color;
 use euclid::{Matrix4D, Point2D, Rect, Size2D};
-use euclid::approxeq::ApproxEq;
 use euclid::num::{One, Zero};
 use euclid::rect::TypedRect;
 use euclid::side_offsets::SideOffsets2D;
-use gfx_traits::{LayerId, ScrollPolicy, StackingContextId};
+use gfx_traits::{ScrollPolicy, StackingContextId};
 use gfx_traits::print_tree::PrintTree;
 use ipc_channel::ipc::IpcSharedMemory;
 use msg::constellation_msg::PipelineId;
 use net_traits::image::base::{Image, PixelFormat};
-use paint_context::PaintContext;
 use range::Range;
 use std::cmp::{self, Ordering};
 use std::collections::HashMap;
 use std::fmt;
 use std::mem;
 use std::sync::Arc;
 use style::computed_values::{border_style, filter, image_rendering, mix_blend_mode};
 use style_traits::cursor::Cursor;
 use text::TextRun;
 use text::glyph::ByteIndex;
-use util::geometry::{self, ScreenPx, max_rect};
+use util::geometry::{self, max_rect};
 use webrender_traits::{self, WebGLContextId};
 
 pub use style::dom::OpaqueNode;
 
 // It seems cleaner to have layout code not mention Azure directly, so let's just reexport this for
 // layout to use.
 pub use azure::azure_hl::GradientStop;
 
 /// The factor that we multiply the blur radius by in order to inflate the boundaries of display
 /// items that involve a blur. This ensures that the display item boundaries include all the ink.
 pub static BLUR_INFLATION_FACTOR: i32 = 3;
 
-/// LayerInfo is used to store PaintLayer metadata during DisplayList construction.
-/// It is also used for tracking LayerIds when creating layers to preserve ordering when
-/// layered DisplayItems should render underneath unlayered DisplayItems.
-#[derive(Clone, Copy, HeapSizeOf, Deserialize, Serialize, Debug)]
-pub struct LayerInfo {
-    /// The base LayerId of this layer.
-    pub layer_id: LayerId,
-
-    /// The scroll policy of this layer.
-    pub scroll_policy: ScrollPolicy,
-
-    /// The subpage that this layer represents, if there is one.
-    pub subpage_pipeline_id: Option<PipelineId>,
-
-    /// The id for the next layer in the sequence. This is used for synthesizing
-    /// layers for content that needs to be displayed on top of this layer.
-    pub next_layer_id: LayerId,
-
-    /// The color of the background in this layer. Used for unpainted content.
-    pub background_color: Color,
-}
-
-impl LayerInfo {
-    pub fn new(id: LayerId,
-               scroll_policy: ScrollPolicy,
-               subpage_pipeline_id: Option<PipelineId>,
-               background_color: Color)
-               -> LayerInfo {
-        LayerInfo {
-            layer_id: id,
-            scroll_policy: scroll_policy,
-            subpage_pipeline_id: subpage_pipeline_id,
-            next_layer_id: id.companion_layer_id(),
-            background_color: background_color,
-        }
-    }
-}
-
 #[derive(HeapSizeOf, Deserialize, Serialize)]
 pub struct DisplayList {
     pub list: Vec<DisplayItem>,
 }
 
 impl DisplayList {
     pub fn new(root_stacking_context: StackingContext,
                all_items: Vec<DisplayItem>)
@@ -180,166 +139,16 @@ impl DisplayList {
                 PopStackingContextItem {
                     base: BaseDisplayItem::empty(),
                     stacking_context_id: stacking_context_id,
                 }
             )));
         }
     }
 
-    /// Draws the DisplayList in order.
-    pub fn draw_into_context<'a>(&self,
-                                 paint_context: &mut PaintContext,
-                                 transform: &Matrix4D<f32>,
-                                 stacking_context_id: StackingContextId,
-                                 start: usize,
-                                 end: usize) {
-        let mut traversal = DisplayListTraversal::new_partial(self,
-                                                              stacking_context_id,
-                                                              start,
-                                                              end);
-        self.draw_with_state(&mut traversal,
-                             paint_context,
-                             transform,
-                             &Point2D::zero(),
-                             None);
-    }
-
-    /// Draws a single DisplayItem into the given PaintContext.
-    pub fn draw_item_at_index_into_context(&self,
-                                           paint_context: &mut PaintContext,
-                                           transform: &Matrix4D<f32>,
-                                           index: usize) {
-        let old_transform = paint_context.draw_target.get_transform();
-        paint_context.draw_target.set_transform(&transform.to_2d());
-
-        let item = &self.list[index];
-        item.draw_into_context(paint_context);
-
-        paint_context.draw_target.set_transform(&old_transform);
-    }
-
-    fn draw_with_state<'a>(&'a self,
-                           traversal: &mut DisplayListTraversal,
-                           paint_context: &mut PaintContext,
-                           transform: &Matrix4D<f32>,
-                           subpixel_offset: &Point2D<Au>,
-                           tile_rect: Option<Rect<Au>>) {
-        while let Some(item) = traversal.next() {
-            match item {
-                &DisplayItem::PushStackingContext(ref stacking_context_item) => {
-                    let context = &stacking_context_item.stacking_context;
-                    if context.intersects_rect_in_parent_context(tile_rect) {
-                        self.draw_stacking_context(traversal,
-                                                   context,
-                                                   paint_context,
-                                                   transform,
-                                                   subpixel_offset);
-                    } else {
-                        traversal.skip_to_end_of_stacking_context(context.id);
-                    }
-                }
-                &DisplayItem::PopStackingContext(_) => return,
-                _ => {
-                    if item.intersects_rect_in_parent_context(tile_rect) {
-                        item.draw_into_context(paint_context);
-                    }
-                }
-            }
-        }
-    }
-
-    fn draw_stacking_context(&self,
-                             traversal: &mut DisplayListTraversal,
-                             stacking_context: &StackingContext,
-                             paint_context: &mut PaintContext,
-                             transform: &Matrix4D<f32>,
-                             subpixel_offset: &Point2D<Au>) {
-        debug_assert!(stacking_context.context_type == StackingContextType::Real);
-
-        let draw_target = paint_context.get_or_create_temporary_draw_target(
-            &stacking_context.filters,
-            stacking_context.blend_mode);
-
-        let old_transform = paint_context.draw_target.get_transform();
-        let pixels_per_px = paint_context.screen_pixels_per_px();
-        let (transform, subpixel_offset) = match stacking_context.layer_info {
-            // If this stacking context starts a layer, the offset and
-            // transformation are handled by layer position within the
-            // compositor.
-            Some(..) => (*transform, *subpixel_offset),
-            None => {
-                let origin = stacking_context.bounds.origin + *subpixel_offset;
-                let pixel_snapped_origin =
-                    Point2D::new(origin.x.to_nearest_pixel(pixels_per_px.get()),
-                                 origin.y.to_nearest_pixel(pixels_per_px.get()));
-
-                let transform = transform
-                    .pre_translated(pixel_snapped_origin.x as AzFloat,
-                                    pixel_snapped_origin.y as AzFloat,
-                                    0.0)
-                    .pre_mul(&stacking_context.transform);
-
-                if transform.is_identity_or_simple_translation() {
-                    let pixel_snapped_origin = Point2D::new(Au::from_f32_px(pixel_snapped_origin.x),
-                                                            Au::from_f32_px(pixel_snapped_origin.y));
-                    (transform, origin - pixel_snapped_origin)
-                } else {
-                    // In the case of a more complicated transformation, don't attempt to
-                    // preserve subpixel offsets. This causes problems with reference tests
-                    // that do scaling and rotation and it's unclear if we even want to be doing
-                    // this.
-                    (transform, Point2D::zero())
-                }
-            }
-        };
-
-        let transformed_transform =
-            match transformed_tile_rect(paint_context.screen_rect, &transform) {
-                Some(transformed) => transformed,
-                None => {
-                    // https://drafts.csswg.org/css-transforms/#transform-function-lists
-                    // If a transform function causes the current transformation matrix (CTM)
-                    // of an object to be non-invertible, the object and its content do not
-                    // get displayed.
-                    return;
-                },
-            };
-
-        {
-            let mut paint_subcontext = PaintContext {
-                draw_target: draw_target.clone(),
-                font_context: &mut *paint_context.font_context,
-                page_rect: paint_context.page_rect,
-                screen_rect: paint_context.screen_rect,
-                clip_rect: Some(stacking_context.overflow),
-                transient_clip: None,
-                layer_kind: paint_context.layer_kind,
-                subpixel_offset: subpixel_offset,
-            };
-
-            // Set up our clip rect and transform.
-            paint_subcontext.draw_target.set_transform(&transform.to_2d());
-            paint_subcontext.push_clip_if_applicable();
-
-            self.draw_with_state(traversal,
-                                 &mut paint_subcontext,
-                                 &transform,
-                                 &subpixel_offset,
-                                 Some(transformed_transform));
-
-            paint_subcontext.remove_transient_clip_if_applicable();
-            paint_subcontext.pop_clip_if_applicable();
-        }
-
-        draw_target.set_transform(&old_transform);
-        paint_context.draw_temporary_draw_target_if_necessary(
-            &draw_target, &stacking_context.filters, stacking_context.blend_mode);
-    }
-
     // Return all nodes containing the point of interest, bottommost first, and
     // respecting the `pointer-events` CSS property.
     pub fn hit_test(&self,
                     translated_point: &Point2D<Au>,
                     client_point: &Point2D<Au>,
                     scroll_offsets: &ScrollOffsetMap)
                     -> Vec<DisplayItemMetadata> {
         let mut result = Vec::new();
@@ -380,22 +189,20 @@ impl DisplayList {
 
     fn hit_test_stacking_context<'a>(&self,
                         traversal: &mut DisplayListTraversal<'a>,
                         stacking_context: &StackingContext,
                         translated_point: &Point2D<Au>,
                         client_point: &Point2D<Au>,
                         scroll_offsets: &ScrollOffsetMap,
                         result: &mut Vec<DisplayItemMetadata>) {
-        let is_fixed = stacking_context.layer_info.map_or(false,
-            |info| info.scroll_policy == ScrollPolicy::FixedPosition);
-
         // Convert the parent translated point into stacking context local transform space if the
         // stacking context isn't fixed.  If it's fixed, we need to use the client point anyway.
         debug_assert!(stacking_context.context_type == StackingContextType::Real);
+        let is_fixed = stacking_context.scroll_policy == ScrollPolicy::FixedPosition;
         let mut translated_point = if is_fixed {
             *client_point
         } else {
             let point = *translated_point - stacking_context.bounds.origin;
             let inv_transform = stacking_context.transform.inverse().unwrap();
             let frac_point = inv_transform.transform_point(&Point2D::new(point.x.to_f32_px(),
                                                                          point.y.to_f32_px()));
             Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y))
@@ -516,33 +323,16 @@ impl<'a> Iterator for DisplayListTravers
                 _ => {}
             }
         }
 
         None
     }
 }
 
-fn transformed_tile_rect(tile_rect: TypedRect<usize, ScreenPx>,
-                         transform: &Matrix4D<f32>)
-                         -> Option<Rect<Au>> {
-    // Invert the current transform, then use this to back transform
-    // the tile rect (placed at the origin) into the space of this
-    // stacking context.
-    let inverse_transform = match transform.inverse() {
-        Some(inverse) => inverse,
-        None => return None,
-    };
-    let inverse_transform_2d = inverse_transform.to_2d();
-    let tile_size = Size2D::new(tile_rect.to_f32().size.width, tile_rect.to_f32().size.height);
-    let tile_rect = Rect::new(Point2D::zero(), tile_size).to_untyped();
-    Some(geometry::f32_rect_to_au_rect(inverse_transform_2d.transform_rect(&tile_rect)))
-}
-
-
 /// Display list sections that make up a stacking context. Each section  here refers
 /// to the steps in CSS 2.1 Appendix E.
 ///
 #[derive(Clone, Copy, Debug, Deserialize, Eq, HeapSizeOf, Ord, PartialEq, PartialOrd, RustcEncodable, Serialize)]
 pub enum DisplayListSection {
     BackgroundAndBorders,
     BlockBackgroundsAndBorders,
     Content,
@@ -584,18 +374,18 @@ pub struct StackingContext {
     pub transform: Matrix4D<f32>,
 
     /// The perspective matrix to be applied to children.
     pub perspective: Matrix4D<f32>,
 
     /// Whether this stacking context creates a new 3d rendering context.
     pub establishes_3d_context: bool,
 
-    /// The layer info for this stacking context, if there is any.
-    pub layer_info: Option<LayerInfo>,
+    /// The scroll policy of this layer.
+    pub scroll_policy: ScrollPolicy,
 
     /// Children of this StackingContext.
     pub children: Vec<StackingContext>,
 
     /// If this StackingContext scrolls its overflow area, this will contain the id.
     pub overflow_scroll_id: Option<StackingContextId>,
 }
 
@@ -607,31 +397,31 @@ impl StackingContext {
                bounds: &Rect<Au>,
                overflow: &Rect<Au>,
                z_index: i32,
                filters: filter::T,
                blend_mode: mix_blend_mode::T,
                transform: Matrix4D<f32>,
                perspective: Matrix4D<f32>,
                establishes_3d_context: bool,
-               layer_info: Option<LayerInfo>,
+               scroll_policy: ScrollPolicy,
                scroll_id: Option<StackingContextId>)
                -> StackingContext {
         StackingContext {
             id: id,
             context_type: context_type,
             bounds: *bounds,
             overflow: *overflow,
             z_index: z_index,
             filters: filters,
             blend_mode: blend_mode,
             transform: transform,
             perspective: perspective,
             establishes_3d_context: establishes_3d_context,
-            layer_info: layer_info,
+            scroll_policy: scroll_policy,
             children: Vec::new(),
             overflow_scroll_id: scroll_id,
         }
     }
 
     pub fn add_child(&mut self, mut child: StackingContext) {
         child.update_overflow_for_all_children();
         self.children.push(child);
@@ -677,31 +467,16 @@ impl StackingContext {
 
     pub fn print_with_tree(&self, print_tree: &mut PrintTree) {
         print_tree.new_level(format!("{:?}", self));
         for kid in self.children() {
             kid.print_with_tree(print_tree);
         }
         print_tree.end_level();
     }
-
-    fn intersects_rect_in_parent_context(&self, rect: Option<Rect<Au>>) -> bool {
-        // We only do intersection checks for real stacking contexts, since
-        // pseudo stacking contexts might not have proper position information.
-        if self.context_type != StackingContextType::Real {
-            return true;
-        }
-
-        let rect = match rect {
-            Some(ref rect) => rect,
-            None => return true,
-        };
-
-        self.overflow_rect_in_parent_space().intersects(rect)
-    }
 }
 
 impl Ord for StackingContext {
     fn cmp(&self, other: &Self) -> Ordering {
         if self.z_index != 0 || other.z_index != 0 {
             return self.z_index.cmp(&other.z_index);
         }
 
@@ -724,19 +499,17 @@ impl Eq for StackingContext {}
 impl PartialEq for StackingContext {
     fn eq(&self, other: &Self) -> bool {
         self.id == other.id
     }
 }
 
 impl fmt::Debug for StackingContext {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let type_string = if self.layer_info.is_some() {
-            "Layered StackingContext"
-        } else if self.context_type == StackingContextType::Real {
+        let type_string =  if self.context_type == StackingContextType::Real {
             "StackingContext"
         } else {
             "Pseudo-StackingContext"
         };
 
         let scrollable_string = if self.overflow_scroll_id.is_some() {
             " (scrolls overflow area)"
         } else {
@@ -1275,102 +1048,16 @@ pub enum BoxShadowClipMode {
     /// `box-shadow`.
     Outset,
     /// The area outside `box_bounds` should be clipped out. Corresponds to the `inset` flag on CSS
     /// `box-shadow`.
     Inset,
 }
 
 impl DisplayItem {
-    /// Paints this display item into the given painting context.
-    fn draw_into_context(&self, paint_context: &mut PaintContext) {
-        let this_clip = &self.base().clip;
-        match paint_context.transient_clip {
-            Some(ref transient_clip) if transient_clip == this_clip => {}
-            Some(_) | None => paint_context.push_transient_clip((*this_clip).clone()),
-        }
-
-        match *self {
-            DisplayItem::SolidColor(ref solid_color) => {
-                if !solid_color.color.a.approx_eq(&0.0) {
-                    paint_context.draw_solid_color(&solid_color.base.bounds, solid_color.color)
-                }
-            }
-
-            DisplayItem::Text(ref text) => {
-                debug!("Drawing text at {:?}.", text.base.bounds);
-                paint_context.draw_text(&**text);
-            }
-
-            DisplayItem::Image(ref image_item) => {
-                debug!("Drawing image at {:?}.", image_item.base.bounds);
-                paint_context.draw_image(
-                    &image_item.base.bounds,
-                    &image_item.stretch_size,
-                    &image_item.tile_spacing,
-                    &image_item.webrender_image,
-                    &image_item.image_data
-                               .as_ref()
-                               .expect("Non-WR painting needs image data!")[..],
-                    image_item.image_rendering.clone());
-            }
-
-            DisplayItem::WebGL(_) => {
-                panic!("Shouldn't be here, WebGL display items are created just with webrender");
-            }
-
-            DisplayItem::Border(ref border) => {
-                paint_context.draw_border(&border.base.bounds,
-                                          &border.border_widths,
-                                          &border.radius,
-                                          &border.color,
-                                          &border.style)
-            }
-
-            DisplayItem::Gradient(ref gradient) => {
-                paint_context.draw_linear_gradient(&gradient.base.bounds,
-                                                   &gradient.start_point,
-                                                   &gradient.end_point,
-                                                   &gradient.stops);
-            }
-
-            DisplayItem::Line(ref line) => {
-                paint_context.draw_line(&line.base.bounds, line.color, line.style)
-            }
-
-            DisplayItem::BoxShadow(ref box_shadow) => {
-                paint_context.draw_box_shadow(&box_shadow.box_bounds,
-                                              &box_shadow.offset,
-                                              box_shadow.color,
-                                              box_shadow.blur_radius,
-                                              box_shadow.spread_radius,
-                                              box_shadow.clip_mode);
-            }
-
-            DisplayItem::Iframe(..) => {}
-
-            DisplayItem::PushStackingContext(..) => {}
-
-            DisplayItem::PopStackingContext(..) => {}
-        }
-    }
-
-    pub fn intersects_rect_in_parent_context(&self, rect: Option<Rect<Au>>) -> bool {
-        let rect = match rect {
-            Some(ref rect) => rect,
-            None => return true,
-        };
-
-        if !rect.intersects(&self.bounds()) {
-            return false;
-        }
-
-        self.base().clip.might_intersect_rect(&rect)
-    }
-
     pub fn base(&self) -> &BaseDisplayItem {
         match *self {
             DisplayItem::SolidColor(ref solid_color) => &solid_color.base,
             DisplayItem::Text(ref text) => &text.base,
             DisplayItem::Image(ref image_item) => &image_item.base,
             DisplayItem::WebGL(ref webgl_item) => &webgl_item.base,
             DisplayItem::Border(ref border) => &border.base,
             DisplayItem::Gradient(ref gradient) => &gradient.base,
--- a/servo/components/gfx_traits/lib.rs
+++ b/servo/components/gfx_traits/lib.rs
@@ -18,17 +18,16 @@ extern crate rustc_serialize;
 extern crate serde;
 #[macro_use]
 extern crate serde_derive;
 
 pub mod color;
 pub mod print_tree;
 
 use range::RangeIndex;
-use std::fmt::{self, Debug, Formatter};
 use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
 
 /// The next ID that will be used for a special stacking context.
 ///
 /// A special stacking context is a stacking context that is one of (a) the outer stacking context
 /// of an element with `overflow: scroll`; (b) generated content; (c) both (a) and (b).
 static NEXT_SPECIAL_STACKING_CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
 
@@ -75,66 +74,16 @@ pub enum LayerType {
 #[derive(Clone, PartialEq, Eq, Copy, Deserialize, Serialize, Debug, HeapSizeOf)]
 pub enum ScrollPolicy {
     /// These layers scroll when the parent receives a scrolling message.
     Scrollable,
     /// These layers do not scroll when the parent receives a scrolling message.
     FixedPosition,
 }
 
-#[derive(Clone, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf)]
-pub struct LayerId(
-    /// The type of the layer. This serves to differentiate layers that share fragments.
-    LayerType,
-    /// The identifier for this layer's fragment, derived from the fragment memory address.
-    usize,
-    /// An index for identifying companion layers, synthesized to ensure that
-    /// content on top of this layer's fragment has the proper rendering order.
-    usize
-);
-
-impl Debug for LayerId {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        let LayerId(layer_type, id, companion) = *self;
-        let type_string = match layer_type {
-            LayerType::FragmentBody => "-FragmentBody",
-            LayerType::OverflowScroll => "-OverflowScroll",
-            LayerType::BeforePseudoContent => "-BeforePseudoContent",
-            LayerType::AfterPseudoContent => "-AfterPseudoContent",
-        };
-
-        write!(f, "{}{}-{}", id, type_string, companion)
-    }
-}
-
-impl LayerId {
-    /// FIXME(#2011, pcwalton): This is unfortunate. Maybe remove this in the future.
-    pub fn null() -> LayerId {
-        LayerId(LayerType::FragmentBody, 0, 0)
-    }
-
-    pub fn new_of_type(layer_type: LayerType, fragment_id: usize) -> LayerId {
-        LayerId(layer_type, fragment_id, 0)
-    }
-
-    pub fn companion_layer_id(&self) -> LayerId {
-        let LayerId(layer_type, id, companion) = *self;
-        LayerId(layer_type, id, companion + 1)
-    }
-
-    pub fn original(&self) -> LayerId {
-        let LayerId(layer_type, id, _) = *self;
-        LayerId(layer_type, id, 0)
-    }
-
-    pub fn kind(&self) -> LayerType {
-        self.0
-    }
-}
-
 /// A newtype struct for denoting the age of messages; prevents race conditions.
 #[derive(PartialEq, Eq, Debug, Copy, Clone, PartialOrd, Ord, Deserialize, Serialize)]
 pub struct Epoch(pub u32);
 
 impl Epoch {
     pub fn next(&mut self) {
         self.0 += 1;
     }
--- a/servo/components/layout/block.rs
+++ b/servo/components/layout/block.rs
@@ -31,43 +31,42 @@ use app_units::{Au, MAX_AU};
 use context::{LayoutContext, SharedLayoutContext};
 use display_list_builder::{BorderPaintingMode, DisplayListBuildState, FragmentDisplayListBuilding};
 use display_list_builder::BlockFlowDisplayListBuilding;
 use euclid::{Point2D, Size2D};
 use floats::{ClearType, FloatKind, Floats, PlacementInfo};
 use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
 use flow::{BLOCK_POSITION_IS_STATIC, CLEARS_LEFT, CLEARS_RIGHT};
 use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, INLINE_POSITION_IS_STATIC};
-use flow::{FragmentationContext, NEEDS_LAYER, PreorderFlowTraversal};
+use flow::{FragmentationContext, PreorderFlowTraversal};
 use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
 use flow::IS_ABSOLUTELY_POSITIONED;
 use flow_list::FlowList;
 use flow_ref::FlowRef;
-use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER, Overflow};
+use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
 use fragment::SpecificFragmentInfo;
 use gfx::display_list::{ClippingRegion, StackingContext};
-use gfx_traits::LayerId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo, MaybeAuto};
 use model::{specified, specified_or_none};
 use rustc_serialize::{Encodable, Encoder};
 use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
 use script_layout_interface::restyle_damage::REPOSITION;
 use sequential;
 use std::cmp::{max, min};
 use std::fmt;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, box_sizing, display, float, overflow_x, overflow_y};
-use style::computed_values::{position, text_align, transform_style};
+use style::computed_values::{position, text_align};
 use style::context::{SharedStyleContext, StyleContext};
 use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
 use style::properties::ServoComputedValues;
-use style::values::computed::{LengthOrNone, LengthOrPercentageOrNone};
-use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
+use style::values::computed::{LengthOrPercentageOrNone, LengthOrPercentage};
+use style::values::computed::LengthOrPercentageOrAuto;
 use util::clamp;
 
 /// Information specific to floated blocks.
 #[derive(Clone, RustcEncodable)]
 pub struct FloatedBlockInfo {
     /// The amount of inline size that is available for the float.
     pub containing_inline_size: Au,
 
@@ -788,18 +787,16 @@ impl BlockFlow {
                                             margins_may_collapse: MarginsMayCollapseFlag)
                                             -> Option<FlowRef> {
         let _scope = layout_debug_scope!("assign_block_size_block_base {:x}",
                                          self.base.debug_id());
 
         let mut break_at = None;
         let content_box = self.fragment.content_box();
         if self.base.restyle_damage.contains(REFLOW) {
-            self.determine_if_layer_needed();
-
             // Our current border-box position.
             let mut cur_b = Au(0);
 
             // Absolute positioning establishes a block formatting context. Don't propagate floats
             // in or out. (But do propagate them between kids.)
             if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
                     margins_may_collapse != MarginsMayCollapseFlag::MarginsMayCollapse {
                 self.base.floats = Floats::new(self.fragment.style.writing_mode);
@@ -1674,44 +1671,16 @@ impl BlockFlow {
         computation.content_intrinsic_sizes.preferred_inline_size =
             max(computation.content_intrinsic_sizes.preferred_inline_size,
                 preferred_inline_size_of_children_without_text_or_replaced_fragments);
 
         self.base.intrinsic_inline_sizes = computation.finish();
         self.base.flags = flags
     }
 
-    fn determine_if_layer_needed(&mut self) {
-        // Fixed position layers get layers.
-        if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) && self.is_fixed() {
-            self.base.flags.insert(NEEDS_LAYER);
-            return
-        }
-
-        // This flow needs a layer if it has a 3d transform, or provides perspective
-        // to child layers. See http://dev.w3.org/csswg/css-transforms/#3d-rendering-contexts.
-        let has_3d_transform = self.fragment.style().transform_requires_layer();
-        let has_perspective = self.fragment.style().get_effects().perspective !=
-            LengthOrNone::None;
-
-        if has_3d_transform || has_perspective {
-            self.base.flags.insert(NEEDS_LAYER);
-            return
-        }
-
-        match (self.fragment.style().get_box().overflow_x,
-               self.fragment.style().get_box().overflow_y.0) {
-            (overflow_x::T::auto, _) | (overflow_x::T::scroll, _) |
-            (_, overflow_x::T::auto) | (_, overflow_x::T::scroll) => {
-                self.base.flags.insert(NEEDS_LAYER);
-            }
-            _ => {}
-        }
-    }
-
     pub fn block_stacking_context_type(&self) -> BlockStackingContextType {
         if self.fragment.establishes_stacking_context() {
             return BlockStackingContextType::StackingContext
         }
 
         if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
                 self.fragment.style.get_box().position != position::T::static_ ||
                 self.base.flags.is_float() {
@@ -1951,30 +1920,24 @@ impl Flow for BlockFlow {
             self.assign_block_size_block_base(
                 layout_context,
                 fragmentation_context,
                 MarginsMayCollapseFlag::MarginsMayCollapse)
         }
     }
 
     fn compute_absolute_position(&mut self, _layout_context: &SharedLayoutContext) {
-        if self.base.flags.contains(NEEDS_LAYER) {
-            self.fragment.flags.insert(HAS_LAYER)
-        }
-
         // FIXME (mbrubeck): Get the real container size, taking the container writing mode into
         // account.  Must handle vertical writing modes.
         let container_size = Size2D::new(self.base.block_container_inline_size, Au(0));
 
         if self.is_root() {
             self.base.clip = ClippingRegion::max();
         }
 
-        let transform_style = self.fragment.style().get_used_transform_style();
-
         if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
             // `overflow: auto` and `overflow: scroll` force creation of layers, since we can only
             // scroll layers.
             match (self.fragment.style().get_box().overflow_x,
                    self.fragment.style().get_box().overflow_y.0) {
                 (overflow_x::T::auto, _) | (overflow_x::T::scroll, _) |
                 (_, overflow_x::T::auto) | (_, overflow_x::T::scroll) => {
                     self.base.clip = ClippingRegion::max();
@@ -2098,26 +2061,16 @@ impl Flow for BlockFlow {
         // Compute the clipping region for children, taking our `overflow` properties and so forth
         // into account.
         let mut clip_for_children = self.base.clip.clone();
         self.fragment.adjust_clipping_region_for_children(&mut clip_for_children,
                                                           &stacking_relative_border_box);
 
         // Process children.
         for kid in self.base.child_iter_mut() {
-            // If this layer preserves the 3d context of children,
-            // then children will need a render layer.
-            // TODO(gw): This isn't always correct. In some cases
-            // this may create extra layers than needed. I think
-            // there are also some edge cases where children don't
-            // get a layer when they should.
-            if transform_style == transform_style::T::preserve_3d {
-                flow::mut_base(kid).flags.insert(NEEDS_LAYER);
-            }
-
             if flow::base(kid).flags.contains(INLINE_POSITION_IS_STATIC) ||
                     flow::base(kid).flags.contains(BLOCK_POSITION_IS_STATIC) {
                 let kid_base = flow::mut_base(kid);
                 let physical_position = kid_base.position.to_physical(kid_base.writing_mode,
                                                                       container_size_for_children);
 
                 // Set the inline and block positions as necessary.
                 if !kid_base.writing_mode.is_vertical() {
@@ -2172,24 +2125,16 @@ impl Flow for BlockFlow {
     }
 
     /// Return the dimensions of the containing block generated by this flow for absolutely-
     /// positioned descendants. For block flows, this is the padding box.
     fn generated_containing_block_size(&self, _: OpaqueFlow) -> LogicalSize<Au> {
         (self.fragment.border_box - self.fragment.style().logical_border_width()).size
     }
 
-    fn layer_id(&self) -> LayerId {
-        self.fragment.layer_id()
-    }
-
-    fn layer_id_for_overflow_scroll(&self) -> LayerId {
-        self.fragment.layer_id_for_overflow_scroll()
-    }
-
     fn is_absolute_containing_block(&self) -> bool {
         self.contains_positioned_fragments()
     }
 
     fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
         if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
                 self.fragment.style().logical_position().inline_start ==
                     LengthOrPercentageOrAuto::Auto &&
--- a/servo/components/layout/context.rs
+++ b/servo/components/layout/context.rs
@@ -2,23 +2,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Data needed by the layout thread.
 
 // for thread_local
 #![allow(unsafe_code)]
 
-use app_units::Au;
-use euclid::Rect;
 use fnv::FnvHasher;
 use gfx::display_list::WebRenderImageInfo;
 use gfx::font_cache_thread::FontCacheThread;
 use gfx::font_context::FontContext;
-use gfx_traits::LayerId;
 use heapsize::HeapSizeOf;
 use ipc_channel::ipc;
 use net_traits::image::base::Image;
 use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread, ImageResponse, ImageState};
 use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder};
 use std::cell::{RefCell, RefMut};
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
@@ -82,19 +79,16 @@ pub struct SharedLayoutContext {
     pub image_cache_thread: ImageCacheThread,
 
     /// A channel for the image cache to send responses to.
     pub image_cache_sender: Mutex<ImageCacheChan>,
 
     /// Interface to the font cache thread.
     pub font_cache_thread: Mutex<FontCacheThread>,
 
-    /// The visible rects for each layer, as reported to us by the compositor.
-    pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, BuildHasherDefault<FnvHasher>>>,
-
     /// A cache of WebRender image info.
     pub webrender_image_cache: Arc<RwLock<HashMap<(Url, UsePlaceholder),
                                                   WebRenderImageInfo,
                                                   BuildHasherDefault<FnvHasher>>>>,
 }
 
 pub struct LayoutContext<'a> {
     pub shared: &'a SharedLayoutContext,
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -14,23 +14,23 @@ use app_units::{AU_PER_PX, Au};
 use azure::azure_hl::Color;
 use block::{BlockFlow, BlockStackingContextType};
 use canvas_traits::{CanvasData, CanvasMsg, FromLayoutMsg};
 use context::SharedLayoutContext;
 use euclid::{Matrix4D, Point2D, Radians, Rect, SideOffsets2D, Size2D};
 use flex::FlexFlow;
 use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
 use flow_ref;
-use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo};
+use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
 use fragment::SpecificFragmentInfo;
 use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem};
 use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
 use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection, GradientDisplayItem};
 use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem};
-use gfx::display_list::{LayerInfo, LineDisplayItem, OpaqueNode};
+use gfx::display_list::{LineDisplayItem, OpaqueNode};
 use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType};
 use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
 use gfx_traits::{ScrollPolicy, StackingContextId, color};
 use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
 use ipc_channel::ipc;
 use list_item::ListItemFlow;
 use model::{self, MaybeAuto, ToGfxMatrix};
 use net_traits::image::base::PixelFormat;
@@ -1405,22 +1405,16 @@ impl FragmentDisplayListBuilding for Fra
 
         // Create the filter pipeline.
         let effects = self.style().get_effects();
         let mut filters = effects.filter.clone();
         if effects.opacity != 1.0 {
             filters.push(Filter::Opacity(effects.opacity))
         }
 
-        let layer_info = if self.flags.contains(HAS_LAYER) {
-            Some(LayerInfo::new(self.layer_id(), scroll_policy, None, color::transparent()))
-        } else {
-            None
-        };
-
         let transform_style = self.style().get_used_transform_style();
         let establishes_3d_context = scrolls_overflow_area ||
             transform_style == transform_style::T::flat;
 
         let context_type = match mode {
             StackingContextCreationMode::PseudoFloat => StackingContextType::PseudoFloat,
             StackingContextCreationMode::PseudoPositioned => StackingContextType::PseudoPositioned,
             _ => StackingContextType::Real,
@@ -1431,17 +1425,17 @@ impl FragmentDisplayListBuilding for Fra
                              &border_box,
                              &overflow,
                              self.effective_z_index(),
                              filters,
                              self.style().get_effects().mix_blend_mode,
                              transform,
                              perspective,
                              establishes_3d_context,
-                             layer_info,
+                             scroll_policy,
                              scroll_id)
     }
 
     fn adjust_clipping_region_for_children(&self,
                                            current_clip: &mut ClippingRegion,
                                            stacking_relative_border_box: &Rect<Au>) {
         // Don't clip if we're text.
         if self.is_scanned_text_fragment() {
--- a/servo/components/layout/flow.rs
+++ b/servo/components/layout/flow.rs
@@ -30,17 +30,17 @@ use block::{BlockFlow, FormattingContext
 use context::{LayoutContext, SharedLayoutContext};
 use display_list_builder::DisplayListBuildState;
 use euclid::{Point2D, Size2D};
 use floats::{Floats, SpeculatedFloatPlacement};
 use flow_list::{FlowList, MutFlowListIterator};
 use flow_ref::{self, FlowRef, WeakFlowRef};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
 use gfx::display_list::{ClippingRegion, StackingContext};
-use gfx_traits::{LayerId, LayerType, StackingContextId};
+use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use inline::InlineFlow;
 use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
 use multicol::MulticolFlow;
 use parallel::FlowParallelInfo;
 use rustc_serialize::{Encodable, Encoder};
 use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW};
 use script_layout_interface::restyle_damage::{REPAINT, REPOSITION, RestyleDamage};
@@ -394,26 +394,16 @@ pub trait Flow: fmt::Debug + Sync + Send
 
     /// Return the size of the containing block generated by this flow for the absolutely-
     /// positioned descendant referenced by `for_flow`. For block flows, this is the padding box.
     ///
     /// NB: Do not change this `&self` to `&mut self` under any circumstances! It has security
     /// implications because this can be called on parents concurrently from descendants!
     fn generated_containing_block_size(&self, _: OpaqueFlow) -> LogicalSize<Au>;
 
-    /// Returns a layer ID for the given fragment.
-    fn layer_id(&self) -> LayerId {
-        LayerId::new_of_type(LayerType::FragmentBody, base(self).flow_id())
-    }
-
-    /// Returns a layer ID for the given fragment.
-    fn layer_id_for_overflow_scroll(&self) -> LayerId {
-        LayerId::new_of_type(LayerType::OverflowScroll, base(self).flow_id())
-    }
-
     /// Attempts to perform incremental fixup of this flow by replacing its fragment's style with
     /// the new style. This can only succeed if the flow has exactly one fragment.
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>);
 
     /// Print any extra children (such as fragments) contained in this Flow
     /// for debugging purposes. Any items inserted into the tree will become
     /// children of this flow.
     fn print_extra_flow_children(&self, _: &mut PrintTree) {
@@ -629,20 +619,16 @@ pub trait InorderFlowTraversal {
     /// descendants should be processed.
     fn should_process(&mut self, flow: &mut Flow) -> bool;
 }
 
 bitflags! {
     #[doc = "Flags used in flows."]
     pub flags FlowFlags: u32 {
         // text align flags
-        #[doc = "Whether this flow must have its own layer. Even if this flag is not set, it might"]
-        #[doc = "get its own layer if it's deemed to be likely to overlap flows with their own"]
-        #[doc = "layer."]
-        const NEEDS_LAYER = 0b0000_0000_0000_0000_0010_0000,
         #[doc = "Whether this flow is absolutely positioned. This is checked all over layout, so a"]
         #[doc = "virtual call is too expensive."]
         const IS_ABSOLUTELY_POSITIONED = 0b0000_0000_0000_0000_0100_0000,
         #[doc = "Whether this flow clears to the left. This is checked all over layout, so a"]
         #[doc = "virtual call is too expensive."]
         const CLEARS_LEFT = 0b0000_0000_0000_0000_1000_0000,
         #[doc = "Whether this flow clears to the right. This is checked all over layout, so a"]
         #[doc = "virtual call is too expensive."]
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -12,17 +12,17 @@ use context::{LayoutContext, SharedLayou
 use euclid::{Point2D, Rect, Size2D};
 use floats::ClearType;
 use flow::{self, ImmutableFlowUtils};
 use flow_ref::{self, FlowRef};
 use gfx;
 use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
 use gfx::text::glyph::ByteIndex;
 use gfx::text::text_run::{TextRun, TextRunSlice};
-use gfx_traits::{FragmentType, LayerId, LayerType, StackingContextId};
+use gfx_traits::{FragmentType, StackingContextId};
 use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
 use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT, LineMetrics};
 use ipc_channel::ipc::IpcSender;
 #[cfg(debug_assertions)]
 use layout_debug;
 use model::{self, Direction, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto};
 use msg::constellation_msg::PipelineId;
 use net_traits::image::base::{Image, ImageMetadata};
@@ -43,17 +43,17 @@ use style::computed_values::{border_coll
 use style::computed_values::{overflow_wrap, overflow_x, position, text_decoration};
 use style::computed_values::{transform_style, vertical_align, white_space, word_break, z_index};
 use style::computed_values::content::ContentItem;
 use style::context::SharedStyleContext;
 use style::dom::TRestyleDamage;
 use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode};
 use style::properties::ServoComputedValues;
 use style::str::char_is_whitespace;
-use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
+use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto};
 use style::values::computed::LengthOrPercentageOrNone;
 use text;
 use text::TextRunScanner;
 use url::Url;
 
 // From gfxFontConstants.h in Firefox.
 static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20;
 static FONT_SUPERSCRIPT_OFFSET_RATIO: f32 = 0.34;
@@ -117,19 +117,16 @@ pub struct Fragment {
     pub inline_context: Option<InlineFragmentContext>,
 
     /// How damaged this fragment is since last reflow.
     pub restyle_damage: RestyleDamage,
 
     /// The pseudo-element that this fragment represents.
     pub pseudo: PseudoElementType<()>,
 
-    /// Various flags for this fragment.
-    pub flags: FragmentFlags,
-
     /// A debug ID that is consistent for the life of this fragment (via transform etc).
     /// This ID should not be considered stable across multiple layouts or fragment
     /// manipulations.
     debug_id: DebugId,
 
     /// The ID of the StackingContext that contains this fragment. This is initialized
     /// to 0, but it assigned during the collect_stacking_contexts phase of display
     /// list construction.
@@ -914,17 +911,16 @@ impl Fragment {
             selected_style: node.selected_style(style_context),
             restyle_damage: restyle_damage,
             border_box: LogicalRect::zero(writing_mode),
             border_padding: LogicalMargin::zero(writing_mode),
             margin: LogicalMargin::zero(writing_mode),
             specific: specific,
             inline_context: None,
             pseudo: node.get_pseudo_element_type().strip(),
-            flags: FragmentFlags::empty(),
             debug_id: DebugId::new(),
             stacking_context_id: StackingContextId::new(0),
         }
     }
 
     /// Constructs a new `Fragment` instance from an opaque node.
     pub fn from_opaque_node_and_style(node: OpaqueNode,
                                       pseudo: PseudoElementType<()>,
@@ -943,17 +939,16 @@ impl Fragment {
             selected_style: selected_style,
             restyle_damage: restyle_damage,
             border_box: LogicalRect::zero(writing_mode),
             border_padding: LogicalMargin::zero(writing_mode),
             margin: LogicalMargin::zero(writing_mode),
             specific: specific,
             inline_context: None,
             pseudo: pseudo,
-            flags: FragmentFlags::empty(),
             debug_id: DebugId::new(),
             stacking_context_id: StackingContextId::new(0),
         }
     }
 
     /// Transforms this fragment into another fragment of the given type, with the given size,
     /// preserving all the other data.
     pub fn transform(&self, size: LogicalSize<Au>, info: SpecificFragmentInfo)
@@ -971,17 +966,16 @@ impl Fragment {
             selected_style: self.selected_style.clone(),
             restyle_damage: restyle_damage,
             border_box: new_border_box,
             border_padding: self.border_padding,
             margin: self.margin,
             specific: info,
             inline_context: self.inline_context.clone(),
             pseudo: self.pseudo.clone(),
-            flags: FragmentFlags::empty(),
             debug_id: self.debug_id.clone(),
             stacking_context_id: StackingContextId::new(0),
         }
     }
 
     /// Transforms this fragment using the given `SplitInfo`, preserving all the other data.
     pub fn transform_with_split_info(&self, split: &SplitInfo, text_run: Arc<TextRun>)
                                      -> Fragment {
@@ -2530,31 +2524,40 @@ impl Fragment {
     pub fn establishes_stacking_context(&self) -> bool {
         // Text fragments shouldn't create stacking contexts.
         match self.specific {
             SpecificFragmentInfo::ScannedText(_) |
             SpecificFragmentInfo::UnscannedText(_) => return false,
             _ => {}
         }
 
-        if self.flags.contains(HAS_LAYER) {
-            return true
-        }
         if self.style().get_effects().opacity != 1.0 {
             return true
         }
         if !self.style().get_effects().filter.is_empty() {
             return true
         }
         if self.style().get_effects().mix_blend_mode != mix_blend_mode::T::normal {
             return true
         }
         if self.style().get_effects().transform.0.is_some() {
             return true
         }
+
+        // TODO(mrobinson): Determine if this is necessary, since blocks with
+        // transformations already create stacking contexts.
+        if self.style().get_effects().perspective != LengthOrNone::None {
+            return true
+        }
+
+        // Fixed position blocks always create stacking contexts.
+        if self.style.get_box().position == position::T::fixed {
+            return true
+        }
+
         match self.style().get_used_transform_style() {
             transform_style::T::flat | transform_style::T::preserve_3d => {
                 return true
             }
             transform_style::T::auto => {}
         }
 
         // FIXME(pcwalton): Don't unconditionally form stacking contexts for `overflow_x: scroll`
@@ -2869,31 +2872,16 @@ impl Fragment {
             PseudoElementType::Normal => FragmentType::FragmentBody,
             PseudoElementType::Before(_) => FragmentType::BeforePseudoContent,
             PseudoElementType::After(_) => FragmentType::AfterPseudoContent,
             PseudoElementType::DetailsSummary(_) => FragmentType::FragmentBody,
             PseudoElementType::DetailsContent(_) => FragmentType::FragmentBody,
         }
     }
 
-    pub fn layer_id(&self) -> LayerId {
-        let layer_type = match self.pseudo {
-            PseudoElementType::Normal => LayerType::FragmentBody,
-            PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
-            PseudoElementType::After(_) => LayerType::AfterPseudoContent,
-            PseudoElementType::DetailsSummary(_) => LayerType::FragmentBody,
-            PseudoElementType::DetailsContent(_) => LayerType::FragmentBody,
-        };
-        LayerId::new_of_type(layer_type, self.node.id() as usize)
-    }
-
-    pub fn layer_id_for_overflow_scroll(&self) -> LayerId {
-        LayerId::new_of_type(LayerType::OverflowScroll, self.node.id() as usize)
-    }
-
     /// Returns true if any of the inline styles associated with this fragment have
     /// `vertical-align` set to `top` or `bottom`.
     pub fn is_vertically_aligned_to_top_or_bottom(&self) -> bool {
         match self.style.get_box().vertical_align {
             vertical_align::T::top | vertical_align::T::bottom => return true,
             _ => {}
         }
         if let Some(ref inline_context) = self.inline_context {
@@ -3089,23 +3077,16 @@ impl Overflow {
     }
 
     pub fn translate(&mut self, point: &Point2D<Au>) {
         self.scroll = self.scroll.translate(point);
         self.paint = self.paint.translate(point);
     }
 }
 
-bitflags! {
-    pub flags FragmentFlags: u8 {
-        /// Whether this fragment has a layer.
-        const HAS_LAYER = 0x01,
-    }
-}
-
 /// Specified distances from the margin edge of a block to its content in the inline direction.
 /// These are returned by `guess_inline_content_edge_offsets()` and are used in the float placement
 /// speculation logic.
 #[derive(Copy, Clone, Debug)]
 pub struct SpeculatedInlineContentEdgeOffsets {
     pub start: Au,
     pub end: Au,
 }
--- a/servo/components/layout/query.rs
+++ b/servo/components/layout/query.rs
@@ -7,24 +7,23 @@
 use app_units::Au;
 use construct::ConstructionResult;
 use euclid::point::Point2D;
 use euclid::rect::Rect;
 use euclid::size::Size2D;
 use flow::{self, Flow};
 use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
 use gfx::display_list::{DisplayItemMetadata, DisplayList, OpaqueNode, ScrollOffsetMap};
-use gfx_traits::LayerId;
 use ipc_channel::ipc::IpcSender;
 use opaque_node::OpaqueNodeMethods;
 use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse};
 use script_layout_interface::rpc::{HitTestResponse, LayoutRPC};
 use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse};
-use script_layout_interface::rpc::{NodeLayerIdResponse, NodeOverflowResponse};
-use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse};
+use script_layout_interface::rpc::{NodeOverflowResponse, OffsetParentResponse};
+use script_layout_interface::rpc::ResolvedStyleResponse;
 use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
 use script_traits::LayoutMsg as ConstellationMsg;
 use script_traits::UntrustedNodeAddress;
 use sequential;
 use std::cmp::{min, max};
 use std::ops::Deref;
 use std::sync::{Arc, Mutex};
 use string_cache::Atom;
@@ -56,18 +55,16 @@ pub struct LayoutThreadData {
     pub content_box_response: Rect<Au>,
 
     /// A queued response for the content boxes of a node.
     pub content_boxes_response: Vec<Rect<Au>>,
 
     /// A queued response for the client {top, left, width, height} of a node in pixels.
     pub client_rect_response: Rect<i32>,
 
-    pub layer_id_response: Option<LayerId>,
-
     /// A queued response for the node at a given point
     pub hit_test_response: (Option<DisplayItemMetadata>, bool),
 
     /// A pair of overflow property in x and y
     pub overflow_response: NodeOverflowResponse,
 
     /// A queued response for the scroll {top, left, width, height} of a node in pixels.
     pub scroll_area_response: Rect<i32>,
@@ -175,23 +172,16 @@ impl LayoutRPC for LayoutRPCImpl {
     }
 
     fn node_scroll_area(&self) -> NodeGeometryResponse {
         NodeGeometryResponse {
             client_rect: self.0.lock().unwrap().scroll_area_response
         }
     }
 
-    fn node_layer_id(&self) -> NodeLayerIdResponse {
-        NodeLayerIdResponse {
-            layer_id: self.0.lock().unwrap().layer_id_response
-                          .expect("layer_id is not correctly fetched, see PR #9968")
-        }
-    }
-
     /// Retrieves the resolved value for a CSS style property.
     fn resolved_style(&self) -> ResolvedStyleResponse {
         let &LayoutRPCImpl(ref rw_data) = self;
         let rw_data = rw_data.lock().unwrap();
         ResolvedStyleResponse(rw_data.resolved_style_response.clone())
     }
 
     fn offset_parent(&self) -> OffsetParentResponse {
@@ -582,21 +572,16 @@ impl FragmentBorderBoxIterator for Paren
 
 pub fn process_node_geometry_request<N: LayoutNode>(requested_node: N, layout_root: &mut Flow)
         -> Rect<i32> {
     let mut iterator = FragmentLocatingFragmentIterator::new(requested_node.opaque());
     sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
     iterator.client_rect
 }
 
-pub fn process_node_layer_id_request<N: LayoutNode>(requested_node: N) -> LayerId {
-    let layout_node = requested_node.to_threadsafe();
-    layout_node.layer_id()
-}
-
 pub fn process_node_scroll_area_request< N: LayoutNode>(requested_node: N, layout_root: &mut Flow)
         -> Rect<i32> {
     let mut iterator = UnioningFragmentScrollAreaIterator::new(requested_node.opaque());
     sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
     match iterator.overflow_direction {
         OverflowDirection::RightAndDown => {
             let right = max(iterator.union_rect.size.width, iterator.origin_rect.size.width);
             let bottom = max(iterator.union_rect.size.height, iterator.origin_rect.size.height);
--- a/servo/components/layout/webrender_helpers.rs
+++ b/servo/components/layout/webrender_helpers.rs
@@ -21,27 +21,25 @@ use webrender_traits::{self, AuxiliaryLi
 
 trait WebRenderStackingContextConverter {
     fn convert_to_webrender<'a>(&self,
                                 traversal: &mut DisplayListTraversal<'a>,
                                 api: &mut webrender_traits::RenderApi,
                                 pipeline_id: webrender_traits::PipelineId,
                                 epoch: webrender_traits::Epoch,
                                 scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
-                                scroll_policy: ScrollPolicy,
                                 frame_builder: &mut WebRenderFrameBuilder)
                                 -> webrender_traits::StackingContextId;
 
     fn convert_children_to_webrender<'a>(&self,
                                          traversal: &mut DisplayListTraversal<'a>,
                                          api: &mut webrender_traits::RenderApi,
                                          pipeline_id: webrender_traits::PipelineId,
                                          epoch: webrender_traits::Epoch,
                                          scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
-                                         scroll_policy: ScrollPolicy,
                                          builder: &mut webrender_traits::DisplayListBuilder,
                                          frame_builder: &mut WebRenderFrameBuilder,
                                          force_positioned_stacking_level: bool);
 }
 
 pub trait WebRenderDisplayListConverter {
     fn convert_to_webrender(&self,
                             api: &mut webrender_traits::RenderApi,
@@ -251,17 +249,16 @@ impl ToFilterOps for filter::T {
 
 impl WebRenderStackingContextConverter for StackingContext {
     fn convert_children_to_webrender<'a>(&self,
                                          traversal: &mut DisplayListTraversal<'a>,
                                          api: &mut webrender_traits::RenderApi,
                                          pipeline_id: webrender_traits::PipelineId,
                                          epoch: webrender_traits::Epoch,
                                          scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
-                                         scroll_policy: ScrollPolicy,
                                          builder: &mut webrender_traits::DisplayListBuilder,
                                          frame_builder: &mut WebRenderFrameBuilder,
                                          _force_positioned_stacking_level: bool) {
         while let Some(item) = traversal.next() {
             match item {
                 &DisplayItem::PushStackingContext(ref stacking_context_item) => {
                     let stacking_context = &stacking_context_item.stacking_context;
                     debug_assert!(stacking_context.context_type == StackingContextType::Real);
@@ -273,41 +270,35 @@ impl WebRenderStackingContextConverter f
                     };
 
                     let stacking_context_id =
                         stacking_context.convert_to_webrender(traversal,
                                                               api,
                                                               pipeline_id,
                                                               epoch,
                                                               scroll_layer_id_for_children,
-                                                              scroll_policy,
                                                               frame_builder);
                     builder.push_stacking_context(stacking_context_id);
 
                 }
                 &DisplayItem::PopStackingContext(_) => return,
                 _ => item.convert_to_webrender(builder, frame_builder),
             }
         }
     }
 
     fn convert_to_webrender<'a>(&self,
                                 traversal: &mut DisplayListTraversal<'a>,
                                 api: &mut webrender_traits::RenderApi,
                                 pipeline_id: webrender_traits::PipelineId,
                                 epoch: webrender_traits::Epoch,
                                 scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
-                                mut scroll_policy: ScrollPolicy,
                                 frame_builder: &mut WebRenderFrameBuilder)
                                 -> webrender_traits::StackingContextId {
-        if let Some(ref layer_info) = self.layer_info {
-            scroll_policy = layer_info.scroll_policy
-        }
-
-        let webrender_scroll_policy = match scroll_policy {
+        let webrender_scroll_policy = match self.scroll_policy {
             ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable,
             ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed,
         };
 
         let webrender_stacking_context_id = self.id.convert_to_webrender();
 
         let outer_overflow = if self.overflow_scroll_id.is_none() {
             self.overflow.to_rectf()
@@ -348,31 +339,29 @@ impl WebRenderStackingContextConverter f
                                                        Vec::new(),
                                                        &mut frame_builder.auxiliary_lists_builder);
             let mut inner_builder = webrender_traits::DisplayListBuilder::new();
             self.convert_children_to_webrender(traversal,
                                                api,
                                                pipeline_id,
                                                epoch,
                                                None,
-                                               scroll_policy,
                                                &mut inner_builder,
                                                frame_builder,
                                                false);
 
             frame_builder.add_display_list(api, inner_builder.finalize(), &mut inner_sc);
             let new_id = frame_builder.add_stacking_context(api, pipeline_id, inner_sc);
             builder.push_stacking_context(new_id);
         } else {
             self.convert_children_to_webrender(traversal,
                                                api,
                                                pipeline_id,
                                                epoch,
                                                scroll_layer_id,
-                                               scroll_policy,
                                                &mut builder,
                                                frame_builder,
                                                false);
         }
 
 
         frame_builder.add_display_list(api, builder.finalize(), &mut sc);
         frame_builder.add_stacking_context(api, pipeline_id, sc)
@@ -392,17 +381,16 @@ impl WebRenderDisplayListConverter for D
         match item {
             Some(&DisplayItem::PushStackingContext(ref stacking_context_item)) => {
                 let stacking_context = &stacking_context_item.stacking_context;
                 stacking_context.convert_to_webrender(&mut traversal,
                                                       api,
                                                       pipeline_id,
                                                       epoch,
                                                       scroll_layer_id,
-                                                      ScrollPolicy::Scrollable,
                                                       frame_builder)
             }
             _ => unreachable!("DisplayList did not start with StackingContext."),
 
         }
     }
 }
 
--- a/servo/components/layout_thread/lib.rs
+++ b/servo/components/layout_thread/lib.rs
@@ -46,37 +46,37 @@ extern crate webrender_traits;
 use app_units::Au;
 use azure::azure::AzColor;
 use euclid::Matrix4D;
 use euclid::point::Point2D;
 use euclid::rect::Rect;
 use euclid::scale_factor::ScaleFactor;
 use euclid::size::Size2D;
 use fnv::FnvHasher;
-use gfx::display_list::{ClippingRegion, DisplayList, LayerInfo, OpaqueNode};
+use gfx::display_list::{ClippingRegion, DisplayList, OpaqueNode};
 use gfx::display_list::{StackingContext, StackingContextType, WebRenderImageInfo};
 use gfx::font;
 use gfx::font_cache_thread::FontCacheThread;
 use gfx::font_context;
-use gfx_traits::{Epoch, FragmentType, LayerId, ScrollPolicy, StackingContextId, color};
+use gfx_traits::{Epoch, FragmentType, ScrollPolicy, StackingContextId, color};
 use heapsize::HeapSizeOf;
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
 use ipc_channel::router::ROUTER;
 use layout::animation;
 use layout::construct::ConstructionResult;
 use layout::context::{LayoutContext, SharedLayoutContext, heap_size_of_local_context};
 use layout::display_list_builder::ToGfxColor;
 use layout::flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
 use layout::flow_ref::{self, FlowRef};
 use layout::incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT};
 use layout::layout_debug;
 use layout::parallel;
 use layout::query::{LayoutRPCImpl, LayoutThreadData, process_content_box_request, process_content_boxes_request};
 use layout::query::{process_margin_style_query, process_node_overflow_request, process_resolved_style_request};
-use layout::query::{process_node_geometry_request, process_node_layer_id_request, process_node_scroll_area_request};
+use layout::query::{process_node_geometry_request, process_node_scroll_area_request};
 use layout::query::process_offset_parent_query;
 use layout::sequential;
 use layout::traversal::{ComputeAbsolutePositions, RecalcStyleAndConstructFlows};
 use layout::webrender_helpers::{WebRenderDisplayListConverter, WebRenderFrameBuilder};
 use layout::wrapper::{LayoutNodeLayoutData, NonOpaqueStyleAndLayoutData};
 use layout_traits::LayoutThreadFactory;
 use msg::constellation_msg::PipelineId;
 use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
@@ -119,19 +119,16 @@ use style::timer::Timer;
 use style::workqueue::WorkQueue;
 use url::Url;
 use util::geometry::max_rect;
 use util::opts;
 use util::prefs::PREFS;
 use util::resource_files::read_resource_file;
 use util::thread;
 
-/// The number of screens we have to traverse before we decide to generate new display lists.
-const DISPLAY_PORT_THRESHOLD_SIZE_FACTOR: i32 = 4;
-
 /// Information needed by the layout thread.
 pub struct LayoutThread {
     /// The ID of the pipeline that we belong to.
     id: PipelineId,
 
     /// The URL of the pipeline that we belong to.
     url: Url,
 
@@ -192,20 +189,16 @@ pub struct LayoutThread {
     new_animations_receiver: Receiver<Animation>,
 
     /// The number of Web fonts that have been requested but not yet loaded.
     outstanding_web_fonts: Arc<AtomicUsize>,
 
     /// The root of the flow tree.
     root_flow: Option<FlowRef>,
 
-    /// The position and size of the visible rect for each layer. We do not build display lists
-    /// for any areas more than `DISPLAY_PORT_SIZE_FACTOR` screens away from this area.
-    visible_rects: Arc<HashMap<LayerId, Rect<Au>, BuildHasherDefault<FnvHasher>>>,
-
     /// The list of currently-running animations.
     running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
 
     /// The list of animations that have expired since the last style recalculation.
     expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
 
     /// A counter for epoch messages
     epoch: Epoch,
@@ -441,31 +434,29 @@ impl LayoutThread {
             font_cache_receiver: font_cache_receiver,
             font_cache_sender: ipc_font_cache_sender,
             parallel_traversal: parallel_traversal,
             generation: 0,
             new_animations_sender: new_animations_sender,
             new_animations_receiver: new_animations_receiver,
             outstanding_web_fonts: outstanding_web_fonts_counter,
             root_flow: None,
-            visible_rects: Arc::new(HashMap::with_hasher(Default::default())),
             running_animations: Arc::new(RwLock::new(HashMap::new())),
             expired_animations: Arc::new(RwLock::new(HashMap::new())),
             epoch: Epoch(0),
             viewport_size: Size2D::new(Au(0), Au(0)),
             webrender_api: webrender_api_sender.create_api(),
             rw_data: Arc::new(Mutex::new(
                 LayoutThreadData {
                     constellation_chan: constellation_chan,
                     display_list: None,
                     stylist: stylist,
                     content_box_response: Rect::zero(),
                     content_boxes_response: Vec::new(),
                     client_rect_response: Rect::zero(),
-                    layer_id_response: None,
                     hit_test_response: (None, false),
                     scroll_area_response: Rect::zero(),
                     overflow_response: NodeOverflowResponse(None),
                     resolved_style_response: None,
                     offset_parent_response: OffsetParentResponse::empty(),
                     margin_style_response: MarginStyleResponse::empty(),
                     stacking_context_scroll_offsets: HashMap::new(),
                 })),
@@ -518,17 +509,16 @@ impl LayoutThread {
                 expired_animations: self.expired_animations.clone(),
                 error_reporter: self.error_reporter.clone(),
                 local_context_creation_data: Mutex::new(local_style_context_creation_data),
                 timer: self.timer.clone(),
             },
             image_cache_thread: self.image_cache_thread.clone(),
             image_cache_sender: Mutex::new(self.image_cache_sender.clone()),
             font_cache_thread: Mutex::new(self.font_cache_thread.clone()),
-            visible_rects: self.visible_rects.clone(),
             webrender_image_cache: self.webrender_image_cache.clone(),
         }
     }
 
     /// Receives and dispatches messages from the script and constellation threads
     fn handle_request<'a, 'b>(&mut self, possibly_locked_rw_data: &mut RwData<'a, 'b>) -> bool {
         enum Request {
             FromPipeline(LayoutControlMsg),
@@ -556,20 +546,16 @@ impl LayoutThread {
                 msg = port_from_font_cache.recv() => {
                     msg.unwrap();
                     Request::FromFontCache
                 }
             }
         };
 
         match request {
-            Request::FromPipeline(LayoutControlMsg::SetVisibleRects(new_visible_rects)) => {
-                self.handle_request_helper(Msg::SetVisibleRects(new_visible_rects),
-                                           possibly_locked_rw_data)
-            },
             Request::FromPipeline(LayoutControlMsg::SetStackingContextScrollStates(
                     new_scroll_states)) => {
                 self.handle_request_helper(Msg::SetStackingContextScrollStates(new_scroll_states),
                                            possibly_locked_rw_data)
             },
             Request::FromPipeline(LayoutControlMsg::TickAnimations) => {
                 self.handle_request_helper(Msg::TickAnimations, possibly_locked_rw_data)
             },
@@ -649,19 +635,16 @@ impl LayoutThread {
                         self.profiler_metadata(),
                         self.time_profiler_chan.clone(),
                         || self.handle_reflow(&data, possibly_locked_rw_data));
             },
             Msg::TickAnimations => self.tick_all_animations(possibly_locked_rw_data),
             Msg::ReflowWithNewlyLoadedWebFont => {
                 self.reflow_with_newly_loaded_web_font(possibly_locked_rw_data)
             }
-            Msg::SetVisibleRects(new_visible_rects) => {
-                self.set_visible_rects(new_visible_rects, possibly_locked_rw_data);
-            }
             Msg::SetStackingContextScrollStates(new_scroll_states) => {
                 self.set_stacking_context_scroll_states(new_scroll_states,
                                                         possibly_locked_rw_data);
             }
             Msg::ReapStyleAndLayoutData(dead_data) => {
                 unsafe {
                     self.handle_reap_style_and_layout_data(dead_data)
                 }
@@ -930,44 +913,38 @@ impl LayoutThread {
                                                  &Rect::zero(),
                                                  &Rect::zero(),
                                                  0,
                                                  filter::T::new(Vec::new()),
                                                  mix_blend_mode::T::normal,
                                                  Matrix4D::identity(),
                                                  Matrix4D::identity(),
                                                  true,
-                                                 None,
+                                                 ScrollPolicy::Scrollable,
                                                  None);
 
                         let display_list_entries =
                             sequential::build_display_list_for_subtree(layout_root,
                                                                        &mut root_stacking_context,
                                                                        shared_layout_context);
 
                         debug!("Done building display list.");
 
-                        let root_background_color = get_root_flow_background_color(layout_root);
                         let root_size = {
                             let root_flow = flow::base(layout_root);
                             if rw_data.stylist.viewport_constraints().is_some() {
                                 root_flow.position.size.to_physical(root_flow.writing_mode)
                             } else {
                                 root_flow.overflow.scroll.size
                             }
                         };
 
                         let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
                         root_stacking_context.bounds = origin;
                         root_stacking_context.overflow = origin;
-                        root_stacking_context.layer_info =
-                            Some(LayerInfo::new(layout_root.layer_id(),
-                                                ScrollPolicy::Scrollable,
-                                                None,
-                                                root_background_color));
 
                         rw_data.display_list =
                             Some(Arc::new(DisplayList::new(root_stacking_context,
                                                            display_list_entries)))
                     }
                     (ReflowGoal::ForScriptQuery, false) => {}
                 }
             }
@@ -1061,19 +1038,16 @@ impl LayoutThread {
                         rw_data.content_boxes_response = Vec::new();
                     },
                     ReflowQueryType::HitTestQuery(..) => {
                         rw_data.hit_test_response = (None, false);
                     },
                     ReflowQueryType::NodeGeometryQuery(_) => {
                         rw_data.client_rect_response = Rect::zero();
                     },
-                    ReflowQueryType::NodeLayerIdQuery(_) => {
-                        rw_data.layer_id_response = None;
-                    },
                     ReflowQueryType::NodeScrollGeometryQuery(_) => {
                         rw_data.scroll_area_response = Rect::zero();
                     },
                     ReflowQueryType::NodeOverflowQuery(_) => {
                         rw_data.overflow_response = NodeOverflowResponse(None);
                     },
                     ReflowQueryType::ResolvedStyleQuery(_, _, _) => {
                         rw_data.resolved_style_response = None;
@@ -1274,20 +1248,16 @@ impl LayoutThread {
             ReflowQueryType::NodeScrollGeometryQuery(node) => {
                 let node = unsafe { ServoLayoutNode::new(&node) };
                 rw_data.scroll_area_response = process_node_scroll_area_request(node, root_flow);
             },
             ReflowQueryType::NodeOverflowQuery(node) => {
                 let node = unsafe { ServoLayoutNode::new(&node) };
                 rw_data.overflow_response = process_node_overflow_request(node);
             },
-            ReflowQueryType::NodeLayerIdQuery(node) => {
-                let node = unsafe { ServoLayoutNode::new(&node) };
-                rw_data.layer_id_response = Some(process_node_layer_id_request(node));
-            },
             ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => {
                 let node = unsafe { ServoLayoutNode::new(&node) };
                 let layout_context = LayoutContext::new(&shared_layout_context);
                 rw_data.resolved_style_response =
                     process_resolved_style_request(node,
                                                    &layout_context,
                                                    pseudo,
                                                    property,
@@ -1300,76 +1270,16 @@ impl LayoutThread {
             ReflowQueryType::MarginStyleQuery(node) => {
                 let node = unsafe { ServoLayoutNode::new(&node) };
                 rw_data.margin_style_response = process_margin_style_query(node);
             },
             ReflowQueryType::NoQuery => {}
         }
     }
 
-    fn set_visible_rects<'a, 'b>(&mut self,
-                                 new_visible_rects: Vec<(LayerId, Rect<Au>)>,
-                                 possibly_locked_rw_data: &mut RwData<'a, 'b>)
-                                 -> bool {
-        let mut rw_data = possibly_locked_rw_data.lock();
-
-        // First, determine if we need to regenerate the display lists. This will happen if the
-        // layers have moved more than `DISPLAY_PORT_THRESHOLD_SIZE_FACTOR` away from their last
-        // positions.
-        let mut must_regenerate_display_lists = false;
-        let mut old_visible_rects = HashMap::with_hasher(Default::default());
-        let inflation_amount =
-            Size2D::new(self.viewport_size.width * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR,
-                        self.viewport_size.height * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR);
-        for &(ref layer_id, ref new_visible_rect) in &new_visible_rects {
-            match self.visible_rects.get(layer_id) {
-                None => {
-                    old_visible_rects.insert(*layer_id, *new_visible_rect);
-                }
-                Some(old_visible_rect) => {
-                    old_visible_rects.insert(*layer_id, *old_visible_rect);
-
-                    if !old_visible_rect.inflate(inflation_amount.width, inflation_amount.height)
-                                        .intersects(new_visible_rect) {
-                        must_regenerate_display_lists = true;
-                    }
-                }
-            }
-        }
-
-        if !must_regenerate_display_lists {
-            // Update `visible_rects` in case there are new layers that were discovered.
-            self.visible_rects = Arc::new(old_visible_rects);
-            return true
-        }
-
-        debug!("regenerating display lists!");
-        for &(ref layer_id, ref new_visible_rect) in &new_visible_rects {
-            old_visible_rects.insert(*layer_id, *new_visible_rect);
-        }
-        self.visible_rects = Arc::new(old_visible_rects);
-
-        // Regenerate the display lists.
-        let reflow_info = Reflow {
-            goal: ReflowGoal::ForDisplay,
-            page_clip_rect: max_rect(),
-        };
-
-        let mut layout_context = self.build_shared_layout_context(&*rw_data,
-                                                                  false,
-                                                                  reflow_info.goal);
-
-        self.perform_post_main_layout_passes(&reflow_info,
-                                             None,
-                                             None,
-                                             &mut *rw_data,
-                                             &mut layout_context);
-        true
-    }
-
     fn set_stacking_context_scroll_states<'a, 'b>(
             &mut self,
             new_scroll_states: Vec<StackingContextScrollState>,
             possibly_locked_rw_data: &mut RwData<'a, 'b>) {
         let mut rw_data = possibly_locked_rw_data.lock();
         let mut script_scroll_states = vec![];
         let mut layout_scroll_states = HashMap::new();
         for new_scroll_state in &new_scroll_states {
@@ -1665,19 +1575,19 @@ fn get_ua_stylesheets() -> Result<UserAg
 
 /// Returns true if the given reflow query type needs a full, up-to-date display list to be present
 /// or false if it only needs stacking-relative positions.
 fn reflow_query_type_needs_display_list(query_type: &ReflowQueryType) -> bool {
     match *query_type {
         ReflowQueryType::HitTestQuery(..) => true,
         ReflowQueryType::ContentBoxQuery(_) | ReflowQueryType::ContentBoxesQuery(_) |
         ReflowQueryType::NodeGeometryQuery(_) | ReflowQueryType::NodeScrollGeometryQuery(_) |
-        ReflowQueryType::NodeOverflowQuery(_) | ReflowQueryType::NodeLayerIdQuery(_) |
-        ReflowQueryType::ResolvedStyleQuery(..) | ReflowQueryType::OffsetParentQuery(_) |
-        ReflowQueryType::MarginStyleQuery(_) | ReflowQueryType::NoQuery => false,
+        ReflowQueryType::NodeOverflowQuery(_) | ReflowQueryType::ResolvedStyleQuery(..) |
+        ReflowQueryType::OffsetParentQuery(_) | ReflowQueryType::MarginStyleQuery(_) |
+        ReflowQueryType::NoQuery => false,
     }
 }
 
 lazy_static! {
     static ref UA_STYLESHEETS: UserAgentStylesheets = {
         match get_ua_stylesheets() {
             Ok(stylesheets) => stylesheets,
             Err(filename) => {
--- a/servo/components/script/dom/window.rs
+++ b/servo/components/script/dom/window.rs
@@ -39,17 +39,16 @@ use dom::messageevent::MessageEvent;
 use dom::navigator::Navigator;
 use dom::node::{Node, from_untrusted_node_address, window_from_node};
 use dom::performance::Performance;
 use dom::promise::Promise;
 use dom::screen::Screen;
 use dom::storage::Storage;
 use euclid::{Point2D, Rect, Size2D};
 use fetch;
-use gfx_traits::LayerId;
 use ipc_channel::ipc::{self, IpcSender};
 use js::jsapi::{HandleObject, HandleValue, JSAutoCompartment, JSContext};
 use js::jsapi::{JS_GC, JS_GetRuntime, SetWindowProxy};
 use js::jsval::UndefinedValue;
 use js::rust::Runtime;
 use msg::constellation_msg::{FrameType, LoadData, PipelineId, ReferrerPolicy, WindowSizeType};
 use net_traits::ResourceThreads;
 use net_traits::bluetooth_thread::BluetoothMethodMsg;
@@ -930,21 +929,21 @@ impl Window {
         if x == self.ScrollX() as f64 && y == self.ScrollY() as f64 {
             return;
         }
 
         //TODO Step 11
         //let document = self.Document();
         // Step 12
         self.perform_a_scroll(x.to_f32().unwrap_or(0.0f32), y.to_f32().unwrap_or(0.0f32),
-                              LayerId::null(), behavior, None);
+                              behavior, None);
     }
 
     /// https://drafts.csswg.org/cssom-view/#perform-a-scroll
-    pub fn perform_a_scroll(&self, x: f32, y: f32, layer_id: LayerId,
+    pub fn perform_a_scroll(&self, x: f32, y: f32,
                             behavior: ScrollBehavior, element: Option<&Element>) {
         //TODO Step 1
         let point = Point2D::new(x, y);
         let smooth = match behavior {
             ScrollBehavior::Auto => {
                 element.map_or(false, |_element| {
                     // TODO check computed scroll-behaviour CSS property
                     true
@@ -954,17 +953,17 @@ impl Window {
             ScrollBehavior::Smooth => true
         };
 
         // TODO (farodin91): Raise an event to stop the current_viewport
         self.update_viewport_for_scroll(x, y);
 
         let global_scope = self.upcast::<GlobalScope>();
         let message = ConstellationMsg::ScrollFragmentPoint(
-            global_scope.pipeline_id(), layer_id, point, smooth);
+            global_scope.pipeline_id(), point, smooth);
         global_scope.constellation_chan().send(message).unwrap();
     }
 
     pub fn update_viewport_for_scroll(&self, x: f32, y: f32) {
         let size = self.current_viewport.get().size;
         let new_viewport = Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size);
         self.current_viewport.set(new_viewport)
     }
@@ -1234,29 +1233,21 @@ impl Window {
                 None => break,
             }
         }
         let offset = self.current_viewport.get().origin;
         Point2D::new(offset.x.to_f32_px(), offset.y.to_f32_px())
     }
 
     // https://drafts.csswg.org/cssom-view/#dom-element-scroll
-    pub fn scroll_node(&self, node: TrustedNodeAddress,
+    pub fn scroll_node(&self, _node: TrustedNodeAddress,
                        x_: f64, y_: f64, behavior: ScrollBehavior) {
-        if !self.reflow(ReflowGoal::ForScriptQuery,
-                        ReflowQueryType::NodeLayerIdQuery(node),
-                        ReflowReason::Query) {
-            return;
-        }
-
-        let layer_id = self.layout_rpc.node_layer_id().layer_id;
-
         // Step 12
         self.perform_a_scroll(x_.to_f32().unwrap_or(0.0f32), y_.to_f32().unwrap_or(0.0f32),
-                              layer_id, behavior, None);
+                              behavior, None);
     }
 
     pub fn resolved_style_query(&self,
                             element: TrustedNodeAddress,
                             pseudo: Option<PseudoElement>,
                             property: &Atom) -> Option<DOMString> {
         if !self.reflow(ReflowGoal::ForScriptQuery,
                         ReflowQueryType::ResolvedStyleQuery(element, pseudo, property.clone()),
@@ -1604,17 +1595,16 @@ fn debug_reflow_events(id: PipelineId, g
     });
 
     debug_msg.push_str(match *query_type {
         ReflowQueryType::NoQuery => "\tNoQuery",
         ReflowQueryType::ContentBoxQuery(_n) => "\tContentBoxQuery",
         ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
         ReflowQueryType::HitTestQuery(..) => "\tHitTestQuery",
         ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
-        ReflowQueryType::NodeLayerIdQuery(_n) => "\tNodeLayerIdQuery",
         ReflowQueryType::NodeOverflowQuery(_n) => "\tNodeOverFlowQuery",
         ReflowQueryType::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery",
         ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
         ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery",
         ReflowQueryType::MarginStyleQuery(_n) => "\tMarginStyleQuery",
     });
 
     debug_msg.push_str(match *reason {
--- a/servo/components/script/script_thread.rs
+++ b/servo/components/script/script_thread.rs
@@ -52,17 +52,16 @@ use dom::servoparser::{ParserContext, Se
 use dom::servoparser::html::{ParseContext, parse_html};
 use dom::servoparser::xml::{self, parse_xml};
 use dom::transitionevent::TransitionEvent;
 use dom::uievent::UIEvent;
 use dom::window::{ReflowReason, Window};
 use dom::worker::TrustedWorkerAddress;
 use euclid::Rect;
 use euclid::point::Point2D;
-use gfx_traits::LayerId;
 use hyper::header::{ContentType, Headers, HttpDate, LastModified};
 use hyper::header::ReferrerPolicy as ReferrerPolicyHeader;
 use hyper::method::Method;
 use hyper::mime::{Mime, SubLevel, TopLevel};
 use hyper_serde::Serde;
 use ipc_channel::ipc::{self, IpcSender};
 use ipc_channel::router::ROUTER;
 use js::glue::GetWindowProxyClass;
@@ -1878,20 +1877,17 @@ impl ScriptThread {
         // paint thread currently does the same for drawing elements. This is important for pages
         // that require pixel perfect scroll positioning for proper display (like Acid2). Since we
         // don't have the device pixel ratio here, this might not be accurate, but should work as
         // long as the ratio is a whole number. Once #8275 is fixed this should actually take into
         // account the real device pixel ratio.
         let point = Point2D::new(rect.origin.x.to_nearest_px() as f32,
                                  rect.origin.y.to_nearest_px() as f32);
 
-        let message = ConstellationMsg::ScrollFragmentPoint(pipeline_id,
-                                                            LayerId::null(),
-                                                            point,
-                                                            false);
+        let message = ConstellationMsg::ScrollFragmentPoint(pipeline_id, point, false);
         self.constellation_chan.send(message).unwrap();
     }
 
     /// Reflows non-incrementally, rebuilding the entire layout tree in the process.
     fn rebuild_and_force_reflow(&self, context: &BrowsingContext, reason: ReflowReason) {
         let document = context.active_document();
         document.dirty_all_nodes();
         let window = window_from_node(&*document);
--- a/servo/components/script_layout_interface/message.rs
+++ b/servo/components/script_layout_interface/message.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use {OpaqueStyleAndLayoutData, TrustedNodeAddress};
 use app_units::Au;
 use euclid::point::Point2D;
 use euclid::rect::Rect;
-use gfx_traits::{Epoch, LayerId};
+use gfx_traits::Epoch;
 use ipc_channel::ipc::{IpcReceiver, IpcSender};
 use msg::constellation_msg::PipelineId;
 use net_traits::image_cache_thread::ImageCacheThread;
 use profile_traits::mem::ReportsChan;
 use rpc::LayoutRPC;
 use script_traits::{ConstellationControlMsg, LayoutControlMsg};
 use script_traits::{LayoutMsg as ConstellationMsg, StackingContextScrollState, WindowSizeData};
 use std::sync::Arc;
@@ -43,20 +43,16 @@ pub enum Msg {
     ///
     /// The inner field is the number of *milliseconds* to advance, and the bool
     /// field is whether animations should be force-ticked.
     AdvanceClockMs(i32, bool),
 
     /// Requests that the layout thread reflow with a newly-loaded Web font.
     ReflowWithNewlyLoadedWebFont,
 
-    /// Updates the layout visible rects, affecting the area that display lists will be constructed
-    /// for.
-    SetVisibleRects(Vec<(LayerId, Rect<Au>)>),
-
     /// Destroys layout data associated with a DOM node.
     ///
     /// TODO(pcwalton): Maybe think about batching to avoid message traffic.
     ReapStyleAndLayoutData(OpaqueStyleAndLayoutData),
 
     /// Requests that the layout thread measure its memory usage. The resulting reports are sent back
     /// via the supplied channel.
     CollectReports(ReportsChan),
@@ -94,17 +90,16 @@ pub enum Msg {
 #[derive(PartialEq)]
 pub enum ReflowQueryType {
     NoQuery,
     ContentBoxQuery(TrustedNodeAddress),
     ContentBoxesQuery(TrustedNodeAddress),
     NodeOverflowQuery(TrustedNodeAddress),
     HitTestQuery(Point2D<f32>, Point2D<f32>, bool),
     NodeGeometryQuery(TrustedNodeAddress),
-    NodeLayerIdQuery(TrustedNodeAddress),
     NodeScrollGeometryQuery(TrustedNodeAddress),
     ResolvedStyleQuery(TrustedNodeAddress, Option<PseudoElement>, Atom),
     OffsetParentQuery(TrustedNodeAddress),
     MarginStyleQuery(TrustedNodeAddress),
 }
 
 /// Information needed for a reflow.
 pub struct Reflow {
--- a/servo/components/script_layout_interface/rpc.rs
+++ b/servo/components/script_layout_interface/rpc.rs
@@ -1,16 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
 use euclid::point::Point2D;
 use euclid::rect::Rect;
-use gfx_traits::LayerId;
 use script_traits::UntrustedNodeAddress;
 use style::properties::longhands::{margin_top, margin_right, margin_bottom, margin_left, overflow_x};
 
 /// Synchronous messages that script can send to layout.
 ///
 /// In general, you should use messages to talk to Layout. Use the RPC interface
 /// if and only if the work is
 ///
@@ -23,18 +22,16 @@ pub trait LayoutRPC {
     /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
     fn content_boxes(&self) -> ContentBoxesResponse;
     /// Requests the geometry of this node. Used by APIs such as `clientTop`.
     fn node_geometry(&self) -> NodeGeometryResponse;
     /// Requests the overflow-x and overflow-y of this node. Used by `scrollTop` etc.
     fn node_overflow(&self) -> NodeOverflowResponse;
     /// Requests the scroll geometry of this node. Used by APIs such as `scrollTop`.
     fn node_scroll_area(&self) -> NodeGeometryResponse;
-    /// Requests the layer id of this node. Used by APIs such as `scrollTop`
-    fn node_layer_id(&self) -> NodeLayerIdResponse;
     /// Requests the node containing the point of interest
     fn hit_test(&self) -> HitTestResponse;
     /// Query layout for the resolved value of a given CSS property
     fn resolved_style(&self) -> ResolvedStyleResponse;
     fn offset_parent(&self) -> OffsetParentResponse;
     /// Query layout for the resolve values of the margin properties for an element.
     fn margin_style(&self) -> MarginStyleResponse;
 
@@ -46,20 +43,16 @@ pub struct ContentBoxResponse(pub Rect<A
 pub struct ContentBoxesResponse(pub Vec<Rect<Au>>);
 
 pub struct NodeGeometryResponse {
     pub client_rect: Rect<i32>,
 }
 
 pub struct NodeOverflowResponse(pub Option<Point2D<overflow_x::computed_value::T>>);
 
-pub struct NodeLayerIdResponse {
-    pub layer_id: LayerId,
-}
-
 pub struct HitTestResponse {
     pub node_address: Option<UntrustedNodeAddress>,
 }
 
 pub struct ResolvedStyleResponse(pub Option<String>);
 
 #[derive(Clone)]
 pub struct OffsetParentResponse {
--- a/servo/components/script_layout_interface/wrapper_traits.rs
+++ b/servo/components/script_layout_interface/wrapper_traits.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #![allow(unsafe_code)]
 
 use HTMLCanvasData;
 use LayoutNodeType;
 use OpaqueStyleAndLayoutData;
 use SVGSVGData;
-use gfx_traits::{ByteIndex, LayerId, LayerType};
+use gfx_traits::ByteIndex;
 use msg::constellation_msg::PipelineId;
 use range::Range;
 use restyle_damage::RestyleDamage;
 use std::fmt::Debug;
 use std::sync::Arc;
 use string_cache::{Atom, Namespace};
 use style::atomic_refcell::AtomicRefCell;
 use style::computed_values::display;
@@ -372,31 +372,16 @@ pub trait ThreadSafeLayoutNode: Clone + 
     fn svg_data(&self) -> Option<SVGSVGData>;
 
     /// If this node is an iframe element, returns its pipeline ID. If this node is
     /// not an iframe element, fails.
     fn iframe_pipeline_id(&self) -> PipelineId;
 
     fn get_colspan(&self) -> u32;
 
-    fn layer_id(&self) -> LayerId {
-        let layer_type = match self.get_pseudo_element_type() {
-            PseudoElementType::Normal => LayerType::FragmentBody,
-            PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
-            PseudoElementType::After(_) => LayerType::AfterPseudoContent,
-            PseudoElementType::DetailsSummary(_) => LayerType::FragmentBody,
-            PseudoElementType::DetailsContent(_) => LayerType::FragmentBody,
-        };
-        LayerId::new_of_type(layer_type, self.opaque().id() as usize)
-    }
-
-    fn layer_id_for_overflow_scroll(&self) -> LayerId {
-        LayerId::new_of_type(LayerType::OverflowScroll, self.opaque().id() as usize)
-    }
-
     fn get_style_data(&self) -> Option<&AtomicRefCell<PersistentStyleData>>;
 }
 
 // This trait is only public so that it can be implemented by the gecko wrapper.
 // It can be used to violate thread-safety, so don't use it elsewhere in layout!
 #[allow(unsafe_code)]
 pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode {
     unsafe fn dangerous_first_child(&self) -> Option<Self>;
--- a/servo/components/script_traits/lib.rs
+++ b/servo/components/script_traits/lib.rs
@@ -6,17 +6,16 @@
 //! The traits are here instead of in script so that these modules won't have
 //! to depend on script.
 
 #![feature(custom_derive, plugin, proc_macro, rustc_attrs, structural_match)]
 #![plugin(heapsize_plugin, plugins)]
 #![deny(missing_docs)]
 #![deny(unsafe_code)]
 
-extern crate app_units;
 extern crate canvas_traits;
 extern crate cookie as cookie_rs;
 extern crate devtools_traits;
 extern crate euclid;
 extern crate gfx_traits;
 extern crate heapsize;
 extern crate hyper_serde;
 extern crate ipc_channel;
@@ -31,27 +30,25 @@ extern crate serde;
 extern crate serde_derive;
 extern crate style_traits;
 extern crate time;
 extern crate url;
 
 mod script_msg;
 pub mod webdriver_msg;
 
-use app_units::Au;
 use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
 use euclid::Size2D;
 use euclid::length::Length;
 use euclid::point::Point2D;
 use euclid::rect::Rect;
 use euclid::scale_factor::ScaleFactor;
 use euclid::size::TypedSize2D;
 use gfx_traits::DevicePixel;
 use gfx_traits::Epoch;
-use gfx_traits::LayerId;
 use gfx_traits::StackingContextId;
 use heapsize::HeapSizeOf;
 use ipc_channel::ipc::{IpcReceiver, IpcSender};
 use libc::c_void;
 use msg::constellation_msg::{FrameId, FrameType, Image, Key, KeyModifiers, KeyState, LoadData};
 use msg::constellation_msg::{PipelineId, PipelineNamespaceId, ReferrerPolicy};
 use msg::constellation_msg::{TraversalDirection, WindowSizeType};
 use net_traits::{LoadOrigin, ResourceThreads};
@@ -110,18 +107,16 @@ impl UntrustedNodeAddress {
 #[derive(Deserialize, Serialize)]
 pub enum LayoutControlMsg {
     /// Requests that this layout thread exit.
     ExitNow,
     /// Requests the current epoch (layout counter) from this layout.
     GetCurrentEpoch(IpcSender<Epoch>),
     /// Asks layout to run another step in its animation.
     TickAnimations,
-    /// Informs layout as to which regions of the page are visible.
-    SetVisibleRects(Vec<(LayerId, Rect<Au>)>),
     /// Tells layout about the new scrolling offsets of each scrollable stacking context.
     SetStackingContextScrollStates(Vec<StackingContextScrollState>),
     /// Requests the current load state of Web fonts. `true` is returned if fonts are still loading
     /// and `false` is returned if all fonts have loaded.
     GetWebFontLoadState(IpcSender<bool>),
 }
 
 /// The initial data associated with a newly-created framed pipeline.
--- a/servo/components/script_traits/script_msg.rs
+++ b/servo/components/script_traits/script_msg.rs
@@ -8,17 +8,16 @@ use DocumentState;
 use IFrameLoadInfo;
 use MozBrowserEvent;
 use WorkerGlobalScopeInit;
 use WorkerScriptLoadOrigin;
 use canvas_traits::CanvasMsg;
 use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
 use euclid::point::Point2D;
 use euclid::size::Size2D;
-use gfx_traits::LayerId;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
 use msg::constellation_msg::{PipelineId, TraversalDirection};
 use net_traits::CoreResourceMsg;
 use offscreen_gl_context::{GLContextAttributes, GLLimits};
 use style_traits::cursor::Cursor;
 use style_traits::viewport::ViewportConstraints;
 use url::Url;
@@ -109,17 +108,17 @@ pub enum ScriptMsg {
     ActivateDocument(PipelineId),
     /// Set the document state for a pipeline (used by screenshot / reftests)
     SetDocumentState(PipelineId, DocumentState),
     /// Update the pipeline Url, which can change after redirections.
     SetFinalUrl(PipelineId, Url),
     /// Check if an alert dialog box should be presented
     Alert(PipelineId, String, IpcSender<bool>),
     /// Scroll a page in a window
-    ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>, bool),
+    ScrollFragmentPoint(PipelineId, Point2D<f32>, bool),
     /// Set title of current page
     /// https://html.spec.whatwg.org/multipage/#document.title
     SetTitle(PipelineId, Option<String>),
     /// Send a key event
     SendKeyEvent(Option<char>, Key, KeyState, KeyModifiers),
     /// Get Window Informations size and position
     GetClientWindow(IpcSender<(Size2D<u32>, Point2D<i32>)>),
     /// Move the window to a point