servo: Merge #17892 - WR multi-document update (from kvark:wr); r=glennw
☠☠ backed out by af665482a57d ☠ ☠
authorDzmitry Malyshau <kvark@mozilla.com>
Fri, 28 Jul 2017 13:26:52 -0500
changeset 420453 c424ad1c5f9441f43f3f792d853170f3fd8216e9
parent 420452 a417b9d7712d6aab5037904e1103d8d5e2e0a99e
child 420454 6deaeb0100a26e6ccf89ee01ec82876293beb1e4
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglennw
bugs17892
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #17892 - WR multi-document update (from kvark:wr); r=glennw <!-- Please describe your changes on the following line: --> The PR updates WR version to support multiple documents (https://github.com/servo/webrender/pull/1509) but doesn't take advantage of this new feature yet. It also makes Servo to use `DevicePixel` from WR instead of rolling out another one. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [ ] `./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 _____ no extra logic <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 12a49dc0be8a8acd12440dd7191b349ca17de7c8
servo/Cargo.lock
servo/components/compositing/compositor.rs
servo/components/compositing/compositor_thread.rs
servo/components/compositing/windowing.rs
servo/components/constellation/constellation.rs
servo/components/constellation/pipeline.rs
servo/components/layout_thread/lib.rs
servo/components/layout_traits/lib.rs
servo/components/script_traits/lib.rs
servo/components/servo/lib.rs
servo/components/style_traits/Cargo.toml
servo/components/style_traits/lib.rs
servo/ports/cef/window.rs
servo/ports/glutin/window.rs
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -3084,16 +3084,17 @@ dependencies = [
  "app_units 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webrender_api 0.48.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3463,17 +3464,17 @@ dependencies = [
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "webdriver 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
 version = "0.48.0"
-source = "git+https://github.com/servo/webrender#283192c41743a59da87b065cbc14c659d94c90b5"
+source = "git+https://github.com/servo/webrender#1ec6fb9ae47d8356920975a4be60552608dbfa1b"
 dependencies = [
  "app_units 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3492,17 +3493,17 @@ dependencies = [
  "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.48.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "webrender_api"
 version = "0.48.0"
-source = "git+https://github.com/servo/webrender#283192c41743a59da87b065cbc14c659d94c90b5"
+source = "git+https://github.com/servo/webrender#1ec6fb9ae47d8356920975a4be60552608dbfa1b"
 dependencies = [
  "app_units 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/components/compositing/compositor.rs
+++ b/servo/components/compositing/compositor.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 CompositionPipeline;
 use SendableFrameTree;
 use compositor_thread::{CompositorProxy, CompositorReceiver};
 use compositor_thread::{InitialCompositorState, Msg, RenderListener};
-use euclid::{Point2D, TypedPoint2D, TypedVector2D, TypedRect, ScaleFactor, TypedSize2D};
+use euclid::{Point2D, TypedPoint2D, TypedVector2D, ScaleFactor};
 use gfx_traits::Epoch;
 use gleam::gl;
 use image::{DynamicImage, ImageFormat, RgbImage};
 use ipc_channel::ipc::{self, IpcSharedMemory};
 use msg::constellation_msg::{Key, KeyModifiers, KeyState};
 use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId, TraversalDirection};
 use net_traits::image::base::{Image, PixelFormat};
 use profile_traits::time::{self, ProfilerCategory, profile};
@@ -29,17 +29,18 @@ use std::fs::File;
 use std::rc::Rc;
 use std::sync::mpsc::Sender;
 use std::time::{Duration, Instant};
 use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
 use style_traits::viewport::ViewportConstraints;
 use time::{precise_time_ns, precise_time_s};
 use touch::{TouchHandler, TouchAction};
 use webrender;
-use webrender_api::{self, ClipId, LayoutPoint, LayoutVector2D, ScrollEventPhase, ScrollLocation, ScrollClamping};
+use webrender_api::{self, ClipId, DeviceUintRect, DeviceUintSize, LayoutPoint, LayoutVector2D};
+use webrender_api::{ScrollEventPhase, ScrollLocation, ScrollClamping};
 use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods};
 
 #[derive(Debug, PartialEq)]
 enum UnableToComposite {
     WindowUnprepared,
     NotReadyToPaintImage(NotReadyToPaint),
 }
 
@@ -105,20 +106,20 @@ pub struct IOCompositor<Window: WindowMe
 
     /// Tracks details about each active pipeline that the compositor knows about.
     pipeline_details: HashMap<PipelineId, PipelineDetails>,
 
     /// The scene scale, to allow for zooming and high-resolution painting.
     scale: ScaleFactor<f32, LayerPixel, DevicePixel>,
 
     /// The size of the rendering area.
-    frame_size: TypedSize2D<u32, DevicePixel>,
+    frame_size: DeviceUintSize,
 
     /// The position and size of the window within the rendering area.
-    window_rect: TypedRect<u32, DevicePixel>,
+    window_rect: DeviceUintRect,
 
     /// "Mobile-style" zoom that does not reflow the page.
     viewport_zoom: PinchZoomFactor,
 
     /// Viewport zoom constraints provided by @viewport.
     min_viewport_zoom: Option<PinchZoomFactor>,
     max_viewport_zoom: Option<PinchZoomFactor>,
 
@@ -174,16 +175,19 @@ pub struct IOCompositor<Window: WindowMe
     /// Whether a scroll is in progress; i.e. whether the user's fingers are down.
     scroll_in_progress: bool,
 
     in_scroll_transaction: Option<Instant>,
 
     /// The webrender renderer.
     webrender: webrender::Renderer,
 
+    /// The active webrender document.
+    webrender_document: webrender_api::DocumentId,
+
     /// The webrender interface, if enabled.
     webrender_api: webrender_api::RenderApi,
 
     /// GL functions interface (may be GL or GLES)
     gl: Rc<gl::Gl>,
 }
 
 #[derive(Copy, Clone)]
@@ -373,17 +377,18 @@ impl<Window: WindowMethods> IOCompositor
             frame_tree_id: FrameTreeId(0),
             constellation_chan: state.constellation_chan,
             time_profiler_chan: state.time_profiler_chan,
             last_composite_time: 0,
             ready_to_save_state: ReadyState::Unknown,
             scroll_in_progress: false,
             in_scroll_transaction: None,
             webrender: state.webrender,
-            webrender_api: state.webrender_api_sender.create_api(),
+            webrender_document: state.webrender_document,
+            webrender_api: state.webrender_api,
         }
     }
 
     pub fn create(window: Rc<Window>, state: InitialCompositorState) -> IOCompositor<Window> {
         let mut compositor = IOCompositor::new(window, state);
 
         let compositor_proxy_for_webrender = compositor.channel_to_self
                                                        .clone_compositor_proxy();
@@ -670,18 +675,18 @@ impl<Window: WindowMethods> IOCompositor
     }
 
     fn set_frame_tree(&mut self, frame_tree: &SendableFrameTree) {
         debug!("Setting the frame tree for pipeline {}", frame_tree.pipeline.id);
 
         self.root_pipeline = Some(frame_tree.pipeline.clone());
 
         let pipeline_id = frame_tree.pipeline.id.to_webrender();
-        self.webrender_api.set_root_pipeline(pipeline_id);
-        self.webrender_api.generate_frame(None);
+        self.webrender_api.set_root_pipeline(self.webrender_document, pipeline_id);
+        self.webrender_api.generate_frame(self.webrender_document, None);
 
         self.create_pipeline_details_for_frame_tree(&frame_tree);
 
         self.send_window_size(WindowSizeType::Initial);
 
         self.frame_tree_id.next();
     }
 
@@ -695,24 +700,17 @@ impl<Window: WindowMethods> IOCompositor
 
     fn remove_pipeline_root_layer(&mut self, pipeline_id: PipelineId) {
         self.pipeline_details.remove(&pipeline_id);
     }
 
     fn send_window_size(&self, size_type: WindowSizeType) {
         let dppx = self.page_zoom * self.hidpi_factor();
 
-        let window_rect = {
-            let offset = webrender_api::DeviceUintPoint::new(self.window_rect.origin.x, self.window_rect.origin.y);
-            let size = webrender_api::DeviceUintSize::new(self.window_rect.size.width, self.window_rect.size.height);
-            webrender_api::DeviceUintRect::new(offset, size)
-        };
-
-        let frame_size = webrender_api::DeviceUintSize::new(self.frame_size.width, self.frame_size.height);
-        self.webrender_api.set_window_parameters(frame_size, window_rect);
+        self.webrender_api.set_window_parameters(self.webrender_document, self.frame_size, self.window_rect);
 
         let initial_viewport = self.window_rect.size.to_f32() / dppx;
 
         let data = WindowSizeData {
             device_pixel_ratio: dppx,
             initial_viewport: initial_viewport,
         };
         let top_level_browsing_context_id = match self.root_pipeline {
@@ -722,17 +720,19 @@ impl<Window: WindowMethods> IOCompositor
         let msg = ConstellationMsg::WindowSize(top_level_browsing_context_id, data, size_type);
 
         if let Err(e) = self.constellation_chan.send(msg) {
             warn!("Sending window resize to constellation failed ({}).", e);
         }
     }
 
     fn scroll_fragment_to_point(&mut self, id: ClipId, point: Point2D<f32>) {
-        self.webrender_api.scroll_node_with_id(LayoutPoint::from_untyped(&point), id,
+        self.webrender_api.scroll_node_with_id(self.webrender_document,
+                                               LayoutPoint::from_untyped(&point),
+                                               id,
                                                ScrollClamping::ToContentBounds);
     }
 
     fn handle_window_message(&mut self, event: WindowEvent) {
         match event {
             WindowEvent::Idle => {}
 
             WindowEvent::Refresh => {
@@ -816,22 +816,22 @@ impl<Window: WindowMethods> IOCompositor
                 if let Err(e) = self.constellation_chan.send(msg) {
                     warn!("Sending reload to constellation failed ({}).", e);
                 }
             }
 
             WindowEvent::ToggleWebRenderProfiler => {
                 let profiler_enabled = self.webrender.get_profiler_enabled();
                 self.webrender.set_profiler_enabled(!profiler_enabled);
-                self.webrender_api.generate_frame(None);
+                self.webrender_api.generate_frame(self.webrender_document, None);
             }
         }
     }
 
-    fn on_resize_window_event(&mut self, new_size: TypedSize2D<u32, DevicePixel>) {
+    fn on_resize_window_event(&mut self, new_size: DeviceUintSize) {
         debug!("compositor resizing to {:?}", new_size.to_untyped());
 
         // A size change could also mean a resolution change.
         let new_scale_factor = self.window.hidpi_factor();
         if self.scale_factor != new_scale_factor {
             self.scale_factor = new_scale_factor;
             self.update_zoom_transform();
         }
@@ -1118,17 +1118,17 @@ impl<Window: WindowMethods> IOCompositor
                     };
                     // TODO: units don't match!
                     let delta = combined_delta / self.scale.get();
 
                     let cursor =
                         (combined_event.cursor.to_f32() / self.scale).to_untyped();
                     let location = webrender_api::ScrollLocation::Delta(delta);
                     let cursor = webrender_api::WorldPoint::from_untyped(&cursor);
-                    self.webrender_api.scroll(location, cursor, combined_event.phase);
+                    self.webrender_api.scroll(self.webrender_document, location, cursor, combined_event.phase);
                     last_combined_event = None
                 }
             }
 
             match (&mut last_combined_event, scroll_event.phase) {
                 (last_combined_event @ &mut None, _) => {
                     *last_combined_event = Some(ScrollZoomEvent {
                         magnification: scroll_event.magnification,
@@ -1174,17 +1174,17 @@ impl<Window: WindowMethods> IOCompositor
                     let calculated_delta = webrender_api::LayoutVector2D::from_untyped(&scaled_delta);
                                            ScrollLocation::Delta(calculated_delta)
                 },
                 // Leave ScrollLocation unchanged if it is Start or End location.
                 sl @ ScrollLocation::Start | sl @ ScrollLocation::End => sl,
             };
             let cursor = (combined_event.cursor.to_f32() / self.scale).to_untyped();
             let cursor = webrender_api::WorldPoint::from_untyped(&cursor);
-            self.webrender_api.scroll(scroll_location, cursor, combined_event.phase);
+            self.webrender_api.scroll(self.webrender_document, scroll_location, cursor, combined_event.phase);
             self.waiting_for_results_of_scroll = true
         }
 
         if had_events {
             self.send_viewport_rects();
         }
     }
 
@@ -1272,17 +1272,17 @@ impl<Window: WindowMethods> IOCompositor
                                           .max(MIN_ZOOM).min(MAX_ZOOM));
         self.update_zoom_transform();
         self.send_window_size(WindowSizeType::Resize);
         self.update_page_zoom_for_webrender();
     }
 
     fn update_page_zoom_for_webrender(&mut self) {
         let page_zoom = webrender_api::ZoomFactor::new(self.page_zoom.get());
-        self.webrender_api.set_page_zoom(page_zoom);
+        self.webrender_api.set_page_zoom(self.webrender_document, page_zoom);
     }
 
     /// Simulate a pinch zoom
     fn on_pinch_zoom_window_event(&mut self, magnification: f32) {
         self.pending_scroll_zoom_events.push(ScrollZoomEvent {
             magnification: magnification,
             scroll_location: ScrollLocation::Delta(TypedVector2D::zero()), // TODO: Scroll to keep the center in view?
             cursor:  TypedPoint2D::new(-1, -1), // Make sure this hits the base layer.
@@ -1310,17 +1310,17 @@ impl<Window: WindowMethods> IOCompositor
         let msg = ConstellationMsg::KeyEvent(ch, key, state, modifiers);
         if let Err(e) = self.constellation_chan.send(msg) {
             warn!("Sending key event to constellation failed ({}).", e);
         }
     }
 
     fn send_viewport_rects(&self) {
         let mut scroll_states_per_pipeline = HashMap::new();
-        for scroll_layer_state in self.webrender_api.get_scroll_node_state() {
+        for scroll_layer_state in self.webrender_api.get_scroll_node_state(self.webrender_document) {
             if scroll_layer_state.id.external_id().is_none() &&
                !scroll_layer_state.id.is_root_scroll_node() {
                 continue;
             }
 
             let scroll_state = ScrollState {
                 scroll_root_id: scroll_layer_state.id,
                 scroll_offset: scroll_layer_state.scroll_offset.to_untyped(),
@@ -1459,18 +1459,17 @@ impl<Window: WindowMethods> IOCompositor
             CompositeTarget::Window => RenderTargetInfo::empty(),
             _ => initialize_png(&*self.gl, width, height)
         };
 
         profile(ProfilerCategory::Compositing, None, self.time_profiler_chan.clone(), || {
             debug!("compositor: compositing");
 
             // Paint the scene.
-            let size = webrender_api::DeviceUintSize::from_untyped(&self.frame_size.to_untyped());
-            self.webrender.render(size);
+            self.webrender.render(self.frame_size);
         });
 
         let rv = match target {
             CompositeTarget::Window => None,
             CompositeTarget::WindowAndPng => {
                 let img = self.draw_img(render_target_info,
                                         width,
                                         height);
@@ -1560,17 +1559,17 @@ impl<Window: WindowMethods> IOCompositor
     }
 
     fn start_scrolling_bounce_if_necessary(&mut self) {
         if self.scroll_in_progress {
             return
         }
 
         if self.webrender.layers_are_bouncing_back() {
-            self.webrender_api.tick_scrolling_bounce_animations();
+            self.webrender_api.tick_scrolling_bounce_animations(self.webrender_document);
             self.send_viewport_rects()
         }
     }
 
     pub fn handle_events(&mut self, messages: Vec<WindowEvent>) -> bool {
         // Check for new messages coming from the other threads in the system.
         let mut compositor_messages = vec![];
         let mut found_recomposite_msg = false;
--- a/servo/components/compositing/compositor_thread.rs
+++ b/servo/components/compositing/compositor_thread.rs
@@ -189,10 +189,11 @@ pub struct InitialCompositorState {
     /// A channel to the constellation.
     pub constellation_chan: Sender<ConstellationMsg>,
     /// A channel to the time profiler thread.
     pub time_profiler_chan: time::ProfilerChan,
     /// A channel to the memory profiler thread.
     pub mem_profiler_chan: mem::ProfilerChan,
     /// Instance of webrender API
     pub webrender: webrender::Renderer,
-    pub webrender_api_sender: webrender_api::RenderApiSender,
+    pub webrender_document: webrender_api::DocumentId,
+    pub webrender_api: webrender_api::RenderApi,
 }
--- a/servo/components/compositing/windowing.rs
+++ b/servo/components/compositing/windowing.rs
@@ -1,29 +1,29 @@
 /* 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/. */
 
 //! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
 
 use compositor_thread::EventLoopWaker;
 use euclid::{Point2D, Size2D};
-use euclid::{TypedPoint2D, TypedRect, ScaleFactor, TypedSize2D};
+use euclid::{ScaleFactor, TypedPoint2D, TypedSize2D};
 use gleam::gl;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::{Key, KeyModifiers, KeyState, TraversalDirection};
 use net_traits::net_error_list::NetError;
 use script_traits::{LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
 use servo_geometry::DeviceIndependentPixel;
 use servo_url::ServoUrl;
 use std::fmt::{Debug, Error, Formatter};
 use std::rc::Rc;
 use style_traits::DevicePixel;
 use style_traits::cursor::Cursor;
-use webrender_api::ScrollLocation;
+use webrender_api::{DeviceUintSize, DeviceUintRect, ScrollLocation};
 
 #[derive(Clone)]
 pub enum MouseWindowEvent {
     Click(MouseButton, TypedPoint2D<f32, DevicePixel>),
     MouseDown(MouseButton, TypedPoint2D<f32, DevicePixel>),
     MouseUp(MouseButton, TypedPoint2D<f32, DevicePixel>),
 }
 
@@ -36,17 +36,17 @@ pub enum WindowEvent {
     /// FIXME(pcwalton): This is kind of ugly and may not work well with multiprocess Servo.
     /// It's possible that this should be something like
     /// `CompositorMessageWindowEvent(compositor_thread::Msg)` instead.
     Idle,
     /// Sent when part of the window is marked dirty and needs to be redrawn. Before sending this
     /// message, the window must make the same GL context as in `PrepareRenderingEvent` current.
     Refresh,
     /// Sent when the window is resized.
-    Resize(TypedSize2D<u32, DevicePixel>),
+    Resize(DeviceUintSize),
     /// Touchpad Pressure
     TouchpadPressure(TypedPoint2D<f32, DevicePixel>, f32, TouchpadPressurePhase),
     /// Sent when a new URL is to be loaded.
     LoadUrl(String),
     /// Sent when a mouse hit test is to be performed.
     MouseWindowEventClass(MouseWindowEvent),
     /// Sent when a mouse move.
     MouseWindowMoveEventClass(TypedPoint2D<f32, DevicePixel>),
@@ -100,19 +100,19 @@ impl Debug for WindowEvent {
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub enum AnimationState {
     Idle,
     Animating,
 }
 
 pub trait WindowMethods {
     /// Returns the rendering area size in hardware pixels.
-    fn framebuffer_size(&self) -> TypedSize2D<u32, DevicePixel>;
+    fn framebuffer_size(&self) -> DeviceUintSize;
     /// Returns the position and size of the window within the rendering area.
-    fn window_rect(&self) -> TypedRect<u32, DevicePixel>;
+    fn window_rect(&self) -> DeviceUintRect;
     /// Returns the size of the window in density-independent "px" units.
     fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel>;
     /// Presents the window to the screen (perhaps by page flipping).
     fn present(&self);
 
     /// Return the size of the window with head and borders and position of the window values
     fn client_window(&self) -> (Size2D<u32>, Point2D<i32>);
     /// Set the size inside of borders and head
--- a/servo/components/constellation/constellation.rs
+++ b/servo/components/constellation/constellation.rs
@@ -223,18 +223,21 @@ pub struct Constellation<Message, LTF, S
     /// A channel for the constellation to send messages to the
     /// memory profiler thread.
     mem_profiler_chan: mem::ProfilerChan,
 
     /// A channel for the constellation to send messages to the
     /// timer thread.
     scheduler_chan: IpcSender<TimerSchedulerMsg>,
 
+    /// A single WebRender document the constellation operates on.
+    webrender_document: webrender_api::DocumentId,
+
     /// A channel for the constellation to send messages to the
-    /// Webrender thread.
+    /// WebRender thread.
     webrender_api_sender: webrender_api::RenderApiSender,
 
     /// The set of all event loops in the browser. We generate a new
     /// event loop for each registered domain name (aka eTLD+1) in
     /// each top-level browsing context. We store the event loops in a map
     /// indexed by top-level browsing context id
     /// (as a `TopLevelBrowsingContextId`) and registered
     /// domain name (as a `Host`) to event loops. This double
@@ -320,16 +323,19 @@ pub struct InitialConstellationState {
     pub private_resource_threads: ResourceThreads,
 
     /// A channel to the time profiler thread.
     pub time_profiler_chan: time::ProfilerChan,
 
     /// A channel to the memory profiler thread.
     pub mem_profiler_chan: mem::ProfilerChan,
 
+    /// Webrender document ID.
+    pub webrender_document: webrender_api::DocumentId,
+
     /// Webrender API.
     pub webrender_api_sender: webrender_api::RenderApiSender,
 
     /// Whether the constellation supports the clipboard.
     /// TODO: this field is not used, remove it?
     pub supports_clipboard: bool,
 }
 
@@ -556,16 +562,17 @@ impl<Message, LTF, STF> Constellation<Me
                         },
                     }
                 } else {
                     None
                 },
                 webdriver: WebDriverData::new(),
                 scheduler_chan: TimerScheduler::start(),
                 document_states: HashMap::new(),
+                webrender_document: state.webrender_document,
                 webrender_api_sender: state.webrender_api_sender,
                 shutting_down: false,
                 handled_warnings: VecDeque::new(),
                 random_pipeline_closure: opts::get().random_pipeline_closure_probability.map(|prob| {
                     let seed = opts::get().random_pipeline_closure_seed.unwrap_or_else(random);
                     let rng = ServoRng::from_seed(&[seed]);
                     warn!("Randomly closing pipelines.");
                     info!("Using seed {} for random pipeline closure.", seed);
@@ -659,38 +666,39 @@ impl<Message, LTF, STF> Constellation<Me
 
         let prev_visibility = self.browsing_contexts.get(&browsing_context_id)
             .and_then(|browsing_context| self.pipelines.get(&browsing_context.pipeline_id))
             .map(|pipeline| pipeline.visible)
             .or(parent_visibility);
 
         let result = Pipeline::spawn::<Message, LTF, STF>(InitialPipelineState {
             id: pipeline_id,
-            browsing_context_id: browsing_context_id,
-            top_level_browsing_context_id: top_level_browsing_context_id,
-            parent_info: parent_info,
+            browsing_context_id,
+            top_level_browsing_context_id,
+            parent_info,
             constellation_chan: self.script_sender.clone(),
             layout_to_constellation_chan: self.layout_sender.clone(),
             scheduler_chan: self.scheduler_chan.clone(),
             compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
             devtools_chan: self.devtools_chan.clone(),
             bluetooth_thread: self.bluetooth_thread.clone(),
             swmanager_thread: self.swmanager_sender.clone(),
             font_cache_thread: self.font_cache_thread.clone(),
-            resource_threads: resource_threads,
+            resource_threads,
             time_profiler_chan: self.time_profiler_chan.clone(),
             mem_profiler_chan: self.mem_profiler_chan.clone(),
             window_size: initial_window_size,
-            event_loop: event_loop,
-            load_data: load_data,
+            event_loop,
+            load_data,
             device_pixel_ratio: self.window_size.device_pixel_ratio,
             pipeline_namespace_id: self.next_pipeline_namespace_id(),
-            prev_visibility: prev_visibility,
+            prev_visibility,
             webrender_api_sender: self.webrender_api_sender.clone(),
-            is_private: is_private,
+            webrender_document: self.webrender_document,
+            is_private,
             webvr_thread: self.webvr_thread.clone()
         });
 
         let pipeline = match result {
             Ok(result) => result,
             Err(e) => return self.handle_send_error(pipeline_id, e),
         };
 
--- a/servo/components/constellation/pipeline.rs
+++ b/servo/components/constellation/pipeline.rs
@@ -151,25 +151,29 @@ pub struct InitialPipelineState {
     pub device_pixel_ratio: ScaleFactor<f32, CSSPixel, DevicePixel>,
 
     /// The event loop to run in, if applicable.
     pub event_loop: Option<Rc<EventLoop>>,
 
     /// Information about the page to load.
     pub load_data: LoadData,
 
+
     /// The ID of the pipeline namespace for this script thread.
     pub pipeline_namespace_id: PipelineNamespaceId,
 
     /// Pipeline visibility to be inherited
     pub prev_visibility: Option<bool>,
 
     /// Webrender api.
     pub webrender_api_sender: webrender_api::RenderApiSender,
 
+    /// The ID of the document processed by this script thread.
+    pub webrender_document: webrender_api::DocumentId,
+
     /// Whether this pipeline is considered private.
     pub is_private: bool,
     /// A channel to the webvr thread.
     pub webvr_thread: Option<IpcSender<WebVRMsg>>,
 }
 
 impl Pipeline {
     /// Starts a layout thread, and possibly a script thread, in
@@ -260,16 +264,17 @@ impl Pipeline {
                     prefs: PREFS.cloned(),
                     pipeline_port: pipeline_port,
                     pipeline_namespace_id: state.pipeline_namespace_id,
                     layout_content_process_shutdown_chan: layout_content_process_shutdown_chan,
                     layout_content_process_shutdown_port: layout_content_process_shutdown_port,
                     script_content_process_shutdown_chan: script_content_process_shutdown_chan,
                     script_content_process_shutdown_port: script_content_process_shutdown_port,
                     webrender_api_sender: state.webrender_api_sender,
+                    webrender_document: state.webrender_document,
                     webvr_thread: state.webvr_thread,
                 };
 
                 // Spawn the child process.
                 //
                 // Yes, that's all there is to it!
                 if opts::multiprocess() {
                     let _ = unprivileged_pipeline_content.spawn_multiprocess()?;
@@ -459,16 +464,17 @@ pub struct UnprivilegedPipelineContent {
     prefs: HashMap<String, Pref>,
     pipeline_port: IpcReceiver<LayoutControlMsg>,
     pipeline_namespace_id: PipelineNamespaceId,
     layout_content_process_shutdown_chan: IpcSender<()>,
     layout_content_process_shutdown_port: IpcReceiver<()>,
     script_content_process_shutdown_chan: IpcSender<()>,
     script_content_process_shutdown_port: IpcReceiver<()>,
     webrender_api_sender: webrender_api::RenderApiSender,
+    webrender_document: webrender_api::DocumentId,
     webvr_thread: Option<IpcSender<WebVRMsg>>,
 }
 
 impl UnprivilegedPipelineContent {
     pub fn start_all<Message, LTF, STF>(self, wait_for_completion: bool)
         where LTF: LayoutThreadFactory<Message=Message>,
               STF: ScriptThreadFactory<Message=Message>
     {
@@ -505,16 +511,17 @@ impl UnprivilegedPipelineContent {
                     self.layout_to_constellation_chan,
                     self.script_chan,
                     image_cache.clone(),
                     self.font_cache_thread,
                     self.time_profiler_chan,
                     self.mem_profiler_chan,
                     Some(self.layout_content_process_shutdown_chan),
                     self.webrender_api_sender,
+                    self.webrender_document,
                     self.prefs.get("layout.threads").expect("exists").value()
                         .as_u64().expect("count") as usize,
                     paint_time_metrics);
 
         if wait_for_completion {
             let _ = self.script_content_process_shutdown_port.recv();
             let _ = self.layout_content_process_shutdown_port.recv();
         }
--- a/servo/components/layout_thread/lib.rs
+++ b/servo/components/layout_thread/lib.rs
@@ -237,16 +237,19 @@ pub struct LayoutThread {
                                                  WebRenderImageInfo>>>,
     /// The executor for paint worklets.
     /// Will be None if the script thread hasn't added any paint worklet modules.
     registered_painters: Arc<RwLock<FnvHashMap<Atom, RegisteredPainter>>>,
 
     /// Webrender interface.
     webrender_api: webrender_api::RenderApi,
 
+    /// Webrender document.
+    webrender_document: webrender_api::DocumentId,
+
     /// The timer object to control the timing of the animations. This should
     /// only be a test-mode timer during testing for animations.
     timer: Timer,
 
     // Number of layout threads. This is copied from `servo_config::opts`, but we'd
     // rather limit the dependency on that module here.
     layout_threads: usize,
 
@@ -270,16 +273,17 @@ impl LayoutThreadFactory for LayoutThrea
               constellation_chan: IpcSender<ConstellationMsg>,
               script_chan: IpcSender<ConstellationControlMsg>,
               image_cache: Arc<ImageCache>,
               font_cache_thread: FontCacheThread,
               time_profiler_chan: time::ProfilerChan,
               mem_profiler_chan: mem::ProfilerChan,
               content_process_shutdown_chan: Option<IpcSender<()>>,
               webrender_api_sender: webrender_api::RenderApiSender,
+              webrender_document: webrender_api::DocumentId,
               layout_threads: usize,
               paint_time_metrics: PaintTimeMetrics) {
         thread::Builder::new().name(format!("LayoutThread {:?}", id)).spawn(move || {
             thread_state::initialize(thread_state::LAYOUT);
 
             // In order to get accurate crash reports, we install the top-level bc id.
             TopLevelBrowsingContextId::install(top_level_browsing_context_id);
 
@@ -293,16 +297,17 @@ impl LayoutThreadFactory for LayoutThrea
                                                pipeline_port,
                                                constellation_chan,
                                                script_chan,
                                                image_cache.clone(),
                                                font_cache_thread,
                                                time_profiler_chan,
                                                mem_profiler_chan.clone(),
                                                webrender_api_sender,
+                                               webrender_document,
                                                layout_threads,
                                                paint_time_metrics);
 
                 let reporter_name = format!("layout-reporter-{}", id);
                 mem_profiler_chan.run_with_memory_reporting(|| {
                     layout.start();
                 }, reporter_name, sender, Msg::CollectReports);
             }
@@ -455,16 +460,17 @@ impl LayoutThread {
            pipeline_port: IpcReceiver<LayoutControlMsg>,
            constellation_chan: IpcSender<ConstellationMsg>,
            script_chan: IpcSender<ConstellationControlMsg>,
            image_cache: Arc<ImageCache>,
            font_cache_thread: FontCacheThread,
            time_profiler_chan: time::ProfilerChan,
            mem_profiler_chan: mem::ProfilerChan,
            webrender_api_sender: webrender_api::RenderApiSender,
+           webrender_document: webrender_api::DocumentId,
            layout_threads: usize,
            paint_time_metrics: PaintTimeMetrics)
            -> LayoutThread {
         // The device pixel ratio is incorrect (it does not have the hidpi value),
         // but it will be set correctly when the initial reflow takes place.
         let device = Device::new(
             MediaType::Screen,
             opts::get().initial_window_size.to_f32() * ScaleFactor::new(1.0),
@@ -528,16 +534,17 @@ impl LayoutThread {
             outstanding_web_fonts: outstanding_web_fonts_counter,
             root_flow: RefCell::new(None),
             document_shared_lock: None,
             running_animations: ServoArc::new(RwLock::new(FnvHashMap::default())),
             expired_animations: ServoArc::new(RwLock::new(FnvHashMap::default())),
             epoch: Cell::new(Epoch(0)),
             viewport_size: Size2D::new(Au(0), Au(0)),
             webrender_api: webrender_api_sender.create_api(),
+            webrender_document,
             stylist: stylist,
             rw_data: Arc::new(Mutex::new(
                 LayoutThreadData {
                     constellation_chan: constellation_chan,
                     display_list: None,
                     content_box_response: None,
                     content_boxes_response: Vec::new(),
                     client_rect_response: Rect::zero(),
@@ -797,16 +804,17 @@ impl LayoutThread {
                              info.constellation_chan,
                              info.script_chan.clone(),
                              info.image_cache.clone(),
                              self.font_cache_thread.clone(),
                              self.time_profiler_chan.clone(),
                              self.mem_profiler_chan.clone(),
                              info.content_process_shutdown_chan,
                              self.webrender_api.clone_sender(),
+                             self.webrender_document,
                              info.layout_threads,
                              info.paint_time_metrics);
     }
 
     /// Enters a quiescent state in which no new messages will be processed until an `ExitNow` is
     /// received. A pong is immediately sent on the given response channel.
     fn prepare_to_exit(&mut self, response_chan: Sender<()>) {
         response_chan.send(()).unwrap();
@@ -1040,22 +1048,23 @@ impl LayoutThread {
             let viewport_size = webrender_api::LayoutSize::from_untyped(&viewport_size);
 
             // Set paint metrics if needed right before sending the display list to WebRender.
             // XXX At some point, we may want to set this metric from WebRender itself.
             self.paint_time_metrics.maybe_set_first_paint(self);
             self.paint_time_metrics.maybe_set_first_contentful_paint(self, &display_list);
 
             self.webrender_api.set_display_list(
+                self.webrender_document,
+                webrender_api::Epoch(epoch.0),
                 Some(get_root_flow_background_color(layout_root)),
-                webrender_api::Epoch(epoch.0),
                 viewport_size,
                 builder.finalize(),
                 true);
-            self.webrender_api.generate_frame(None);
+            self.webrender_api.generate_frame(self.webrender_document, None);
         });
     }
 
     /// The high-level routine that performs layout threads.
     fn handle_reflow<'a, 'b>(&mut self,
                              data: &mut ScriptReflowResult,
                              possibly_locked_rw_data: &mut RwData<'a, 'b>) {
         let document = unsafe { ServoLayoutNode::new(&data.document) };
--- a/servo/components/layout_traits/lib.rs
+++ b/servo/components/layout_traits/lib.rs
@@ -45,11 +45,12 @@ pub trait LayoutThreadFactory {
               constellation_chan: IpcSender<ConstellationMsg>,
               script_chan: IpcSender<ConstellationControlMsg>,
               image_cache: Arc<ImageCache>,
               font_cache_thread: FontCacheThread,
               time_profiler_chan: time::ProfilerChan,
               mem_profiler_chan: mem::ProfilerChan,
               content_process_shutdown_chan: Option<IpcSender<()>>,
               webrender_api_sender: webrender_api::RenderApiSender,
+              webrender_document: webrender_api::DocumentId,
               layout_threads: usize,
               paint_time_metrics: PaintTimeMetrics);
 }
--- a/servo/components/script_traits/lib.rs
+++ b/servo/components/script_traits/lib.rs
@@ -61,20 +61,18 @@ use serde::{Deserialize, Deserializer, S
 use servo_atoms::Atom;
 use servo_url::ImmutableOrigin;
 use servo_url::ServoUrl;
 use std::collections::HashMap;
 use std::fmt;
 use std::sync::Arc;
 use std::sync::mpsc::{Receiver, Sender, RecvTimeoutError};
 use style_traits::CSSPixel;
-use style_traits::DevicePixel;
 use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
-use webrender_api::ClipId;
-use webrender_api::ImageKey;
+use webrender_api::{ClipId, DevicePixel, ImageKey};
 use webvr_traits::{WebVREvent, WebVRMsg};
 
 pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry};
 pub use script_msg::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders, DOMMessage};
 
 /// The address of a node. Layout sends these back. They must be validated via
 /// `from_untrusted_node_address` before they can be used, because we do not trust layout.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
--- a/servo/components/servo/lib.rs
+++ b/servo/components/servo/lib.rs
@@ -169,36 +169,35 @@ impl<Window> Browser<Window> where Windo
             let recorder = if opts.webrender_record {
                 let record_path = PathBuf::from("wr-record.bin");
                 let recorder = Box::new(webrender::BinaryRecorder::new(&record_path));
                 Some(recorder as Box<webrender::ApiRecordingReceiver>)
             } else {
                 None
             };
 
-            let framebuffer_size = window.framebuffer_size();
-            let framebuffer_size = webrender_api::DeviceUintSize::new(framebuffer_size.width,
-                                                                      framebuffer_size.height);
-
             webrender::Renderer::new(window.gl(), webrender::RendererOptions {
                 device_pixel_ratio: device_pixel_ratio,
                 resource_override_path: Some(resource_path),
                 enable_aa: opts.enable_text_antialiasing,
                 enable_profiler: opts.webrender_stats,
                 enable_batcher: opts.webrender_batch,
                 debug: opts.webrender_debug,
                 recorder: recorder,
                 precache_shaders: opts.precache_shaders,
                 enable_scrollbars: opts.output_file.is_none(),
                 renderer_kind: renderer_kind,
                 enable_subpixel_aa: opts.enable_subpixel_text_antialiasing,
                 ..Default::default()
-            }, framebuffer_size).expect("Unable to initialize webrender!")
+            }).expect("Unable to initialize webrender!")
         };
 
+        let webrender_api = webrender_api_sender.create_api();
+        let webrender_document = webrender_api.add_document(window.framebuffer_size());
+
         // Important that this call is done in a single-threaded fashion, we
         // can't defer it after `create_constellation` has started.
         script::init();
 
         // Create the constellation, which maintains the engine
         // pipelines, including the script and layout threads, as well
         // as the navigation context.
         let (constellation_chan, sw_senders) = create_constellation(opts.user_agent.clone(),
@@ -206,17 +205,18 @@ impl<Window> Browser<Window> where Windo
                                                                     target_url,
                                                                     compositor_proxy.clone_compositor_proxy(),
                                                                     time_profiler_chan.clone(),
                                                                     mem_profiler_chan.clone(),
                                                                     debugger_chan,
                                                                     devtools_chan,
                                                                     supports_clipboard,
                                                                     &webrender,
-                                                                    webrender_api_sender.clone());
+                                                                    webrender_document,
+                                                                    webrender_api_sender);
 
         // Send the constellation's swmanager sender to service worker manager thread
         script::init_service_workers(sw_senders);
 
         if cfg!(feature = "webdriver") {
             if let Some(port) = opts.webdriver_port {
                 webdriver(port, constellation_chan.clone());
             }
@@ -225,18 +225,19 @@ impl<Window> Browser<Window> where Windo
         // The compositor coordinates with the client window to create the final
         // rendered page and display it somewhere.
         let compositor = IOCompositor::create(window, InitialCompositorState {
             sender: compositor_proxy,
             receiver: compositor_receiver,
             constellation_chan: constellation_chan.clone(),
             time_profiler_chan: time_profiler_chan,
             mem_profiler_chan: mem_profiler_chan,
-            webrender: webrender,
-            webrender_api_sender: webrender_api_sender,
+            webrender,
+            webrender_document,
+            webrender_api,
         });
 
         Browser {
             compositor: compositor,
             constellation_chan: constellation_chan,
         }
     }
 
@@ -282,42 +283,44 @@ fn create_constellation(user_agent: Cow<
                         url: ServoUrl,
                         compositor_proxy: CompositorProxy,
                         time_profiler_chan: time::ProfilerChan,
                         mem_profiler_chan: mem::ProfilerChan,
                         debugger_chan: Option<debugger::Sender>,
                         devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
                         supports_clipboard: bool,
                         webrender: &webrender::Renderer,
+                        webrender_document: webrender_api::DocumentId,
                         webrender_api_sender: webrender_api::RenderApiSender)
                         -> (Sender<ConstellationMsg>, SWManagerSenders) {
     let bluetooth_thread: IpcSender<BluetoothRequest> = BluetoothThreadFactory::new();
 
     let (public_resource_threads, private_resource_threads) =
         new_resource_threads(user_agent,
                              devtools_chan.clone(),
                              time_profiler_chan.clone(),
                              config_dir);
     let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(),
                                                  Some(webrender_api_sender.create_api()));
 
     let resource_sender = public_resource_threads.sender();
 
     let initial_state = InitialConstellationState {
-        compositor_proxy: compositor_proxy,
-        debugger_chan: debugger_chan,
-        devtools_chan: devtools_chan,
-        bluetooth_thread: bluetooth_thread,
-        font_cache_thread: font_cache_thread,
-        public_resource_threads: public_resource_threads,
-        private_resource_threads: private_resource_threads,
-        time_profiler_chan: time_profiler_chan,
-        mem_profiler_chan: mem_profiler_chan,
-        supports_clipboard: supports_clipboard,
-        webrender_api_sender: webrender_api_sender,
+        compositor_proxy,
+        debugger_chan,
+        devtools_chan,
+        bluetooth_thread,
+        font_cache_thread,
+        public_resource_threads,
+        private_resource_threads,
+        time_profiler_chan,
+        mem_profiler_chan,
+        supports_clipboard,
+        webrender_document,
+        webrender_api_sender,
     };
     let (constellation_chan, from_swmanager_sender) =
         Constellation::<script_layout_interface::message::Msg,
                         layout_thread::LayoutThread,
                         script::script_thread::ScriptThread>::start(initial_state);
 
     if PREFS.is_webvr_enabled() {
         // WebVR initialization
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -17,8 +17,9 @@ gecko = []
 app_units = "0.5"
 bitflags = "0.7"
 cssparser = "0.18"
 euclid = "0.15"
 heapsize = {version = "0.4", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true}
+webrender_api = {git = "https://github.com/servo/webrender"}
--- a/servo/components/style_traits/lib.rs
+++ b/servo/components/style_traits/lib.rs
@@ -16,16 +16,19 @@
 extern crate app_units;
 #[macro_use] extern crate bitflags;
 #[macro_use] extern crate cssparser;
 extern crate euclid;
 #[cfg(feature = "servo")] extern crate heapsize;
 #[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
 extern crate selectors;
 #[cfg(feature = "servo")] #[macro_use] extern crate serde;
+extern crate webrender_api;
+
+pub use webrender_api::DevicePixel;
 
 use cssparser::{CowRcStr, Token};
 use selectors::parser::SelectorParseError;
 
 /// Opaque type stored in type-unsafe work queues for parallel layout.
 /// Must be transmutable to and from `TNode`.
 pub type UnsafeNode = (usize, usize);
 
@@ -54,22 +57,16 @@ impl PinchZoomFactor {
 /// the desktop-style "full page" zoom that enlarges content but then reflows the layout viewport
 /// so it still exactly fits the visible area.
 ///
 /// At the default zoom level of 100%, one `CSSPixel` is equal to one `DeviceIndependentPixel`.  However, if the
 /// document is zoomed in or out then this scale may be larger or smaller.
 #[derive(Clone, Copy, Debug)]
 pub enum CSSPixel {}
 
-/// One hardware pixel.
-///
-/// This unit corresponds to the smallest addressable element of the display hardware.
-#[derive(Copy, Clone, Debug)]
-pub enum DevicePixel {}
-
 // In summary, the hierarchy of pixel units and the factors to convert from one to the next:
 //
 // DevicePixel
 //   / hidpi_ratio => DeviceIndependentPixel
 //     / desktop_zoom => CSSPixel
 
 pub mod cursor;
 #[macro_use]
--- a/servo/ports/cef/window.rs
+++ b/servo/ports/cef/window.rs
@@ -14,17 +14,17 @@ use eutil::Downcast;
 use interfaces::CefApp;
 use interfaces::CefBrowser;
 use render_handler::CefRenderHandlerExtensions;
 use types::{cef_cursor_handle_t, cef_cursor_type_t, cef_rect_t};
 use wrappers::CefWrap;
 
 use compositing::compositor_thread::EventLoopWaker;
 use compositing::windowing::{WindowEvent, WindowMethods};
-use euclid::{Point2D, TypedPoint2D, TypedRect, Size2D, TypedSize2D, ScaleFactor};
+use euclid::{Point2D, TypedPoint2D, Size2D, TypedSize2D, ScaleFactor};
 use gleam::gl;
 use msg::constellation_msg::{Key, KeyModifiers};
 use net_traits::net_error_list::NetError;
 use script_traits::LoadData;
 use servo::ipc_channel::ipc::IpcSender;
 use servo_geometry::DeviceIndependentPixel;
 use std::cell::RefCell;
 use std::ffi::CString;
@@ -33,25 +33,26 @@ use std::ptr;
 use std::rc::Rc;
 use servo_url::ServoUrl;
 use style_traits::cursor::Cursor;
 use style_traits::DevicePixel;
 #[cfg(target_os="linux")]
 extern crate x11;
 #[cfg(target_os="linux")]
 use self::x11::xlib::{XInitThreads,XOpenDisplay};
+use webrender_api::{DeviceUintSize, DeviceUintRect};
 
 #[cfg(target_os="linux")]
 pub static mut DISPLAY: *mut c_void = 0 as *mut c_void;
 
 /// The type of an off-screen window.
 #[derive(Clone)]
 pub struct Window {
     cef_browser: RefCell<Option<CefBrowser>>,
-    size: TypedSize2D<u32, DevicePixel>,
+    size: DeviceUintSize,
     gl: Rc<gl::Gl>,
 }
 
 #[cfg(target_os="macos")]
 fn load_gl() -> Rc<gl::Gl> {
     const RTLD_DEFAULT: *mut c_void = (-2isize) as usize as *mut c_void;
 
     extern {
@@ -169,17 +170,17 @@ impl Window {
     }
 }
 
 impl WindowMethods for Window {
     fn gl(&self) -> Rc<gl::Gl> {
         self.gl.clone()
     }
 
-    fn framebuffer_size(&self) -> TypedSize2D<u32, DevicePixel> {
+    fn framebuffer_size(&self) -> DeviceUintSize {
         let browser = self.cef_browser.borrow();
         match *browser {
             None => self.size,
             Some(ref browser) => {
                 if browser.downcast().callback_executed.get() != true {
                     self.size
                 } else {
                     let mut rect = cef_rect_t::zero();
@@ -200,26 +201,26 @@ impl WindowMethods for Window {
                            check_ptr_exist!(browser.get_host().get_client().get_render_handler(), get_view_rect) {
                             browser.get_host()
                                    .get_client()
                                    .get_render_handler()
                                    .get_view_rect((*browser).clone(), &mut rect);
                         }
                     }
 
-                    TypedSize2D::new(rect.width as u32, rect.height as u32)
+                    DeviceUintSize::new(rect.width as u32, rect.height as u32)
                 }
             }
         }
     }
 
-    fn window_rect(&self) -> TypedRect<u32, DevicePixel> {
+    fn window_rect(&self) -> DeviceUintRect {
         let size = self.framebuffer_size();
         let origin = TypedPoint2D::zero();
-        TypedRect::new(origin, size)
+        DeviceUintRect::new(origin, size)
     }
 
     fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel> {
         let browser = self.cef_browser.borrow();
         match *browser {
             None => TypedSize2D::new(400.0, 300.0),
             Some(ref browser) => {
                 let mut rect = cef_rect_t::zero();
--- a/servo/ports/glutin/window.rs
+++ b/servo/ports/glutin/window.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! A windowing implementation using glutin.
 
 use NestedEventLoopListener;
 use compositing::compositor_thread::EventLoopWaker;
 use compositing::windowing::{AnimationState, MouseWindowEvent};
 use compositing::windowing::{WindowEvent, WindowMethods};
-use euclid::{Point2D, Size2D, TypedPoint2D, TypedVector2D, TypedRect, ScaleFactor, TypedSize2D};
+use euclid::{Point2D, Size2D, TypedPoint2D, TypedVector2D, ScaleFactor, TypedSize2D};
 #[cfg(target_os = "windows")]
 use gdi32;
 use gleam::gl;
 use glutin;
 use glutin::{Api, ElementState, Event, GlRequest, MouseButton, MouseScrollDelta, VirtualKeyCode};
 #[cfg(not(target_os = "windows"))]
 use glutin::ScanCode;
 use glutin::TouchPhase;
@@ -38,17 +38,17 @@ use std::ffi::CString;
 use std::mem;
 use std::os::raw::c_void;
 use std::ptr;
 use std::rc::Rc;
 use style_traits::DevicePixel;
 use style_traits::cursor::Cursor;
 #[cfg(target_os = "windows")]
 use user32;
-use webrender_api::ScrollLocation;
+use webrender_api::{DeviceUintRect, DeviceUintSize, ScrollLocation};
 #[cfg(target_os = "windows")]
 use winapi;
 
 static mut G_NESTED_EVENT_LOOP_LISTENER: Option<*mut (NestedEventLoopListener + 'static)> = None;
 
 bitflags! {
     flags KeyModifiers: u8 {
         const LEFT_CONTROL = 1,
@@ -957,34 +957,34 @@ fn create_window_proxy(window: &Window) 
     }
 }
 
 impl WindowMethods for Window {
     fn gl(&self) -> Rc<gl::Gl> {
         self.gl.clone()
     }
 
-    fn framebuffer_size(&self) -> TypedSize2D<u32, DevicePixel> {
+    fn framebuffer_size(&self) -> DeviceUintSize {
         match self.kind {
             WindowKind::Window(ref window) => {
                 let scale_factor = window.hidpi_factor() as u32;
                 // TODO(ajeffrey): can this fail?
                 let (width, height) = window.get_inner_size().expect("Failed to get window inner size.");
-                TypedSize2D::new(width * scale_factor, height * scale_factor)
+                DeviceUintSize::new(width, height) * scale_factor
             }
             WindowKind::Headless(ref context) => {
-                TypedSize2D::new(context.width, context.height)
+                DeviceUintSize::new(context.width, context.height)
             }
         }
     }
 
-    fn window_rect(&self) -> TypedRect<u32, DevicePixel> {
+    fn window_rect(&self) -> DeviceUintRect {
         let size = self.framebuffer_size();
         let origin = TypedPoint2D::zero();
-        TypedRect::new(origin, size)
+        DeviceUintRect::new(origin, size)
     }
 
     fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel> {
         match self.kind {
             WindowKind::Window(ref window) => {
                 // TODO(ajeffrey): can this fail?
                 let (width, height) = window.get_inner_size().expect("Failed to get window inner size.");
                 TypedSize2D::new(width as f32, height as f32)