Bug 1357392 - Update webrender to f3fa3481aac63ac93c6ccbe805379875e24e5b77. r=jrmuizel,jerry,lsalzman
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 21 Apr 2017 09:58:56 -0400
changeset 355205 2075cd677dc9a81e7a02afdf356a60419fcde273
parent 355204 68b48ae09aedd2a291867c270b23f6aeac75fcdc
child 355206 ca9968f8bce54bdb1748b50523982e2fa3a30468
push id89659
push userkwierso@gmail.com
push dateThu, 27 Apr 2017 20:29:29 +0000
treeherdermozilla-inbound@f700a9bf4fd1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, jerry, lsalzman
bugs1357392
milestone55.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
Bug 1357392 - Update webrender to f3fa3481aac63ac93c6ccbe805379875e24e5b77. r=jrmuizel,jerry,lsalzman In addition to regenerating the FFI header and re-vendoring third-party rust dependencies, this includes the following changes to webrender_bindings code: - removal of release callback function as a result of changes in 86d4255 - update callback functions for new parameter added in d733af2 - update calls to add_raw_font for API change in 21f2946
gfx/doc/README.webrender
gfx/webrender/Cargo.toml
gfx/webrender/res/cs_clip_image.fs.glsl
gfx/webrender/res/cs_clip_image.vs.glsl
gfx/webrender/res/prim_shared.glsl
gfx/webrender/res/ps_border_corner.fs.glsl
gfx/webrender/res/ps_border_corner.vs.glsl
gfx/webrender/res/shared.glsl
gfx/webrender/src/clip_scroll_node.rs
gfx/webrender/src/device.rs
gfx/webrender/src/frame_builder.rs
gfx/webrender/src/internal_types.rs
gfx/webrender/src/platform/macos/font.rs
gfx/webrender/src/platform/unix/font.rs
gfx/webrender/src/platform/windows/font.rs
gfx/webrender/src/prim_store.rs
gfx/webrender/src/profiler.rs
gfx/webrender/src/render_backend.rs
gfx/webrender/src/renderer.rs
gfx/webrender/src/resource_cache.rs
gfx/webrender/src/scene.rs
gfx/webrender/src/texture_cache.rs
gfx/webrender/src/tiling.rs
gfx/webrender_bindings/Cargo.toml
gfx/webrender_bindings/RendererOGL.cpp
gfx/webrender_bindings/RendererOGL.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
gfx/webrender_traits/Cargo.toml
gfx/webrender_traits/src/api.rs
gfx/webrender_traits/src/channel.rs
gfx/webrender_traits/src/channel_ipc.rs
gfx/webrender_traits/src/display_item.rs
gfx/webrender_traits/src/display_list.rs
gfx/webrender_traits/src/font.rs
gfx/webrender_traits/src/image.rs
gfx/webrender_traits/src/lib.rs
gfx/webrender_traits/src/webgl.rs
third_party/rust/gleam/.cargo-checksum.json
third_party/rust/gleam/Cargo.toml
third_party/rust/gleam/build.rs
third_party/rust/gleam/src/gl.rs
third_party/rust/gleam/src/gl_fns.rs
third_party/rust/gleam/src/gles_fns.rs
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
--- a/gfx/doc/README.webrender
+++ b/gfx/doc/README.webrender
@@ -74,9 +74,9 @@ there is another crate in m-c called moz
 the same folder to store its rust dependencies. If one of the libraries that is
 required by both mozjs_sys and webrender is updated without updating the other
 project's Cargo.lock file, that results in build bustage.
 This means that any time you do this sort of manual update of packages, you need
 to make sure that mozjs_sys also has its Cargo.lock file updated if needed, hence
 the need to run the cargo update command in js/src as well. Hopefully this will
 be resolved soon.
 
-Latest Commit: 07b6c6a1f93b5d8af1dd9ae825906dcf5c310810
+Latest Commit: f3fa3481aac63ac93c6ccbe805379875e24e5b77
--- a/gfx/webrender/Cargo.toml
+++ b/gfx/webrender/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "webrender"
-version = "0.32.0"
+version = "0.35.0"
 authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
 license = "MPL-2.0"
 repository = "https://github.com/servo/webrender"
 build = "build.rs"
 
 [features]
 default = ["freetype-lib", "webgl"]
 freetype-lib = ["freetype/servo-freetype-sys"]
@@ -14,17 +14,17 @@ webgl = ["offscreen_gl_context", "webren
 
 [dependencies]
 app_units = "0.4"
 bincode = "1.0.0-alpha6"
 bit-set = "0.4"
 byteorder = "1.0"
 euclid = "0.11"
 fnv = "1.0"
-gleam = "0.4.2"
+gleam = "0.4.3"
 lazy_static = "0.2"
 log = "0.3"
 num-traits = "0.1.32"
 offscreen_gl_context = {version = "0.8.0", features = ["serde", "osmesa"], optional = true}
 time = "0.1"
 threadpool = "1.3.2"
 webrender_traits = {path = "../webrender_traits"}
 bitflags = "0.7"
--- a/gfx/webrender/res/cs_clip_image.fs.glsl
+++ b/gfx/webrender/res/cs_clip_image.fs.glsl
@@ -6,12 +6,12 @@ void main(void) {
     float alpha = 1.f;
     vec2 local_pos = init_transform_fs(vPos, vLocalRect, alpha);
 
     bool repeat_mask = false; //TODO
     vec2 clamped_mask_uv = repeat_mask ? fract(vClipMaskUv.xy) :
         clamp(vClipMaskUv.xy, vec2(0.0, 0.0), vec2(1.0, 1.0));
     vec2 source_uv = clamp(clamped_mask_uv * vClipMaskUvRect.zw + vClipMaskUvRect.xy,
         vClipMaskUvInnerRect.xy, vClipMaskUvInnerRect.zw);
-    float clip_alpha = texture(sMask, source_uv).r; //careful: texture has type A8
+    float clip_alpha = texture(sColor0, source_uv).r; //careful: texture has type A8
 
     oFragColor = vec4(min(alpha, clip_alpha), 1.0, 1.0, 1.0);
 }
--- a/gfx/webrender/res/cs_clip_image.vs.glsl
+++ b/gfx/webrender/res/cs_clip_image.vs.glsl
@@ -25,14 +25,14 @@ void main(void) {
                                                layer,
                                                area,
                                                cci.segment_index);
 
     vLocalRect = vi.clipped_local_rect;
     vPos = vi.local_pos;
 
     vClipMaskUv = vec3((vPos.xy / vPos.z - local_rect.p0) / local_rect.size, 0.0);
-    vec2 texture_size = vec2(textureSize(sMask, 0));
+    vec2 texture_size = vec2(textureSize(sColor0, 0));
     vClipMaskUvRect = vec4(mask.uv_rect.p0, mask.uv_rect.size) / texture_size.xyxy;
     // applying a half-texel offset to the UV boundaries to prevent linear samples from the outside
     vec4 inner_rect = vec4(mask.uv_rect.p0, mask.uv_rect.p0 + mask.uv_rect.size);
     vClipMaskUvInnerRect = (inner_rect + vec4(0.5, 0.5, -0.5, -0.5)) / texture_size.xyxy;
 }
--- a/gfx/webrender/res/prim_shared.glsl
+++ b/gfx/webrender/res/prim_shared.glsl
@@ -85,17 +85,18 @@ RectWithSize intersect_rect(RectWithSize
 }
 
 RectWithEndpoint intersect_rect(RectWithEndpoint a, RectWithEndpoint b) {
     vec4 p = clamp_rect(vec4(a.p0, a.p1), b);
     return RectWithEndpoint(p.xy, max(p.xy, p.zw));
 }
 
 
-flat varying RectWithEndpoint vClipMaskUvBounds;
+// TODO: convert back to RectWithEndPoint if driver issues are resolved, if ever.
+flat varying vec4 vClipMaskUvBounds;
 varying vec3 vClipMaskUv;
 
 #ifdef WR_VERTEX_SHADER
 
 #define VECS_PER_LAYER             13
 #define VECS_PER_RENDER_TASK        3
 #define VECS_PER_PRIM_GEOM          2
 
@@ -739,18 +740,17 @@ struct BoxShadow {
 BoxShadow fetch_boxshadow(int index) {
     vec4 data[4] = fetch_data_4(index);
     return BoxShadow(data[0], data[1], data[2], data[3]);
 }
 
 void write_clip(vec2 global_pos, ClipArea area) {
     vec2 texture_size = vec2(textureSize(sCacheA8, 0).xy);
     vec2 uv = global_pos + area.task_bounds.xy - area.screen_origin_target_index.xy;
-    vClipMaskUvBounds = RectWithEndpoint(area.task_bounds.xy / texture_size,
-                                         area.task_bounds.zw / texture_size);
+    vClipMaskUvBounds = area.task_bounds / texture_size.xyxy;
     vClipMaskUv = vec3(uv / texture_size, area.screen_origin_target_index.z);
 }
 #endif //WR_VERTEX_SHADER
 
 #ifdef WR_FRAGMENT_SHADER
 float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) {
     vec2 d = max(p0 - pos, pos - p1);
     return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y));
@@ -782,20 +782,20 @@ vec2 init_transform_fs(vec3 local_pos, R
     fragment_alpha = 1.0 - smoothstep(0.0, afwidth, d);
 
     return pos;
 }
 
 float do_clip() {
     // anything outside of the mask is considered transparent
     bvec4 inside = lessThanEqual(
-        vec4(vClipMaskUvBounds.p0, vClipMaskUv.xy),
-        vec4(vClipMaskUv.xy, vClipMaskUvBounds.p1));
+        vec4(vClipMaskUvBounds.xy, vClipMaskUv.xy),
+        vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw));
     // check for the dummy bounds, which are given to the opaque objects
-    return vClipMaskUvBounds.p0 == vClipMaskUvBounds.p1 ? 1.0:
+    return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0:
         all(inside) ? textureLod(sCacheA8, vClipMaskUv, 0.0).r : 0.0;
 }
 
 vec4 dither(vec4 color) {
     const int matrix_mask = 7;
 
     ivec2 pos = ivec2(gl_FragCoord.xy) & ivec2(matrix_mask);
     float noise_normalized = (texelFetch(sDither, pos, 0).r * 255.0 + 0.5) / 64.0;
--- a/gfx/webrender/res/ps_border_corner.fs.glsl
+++ b/gfx/webrender/res/ps_border_corner.fs.glsl
@@ -54,16 +54,27 @@ float sdEllipse( vec2 p, in vec2 ab ) {
     return length(r - p ) * sign(p.y-r.y);
 }
 
 float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) {
     vec2 dir_to_p0 = p0 - p;
     return dot(normalize(perp_dir), dir_to_p0);
 }
 
+float distance_to_ellipse(vec2 p, vec2 radii) {
+    // sdEllipse fails on exact circles, so handle equal
+    // radii here. The branch coherency should make this
+    // a performance win for the circle case too.
+    if (radii.x == radii.y) {
+        return length(p) - radii.x;
+    } else {
+        return sdEllipse(p, radii);
+    }
+}
+
 void main(void) {
     float alpha = 1.0;
 #ifdef WR_FEATURE_TRANSFORM
     alpha = 0.0;
     vec2 local_pos = init_transform_fs(vLocalPos, vLocalRect, alpha);
 #else
     vec2 local_pos = vLocalPos;
 #endif
@@ -73,42 +84,21 @@ void main(void) {
     // Find the appropriate distance to apply the AA smoothstep over.
     vec2 fw = fwidth(local_pos);
     float afwidth = length(fw);
 
     // Only apply the clip AA if inside the clip region. This is
     // necessary for correctness when the border width is greater
     // than the border radius.
     if (all(lessThan(local_pos * vClipSign, vClipCenter * vClipSign))) {
-        float d0, d1;
+        vec2 p = local_pos - vClipCenter;
 
-        // sdEllipse fails on exact circles, so handle equal
-        // radii here. The branch coherency should make this
-        // a performance win for the circle case too.
-        if (vOuterRadii.x == vOuterRadii.y) {
-            // Get the distances to the inner and outer radii.
-            d0 = distance(vClipCenter, local_pos) - vOuterRadii.x;
-        } else {
-            // Get the distance to the outer ellipse.
-            vec2 p = local_pos - vClipCenter;
-            d0 = sdEllipse(p, vOuterRadii);
-        }
-
-        if (vInnerRadii.x == vInnerRadii.y) {
-            d1 = distance(vClipCenter, local_pos) - vInnerRadii.x;
-        } else {
-            // Get distance to inner ellipse. Skip if the inner
-            // radius is <= 0.0 to avoid FP errors.
-            if (vInnerRadii.x <= 0.0 || vInnerRadii.y <= 0.0) {
-                d1 = -d0;
-            } else {
-                vec2 p = local_pos - vClipCenter;
-                d1 = sdEllipse(p, vInnerRadii);
-            }
-        }
+        // Get signed distance from the inner/outer clips.
+        float d0 = distance_to_ellipse(p, vOuterRadii);
+        float d1 = distance_to_ellipse(p, vInnerRadii);
 
         // Signed distance field subtract
         float d = max(d0, 0.5 * afwidth - d1);
 
         // Only apply AA to fragments outside the signed distance field.
         alpha = min(alpha, 1.0 - smoothstep(0.0, afwidth, d));
     }
 
--- a/gfx/webrender/res/ps_border_corner.vs.glsl
+++ b/gfx/webrender/res/ps_border_corner.vs.glsl
@@ -1,31 +1,33 @@
 #line 1
 /* 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/. */
 
 void set_radii(vec2 border_radius,
-               vec2 border_width,
-               vec2 outer_corner,
-               vec2 gradient_sign) {
+               vec2 border_width) {
     if (border_radius.x > 0.0 && border_radius.y > 0.0) {
         // Set inner/outer radius on valid border radius.
         vOuterRadii = border_radius;
     } else {
         // No border radius - ensure clip has no effect.
         vOuterRadii = vec2(2.0 * border_width);
     }
 
-    if (border_radius.x > border_width.x && border_radius.y > border_width.y) {
-        vInnerRadii = max(vec2(0.0), border_radius - border_width);
+    if (all(greaterThan(border_radius, border_width))) {
+        vInnerRadii = border_radius - border_width;
     } else {
         vInnerRadii = vec2(0.0);
     }
+}
 
+void set_edge_line(vec2 border_width,
+                   vec2 outer_corner,
+                   vec2 gradient_sign) {
     vec2 gradient = border_width * gradient_sign;
     vColorEdgeLine = vec4(outer_corner, vec2(-gradient.y, gradient.x));
 }
 
 void main(void) {
     Primitive prim = load_primitive();
     Border border = fetch_border(prim.prim_index);
     int sub_part = prim.sub_index;
@@ -36,60 +38,64 @@ void main(void) {
         case 0: {
             segment_rect.p0 = corners.tl_outer;
             segment_rect.size = corners.tl_inner - corners.tl_outer;
             vColor0 = border.colors[0];
             vColor1 = border.colors[1];
             vClipCenter = corners.tl_outer + border.radii[0].xy;
             vClipSign = vec2(1.0);
             set_radii(border.radii[0].xy,
-                      border.widths.xy,
-                      corners.tl_outer,
-                      vec2(1.0, 1.0));
+                      border.widths.xy);
+            set_edge_line(border.widths.xy,
+                          corners.tl_outer,
+                          vec2(1.0, 1.0));
             break;
         }
         case 1: {
             segment_rect.p0 = vec2(corners.tr_inner.x, corners.tr_outer.y);
             segment_rect.size = vec2(corners.tr_outer.x - corners.tr_inner.x,
                                      corners.tr_inner.y - corners.tr_outer.y);
             vColor0 = border.colors[1];
             vColor1 = border.colors[2];
             vClipCenter = corners.tr_outer + vec2(-border.radii[0].z, border.radii[0].w);
             vClipSign = vec2(-1.0, 1.0);
             set_radii(border.radii[0].zw,
-                      border.widths.zy,
-                      corners.tr_outer,
-                      vec2(-1.0, 1.0));
+                      border.widths.zy);
+            set_edge_line(border.widths.zy,
+                          corners.tr_outer,
+                          vec2(-1.0, 1.0));
             break;
         }
         case 2: {
             segment_rect.p0 = corners.br_inner;
             segment_rect.size = corners.br_outer - corners.br_inner;
             vColor0 = border.colors[2];
             vColor1 = border.colors[3];
             vClipCenter = corners.br_outer - border.radii[1].xy;
             vClipSign = vec2(-1.0, -1.0);
             set_radii(border.radii[1].xy,
-                      border.widths.zw,
-                      corners.br_outer,
-                      vec2(-1.0, -1.0));
+                      border.widths.zw);
+            set_edge_line(border.widths.zw,
+                          corners.br_outer,
+                          vec2(-1.0, -1.0));
             break;
         }
         case 3: {
             segment_rect.p0 = vec2(corners.bl_outer.x, corners.bl_inner.y);
             segment_rect.size = vec2(corners.bl_inner.x - corners.bl_outer.x,
                                      corners.bl_outer.y - corners.bl_inner.y);
             vColor0 = border.colors[3];
             vColor1 = border.colors[0];
             vClipCenter = corners.bl_outer + vec2(border.radii[1].z, -border.radii[1].w);
             vClipSign = vec2(1.0, -1.0);
             set_radii(border.radii[1].zw,
-                      border.widths.xw,
-                      corners.bl_outer,
-                      vec2(1.0, -1.0));
+                      border.widths.xw);
+            set_edge_line(border.widths.xw,
+                          corners.bl_outer,
+                          vec2(1.0, -1.0));
             break;
         }
     }
 
 #ifdef WR_FEATURE_TRANSFORM
     TransformVertexInfo vi = write_transform_vertex(segment_rect,
                                                     prim.local_clip_rect,
                                                     prim.z,
--- a/gfx/webrender/res/shared.glsl
+++ b/gfx/webrender/res/shared.glsl
@@ -38,17 +38,16 @@ uniform sampler2D sColor0;
 uniform sampler2D sColor1;
 uniform sampler2D sColor2;
 #else
 uniform sampler2DRect sColor0;
 uniform sampler2DRect sColor1;
 uniform sampler2DRect sColor2;
 #endif
 uniform sampler2D sDither;
-uniform sampler2D sMask;
 
 //======================================================================================
 // Interpolator definitions
 //======================================================================================
 
 //======================================================================================
 // VS only types and UBOs
 //======================================================================================
--- a/gfx/webrender/src/clip_scroll_node.rs
+++ b/gfx/webrender/src/clip_scroll_node.rs
@@ -4,21 +4,21 @@
 
 use euclid::Point3D;
 use geometry::ray_intersects_rect;
 use mask_cache::{ClipSource, MaskCacheInfo, RegionMode};
 use prim_store::GpuBlock32;
 use renderer::VertexDataStore;
 use spring::{DAMPING, STIFFNESS, Spring};
 use tiling::PackedLayerIndex;
-use util::TransformedRect;
+use util::TransformedRectKind;
 use webrender_traits::{ClipId, ClipRegion, LayerPixel, LayerPoint, LayerRect, LayerSize};
 use webrender_traits::{LayerToScrollTransform, LayerToWorldTransform, PipelineId};
 use webrender_traits::{ScrollEventPhase, ScrollLayerRect, ScrollLocation, WorldPoint};
-use webrender_traits::WorldPoint4D;
+use webrender_traits::{DeviceIntRect, WorldPoint4D};
 
 #[cfg(target_os = "macos")]
 const CAN_OVERSCROLL: bool = true;
 
 #[cfg(not(target_os = "macos"))]
 const CAN_OVERSCROLL: bool = false;
 
 #[derive(Clone, Debug)]
@@ -32,32 +32,32 @@ pub struct ClipInfo {
 
     /// The packed layer index for this node, which is used to render a clip mask
     /// for it, if necessary.
     pub packed_layer_index: PackedLayerIndex,
 
     /// The final transformed rectangle of this clipping region for this node,
     /// which depends on the screen rectangle and the transformation of all of
     /// the parents.
-    pub xf_rect: Option<TransformedRect>,
+    pub screen_bounding_rect: Option<(TransformedRectKind, DeviceIntRect)>,
 }
 
 impl ClipInfo {
     pub fn new(clip_region: &ClipRegion,
                clip_store: &mut VertexDataStore<GpuBlock32>,
                packed_layer_index: PackedLayerIndex,)
                -> ClipInfo {
         // We pass true here for the MaskCacheInfo because this type of
         // mask needs an extra clip for the clip rectangle.
         let clip_sources = vec![ClipSource::Region(clip_region.clone(), RegionMode::IncludeRect)];
         ClipInfo {
             mask_cache_info: MaskCacheInfo::new(&clip_sources, clip_store),
             clip_sources: clip_sources,
             packed_layer_index: packed_layer_index,
-            xf_rect: None,
+            screen_bounding_rect: None,
         }
     }
 
     pub fn is_masking(&self) -> bool {
         match self.mask_cache_info {
             Some(ref info) => info.is_masking(),
             _ => false,
         }
--- a/gfx/webrender/src/device.rs
+++ b/gfx/webrender/src/device.rs
@@ -47,24 +47,26 @@ pub enum DepthFunction {
     Less = gl::LESS,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum TextureTarget {
     Default,
     Array,
     Rect,
+    External,
 }
 
 impl TextureTarget {
     pub fn to_gl_target(&self) -> gl::GLuint {
         match *self {
             TextureTarget::Default => gl::TEXTURE_2D,
             TextureTarget::Array => gl::TEXTURE_2D_ARRAY,
             TextureTarget::Rect => gl::TEXTURE_RECTANGLE,
+            TextureTarget::External => gl::TEXTURE_EXTERNAL_OES,
         }
     }
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum TextureFilter {
     Nearest,
     Linear,
@@ -1552,21 +1554,16 @@ impl Device {
         let u_color_2 = self.gl.get_uniform_location(program.id, "sColor2");
         if u_color_2 != -1 {
             self.gl.uniform_1i(u_color_2, TextureSampler::Color2 as i32);
         }
         let u_noise = self.gl.get_uniform_location(program.id, "sDither");
         if u_noise != -1 {
             self.gl.uniform_1i(u_noise, TextureSampler::Dither as i32);
         }
-        let u_mask = self.gl.get_uniform_location(program.id, "sMask");
-        if u_mask != -1 {
-            self.gl.uniform_1i(u_mask, TextureSampler::Mask as i32);
-        }
-
         let u_cache_a8 = self.gl.get_uniform_location(program.id, "sCacheA8");
         if u_cache_a8 != -1 {
             self.gl.uniform_1i(u_cache_a8, TextureSampler::CacheA8 as i32);
         }
         let u_cache_rgba8 = self.gl.get_uniform_location(program.id, "sCacheRGBA8");
         if u_cache_rgba8 != -1 {
             self.gl.uniform_1i(u_cache_rgba8, TextureSampler::CacheRGBA8 as i32);
         }
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -197,17 +197,17 @@ impl FrameBuilder {
                                     -> ClipScrollGroupIndex {
         let packed_layer_index = PackedLayerIndex(self.packed_layers.len());
         self.packed_layers.push(PackedLayer::empty());
 
         self.clip_scroll_group_store.push(ClipScrollGroup {
             stacking_context_index: stacking_context_index,
             clip_id: clip_id,
             packed_layer_index: packed_layer_index,
-            xf_rect: None,
+            screen_bounding_rect: None,
          });
 
         ClipScrollGroupIndex(self.clip_scroll_group_store.len() - 1, clip_id)
     }
 
     pub fn push_stacking_context(&mut self,
                                  reference_frame_offset: &LayerPoint,
                                  pipeline_id: PipelineId,
@@ -1173,17 +1173,17 @@ impl FrameBuilder {
 
                     if !stacking_context.is_visible {
                         continue;
                     }
 
                     let stacking_context_index = *sc_stack.last().unwrap();
                     let group_index = self.stacking_context_store[stacking_context_index.0]
                                           .clip_scroll_group(clip_id);
-                    if self.clip_scroll_group_store[group_index.0].xf_rect.is_none() {
+                    if self.clip_scroll_group_store[group_index.0].screen_bounding_rect.is_none() {
                         continue
                     }
 
                     for i in 0..prim_count {
                         let prim_index = PrimitiveIndex(first_prim_index.0 + i);
 
                         if self.prim_store.cpu_bounding_rects[prim_index.0].is_some() {
                             let prim_metadata = self.prim_store.get_metadata(prim_index);
@@ -1397,19 +1397,19 @@ impl<'a> LayerRectCalculationAndCullingP
                                                 0.0);
             packed_layer.set_transform(transform);
 
             // Meanwhile, the combined viewport rect is relative to the reference frame, so
             // we move it into the local coordinate system of the node.
             let local_viewport_rect =
                 node.combined_local_viewport_rect.translate(&-node.local_viewport_rect.origin);
 
-            node_clip_info.xf_rect = packed_layer.set_rect(&local_viewport_rect,
-                                                           self.screen_rect,
-                                                           self.device_pixel_ratio);
+            node_clip_info.screen_bounding_rect = packed_layer.set_rect(&local_viewport_rect,
+                                                                        self.screen_rect,
+                                                                        self.device_pixel_ratio);
 
             let mask_info = match node_clip_info.mask_cache_info {
                 Some(ref mut mask_info) => mask_info,
                 _ => continue,
             };
 
             let auxiliary_lists = self.auxiliary_lists_map.get(&node.pipeline_id)
                                                           .expect("No auxiliary lists?");
@@ -1452,19 +1452,19 @@ impl<'a> LayerRectCalculationAndCullingP
             }
 
             // Here we move the viewport rectangle into the coordinate system
             // of the stacking context content.
             let viewport_rect =
                 &node.combined_local_viewport_rect
                      .translate(&-stacking_context.reference_frame_offset)
                      .translate(&-node.scrolling.offset);
-            group.xf_rect = packed_layer.set_rect(viewport_rect,
-                                                  self.screen_rect,
-                                                  self.device_pixel_ratio);
+            group.screen_bounding_rect = packed_layer.set_rect(viewport_rect,
+                                                               self.screen_rect,
+                                                               self.device_pixel_ratio);
         }
     }
 
     fn compute_stacking_context_visibility(&mut self) {
         for context_index in 0..self.frame_builder.stacking_context_store.len() {
             let is_visible = {
                 // We don't take into account visibility of children here, so we must
                 // do that later.
@@ -1530,19 +1530,20 @@ impl<'a> LayerRectCalculationAndCullingP
             current_id = node.parent;
 
             let clip_info = match node.node_type {
                 NodeType::Clip(ref clip) if clip.is_masking() => clip,
                 _ => continue,
             };
 
             if bounding_rect.is_none() {
-                bounding_rect =
-                    Some(clip_info.xf_rect.as_ref().map_or_else(DeviceIntRect::zero,
-                                                                |x| x.bounding_rect))
+                bounding_rect = Some(match clip_info.screen_bounding_rect {
+                    Some((_kind, rect)) => rect,
+                    None => DeviceIntRect::zero(),
+                });
             }
             self.current_clip_stack.push((clip_info.packed_layer_index,
                                           clip_info.mask_cache_info.clone().unwrap()))
         }
         self.current_clip_stack.reverse();
 
         self.current_clip_info = Some((id, bounding_rect));
         bounding_rect
--- a/gfx/webrender/src/internal_types.rs
+++ b/gfx/webrender/src/internal_types.rs
@@ -51,26 +51,25 @@ const COLOR_FLOAT_TO_FIXED: f32 = 255.0;
 const COLOR_FLOAT_TO_FIXED_WIDE: f32 = 65535.0;
 pub const ANGLE_FLOAT_TO_FIXED: f32 = 65535.0;
 
 pub const ORTHO_NEAR_PLANE: f32 = -1000000.0;
 pub const ORTHO_FAR_PLANE: f32 = 1000000.0;
 
 #[derive(Clone)]
 pub enum FontTemplate {
-    Raw(Arc<Vec<u8>>),
+    Raw(Arc<Vec<u8>>, u32),
     Native(NativeFontHandle),
 }
 
 #[derive(Debug, PartialEq, Eq)]
 pub enum TextureSampler {
     Color0,
     Color1,
     Color2,
-    Mask,
     CacheA8,
     CacheRGBA8,
     Data16,
     Data32,
     Data64,
     Data128,
     Layers,
     RenderTasks,
@@ -279,30 +278,29 @@ pub enum TextureUpdateOp {
         height: u32,
         data: Arc<Vec<u8>>,
         stride: Option<u32>,
         offset: u32,
     },
     UpdateForExternalBuffer {
         rect: DeviceUintRect,
         id: ExternalImageId,
+        channel_index: u8,
         stride: Option<u32>,
     },
     Grow {
         width: u32,
         height: u32,
         format: ImageFormat,
         filter: TextureFilter,
         mode: RenderTargetMode,
     },
     Free,
 }
 
-pub type ExternalImageUpdateList = Vec<ExternalImageId>;
-
 pub struct TextureUpdate {
     pub id: CacheTextureId,
     pub op: TextureUpdateOp,
 }
 
 pub struct TextureUpdateList {
     pub updates: Vec<TextureUpdate>,
 }
@@ -342,17 +340,17 @@ impl RendererFrame {
             layers_bouncing_back: layers_bouncing_back,
             frame: frame,
         }
     }
 }
 
 pub enum ResultMsg {
     RefreshShader(PathBuf),
-    NewFrame(RendererFrame, TextureUpdateList, ExternalImageUpdateList, BackendProfileCounters),
+    NewFrame(RendererFrame, TextureUpdateList, BackendProfileCounters),
 }
 
 #[repr(u32)]
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum AxisDirection {
     Horizontal,
     Vertical,
 }
--- a/gfx/webrender/src/platform/macos/font.rs
+++ b/gfx/webrender/src/platform/macos/font.rs
@@ -12,16 +12,17 @@ use core_graphics::font::{CGFont, CGGlyp
 use core_graphics::geometry::{CGPoint, CGSize, CGRect};
 use core_text::font::CTFont;
 use core_text::font_descriptor::kCTFontDefaultOrientation;
 use core_text;
 use std::collections::HashMap;
 use std::collections::hash_map::Entry;
 use webrender_traits::{ColorU, FontKey, FontRenderMode, GlyphDimensions};
 use webrender_traits::{GlyphKey, GlyphOptions, SubpixelPoint};
+use webrender_traits::NativeFontHandle;
 use gamma_lut::{GammaLut, Color as ColorLut};
 
 pub struct FontContext {
     cg_fonts: HashMap<FontKey, CGFont>,
     ct_fonts: HashMap<(FontKey, Au), CTFont>,
     gamma_lut: GammaLut,
 }
 
@@ -121,35 +122,36 @@ impl FontContext {
 
         FontContext {
             cg_fonts: HashMap::new(),
             ct_fonts: HashMap::new(),
             gamma_lut: GammaLut::new(contrast, gamma, gamma),
         }
     }
 
-    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
+    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
         if self.cg_fonts.contains_key(font_key) {
             return
         }
 
+        assert_eq!(index, 0);
         let data_provider = CGDataProvider::from_buffer(bytes);
         let cg_font = match CGFont::from_data_provider(data_provider) {
             Err(_) => return,
             Ok(cg_font) => cg_font,
         };
         self.cg_fonts.insert((*font_key).clone(), cg_font);
     }
 
-    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: CGFont) {
+    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: NativeFontHandle) {
         if self.cg_fonts.contains_key(font_key) {
             return
         }
 
-        self.cg_fonts.insert((*font_key).clone(), native_font_handle);
+        self.cg_fonts.insert((*font_key).clone(), native_font_handle.0);
     }
 
     pub fn delete_font(&mut self, font_key: &FontKey) {
         if let Some(_) = self.cg_fonts.remove(font_key) {
             // Unstable Rust has a retain() method on HashMap that will
             // let us do this in-place. https://github.com/rust-lang/rust/issues/36648
             let ct_font_keys = self.ct_fonts.keys()
                                             .filter(|k| k.0 == *font_key)
--- a/gfx/webrender/src/platform/unix/font.rs
+++ b/gfx/webrender/src/platform/unix/font.rs
@@ -56,25 +56,24 @@ impl FontContext {
         }
 
         FontContext {
             lib: lib,
             faces: HashMap::new(),
         }
     }
 
-    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
+    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
         if !self.faces.contains_key(&font_key) {
             let mut face: FT_Face = ptr::null_mut();
-            let face_index = 0 as FT_Long;
             let result = unsafe {
                 FT_New_Memory_Face(self.lib,
                                    bytes.as_ptr(),
                                    bytes.len() as FT_Long,
-                                   face_index,
+                                   index as FT_Long,
                                    &mut face)
             };
             if result.succeeded() && !face.is_null() {
                 self.faces.insert(*font_key, Face {
                     face: face,
                     //_bytes: bytes
                 });
             } else {
--- a/gfx/webrender/src/platform/windows/font.rs
+++ b/gfx/webrender/src/platform/windows/font.rs
@@ -112,23 +112,23 @@ impl FontContext {
         let gdi_gamma = 2.3;
         FontContext {
             fonts: HashMap::new(),
             gamma_lut: GammaLut::new(contrast, gamma, gamma),
             gdi_gamma_lut: GammaLut::new(contrast, gdi_gamma, gdi_gamma),
         }
     }
 
-    pub fn add_raw_font(&mut self, font_key: &FontKey, data: &[u8]) {
+    pub fn add_raw_font(&mut self, font_key: &FontKey, data: &[u8], index: u32) {
         if self.fonts.contains_key(font_key) {
             return
         }
 
         if let Some(font_file) = dwrote::FontFile::new_from_data(data) {
-            let face = font_file.create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
+            let face = font_file.create_face(index, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
             self.fonts.insert((*font_key).clone(), face);
         } else {
             // XXX add_raw_font needs to have a way to return an error
             debug!("DWrite WR failed to load font from data, using Arial instead");
             self.add_native_font(font_key, DEFAULT_FONT_DESCRIPTOR.clone());
         }
     }
 
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.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/. */
 
 use app_units::Au;
-use euclid::{Point2D, Size2D};
+use euclid::{Size2D};
 use gpu_store::GpuStoreAddress;
 use internal_types::{SourceTexture, PackedTexel};
 use mask_cache::{ClipMode, ClipSource, MaskCacheInfo};
 use renderer::{VertexDataStore, GradientDataStore};
 use render_task::{RenderTask, RenderTaskLocation};
 use resource_cache::{CacheItem, ImageProperties, ResourceCache};
 use std::mem;
 use std::usize;
 use util::TransformedRect;
 use webrender_traits::{AuxiliaryLists, ColorF, ImageKey, ImageRendering, YuvColorSpace};
 use webrender_traits::{ClipRegion, ComplexClipRegion, ItemRange, GlyphKey};
 use webrender_traits::{FontKey, FontRenderMode, WebGLContextId};
 use webrender_traits::{device_length, DeviceIntRect, DeviceIntSize};
 use webrender_traits::{DeviceRect, DevicePoint, DeviceSize};
-use webrender_traits::{LayerRect, LayerSize, LayerPoint};
+use webrender_traits::{LayerRect, LayerSize, LayerPoint, LayoutPoint};
 use webrender_traits::{LayerToWorldTransform, GlyphInstance, GlyphOptions};
 use webrender_traits::{ExtendMode, GradientStop, TileOffset};
 
 pub const CLIP_DATA_GPU_SIZE: usize = 5;
 pub const MASK_DATA_GPU_SIZE: usize = 1;
 
 /// Stores two coordinates in texel space. The coordinates
 /// are stored in texel coordinates because the texture atlas
@@ -1157,17 +1157,17 @@ impl PrimitiveStore {
 
                         dest_glyphs[actual_glyph_count] = GpuBlock16::from(GlyphPrimitive {
                             padding: LayerPoint::zero(),
                             offset: local_glyph_rect.origin,
                         });
 
                         text.glyph_instances.push(GlyphInstance {
                             index: src.index,
-                            point: Point2D::new(src.point.x, src.point.y),
+                            point: LayoutPoint::new(src.point.x, src.point.y),
                         });
 
                         actual_glyph_count += 1;
                     }
 
                     // Expand the rectangle of the text run by the blur radius.
                     let local_rect = local_rect.inflate(text.blur_radius.to_f32_px(),
                                                         text.blur_radius.to_f32_px());
@@ -1277,183 +1277,57 @@ impl PrimitiveStore {
         if prim_needs_resolve {
             self.prims_to_resolve.push(prim_index);
         }
 
         rebuild_bounding_rect
     }
 }
 
-#[derive(Clone)]
-#[repr(C)]
-pub struct GpuBlock16 {
-    data: [f32; 4],
-}
 
-impl Default for GpuBlock16 {
-    fn default() -> GpuBlock16 {
-        GpuBlock16 {
-            data: unsafe { mem::uninitialized() }
-        }
-    }
-}
-
-impl From<TextRunPrimitiveGpu> for GpuBlock16 {
-    fn from(data: TextRunPrimitiveGpu) -> GpuBlock16 {
-        unsafe {
-            mem::transmute::<TextRunPrimitiveGpu, GpuBlock16>(data)
+macro_rules! define_gpu_block {
+    ($name:ident: $ty:ty = $($derive:ident),* ) => (
+        #[derive(Clone)]
+        #[repr(C)]
+        pub struct $name {
+            data: $ty,
         }
-    }
-}
-
-impl From<RectanglePrimitive> for GpuBlock16 {
-    fn from(data: RectanglePrimitive) -> GpuBlock16 {
-        unsafe {
-            mem::transmute::<RectanglePrimitive, GpuBlock16>(data)
-        }
-    }
-}
-
-impl From<InstanceRect> for GpuBlock16 {
-    fn from(data: InstanceRect) -> GpuBlock16 {
-        unsafe {
-            mem::transmute::<InstanceRect, GpuBlock16>(data)
-        }
-    }
-}
 
-impl From<ImagePrimitiveGpu> for GpuBlock16 {
-    fn from(data: ImagePrimitiveGpu) -> GpuBlock16 {
-        unsafe {
-            mem::transmute::<ImagePrimitiveGpu, GpuBlock16>(data)
+        impl Default for $name {
+            fn default() -> $name {
+                $name {
+                    data: unsafe { mem::uninitialized() }
+                }
+            }
         }
-    }
-}
-
-impl From<GlyphPrimitive> for GpuBlock16 {
-    fn from(data: GlyphPrimitive) -> GpuBlock16 {
-        unsafe {
-            mem::transmute::<GlyphPrimitive, GpuBlock16>(data)
-        }
-    }
-}
-
-#[derive(Clone)]
-#[repr(C)]
-pub struct GpuBlock32 {
-    data: [f32; 8],
-}
 
-impl Default for GpuBlock32 {
-    fn default() -> GpuBlock32 {
-        GpuBlock32 {
-            data: unsafe { mem::uninitialized() }
-        }
-    }
-}
-
-impl From<GradientStopGpu> for GpuBlock32 {
-    fn from(data: GradientStopGpu) -> GpuBlock32 {
-        unsafe {
-            mem::transmute::<GradientStopGpu, GpuBlock32>(data)
-        }
-    }
-}
-
-impl From<YuvImagePrimitiveGpu> for GpuBlock16 {
-    fn from(data: YuvImagePrimitiveGpu) -> GpuBlock16 {
-        unsafe {
-            mem::transmute::<YuvImagePrimitiveGpu, GpuBlock16>(data)
-        }
-    }
+        $(
+            impl From<$derive> for $name {
+                fn from(data: $derive) -> $name {
+                    unsafe { mem::transmute(data) }
+                }
+            }
+        )*
+    )
 }
 
-impl From<ClipRect> for GpuBlock32 {
-    fn from(data: ClipRect) -> GpuBlock32 {
-        unsafe {
-            mem::transmute::<ClipRect, GpuBlock32>(data)
-        }
-    }
-}
-
-impl From<ImageMaskData> for GpuBlock32 {
-    fn from(data: ImageMaskData) -> GpuBlock32 {
-        unsafe {
-            mem::transmute::<ImageMaskData, GpuBlock32>(data)
-        }
-    }
-}
-
-impl From<ClipCorner> for GpuBlock32 {
-    fn from(data: ClipCorner) -> GpuBlock32 {
-        unsafe {
-            mem::transmute::<ClipCorner, GpuBlock32>(data)
-        }
-    }
-}
-
-#[derive(Clone)]
-#[repr(C)]
-pub struct GpuBlock64 {
-    data: [f32; 16],
-}
-
-impl Default for GpuBlock64 {
-    fn default() -> GpuBlock64 {
-        GpuBlock64 {
-            data: unsafe { mem::uninitialized() }
-        }
-    }
-}
+define_gpu_block!(GpuBlock16: [f32; 4] =
+    RectanglePrimitive, InstanceRect, GlyphPrimitive,
+    TextRunPrimitiveGpu, ImagePrimitiveGpu, YuvImagePrimitiveGpu
+);
+define_gpu_block!(GpuBlock32: [f32; 8] =
+    GradientStopGpu, ClipCorner, ClipRect, ImageMaskData
+);
+define_gpu_block!(GpuBlock64: [f32; 16] =
+    GradientPrimitiveGpu, RadialGradientPrimitiveGpu, BoxShadowPrimitiveGpu
+);
+define_gpu_block!(GpuBlock128: [f32; 32] =
+    BorderPrimitiveGpu
+);
 
-impl From<GradientPrimitiveGpu> for GpuBlock64 {
-    fn from(data: GradientPrimitiveGpu) -> GpuBlock64 {
-        unsafe {
-            mem::transmute::<GradientPrimitiveGpu, GpuBlock64>(data)
-        }
-    }
-}
-
-impl From<RadialGradientPrimitiveGpu> for GpuBlock64 {
-    fn from(data: RadialGradientPrimitiveGpu) -> GpuBlock64 {
-        unsafe {
-            mem::transmute::<RadialGradientPrimitiveGpu, GpuBlock64>(data)
-        }
-    }
-}
-
-impl From<BoxShadowPrimitiveGpu> for GpuBlock64 {
-    fn from(data: BoxShadowPrimitiveGpu) -> GpuBlock64 {
-        unsafe {
-            mem::transmute::<BoxShadowPrimitiveGpu, GpuBlock64>(data)
-        }
-    }
-}
-
-#[derive(Clone)]
-#[repr(C)]
-pub struct GpuBlock128 {
-    data: [f32; 32],
-}
-
-impl Default for GpuBlock128 {
-    fn default() -> GpuBlock128 {
-        GpuBlock128 {
-            data: unsafe { mem::uninitialized() }
-        }
-    }
-}
-
-impl From<BorderPrimitiveGpu> for GpuBlock128 {
-    fn from(data: BorderPrimitiveGpu) -> GpuBlock128 {
-        unsafe {
-            mem::transmute::<BorderPrimitiveGpu, GpuBlock128>(data)
-        }
-    }
-}
 
 //Test for one clip region contains another
 trait InsideTest<T> {
     fn might_contain(&self, clip: &T) -> bool;
 }
 
 impl InsideTest<ComplexClipRegion> for ComplexClipRegion {
     // Returns true if clip is inside self, can return false negative
--- a/gfx/webrender/src/profiler.rs
+++ b/gfx/webrender/src/profiler.rs
@@ -282,29 +282,68 @@ impl TextureCacheProfileCounters {
             pages_rgba8: ResourceProfileCounter::new("Texture RGBA8 cached pages"),
             pages_rg8: ResourceProfileCounter::new("Texture RG8 cached pages"),
         }
     }
 }
 
 #[derive(Clone)]
 pub struct BackendProfileCounters {
+    pub total_time: TimeProfileCounter,
+    pub resources: ResourceProfileCounters,
+    pub ipc: IpcProfileCounters,
+}
+
+#[derive(Clone)]
+pub struct ResourceProfileCounters {
     pub font_templates: ResourceProfileCounter,
     pub image_templates: ResourceProfileCounter,
+    pub texture_cache: TextureCacheProfileCounters,
+}
+
+#[derive(Clone)]
+pub struct IpcProfileCounters {
+    pub serialize_time: TimeProfileCounter,
+    pub deserialize_time: TimeProfileCounter,
+    pub send_time: TimeProfileCounter,
     pub total_time: TimeProfileCounter,
-    pub texture_cache: TextureCacheProfileCounters,
+    pub display_len: IntProfileCounter,
+    pub aux_len: IntProfileCounter,
+}
+
+impl IpcProfileCounters {
+    pub fn set(&mut self, serial_start: u64, serial_end: u64, 
+                              deserial_start: u64, deserial_end: u64,
+                              display_len: usize, aux_len: usize) {
+        self.serialize_time.set(serial_end - serial_start);
+        self.deserialize_time.set(deserial_end - deserial_start);
+        self.send_time.set(deserial_start - serial_end);
+        self.total_time.set(deserial_end - serial_start);
+        self.display_len.set(display_len);
+        self.aux_len.set(aux_len);
+    }
 }
 
 impl BackendProfileCounters {
     pub fn new() -> BackendProfileCounters {
         BackendProfileCounters {
-            font_templates: ResourceProfileCounter::new("Font Templates"),
-            image_templates: ResourceProfileCounter::new("Image Templates"),
             total_time: TimeProfileCounter::new("Backend CPU Time", false),
-            texture_cache: TextureCacheProfileCounters::new(),
+            resources: ResourceProfileCounters {
+                font_templates: ResourceProfileCounter::new("Font Templates"),
+                image_templates: ResourceProfileCounter::new("Image Templates"),
+                texture_cache: TextureCacheProfileCounters::new(),
+            },
+            ipc: IpcProfileCounters {
+                serialize_time: TimeProfileCounter::new("IPC Serialize Time", false),
+                deserialize_time: TimeProfileCounter::new("IPC Deserialize Time", false),
+                send_time: TimeProfileCounter::new("IPC Send Time", false),
+                total_time: TimeProfileCounter::new("IPC Time", false),
+                display_len: IntProfileCounter::new("IPC Display List Len"),
+                aux_len: IntProfileCounter::new("IPC Aux List Len"),
+            }
         }
     }
 
     pub fn reset(&mut self) {
         self.total_time.reset();
     }
 }
 
@@ -557,29 +596,31 @@ pub struct Profiler {
     x_left: f32,
     y_left: f32,
     x_right: f32,
     y_right: f32,
     backend_time: ProfileGraph,
     compositor_time: ProfileGraph,
     gpu_time: ProfileGraph,
     gpu_frames: GpuFrameCollection,
+    ipc_time: ProfileGraph,
 }
 
 impl Profiler {
     pub fn new() -> Profiler {
         Profiler {
             x_left: 0.0,
             y_left: 0.0,
             x_right: 0.0,
             y_right: 0.0,
             backend_time: ProfileGraph::new(600),
             compositor_time: ProfileGraph::new(600),
             gpu_time: ProfileGraph::new(600),
             gpu_frames: GpuFrameCollection::new(),
+            ipc_time: ProfileGraph::new(600),
         }
     }
 
     fn draw_counters(&mut self,
                      counters: &[&ProfileCounter],
                      debug_renderer: &mut DebugRenderer,
                      left: bool) {
         let mut label_rect = Rect::zero();
@@ -672,48 +713,63 @@ impl Profiler {
             &frame_profile.total_primitives,
             &frame_profile.visible_primitives,
             &frame_profile.passes,
             &frame_profile.color_targets,
             &frame_profile.alpha_targets,
         ], debug_renderer, true);
 
         self.draw_counters(&[
-            &backend_profile.font_templates,
-            &backend_profile.image_templates,
+            &backend_profile.resources.font_templates,
+            &backend_profile.resources.image_templates,
         ], debug_renderer, true);
 
         self.draw_counters(&[
-            &backend_profile.texture_cache.pages_a8,
-            &backend_profile.texture_cache.pages_rgb8,
-            &backend_profile.texture_cache.pages_rgba8,
-            &backend_profile.texture_cache.pages_rg8,
+            &backend_profile.resources.texture_cache.pages_a8,
+            &backend_profile.resources.texture_cache.pages_rgb8,
+            &backend_profile.resources.texture_cache.pages_rgba8,
+            &backend_profile.resources.texture_cache.pages_rg8,
+        ], debug_renderer, true);
+
+        self.draw_counters(&[
+            &backend_profile.ipc.serialize_time,
+            &backend_profile.ipc.send_time,
+            &backend_profile.ipc.deserialize_time,
+            &backend_profile.ipc.total_time,
+            &backend_profile.ipc.display_len,
+            &backend_profile.ipc.aux_len,
         ], debug_renderer, true);
 
         self.draw_counters(&[
             &renderer_profile.draw_calls,
             &renderer_profile.vertices,
         ], debug_renderer, true);
 
         self.draw_counters(&[
             &backend_profile.total_time,
             &renderer_timers.cpu_time,
             &renderer_timers.gpu_time,
         ], debug_renderer, false);
+        
+
 
 
         self.backend_time.push(backend_profile.total_time.nanoseconds);
         self.compositor_time.push(renderer_timers.cpu_time.nanoseconds);
+        self.ipc_time.push(backend_profile.ipc.total_time.nanoseconds);
         self.gpu_time.push(gpu_time);
         self.gpu_frames.push(gpu_time, gpu_samples);
 
+
         let rect = self.backend_time.draw_graph(self.x_left, self.y_left, "CPU (backend)", debug_renderer);
         self.y_left += rect.size.height + PROFILE_PADDING;
         let rect = self.compositor_time.draw_graph(self.x_left, self.y_left, "CPU (compositor)", debug_renderer);
         self.y_left += rect.size.height + PROFILE_PADDING;
+        let rect = self.ipc_time.draw_graph(self.x_left, self.y_left, "DisplayList IPC", debug_renderer);
+        self.y_left += rect.size.height + PROFILE_PADDING;
         let rect = self.gpu_time.draw_graph(self.x_left, self.y_left, "GPU", debug_renderer);
         self.y_left += rect.size.height + PROFILE_PADDING;
         let rect = self.gpu_frames.draw(self.x_left,
                                         self.y_left,
                                         debug_renderer);
         self.y_left += rect.size.height + PROFILE_PADDING;
     }
 }
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -117,20 +117,20 @@ impl RenderBackend {
             let msg = self.api_rx.recv();
             profile_scope!("handle_msg");
             match msg {
                 Ok(msg) => {
                     if let Some(ref mut r) = self.recorder {
                         r.write_msg(frame_counter, &msg);
                     }
                     match msg {
-                        ApiMsg::AddRawFont(id, bytes) => {
-                            profile_counters.font_templates.inc(bytes.len());
+                        ApiMsg::AddRawFont(id, bytes, index) => {
+                            profile_counters.resources.font_templates.inc(bytes.len());
                             self.resource_cache
-                                .add_font_template(id, FontTemplate::Raw(Arc::new(bytes)));
+                                .add_font_template(id, FontTemplate::Raw(Arc::new(bytes), index));
                         }
                         ApiMsg::AddNativeFont(id, native_font_handle) => {
                             self.resource_cache
                                 .add_font_template(id, FontTemplate::Native(native_font_handle));
                         }
                         ApiMsg::DeleteFont(id) => {
                             self.resource_cache.delete_font_template(id);
                         }
@@ -139,17 +139,17 @@ impl RenderBackend {
                             for glyph_key in &glyph_keys {
                                 let glyph_dim = self.resource_cache.get_glyph_dimensions(glyph_key);
                                 glyph_dimensions.push(glyph_dim);
                             };
                             tx.send(glyph_dimensions).unwrap();
                         }
                         ApiMsg::AddImage(id, descriptor, data, tiling) => {
                             if let ImageData::Raw(ref bytes) = data {
-                                profile_counters.image_templates.inc(bytes.len());
+                                profile_counters.resources.image_templates.inc(bytes.len());
                             }
                             self.resource_cache.add_image_template(id, descriptor, data, tiling);
                         }
                         ApiMsg::UpdateImage(id, descriptor, bytes, dirty_rect) => {
                             self.resource_cache.update_image_template(id, descriptor, bytes, dirty_rect);
                         }
                         ApiMsg::DeleteImage(id) => {
                             self.resource_cache.delete_image_template(id);
@@ -207,42 +207,45 @@ impl RenderBackend {
                                                             display_list_descriptor);
                             let auxiliary_lists =
                                 AuxiliaryLists::from_data(auxiliary_data.auxiliary_lists_data,
                                                           auxiliary_lists_descriptor);
 
                             if !preserve_frame_state {
                                 self.discard_frame_state_for_pipeline(pipeline_id);
                             }
+                            
+                            let counters = &mut profile_counters.ipc;
                             profile_counters.total_time.profile(|| {
                                 self.scene.set_display_list(pipeline_id,
                                                             epoch,
                                                             built_display_list,
                                                             background_color,
                                                             viewport_size,
-                                                            auxiliary_lists);
+                                                            auxiliary_lists,
+                                                            counters);
                                 self.build_scene();
-                            })
+                            });
                         }
                         ApiMsg::SetRootPipeline(pipeline_id) => {
                             profile_scope!("SetRootPipeline");
                             self.scene.set_root_pipeline_id(pipeline_id);
 
                             if self.scene.display_lists.get(&pipeline_id).is_none() {
                                 continue;
                             }
 
                             profile_counters.total_time.profile(|| {
                                 self.build_scene();
                             })
                         }
                         ApiMsg::Scroll(delta, cursor, move_phase) => {
                             profile_scope!("Scroll");
                             let frame = {
-                                let counters = &mut profile_counters.texture_cache;
+                                let counters = &mut profile_counters.resources.texture_cache;
                                 profile_counters.total_time.profile(|| {
                                     if self.frame.scroll(delta, cursor, move_phase) {
                                         Some(self.render(counters))
                                     } else {
                                         None
                                     }
                                 })
                             };
@@ -253,17 +256,17 @@ impl RenderBackend {
                                     self.notify_compositor_of_new_scroll_frame(true)
                                 }
                                 None => self.notify_compositor_of_new_scroll_frame(false),
                             }
                         }
                         ApiMsg::ScrollNodeWithId(origin, id) => {
                             profile_scope!("ScrollNodeWithScrollId");
                             let frame = {
-                                let counters = &mut profile_counters.texture_cache;
+                                let counters = &mut profile_counters.resources.texture_cache;
                                 profile_counters.total_time.profile(|| {
                                     if self.frame.scroll_nodes(origin, id) {
                                         Some(self.render(counters))
                                     } else {
                                         None
                                     }
                                 })
                             };
@@ -275,17 +278,17 @@ impl RenderBackend {
                                 }
                                 None => self.notify_compositor_of_new_scroll_frame(false),
                             }
 
                         }
                         ApiMsg::TickScrollingBounce => {
                             profile_scope!("TickScrollingBounce");
                             let frame = {
-                                let counters = &mut profile_counters.texture_cache;
+                                let counters = &mut profile_counters.resources.texture_cache;
                                 profile_counters.total_time.profile(|| {
                                     self.frame.tick_scrolling_bounce_animations();
                                     self.render(counters)
                                 })
                             };
 
                             self.publish_frame_and_notify_compositor(frame, &mut profile_counters);
                         }
@@ -375,17 +378,17 @@ impl RenderBackend {
                             if let Some(property_bindings) = property_bindings {
                                 self.scene.properties.set_properties(property_bindings);
                                 profile_counters.total_time.profile(|| {
                                     self.build_scene();
                                 });
                             }
 
                             let frame = {
-                                let counters = &mut profile_counters.texture_cache;
+                                let counters = &mut profile_counters.resources.texture_cache;
                                 profile_counters.total_time.profile(|| {
                                     self.render(counters)
                                 })
                             };
                             if self.scene.root_pipeline_id.is_some() {
                                 self.publish_frame_and_notify_compositor(frame, &mut profile_counters);
                                 frame_counter += 1;
                             }
@@ -468,18 +471,17 @@ impl RenderBackend {
                                      texture_cache_profile);
         frame
     }
 
     fn publish_frame(&mut self,
                      frame: RendererFrame,
                      profile_counters: &mut BackendProfileCounters) {
         let pending_update = self.resource_cache.pending_updates();
-        let pending_external_image_update = self.resource_cache.pending_external_image_updates();
-        let msg = ResultMsg::NewFrame(frame, pending_update, pending_external_image_update, profile_counters.clone());
+        let msg = ResultMsg::NewFrame(frame, pending_update, profile_counters.clone());
         self.result_tx.send(msg).unwrap();
         profile_counters.reset();
     }
 
     fn publish_frame_and_notify_compositor(&mut self,
                                            frame: RendererFrame,
                                            profile_counters: &mut BackendProfileCounters) {
         self.publish_frame(frame, profile_counters);
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -14,17 +14,17 @@ use debug_render::DebugRenderer;
 use device::{DepthFunction, Device, FrameId, ProgramId, TextureId, VertexFormat, GpuMarker, GpuProfiler};
 use device::{GpuSample, TextureFilter, VAOId, VertexUsageHint, FileWatcherHandler, TextureTarget, ShaderError};
 use euclid::Matrix4D;
 use fnv::FnvHasher;
 use frame_builder::FrameBuilderConfig;
 use gleam::gl;
 use gpu_store::{GpuStore, GpuStoreLayout};
 use internal_types::{CacheTextureId, RendererFrame, ResultMsg, TextureUpdateOp};
-use internal_types::{ExternalImageUpdateList, TextureUpdateList, PackedVertex, RenderTargetMode};
+use internal_types::{TextureUpdateList, PackedVertex, RenderTargetMode};
 use internal_types::{ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE, SourceTexture};
 use internal_types::{BatchTextures, TextureSampler};
 use prim_store::GradientData;
 use profiler::{Profiler, BackendProfileCounters};
 use profiler::{GpuProfileTag, RendererProfileTimers, RendererProfileCounters};
 use record::ApiRecordingReceiver;
 use render_backend::RenderBackend;
 use render_task::RenderTaskData;
@@ -530,17 +530,17 @@ pub struct Renderer {
 
     dither_matrix_texture_id: TextureId,
 
     /// Optional trait object that allows the client
     /// application to provide external buffers for image data.
     external_image_handler: Option<Box<ExternalImageHandler>>,
 
     /// Map of external image IDs to native textures.
-    external_images: HashMap<ExternalImageId, TextureId, BuildHasherDefault<FnvHasher>>,
+    external_images: HashMap<(ExternalImageId, u8), TextureId, BuildHasherDefault<FnvHasher>>,
 
     // Optional trait object that handles WebVR commands.
     // Some WebVR commands such as SubmitFrame must be synced with the WebGL render thread.
     vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>,
 
     /// List of profile results from previous frames. Can be retrieved
     /// via get_frame_profiles().
     cpu_profiles: VecDeque<CpuProfile>,
@@ -800,24 +800,24 @@ impl Renderer {
         ];
 
         // TODO: Ensure that the white texture can never get evicted when the cache supports LRU eviction!
         let white_image_id = texture_cache.new_item_id();
         texture_cache.insert(white_image_id,
                              ImageDescriptor::new(2, 2, ImageFormat::RGBA8, false),
                              TextureFilter::Linear,
                              ImageData::Raw(Arc::new(white_pixels)),
-                             &mut backend_profile_counters.texture_cache);
+                             &mut backend_profile_counters.resources.texture_cache);
 
         let dummy_mask_image_id = texture_cache.new_item_id();
         texture_cache.insert(dummy_mask_image_id,
                              ImageDescriptor::new(2, 2, ImageFormat::A8, false),
                              TextureFilter::Linear,
                              ImageData::Raw(Arc::new(mask_pixels)),
-                             &mut backend_profile_counters.texture_cache);
+                             &mut backend_profile_counters.resources.texture_cache);
 
         let dummy_cache_texture_id = device.create_texture_ids(1, TextureTarget::Array)[0];
         device.init_texture(dummy_cache_texture_id,
                             1,
                             1,
                             ImageFormat::RGBA8,
                             TextureFilter::Linear,
                             RenderTargetMode::LayerRenderTarget(1),
@@ -1032,22 +1032,18 @@ impl Renderer {
     ///
     /// Should be called before `render()`, as texture cache updates are done here.
     pub fn update(&mut self) {
         profile_scope!("update");
 
         // Pull any pending results and return the most recent.
         while let Ok(msg) = self.result_rx.try_recv() {
             match msg {
-                ResultMsg::NewFrame(frame, texture_update_list, external_image_update_list, profile_counters) => {
+                ResultMsg::NewFrame(frame, texture_update_list, profile_counters) => {
                     self.pending_texture_updates.push(texture_update_list);
-
-                    // When a new frame is ready, we could start to update all pending external image requests here.
-                    self.release_external_images(external_image_update_list);
-
                     self.backend_profile_counters = profile_counters;
 
                     // Update the list of available epochs for use during reftests.
                     // This is a workaround for https://github.com/servo/servo/issues/13149.
                     for (pipeline_id, epoch) in &frame.pipeline_epoch_map {
                         self.pipeline_epoch_map.insert(*pipeline_id, *epoch);
                     }
 
@@ -1067,17 +1063,17 @@ impl Renderer {
     // we will add a callback here that is able to ask the caller
     // for the image data.
     fn resolve_source_texture(&mut self, texture_id: &SourceTexture) -> TextureId {
         match *texture_id {
             SourceTexture::Invalid => TextureId::invalid(),
             SourceTexture::WebGL(id) => TextureId::new(id, TextureTarget::Default),
             SourceTexture::External(external_image) => {
                 *self.external_images
-                     .get(&external_image.id)
+                     .get(&(external_image.id, external_image.channel_index))
                      .expect("BUG: External image should be resolved by now!")
             }
             SourceTexture::TextureCache(index) => {
                 self.cache_texture_id_map[index.0]
             }
         }
     }
 
@@ -1225,29 +1221,29 @@ impl Renderer {
                                 }
                                 ImageData::External(ext_image) => {
                                     match ext_image.image_type {
                                         ExternalImageType::ExternalBuffer => {
                                             let handler = self.external_image_handler
                                                               .as_mut()
                                                               .expect("Found external image, but no handler set!");
 
-                                            match handler.lock(ext_image.id).source {
+                                            match handler.lock(ext_image.id, ext_image.channel_index).source {
                                                 ExternalImageSource::RawData(raw) => {
                                                     self.device.init_texture(texture_id,
                                                                              width,
                                                                              height,
                                                                              format,
                                                                              filter,
                                                                              mode,
                                                                              Some(raw));
                                                 }
                                                 _ => panic!("No external buffer found"),
                                             };
-                                            handler.unlock(ext_image.id);
+                                            handler.unlock(ext_image.id, ext_image.channel_index);
                                         }
                                         _ => {
                                             panic!("External texture handle should not use TextureUpdateOp::Create.");
                                         }
                                     }
                                 }
                                 _ => {
                                     panic!("No suitable image buffer for TextureUpdateOp::Create.");
@@ -1275,35 +1271,35 @@ impl Renderer {
                     TextureUpdateOp::Update { page_pos_x, page_pos_y, width, height, data, stride, offset } => {
                         let texture_id = self.cache_texture_id_map[update.id.0];
                         self.device.update_texture(texture_id,
                                                    page_pos_x,
                                                    page_pos_y,
                                                    width, height, stride,
                                                    &data[offset as usize..]);
                     }
-                    TextureUpdateOp::UpdateForExternalBuffer { rect, id, stride } => {
+                    TextureUpdateOp::UpdateForExternalBuffer { rect, id, channel_index, stride } => {
                         let handler = self.external_image_handler
                                           .as_mut()
                                           .expect("Found external image, but no handler set!");
                         let device = &mut self.device;
                         let cached_id = self.cache_texture_id_map[update.id.0];
 
-                        match handler.lock(id).source {
+                        match handler.lock(id, channel_index).source {
                             ExternalImageSource::RawData(data) => {
                                 device.update_texture(cached_id,
                                                       rect.origin.x,
                                                       rect.origin.y,
                                                       rect.size.width,
                                                       rect.size.height,
                                                       stride, data);
                             }
                             _ => panic!("No external buffer found"),
                         };
-                        handler.unlock(id);
+                        handler.unlock(id, channel_index);
                     }
                     TextureUpdateOp::Free => {
                         let texture_id = self.cache_texture_id_map[update.id.0];
                         self.device.deinit_texture(texture_id);
                     }
                 }
             }
         }
@@ -1679,23 +1675,28 @@ impl Renderer {
                                           vao,
                                           shader,
                                           &BatchTextures::no_texture(),
                                           &projection);
             }
             // draw image masks
             for (mask_texture_id, items) in target.clip_batcher.images.iter() {
                 let _gm2 = GpuMarker::new(self.device.rc_gl(), "clip images");
-                let texture_id = self.resolve_source_texture(mask_texture_id);
-                self.device.bind_texture(TextureSampler::Mask, texture_id);
+                let textures = BatchTextures {
+                    colors: [
+                        mask_texture_id.clone(),
+                        SourceTexture::Invalid,
+                        SourceTexture::Invalid,
+                    ]
+                };
                 let shader = self.cs_clip_image.get(&mut self.device).unwrap();
                 self.draw_instanced_batch(items,
                                           vao,
                                           shader,
-                                          &BatchTextures::no_texture(),
+                                          &textures,
                                           &projection);
             }
         }
     }
 
     fn update_deferred_resolves(&mut self, frame: &mut Frame) {
         // The first thing we do is run through any pending deferred
         // resolves, and use a callback to get the UV rect for this
@@ -1706,60 +1707,49 @@ impl Renderer {
                               .as_mut()
                               .expect("Found external image, but no handler set!");
 
             for deferred_resolve in &frame.deferred_resolves {
                 GpuMarker::fire(self.device.gl(), "deferred resolve");
                 let props = &deferred_resolve.image_properties;
                 let ext_image = props.external_image
                                      .expect("BUG: Deferred resolves must be external images!");
-                let image = handler.lock(ext_image.id);
+                let image = handler.lock(ext_image.id, ext_image.channel_index);
                 let texture_target = match ext_image.image_type {
                     ExternalImageType::Texture2DHandle => TextureTarget::Default,
                     ExternalImageType::TextureRectHandle => TextureTarget::Rect,
+                    ExternalImageType::TextureExternalHandle => TextureTarget::External,
                     _ => {
                         panic!("{:?} is not a suitable image type in update_deferred_resolves().",
                             ext_image.image_type);
                     }
                 };
 
                 let texture_id = match image.source {
                     ExternalImageSource::NativeTexture(texture_id) => TextureId::new(texture_id, texture_target),
                     _ => panic!("No native texture found."),
                 };
 
-                self.external_images.insert(ext_image.id, texture_id);
+                self.external_images.insert((ext_image.id, ext_image.channel_index), texture_id);
                 let resource_rect_index = deferred_resolve.resource_address.0 as usize;
                 let resource_rect = &mut frame.gpu_resource_rects[resource_rect_index];
                 resource_rect.uv0 = DevicePoint::new(image.u0, image.v0);
                 resource_rect.uv1 = DevicePoint::new(image.u1, image.v1);
             }
         }
     }
 
     fn unlock_external_images(&mut self) {
         if !self.external_images.is_empty() {
             let handler = self.external_image_handler
                               .as_mut()
                               .expect("Found external image, but no handler set!");
 
-            for (external_id, _) in self.external_images.drain() {
-                handler.unlock(external_id);
-            }
-        }
-    }
-
-    fn release_external_images(&mut self, mut pending_external_image_updates: ExternalImageUpdateList) {
-        if !pending_external_image_updates.is_empty() {
-            let handler = self.external_image_handler
-                              .as_mut()
-                              .expect("found external image updates, but no handler set!");
-
-            for external_id in pending_external_image_updates.drain(..) {
-                handler.release(external_id);
+            for (ext_data, _) in self.external_images.drain() {
+                handler.unlock(ext_data.0, ext_data.1);
             }
         }
     }
 
     fn draw_tile_frame(&mut self,
                        frame: &mut Frame,
                        framebuffer_size: &DeviceUintSize) {
         let _gm = GpuMarker::new(self.device.rc_gl(), "tile frame draw");
@@ -1991,27 +1981,27 @@ pub struct ExternalImage<'a> {
     pub u1: f32,
     pub v1: f32,
     pub source: ExternalImageSource<'a>,
 }
 
 /// The interfaces that an application can implement to support providing
 /// external image buffers.
 /// When the the application passes an external image to WR, it should kepp that
-/// external image life time untile the release() call.
+/// external image life time. People could check the epoch id in RenderNotifier
+/// at the client side to make sure that the external image is not used by WR.
+/// Then, do the clean up for that external image.
 pub trait ExternalImageHandler {
     /// Lock the external image. Then, WR could start to read the image content.
     /// The WR client should not change the image content until the unlock()
     /// call.
-    fn lock(&mut self, key: ExternalImageId) -> ExternalImage;
+    fn lock(&mut self, key: ExternalImageId, channel_index: u8) -> ExternalImage;
     /// Unlock the external image. The WR should not read the image content
     /// after this call.
-    fn unlock(&mut self, key: ExternalImageId);
-    /// Tell the WR client that it could start to release this external image.
-    fn release(&mut self, key: ExternalImageId);
+    fn unlock(&mut self, key: ExternalImageId, channel_index: u8);
 }
 
 pub struct RendererOptions {
     pub device_pixel_ratio: f32,
     pub resource_override_path: Option<PathBuf>,
     pub enable_aa: bool,
     pub enable_profiler: bool,
     pub max_recorded_profiles: usize,
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.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 app_units::Au;
 use device::TextureFilter;
 use fnv::FnvHasher;
 use frame::FrameId;
-use internal_types::{ExternalImageUpdateList, FontTemplate, SourceTexture, TextureUpdateList};
+use internal_types::{FontTemplate, SourceTexture, TextureUpdateList};
 use platform::font::{FontContext, RasterizedGlyph};
 use profiler::TextureCacheProfileCounters;
 use std::cell::RefCell;
 use std::collections::{HashMap, HashSet};
 use std::collections::hash_map::Entry::{self, Occupied, Vacant};
 use std::fmt::Debug;
 use std::hash::BuildHasherDefault;
 use std::hash::Hash;
@@ -21,17 +21,17 @@ use std::sync::mpsc::{channel, Receiver,
 use std::thread;
 use texture_cache::{TextureCache, TextureCacheItemId};
 use thread_profiler::register_thread_with_profiler;
 use webrender_traits::{Epoch, FontKey, GlyphKey, ImageKey, ImageFormat, ImageRendering};
 use webrender_traits::{FontRenderMode, ImageData, GlyphDimensions, WebGLContextId};
 use webrender_traits::{DevicePoint, DeviceIntSize, DeviceUintRect, ImageDescriptor, ColorF};
 use webrender_traits::{GlyphOptions, GlyphInstance, TileOffset, TileSize};
 use webrender_traits::{BlobImageRenderer, BlobImageDescriptor, BlobImageError};
-use webrender_traits::{ExternalImageData, ExternalImageType};
+use webrender_traits::{ExternalImageData, ExternalImageType, LayoutPoint};
 use threadpool::ThreadPool;
 use euclid::Point2D;
 
 const DEFAULT_TILE_SIZE: TileSize = 512;
 
 thread_local!(pub static FONT_CONTEXT: RefCell<FontContext> = RefCell::new(FontContext::new()));
 
 type GlyphCache = ResourceClassCache<RenderedGlyphKey, Option<TextureCacheItemId>>;
@@ -78,17 +78,17 @@ pub struct RenderedGlyphKey {
     pub glyph_options: Option<GlyphOptions>,
 }
 
 impl RenderedGlyphKey {
     pub fn new(font_key: FontKey,
                size: Au,
                color: ColorF,
                index: u32,
-               point: Point2D<f32>,
+               point: LayoutPoint,
                render_mode: FontRenderMode,
                glyph_options: Option<GlyphOptions>) -> RenderedGlyphKey {
         RenderedGlyphKey {
             key: GlyphKey::new(font_key, size, color, index,
                                point, render_mode),
             render_mode: render_mode,
             glyph_options: glyph_options,
         }
@@ -214,17 +214,16 @@ pub struct ResourceCache {
 
     texture_cache: TextureCache,
 
     // TODO(gw): We should expire (parts of) this cache semi-regularly!
     cached_glyph_dimensions: HashMap<GlyphKey, Option<GlyphDimensions>, BuildHasherDefault<FnvHasher>>,
     pending_image_requests: Vec<ImageRequest>,
     glyph_cache_tx: Sender<GlyphCacheMsg>,
     glyph_cache_result_queue: Receiver<GlyphCacheResultMsg>,
-    pending_external_image_update_list: ExternalImageUpdateList,
 
     blob_image_renderer: Option<Box<BlobImageRenderer>>,
     blob_image_requests: HashSet<ImageRequest>,
 }
 
 impl ResourceCache {
     pub fn new(texture_cache: TextureCache,
                workers: Arc<Mutex<ThreadPool>>,
@@ -241,17 +240,16 @@ impl ResourceCache {
             cached_glyph_dimensions: HashMap::default(),
             texture_cache: texture_cache,
             state: State::Idle,
             enable_aa: enable_aa,
             current_frame_id: FrameId(0),
             pending_image_requests: Vec::new(),
             glyph_cache_tx: glyph_cache_tx,
             glyph_cache_result_queue: glyph_cache_result_queue,
-            pending_external_image_update_list: ExternalImageUpdateList::new(),
 
             blob_image_renderer: blob_image_renderer,
             blob_image_requests: HashSet::new(),
         }
     }
 
     pub fn max_texture_size(&self) -> u32 {
         self.texture_cache.max_texture_size()
@@ -341,32 +339,19 @@ impl ResourceCache {
         };
 
         self.image_templates.insert(image_key, resource);
     }
 
     pub fn delete_image_template(&mut self, image_key: ImageKey) {
         let value = self.image_templates.remove(&image_key);
 
-        // If the key is associated to an external image, pass the external id to renderer for cleanup.
-        if let Some(image) = value {
-            if let ImageData::External(ext_image) = image.data {
-                match ext_image.image_type {
-                    ExternalImageType::Texture2DHandle |
-                    ExternalImageType::TextureRectHandle => {
-                        self.pending_external_image_update_list.push(ext_image.id);
-                    }
-                    _ => {}
-                }
-            }
-
-            return;
+        if value.is_none() {
+            println!("Delete the non-exist key:{:?}", image_key);
         }
-
-        println!("Delete the non-exist key:{:?}", image_key);
     }
 
     pub fn add_webgl_texture(&mut self, id: WebGLContextId, texture_id: SourceTexture, size: DeviceIntSize) {
         self.webgl_textures.insert(id, WebGLTexture {
             id: texture_id,
             size: size,
         });
     }
@@ -439,36 +424,32 @@ impl ResourceCache {
                                                glyph_options);
         self.glyph_cache_tx.send(msg).unwrap();
     }
 
     pub fn pending_updates(&mut self) -> TextureUpdateList {
         self.texture_cache.pending_updates()
     }
 
-    pub fn pending_external_image_updates(&mut self) -> ExternalImageUpdateList {
-        mem::replace(&mut self.pending_external_image_update_list, ExternalImageUpdateList::new())
-    }
-
     pub fn get_glyphs<F>(&self,
                          font_key: FontKey,
                          size: Au,
                          color: ColorF,
                          glyph_instances: &[GlyphInstance],
                          render_mode: FontRenderMode,
                          glyph_options: Option<GlyphOptions>,
                          mut f: F) -> SourceTexture where F: FnMut(usize, DevicePoint, DevicePoint) {
         debug_assert!(self.state == State::QueryResources);
         let cache = self.cached_glyphs.as_ref().unwrap();
         let render_mode = self.get_glyph_render_mode(render_mode);
         let mut glyph_key = RenderedGlyphKey::new(font_key,
                                                   size,
                                                   color,
                                                   0,
-                                                  Point2D::new(0.0, 0.0),
+                                                  LayoutPoint::new(0.0, 0.0),
                                                   render_mode,
                                                   glyph_options);
         let mut texture_id = None;
         for (loop_index, glyph_instance) in glyph_instances.iter().enumerate() {
             glyph_key.key.index = glyph_instance.index;
             glyph_key.key.subpixel_point.set_offset(glyph_instance.point, render_mode);
 
             let image_id = cache.get(&glyph_key, self.current_frame_id);
@@ -493,18 +474,18 @@ impl ResourceCache {
             Occupied(entry) => *entry.get(),
             Vacant(entry) => {
                 let mut dimensions = None;
                 let font_template = &self.font_templates[&glyph_key.font_key];
 
                 FONT_CONTEXT.with(|font_context| {
                     let mut font_context = font_context.borrow_mut();
                     match *font_template {
-                        FontTemplate::Raw(ref bytes) => {
-                            font_context.add_raw_font(&glyph_key.font_key, &**bytes);
+                        FontTemplate::Raw(ref bytes, index) => {
+                            font_context.add_raw_font(&glyph_key.font_key, &**bytes, index);
                         }
                         FontTemplate::Native(ref native_font_handle) => {
                             font_context.add_native_font(&glyph_key.font_key,
                                                          (*native_font_handle).clone());
                         }
                     }
 
                     dimensions = font_context.get_glyph_dimensions(glyph_key);
@@ -539,17 +520,18 @@ impl ResourceCache {
 
     pub fn get_image_properties(&self, image_key: ImageKey) -> ImageProperties {
         let image_template = &self.image_templates[&image_key];
 
         let external_image = match image_template.data {
             ImageData::External(ext_image) => {
                 match ext_image.image_type {
                     ExternalImageType::Texture2DHandle |
-                    ExternalImageType::TextureRectHandle => {
+                    ExternalImageType::TextureRectHandle |
+                    ExternalImageType::TextureExternalHandle => {
                         Some(ext_image)
                     },
                     // external buffer uses resource_cache.
                     ExternalImageType::ExternalBuffer => None,
                 }
             },
             // raw and blob image are all using resource_cache.
             ImageData::Raw(..) | ImageData::Blob(..) => None,
@@ -764,17 +746,18 @@ impl ResourceCache {
     fn finalize_image_request(&mut self,
                               request: ImageRequest,
                               image_data: Option<ImageData>,
                               texture_cache_profile: &mut TextureCacheProfileCounters) {
         match self.image_templates.get(&request.key).unwrap().data {
             ImageData::External(ext_image) => {
                 match ext_image.image_type {
                     ExternalImageType::Texture2DHandle |
-                    ExternalImageType::TextureRectHandle => {
+                    ExternalImageType::TextureRectHandle |
+                    ExternalImageType::TextureExternalHandle => {
                         // external handle doesn't need to update the texture_cache.
                     }
                     ExternalImageType::ExternalBuffer => {
                         self.update_texture_cache(&request,
                                                   image_data,
                                                   texture_cache_profile);
                     }
                 }
@@ -879,18 +862,18 @@ fn spawn_glyph_cache_thread(workers: Arc
                     let barrier = Arc::new(Barrier::new(worker_count));
                     for _ in 0..worker_count {
                         let barrier = Arc::clone(&barrier);
                         let font_template = font_template.clone();
                         workers.lock().unwrap().execute(move || {
                             FONT_CONTEXT.with(|font_context| {
                                 let mut font_context = font_context.borrow_mut();
                                 match font_template {
-                                    FontTemplate::Raw(ref bytes) => {
-                                        font_context.add_raw_font(&font_key, &**bytes);
+                                    FontTemplate::Raw(ref bytes, index) => {
+                                        font_context.add_raw_font(&font_key, &**bytes, index);
                                     }
                                     FontTemplate::Native(ref native_font_handle) => {
                                         font_context.add_native_font(&font_key,
                                                                      (*native_font_handle).clone());
                                     }
                                 }
                             });
 
--- a/gfx/webrender/src/scene.rs
+++ b/gfx/webrender/src/scene.rs
@@ -1,16 +1,18 @@
 /* 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 fnv::FnvHasher;
+use profiler::IpcProfileCounters;
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
 use tiling::AuxiliaryListsMap;
+use time::precise_time_ns;
 use webrender_traits::{AuxiliaryLists, BuiltDisplayList, PipelineId, Epoch, ColorF};
 use webrender_traits::{DisplayItem, DynamicProperties, LayerSize, LayoutTransform};
 use webrender_traits::{PropertyBinding, PropertyBindingId};
 
 /// Stores a map of the animated property bindings for the current display list. These
 /// can be used to animate the transform and/or opacity of a display list without
 /// re-submitting the display list itself.
 pub struct SceneProperties {
@@ -114,20 +116,34 @@ impl Scene {
     }
 
     pub fn set_display_list(&mut self,
                             pipeline_id: PipelineId,
                             epoch: Epoch,
                             built_display_list: BuiltDisplayList,
                             background_color: Option<ColorF>,
                             viewport_size: LayerSize,
-                            auxiliary_lists: AuxiliaryLists) {
+                            auxiliary_lists: AuxiliaryLists,
+                            profile_counters: &mut IpcProfileCounters) {
+
+        let display_list_len = built_display_list.data().len();
+        let aux_list_len = auxiliary_lists.data().len();
+        let (serial_start_time, serial_end_time) = built_display_list.serialization_times();
+
+        let deserial_start_time = precise_time_ns();
+
         self.pipeline_auxiliary_lists.insert(pipeline_id, auxiliary_lists);
         self.display_lists.insert(pipeline_id, built_display_list.into_display_items());
 
+        let deserial_end_time = precise_time_ns();
+
+        profile_counters.set(serial_start_time, serial_end_time, 
+                             deserial_start_time, deserial_end_time,
+                             display_list_len, aux_list_len);
+
         let new_pipeline = ScenePipeline {
             pipeline_id: pipeline_id,
             epoch: epoch,
             viewport_size: viewport_size,
             background_color: background_color,
         };
 
         self.pipeline_map.insert(pipeline_id, new_pipeline);
--- a/gfx/webrender/src/texture_cache.rs
+++ b/gfx/webrender/src/texture_cache.rs
@@ -786,25 +786,27 @@ impl TextureCache {
                                    profile);
 
         match result.kind {
             AllocationKind::TexturePage => {
                 match data {
                     ImageData::External(ext_image) => {
                         match ext_image.image_type {
                             ExternalImageType::Texture2DHandle |
-                            ExternalImageType::TextureRectHandle => {
+                            ExternalImageType::TextureRectHandle |
+                            ExternalImageType::TextureExternalHandle => {
                                 panic!("External texture handle should not go through texture_cache.");
                             }
                             ExternalImageType::ExternalBuffer => {
                                 let update_op = TextureUpdate {
                                     id: result.item.texture_id,
                                     op: TextureUpdateOp::UpdateForExternalBuffer {
                                         rect: result.item.allocated_rect,
                                         id: ext_image.id,
+                                        channel_index: ext_image.channel_index,
                                         stride: stride,
                                     },
                                 };
 
                                 self.pending_updates.push(update_op);
                             }
                         }
                     }
@@ -829,17 +831,18 @@ impl TextureCache {
                     }
                 }
             }
             AllocationKind::Standalone => {
                 match data {
                     ImageData::External(ext_image) => {
                         match ext_image.image_type {
                             ExternalImageType::Texture2DHandle |
-                            ExternalImageType::TextureRectHandle => {
+                            ExternalImageType::TextureRectHandle |
+                            ExternalImageType::TextureExternalHandle => {
                                 panic!("External texture handle should not go through texture_cache.");
                             }
                             ExternalImageType::ExternalBuffer => {
                                 let update_op = TextureUpdate {
                                     id: result.item.texture_id,
                                     op: TextureUpdateOp::Create {
                                         width: width,
                                         height: height,
--- a/gfx/webrender/src/tiling.rs
+++ b/gfx/webrender/src/tiling.rs
@@ -373,17 +373,17 @@ impl AlphaRenderItem {
                     user_data: [ backdrop_task.0 as i32,
                                  src_task_index.0 as i32 ],
                     z_sort_index: z,
                 });
             }
             AlphaRenderItem::Primitive(clip_scroll_group_index, prim_index, z) => {
                 let group = &ctx.clip_scroll_group_store[clip_scroll_group_index.0];
                 let prim_metadata = ctx.prim_store.get_metadata(prim_index);
-                let transform_kind = group.xf_rect.as_ref().unwrap().kind;
+                let transform_kind = group.screen_bounding_rect.as_ref().unwrap().0;
                 let needs_clipping = prim_metadata.needs_clipping();
                 let mut flags = AlphaBatchKeyFlags::empty();
                 if needs_clipping {
                     flags |= NEEDS_CLIPPING;
                 }
                 if transform_kind == TransformedRectKind::AxisAligned {
                     flags |= AXIS_ALIGNED;
                 }
@@ -454,16 +454,19 @@ impl AlphaRenderItem {
                     PrimitiveKind::Image => {
                         let image_cpu = &ctx.prim_store.cpu_images[prim_metadata.cpu_prim_index.0];
 
                         let batch_kind = match image_cpu.color_texture_id {
                             SourceTexture::External(ext_image) => {
                                 match ext_image.image_type {
                                     ExternalImageType::Texture2DHandle => AlphaBatchKind::Image,
                                     ExternalImageType::TextureRectHandle => AlphaBatchKind::ImageRect,
+                                    ExternalImageType::TextureExternalHandle => {
+                                        panic!("No implementation for single channel TextureExternalHandle image.");
+                                    }
                                     _ => {
                                         panic!("Non-texture handle type should be handled in other way.");
                                     }
                                 }
                             }
                             _ => {
                                 AlphaBatchKind::Image
                             }
@@ -509,16 +512,18 @@ impl AlphaRenderItem {
                     PrimitiveKind::RadialGradient => {
                         let key = AlphaBatchKey::new(AlphaBatchKind::RadialGradient, flags, blend_mode, textures);
                         let batch = batch_list.get_suitable_batch(&key, item_bounding_rect);
                         batch.add_instance(base_instance.build(prim_metadata.gpu_data_address.0,
                                                                prim_metadata.gpu_data_count,
                                                                0));
                     }
                     PrimitiveKind::YuvImage => {
+                        // TODO (Jerry):
+                        // handle NV12
                         let image_yuv_cpu = &ctx.prim_store.cpu_yuv_images[prim_metadata.cpu_prim_index.0];
                         let key = AlphaBatchKey::new(AlphaBatchKind::YuvImage, flags, blend_mode, textures);
                         let batch = batch_list.get_suitable_batch(&key, item_bounding_rect);
 
                         batch.add_instance(base_instance.build(0,
                                                                image_yuv_cpu.yuv_resource_address.0,
                                                                0));
                     }
@@ -1336,22 +1341,22 @@ impl StackingContext {
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
 pub struct ClipScrollGroupIndex(pub usize, pub ClipId);
 
 #[derive(Debug)]
 pub struct ClipScrollGroup {
     pub stacking_context_index: StackingContextIndex,
     pub clip_id: ClipId,
     pub packed_layer_index: PackedLayerIndex,
-    pub xf_rect: Option<TransformedRect>,
+    pub screen_bounding_rect: Option<(TransformedRectKind, DeviceIntRect)>,
 }
 
 impl ClipScrollGroup {
     pub fn is_visible(&self) -> bool {
-        self.xf_rect.is_some()
+        self.screen_bounding_rect.is_some()
     }
 }
 
 #[derive(Debug, Clone)]
 #[repr(C)]
 pub struct PackedLayer {
     pub transform: LayerToWorldTransform,
     pub inv_transform: WorldToLayerTransform,
@@ -1379,25 +1384,23 @@ impl PackedLayer {
         self.transform = transform;
         self.inv_transform = self.transform.inverse().unwrap();
     }
 
     pub fn set_rect(&mut self,
                     local_rect: &LayerRect,
                     screen_rect: &DeviceIntRect,
                     device_pixel_ratio: f32)
-                    -> Option<TransformedRect> {
+                    -> Option<(TransformedRectKind, DeviceIntRect)> {
         let xf_rect = TransformedRect::new(&local_rect, &self.transform, device_pixel_ratio);
-        if !xf_rect.bounding_rect.intersects(screen_rect) {
-            return None;
-        }
-
-        self.screen_vertices = xf_rect.vertices.clone();
-        self.local_clip_rect = *local_rect;
-        Some(xf_rect)
+        xf_rect.bounding_rect.intersection(screen_rect).map(|rect| {
+            self.screen_vertices = xf_rect.vertices.clone();
+            self.local_clip_rect = *local_rect;
+            (xf_rect.kind, rect)
+        })
     }
 }
 
 #[derive(Debug, Clone)]
 pub struct CompositeOps {
     // Requires only a single texture as input (e.g. most filters)
     pub filters: Vec<LowLevelFilterOp>,
 
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -1,16 +1,16 @@
 [package]
 name = "webrender_bindings"
 version = "0.1.0"
 authors = ["The Mozilla Project Developers"]
 license = "MPL-2.0"
 
 [dependencies]
-webrender_traits = {path = "../webrender_traits", version = "0.33.0"}
+webrender_traits = {path = "../webrender_traits", version = "0.35.0"}
 euclid = "0.11"
 app_units = "0.4"
 gleam = "0.4"
 
 [dependencies.webrender]
 path = "../webrender"
-version = "0.32.0"
+version = "0.35.0"
 default-features = false
--- a/gfx/webrender_bindings/RendererOGL.cpp
+++ b/gfx/webrender_bindings/RendererOGL.cpp
@@ -45,20 +45,16 @@ WrExternalImage LockExternalImage(void* 
 void UnlockExternalImage(void* aObj, WrExternalImageId aId)
 {
   RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj);
   RenderTextureHost* texture = renderer->GetRenderTexture(aId);
   MOZ_ASSERT(texture);
   texture->Unlock();
 }
 
-void ReleaseExternalImage(void* aObj, WrExternalImageId aId)
-{
-}
-
 RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
                          RefPtr<gl::GLContext>&& aGL,
                          RefPtr<widget::CompositorWidget>&& aWidget,
                          wr::WindowId aWindowId,
                          WrRenderer* aWrRenderer,
                          layers::CompositorBridgeParentBase* aBridge)
   : mThread(aThread)
   , mGL(aGL)
@@ -83,17 +79,16 @@ RendererOGL::~RendererOGL()
 
 WrExternalImageHandler
 RendererOGL::GetExternalImageHandler()
 {
   return WrExternalImageHandler {
     this,
     LockExternalImage,
     UnlockExternalImage,
-    ReleaseExternalImage,
   };
 }
 
 void
 RendererOGL::Update()
 {
   wr_renderer_update(mWrRenderer);
 }
--- a/gfx/webrender_bindings/RendererOGL.h
+++ b/gfx/webrender_bindings/RendererOGL.h
@@ -37,17 +37,16 @@ class RenderTextureHost;
 ///
 /// There is one renderer per window, all owned by the render thread.
 /// This class is a similar abstraction to CompositorOGL except that it is used
 /// on the render thread instead of the compositor thread.
 class RendererOGL
 {
   friend WrExternalImage LockExternalImage(void* aObj, WrExternalImageId aId);
   friend void UnlockExternalImage(void* aObj, WrExternalImageId aId);
-  friend void ReleaseExternalImage(void* aObj, WrExternalImageId aId);
 
 public:
   WrExternalImageHandler GetExternalImageHandler();
 
   /// This can be called on the render thread only.
   void Update();
 
   /// This can be called on the render thread only.
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -534,29 +534,28 @@ struct WrExternalImage {
 
     // external image buffer
     buff: *const u8,
     size: usize,
 }
 
 type LockExternalImageCallback = fn(*mut c_void, WrExternalImageId) -> WrExternalImage;
 type UnlockExternalImageCallback = fn(*mut c_void, WrExternalImageId);
-type ReleaseExternalImageCallback = fn(*mut c_void, WrExternalImageId);
 
 #[repr(C)]
 pub struct WrExternalImageHandler {
     external_image_obj: *mut c_void,
     lock_func: LockExternalImageCallback,
     unlock_func: UnlockExternalImageCallback,
-    release_func: ReleaseExternalImageCallback,
 }
 
 impl ExternalImageHandler for WrExternalImageHandler {
     fn lock(&mut self,
-            id: ExternalImageId)
+            id: ExternalImageId,
+            _channel_index: u8)
             -> ExternalImage {
         let image = (self.lock_func)(self.external_image_obj, id.into());
 
         match image.image_type {
             WrExternalImageType::NativeTexture => {
                 ExternalImage {
                     u0: image.u0,
                     v0: image.v0,
@@ -573,24 +572,20 @@ impl ExternalImageHandler for WrExternal
                     v1: image.v1,
                     source: ExternalImageSource::RawData(unsafe { slice::from_raw_parts(image.buff, image.size) }),
                 }
             },
         }
     }
 
     fn unlock(&mut self,
-              id: ExternalImageId) {
+              id: ExternalImageId,
+              _channel_index: u8) {
         (self.unlock_func)(self.external_image_obj, id.into());
     }
-
-    fn release(&mut self,
-               id: ExternalImageId) {
-        (self.release_func)(self.external_image_obj, id.into());
-    }
 }
 
 /// cbindgen:field-names=[mHandle]
 /// cbindgen:struct-gen-op-lt=true
 /// cbindgen:struct-gen-op-lte=true
 #[repr(C)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct WrWindowId(u64);
@@ -734,17 +729,16 @@ pub extern "C" fn wr_renderer_set_extern
                                                          external_image_handler: *mut WrExternalImageHandler) {
     if !external_image_handler.is_null() {
         renderer.set_external_image_handler(Box::new(unsafe {
                                                          WrExternalImageHandler {
                                                              external_image_obj:
                                                                  (*external_image_handler).external_image_obj,
                                                              lock_func: (*external_image_handler).lock_func,
                                                              unlock_func: (*external_image_handler).unlock_func,
-                                                             release_func: (*external_image_handler).release_func,
                                                          }
                                                      }));
     }
 }
 
 #[no_mangle]
 pub extern "C" fn wr_renderer_update(renderer: &mut WrRenderer) {
     renderer.update();
@@ -936,31 +930,33 @@ pub extern "C" fn wr_api_add_external_im
                                                    image_key: WrImageKey,
                                                    descriptor: &WrImageDescriptor,
                                                    external_image_id: WrExternalImageId) {
     assert!(unsafe { is_in_compositor_thread() });
     api.add_image(image_key,
                   descriptor.into(),
                   ImageData::External(ExternalImageData {
                                           id: external_image_id.into(),
+                                          channel_index: 0,
                                           image_type: ExternalImageType::Texture2DHandle,
                                       }),
                   None);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_add_external_image_buffer(api: &mut WrAPI,
                                                    image_key: WrImageKey,
                                                    descriptor: &WrImageDescriptor,
                                                    external_image_id: WrExternalImageId) {
     assert!(unsafe { is_in_compositor_thread() });
     api.add_image(image_key,
                   descriptor.into(),
                   ImageData::External(ExternalImageData {
                                           id: external_image_id.into(),
+                                          channel_index: 0,
                                           image_type: ExternalImageType::ExternalBuffer,
                                       }),
                   None);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_update_image(api: &mut WrAPI,
                                       key: WrImageKey,
@@ -1105,17 +1101,17 @@ pub extern "C" fn wr_api_add_raw_font(ap
                                       font_buffer: *mut u8,
                                       buffer_size: usize) {
     assert!(unsafe { is_in_compositor_thread() });
 
     let font_slice = unsafe { slice::from_raw_parts(font_buffer, buffer_size as usize) };
     let mut font_vector = Vec::new();
     font_vector.extend_from_slice(font_slice);
 
-    api.add_raw_font(key, font_vector);
+    api.add_raw_font(key, font_vector, 0);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_delete_font(api: &mut WrAPI,
                                      key: WrFontKey) {
     assert!(unsafe { is_in_compositor_thread() });
     api.delete_font(key);
 }
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -175,19 +175,23 @@ struct WrPipelineId {
       mHandle == aOther.mHandle;
   }
 };
 
 struct WrState;
 
 struct WrBuiltDisplayListDescriptor {
   size_t display_list_items_size;
+  uint64_t serialization_start_time;
+  uint64_t serialization_end_time;
 
   bool operator==(const WrBuiltDisplayListDescriptor& aOther) const {
-    return display_list_items_size == aOther.display_list_items_size;
+    return display_list_items_size == aOther.display_list_items_size &&
+      serialization_start_time == aOther.serialization_start_time &&
+      serialization_end_time == aOther.serialization_end_time;
   }
 };
 
 struct WrVecU8 {
   uint8_t* data;
   size_t length;
   size_t capacity;
 
@@ -473,29 +477,25 @@ struct WrExternalImage {
       size == aOther.size;
   }
 };
 
 typedef WrExternalImage (*LockExternalImageCallback)(void*, WrExternalImageId);
 
 typedef void (*UnlockExternalImageCallback)(void*, WrExternalImageId);
 
-typedef void (*ReleaseExternalImageCallback)(void*, WrExternalImageId);
-
 struct WrExternalImageHandler {
   void* external_image_obj;
   LockExternalImageCallback lock_func;
   UnlockExternalImageCallback unlock_func;
-  ReleaseExternalImageCallback release_func;
 
   bool operator==(const WrExternalImageHandler& aOther) const {
     return external_image_obj == aOther.external_image_obj &&
       lock_func == aOther.lock_func &&
-      unlock_func == aOther.unlock_func &&
-      release_func == aOther.release_func;
+      unlock_func == aOther.unlock_func;
   }
 };
 
 struct WrWindowId {
   uint64_t mHandle;
 
   bool operator==(const WrWindowId& aOther) const {
     return mHandle == aOther.mHandle;
--- a/gfx/webrender_traits/Cargo.toml
+++ b/gfx/webrender_traits/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "webrender_traits"
-version = "0.33.0"
+version = "0.35.0"
 authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
 license = "MPL-2.0"
 repository = "https://github.com/servo/webrender"
 
 [features]
 nightly = ["euclid/unstable", "serde/unstable"]
 ipc = ["ipc-channel"]
 webgl = ["offscreen_gl_context"]
@@ -15,14 +15,16 @@ app_units = "0.4"
 byteorder = "1.0"
 euclid = "0.11"
 gleam = "0.4"
 heapsize = "0.3.6"
 ipc-channel = {version = "0.7", optional = true}
 offscreen_gl_context = {version = "0.8", features = ["serde"], optional = true}
 serde = "0.9"
 serde_derive = "0.9"
+time = "0.1"
 
 [target.'cfg(target_os = "macos")'.dependencies]
+core-foundation = "0.3"
 core-graphics = "0.7"
 
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.3"
--- a/gfx/webrender_traits/src/api.rs
+++ b/gfx/webrender_traits/src/api.rs
@@ -14,17 +14,17 @@ use {GlyphDimensions, GlyphKey, ImageDat
 use {LayoutTransform, NativeFontHandle, WorldPoint};
 #[cfg(feature = "webgl")]
 use {WebGLCommand, WebGLContextId};
 
 pub type TileSize = u16;
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum ApiMsg {
-    AddRawFont(FontKey, Vec<u8>),
+    AddRawFont(FontKey, Vec<u8>, u32),
     AddNativeFont(FontKey, NativeFontHandle),
     DeleteFont(FontKey),
     /// Gets the glyph dimensions
     GetGlyphDimensions(Vec<GlyphKey>, MsgSender<Vec<Option<GlyphDimensions>>>),
     /// Adds an image from the resource cache.
     AddImage(ImageKey, ImageDescriptor, ImageData, Option<TileSize>),
     /// Updates the the resource cache with the new image data.
     UpdateImage(ImageKey, ImageDescriptor, ImageData, Option<DeviceUintRect>),
@@ -193,18 +193,18 @@ impl RenderApi {
         RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
     }
 
     pub fn generate_font_key(&self) -> FontKey {
         let new_id = self.next_unique_id();
         FontKey::new(new_id.0, new_id.1)
     }
 
-    pub fn add_raw_font(&self, key: FontKey, bytes: Vec<u8>) {
-        let msg = ApiMsg::AddRawFont(key, bytes);
+    pub fn add_raw_font(&self, key: FontKey, bytes: Vec<u8>, index: u32) {
+        let msg = ApiMsg::AddRawFont(key, bytes, index);
         self.api_sender.send(msg).unwrap();
     }
 
     pub fn add_native_font(&self, key: FontKey, native_font_handle: NativeFontHandle) {
         let msg = ApiMsg::AddNativeFont(key, native_font_handle);
         self.api_sender.send(msg).unwrap();
     }
 
--- a/gfx/webrender_traits/src/channel.rs
+++ b/gfx/webrender_traits/src/channel.rs
@@ -40,30 +40,32 @@ impl Payload {
         data.write_u64::<LittleEndian>(self.display_list_data.len() as u64).unwrap();
         data.extend_from_slice(&self.display_list_data);
         data.write_u64::<LittleEndian>(self.auxiliary_lists_data.len() as u64).unwrap();
         data.extend_from_slice(&self.auxiliary_lists_data);
         data
     }
 
     /// Deserializes the given payload from a raw byte vector.
-    pub fn from_data(data: Vec<u8>) -> Payload {
-        let mut payload_reader = Cursor::new(&data[..]);
+    pub fn from_data(data: &[u8]) -> Payload {
+        let mut payload_reader = Cursor::new(data);
         let epoch = Epoch(payload_reader.read_u32::<LittleEndian>().unwrap());
         let pipeline_id = PipelineId(payload_reader.read_u32::<LittleEndian>().unwrap(),
                                      payload_reader.read_u32::<LittleEndian>().unwrap());
 
         let dl_size = payload_reader.read_u64::<LittleEndian>().unwrap() as usize;
         let mut built_display_list_data = vec![0; dl_size];
         payload_reader.read_exact(&mut built_display_list_data[..]).unwrap();
 
         let aux_size = payload_reader.read_u64::<LittleEndian>().unwrap() as usize;
         let mut auxiliary_lists_data = vec![0; aux_size];
         payload_reader.read_exact(&mut auxiliary_lists_data[..]).unwrap();
 
+        assert_eq!(payload_reader.position(), data.len() as u64);
+
         Payload {
             epoch: epoch,
             pipeline_id: pipeline_id,
             display_list_data: built_display_list_data,
             auxiliary_lists_data: auxiliary_lists_data,
         }
     }
 }
--- a/gfx/webrender_traits/src/channel_ipc.rs
+++ b/gfx/webrender_traits/src/channel_ipc.rs
@@ -24,17 +24,17 @@ pub type PayloadReceiver = IpcBytesRecei
 impl PayloadSenderHelperMethods for PayloadSender {
     fn send_payload(&self, data: Payload) -> Result<(), Error> {
         self.send(&data.to_data())
     }
 }
 
 impl PayloadReceiverHelperMethods for PayloadReceiver {
     fn recv_payload(&self) -> Result<Payload, Error> {
-        self.recv().map(|data| Payload::from_data(data) )
+        self.recv().map(|data| Payload::from_data(&data) )
                    .map_err(|e| io::Error::new(ErrorKind::Other, error::Error::description(&e)))
     }
 }
 
 pub fn msg_channel<T: Serialize + Deserialize>() -> Result<(MsgSender<T>, MsgReceiver<T>), Error> {
     ipc::channel()
 }
 
--- a/gfx/webrender_traits/src/display_item.rs
+++ b/gfx/webrender_traits/src/display_item.rs
@@ -538,9 +538,28 @@ impl ClipId {
     }
 
     pub fn external_id(&self) -> Option<u64> {
         match *self {
             ClipId::ClipExternalId(id, _) => Some(id),
             _ => None,
         }
     }
+
+    pub fn is_root_scroll_node(&self) -> bool {
+        match *self {
+            ClipId::Clip(id, _) if id == 0 => true,
+            _ => false,
+        }
+    }
 }
+
+macro_rules! define_empty_heap_size_of {
+    ($name:ident) => {
+        impl ::heapsize::HeapSizeOf for $name {
+            fn heap_size_of_children(&self) -> usize { 0 }
+        }
+    }
+}
+
+define_empty_heap_size_of!(ClipId);
+define_empty_heap_size_of!(RepeatMode);
+define_empty_heap_size_of!(ImageKey);
--- a/gfx/webrender_traits/src/display_list.rs
+++ b/gfx/webrender_traits/src/display_list.rs
@@ -1,15 +1,16 @@
 /* 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 std::mem;
 use std::slice;
+use time::precise_time_ns;
 use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem};
 use {ClipDisplayItem, ClipId, ClipRegion, ColorF, ComplexClipRegion, DisplayItem, ExtendMode};
 use {FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem, GradientStop};
 use {IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering, ItemRange};
 use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, MixBlendMode, PipelineId};
 use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
 use {RectangleDisplayItem, ScrollPolicy, SpecificDisplayItem, StackingContext, TextDisplayItem};
 use {TransformStyle, WebGLContextId, WebGLDisplayItem, YuvColorSpace, YuvImageDisplayItem};
@@ -46,16 +47,20 @@ pub struct BuiltDisplayList {
 ///
 /// A display list consists of some number of display list items, followed by a number of display
 /// items.
 #[repr(C)]
 #[derive(Copy, Clone, Deserialize, Serialize)]
 pub struct BuiltDisplayListDescriptor {
     /// The size in bytes of the display list items in this display list.
     display_list_items_size: usize,
+    /// The first IPC time stamp: before any work has been done
+    serialization_start_time: u64,
+    /// The second IPC time stamp: after serialization
+    serialization_end_time: u64,
 }
 
 impl BuiltDisplayListDescriptor {
     pub fn size(&self) -> usize {
         self.display_list_items_size
     }
 }
 
@@ -86,16 +91,19 @@ impl BuiltDisplayList {
     }
 
     pub fn into_display_items(self) -> Vec<DisplayItem> {
         unsafe {
             convert_vec_blob_to_pod(self.data)
         }
     }
 
+    pub fn serialization_times(&self) -> (u64, u64) {
+      (self.descriptor.serialization_start_time, self.descriptor.serialization_end_time)
+    }
 }
 
 #[derive(Clone)]
 pub struct DisplayListBuilder {
     pub list: Vec<DisplayItem>,
     auxiliary_lists_builder: AuxiliaryListsBuilder,
     pub pipeline_id: PipelineId,
     clip_stack: Vec<ClipId>,
@@ -537,27 +545,33 @@ impl DisplayListBuilder {
                            complex: Vec<ComplexClipRegion>,
                            image_mask: Option<ImageMask>)
                            -> ClipRegion {
         ClipRegion::new(rect, complex, image_mask, &mut self.auxiliary_lists_builder)
     }
 
     pub fn finalize(self) -> (PipelineId, BuiltDisplayList, AuxiliaryLists) {
         unsafe {
+            let serialization_start_time = precise_time_ns();
+
             let blob = convert_vec_pod_to_blob(self.list);
-            let display_list_items_size = blob.len();
+            let aux_list = self.auxiliary_lists_builder.finalize();
+
+            let serialization_end_time = precise_time_ns();
 
             (self.pipeline_id,
              BuiltDisplayList {
                  descriptor: BuiltDisplayListDescriptor {
-                     display_list_items_size: display_list_items_size,
+                    display_list_items_size: blob.len(),
+                    serialization_start_time: serialization_start_time,
+                    serialization_end_time: serialization_end_time,
                  },
                  data: blob,
              },
-             self.auxiliary_lists_builder.finalize())
+             aux_list)
         }
     }
 }
 
 impl ItemRange {
     pub fn new<T>(backing_list: &mut Vec<T>, items: &[T]) -> ItemRange where T: Copy + Clone {
         let start = backing_list.len();
         backing_list.extend_from_slice(items);
--- a/gfx/webrender_traits/src/font.rs
+++ b/gfx/webrender_traits/src/font.rs
@@ -1,22 +1,45 @@
 /* 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::Point2D;
-use {ColorU, ColorF};
+use {ColorU, ColorF, LayoutPoint};
 
+#[cfg(target_os = "macos")] use core_foundation::string::CFString;
 #[cfg(target_os = "macos")] use core_graphics::font::CGFont;
+#[cfg(target_os = "macos")] use serde::de::{self, Deserialize, Deserializer};
+#[cfg(target_os = "macos")] use serde::ser::{Serialize, Serializer};
 #[cfg(target_os = "windows")] use dwrote::FontDescriptor;
 
 
 #[cfg(target_os = "macos")]
-pub type NativeFontHandle = CGFont;
+#[derive(Clone)]
+pub struct NativeFontHandle(pub CGFont);
+
+#[cfg(target_os = "macos")]
+impl Serialize for NativeFontHandle {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
+        let postscript_name = self.0.postscript_name().to_string();
+        postscript_name.serialize(serializer)
+    }
+}
+
+#[cfg(target_os = "macos")]
+impl Deserialize for NativeFontHandle {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer {
+        let postscript_name: String = try!(Deserialize::deserialize(deserializer));
+
+        match CGFont::from_name(&CFString::new(&*postscript_name)) {
+            Ok(font) => Ok(NativeFontHandle(font)),
+            _ => Err(de::Error::custom("Couldn't find a font with that PostScript name!")),
+        }
+    }
+}
 
 /// Native fonts are not used on Linux; all fonts are raw.
 #[cfg(not(any(target_os = "macos", target_os = "windows")))]
 #[cfg_attr(not(any(target_os = "macos", target_os = "windows")), derive(Clone, Serialize, Deserialize))]
 pub struct NativeFontHandle;
 
 #[cfg(target_os = "windows")]
 pub type NativeFontHandle = FontDescriptor;
@@ -102,29 +125,29 @@ impl Into<f64> for SubpixelOffset {
 
 #[derive(Clone, Hash, PartialEq, Eq, Debug, Deserialize, Serialize, Ord, PartialOrd)]
 pub struct SubpixelPoint {
     pub x: SubpixelOffset,
     pub y: SubpixelOffset,
 }
 
 impl SubpixelPoint {
-    pub fn new(point: Point2D<f32>,
+    pub fn new(point: LayoutPoint,
                render_mode: FontRenderMode) -> SubpixelPoint {
         SubpixelPoint {
             x: render_mode.subpixel_quantize_offset(point.x),
             y: render_mode.subpixel_quantize_offset(point.y),
         }
     }
 
     pub fn to_f64(&self) -> (f64, f64) {
         (self.x.into(), self.y.into())
     }
 
-    pub fn set_offset(&mut self, point: Point2D<f32>, render_mode: FontRenderMode) {
+    pub fn set_offset(&mut self, point: LayoutPoint, render_mode: FontRenderMode) {
         self.x = render_mode.subpixel_quantize_offset(point.x);
         self.y = render_mode.subpixel_quantize_offset(point.y);
     }
 }
 
 #[derive(Clone, Hash, PartialEq, Eq, Debug, Deserialize, Serialize, Ord, PartialOrd)]
 pub struct GlyphKey {
     pub font_key: FontKey,
@@ -139,26 +162,26 @@ pub struct GlyphKey {
     pub subpixel_point: SubpixelPoint,
 }
 
 impl GlyphKey {
     pub fn new(font_key: FontKey,
                size: Au,
                color: ColorF,
                index: u32,
-               point: Point2D<f32>,
+               point: LayoutPoint,
                render_mode: FontRenderMode) -> GlyphKey {
         GlyphKey {
             font_key: font_key,
             size: size,
             color: ColorU::from(color),
             index: index,
             subpixel_point: SubpixelPoint::new(point, render_mode),
         }
     }
 }
 
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct GlyphInstance {
     pub index: u32,
-    pub point: Point2D<f32>,
+    pub point: LayoutPoint,
 }
--- a/gfx/webrender_traits/src/image.rs
+++ b/gfx/webrender_traits/src/image.rs
@@ -17,16 +17,31 @@ impl ImageKey {
 
 /// An arbitrary identifier for an external image provided by the
 /// application. It must be a unique identifier for each external
 /// image.
 #[repr(C)]
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
 pub struct ExternalImageId(pub u64);
 
+#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
+pub enum ExternalImageType {
+    Texture2DHandle,        // gl TEXTURE_2D handle
+    TextureRectHandle,      // gl TEXTURE_RECT handle
+    TextureExternalHandle,  // gl TEXTURE_EXTERNAL handle
+    ExternalBuffer,
+}
+
+#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
+pub struct ExternalImageData {
+    pub id: ExternalImageId,
+    pub channel_index: u8,
+    pub image_type: ExternalImageType,
+}
+
 #[repr(u32)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum ImageFormat {
     Invalid  = 0,
     A8       = 1,
     RGB8     = 2,
     RGBA8    = 3,
     RGBAF32  = 4,
@@ -68,29 +83,16 @@ impl ImageDescriptor {
         }
     }
 
     pub fn compute_stride(&self) -> u32 {
         self.stride.unwrap_or(self.width * self.format.bytes_per_pixel().unwrap())
     }
 }
 
-#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
-pub enum ExternalImageType {
-    Texture2DHandle,    // gl TEXTURE_2D handle
-    TextureRectHandle,  // gl TEXTURE_RECT handle
-    ExternalBuffer,
-}
-
-#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
-pub struct ExternalImageData {
-    pub id: ExternalImageId,
-    pub image_type: ExternalImageType,
-}
-
 #[derive(Clone, Serialize, Deserialize)]
 pub enum ImageData {
     Raw(Arc<Vec<u8>>),
     Blob(Arc<BlobImageData>),
     External(ExternalImageData),
 }
 
 impl ImageData {
--- a/gfx/webrender_traits/src/lib.rs
+++ b/gfx/webrender_traits/src/lib.rs
@@ -15,16 +15,20 @@ extern crate gleam;
 extern crate heapsize;
 #[cfg(feature = "ipc")]
 extern crate ipc_channel;
 #[cfg(feature = "webgl")]
 extern crate offscreen_gl_context;
 extern crate serde;
 #[macro_use]
 extern crate serde_derive;
+extern crate time;
+
+#[cfg(target_os = "macos")]
+extern crate core_foundation;
 
 #[cfg(target_os = "macos")]
 extern crate core_graphics;
 
 #[cfg(target_os = "windows")]
 extern crate dwrote;
 
 mod units;
--- a/gfx/webrender_traits/src/webgl.rs
+++ b/gfx/webrender_traits/src/webgl.rs
@@ -61,16 +61,17 @@ pub enum WebGLCommand {
     DrawElements(u32, i32, u32, i64),
     EnableVertexAttribArray(u32),
     FramebufferRenderbuffer(u32, u32, u32, Option<WebGLRenderbufferId>),
     FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
     GetBufferParameter(u32, u32, MsgSender<WebGLResult<WebGLParameter>>),
     GetParameter(u32, MsgSender<WebGLResult<WebGLParameter>>),
     GetProgramParameter(WebGLProgramId, u32, MsgSender<WebGLResult<WebGLParameter>>),
     GetShaderParameter(WebGLShaderId, u32, MsgSender<WebGLResult<WebGLParameter>>),
+    GetShaderPrecisionFormat(u32, u32, MsgSender<WebGLResult<(i32, i32, i32)>>),
     GetActiveAttrib(WebGLProgramId, u32, MsgSender<WebGLResult<(i32, u32, String)>>),
     GetActiveUniform(WebGLProgramId, u32, MsgSender<WebGLResult<(i32, u32, String)>>),
     GetAttribLocation(WebGLProgramId, String, MsgSender<Option<i32>>),
     GetUniformLocation(WebGLProgramId, String, MsgSender<Option<i32>>),
     GetVertexAttrib(u32, u32, MsgSender<WebGLResult<WebGLParameter>>),
     GetShaderInfoLog(WebGLShaderId, MsgSender<String>),
     GetProgramInfoLog(WebGLProgramId, MsgSender<String>),
     PolygonOffset(f32, f32),
@@ -218,16 +219,20 @@ define_resource_id!(WebGLFramebufferId);
 define_resource_id!(WebGLRenderbufferId);
 define_resource_id!(WebGLTextureId);
 define_resource_id!(WebGLProgramId);
 define_resource_id!(WebGLShaderId);
 
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
 pub struct WebGLContextId(pub usize);
 
+impl ::heapsize::HeapSizeOf for WebGLContextId {
+    fn heap_size_of_children(&self) -> usize { 0 }
+}
+
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub enum WebGLError {
     InvalidEnum,
     InvalidFramebufferOperation,
     InvalidOperation,
     InvalidValue,
     OutOfMemory,
     ContextLost,
@@ -310,16 +315,17 @@ impl fmt::Debug for WebGLCommand {
             DrawElements(..) => "DrawElements",
             EnableVertexAttribArray(..) => "EnableVertexAttribArray",
             FramebufferRenderbuffer(..) => "FramebufferRenderbuffer",
             FramebufferTexture2D(..) => "FramebufferTexture2D",
             GetBufferParameter(..) => "GetBufferParameter",
             GetParameter(..) => "GetParameter",
             GetProgramParameter(..) => "GetProgramParameter",
             GetShaderParameter(..) => "GetShaderParameter",
+            GetShaderPrecisionFormat(..) => "GetShaderPrecisionFormat",
             GetActiveAttrib(..) => "GetActiveAttrib",
             GetActiveUniform(..) => "GetActiveUniform",
             GetAttribLocation(..) => "GetAttribLocation",
             GetUniformLocation(..) => "GetUniformLocation",
             GetShaderInfoLog(..) => "GetShaderInfoLog",
             GetProgramInfoLog(..) => "GetProgramInfoLog",
             GetVertexAttrib(..) => "GetVertexAttrib",
             PolygonOffset(..) => "PolygonOffset",
@@ -487,16 +493,18 @@ impl WebGLCommand {
             WebGLCommand::GetBufferParameter(target, param_id, chan) =>
                 Self::buffer_parameter(ctx.gl(), target, param_id, chan),
             WebGLCommand::GetParameter(param_id, chan) =>
                 Self::parameter(ctx.gl(), param_id, chan),
             WebGLCommand::GetProgramParameter(program_id, param_id, chan) =>
                 Self::program_parameter(ctx.gl(), program_id, param_id, chan),
             WebGLCommand::GetShaderParameter(shader_id, param_id, chan) =>
                 Self::shader_parameter(ctx.gl(), shader_id, param_id, chan),
+            WebGLCommand::GetShaderPrecisionFormat(shader_type, precision_type, chan) =>
+                Self::shader_precision_format(ctx.gl(), shader_type, precision_type, chan),
             WebGLCommand::GetUniformLocation(program_id, name, chan) =>
                 Self::uniform_location(ctx.gl(), program_id, name, chan),
             WebGLCommand::GetShaderInfoLog(shader_id, chan) =>
                 Self::shader_info_log(ctx.gl(), shader_id, chan),
             WebGLCommand::GetProgramInfoLog(program_id, chan) =>
                 Self::program_info_log(ctx.gl(), program_id, chan),
             WebGLCommand::CompileShader(shader_id, source) =>
                 Self::compile_shader(ctx.gl(), shader_id, source),
@@ -851,16 +859,38 @@ impl WebGLCommand {
             gl::COMPILE_STATUS =>
                 Ok(WebGLParameter::Bool(gl.get_shader_iv(shader_id.get(), param_id) != 0)),
             _ => Err(WebGLError::InvalidEnum),
         };
 
         chan.send(result).unwrap();
     }
 
+    fn shader_precision_format(gl: &gl::Gl,
+                               shader_type: u32,
+                               precision_type: u32,
+                               chan: MsgSender<WebGLResult<(i32, i32, i32)>>) {
+       
+        let result = match precision_type {
+            gl::LOW_FLOAT |
+            gl::MEDIUM_FLOAT |
+            gl::HIGH_FLOAT |
+            gl::LOW_INT |
+            gl::MEDIUM_INT |
+            gl::HIGH_INT => {
+                Ok(gl.get_shader_precision_format(shader_type, precision_type))
+            },
+            _=> {
+                Err(WebGLError::InvalidEnum)
+            }
+        };
+
+        chan.send(result).unwrap();
+    }
+
     fn uniform_location(gl: &gl::Gl,
                         program_id: WebGLProgramId,
                         name: String,
                         chan: MsgSender<Option<i32>>) {
         let location = gl.get_uniform_location(program_id.get(), &name);
         let location = if location == -1 {
             None
         } else {
--- a/third_party/rust/gleam/.cargo-checksum.json
+++ b/third_party/rust/gleam/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"29b74b95210896ce634c11a9037638668473b5a1b3b1716c505cb04dbb6341fa","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"93d5d180a0ae7c983db41e3127e58b642ed1d512a9a31c23e358969678098edf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"859937a7a48ae13485b1c82ebf5ab0d4f71d93a0cdd835dd0b2851929648f269","src/gl.rs":"ed01b1c8e5cb31de68dde54a857722f3d5b2bdeb8e30bfb2a95b500e3bf5f98a","src/gl_fns.rs":"d6eb7dd171030fe1b350f1616cd2c2e33d9051f70f5edcdd85f146b2745418a0","src/gles_fns.rs":"d00ba76795721c9136f770bb7135db67c95bb714bfa5a00952226b41519e68d7","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"3232655dbe4fc5ab688c05024f2c816b5d20c19ad8216d5c7d85cf915b24e005"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"29b74b95210896ce634c11a9037638668473b5a1b3b1716c505cb04dbb6341fa","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"73e953c91e925c7fdb4666e7c4a578f5531eeb442677a361c8b2e2cf87252b55","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"a9e320b7ebeb61be7f1ae594a0dcc022a6629f18c335e1b9ace11f573201c610","src/gl.rs":"f9070d602edb0ebf2e481614d4541f53b2031578ddbbfa47656dc375a7456a18","src/gl_fns.rs":"5e917e19b6a3a65133df4f47d7d4a387bb68e4f76ffa5807ab1de12d14b80095","src/gles_fns.rs":"761f998fc44c30145132f725728e8e86fd43e73f840c0221868c21539dcfc63c","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"9c46ff982a2e6abed1f50b3077d3176836875d9720906b248335f4c93827a345"}
\ No newline at end of file
--- a/third_party/rust/gleam/Cargo.toml
+++ b/third_party/rust/gleam/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "gleam"
-version = "0.4.2"
+version = "0.4.3"
 license = "Apache-2.0/MIT"
 authors = ["The Servo Project Developers"]
 build = "build.rs"
 documentation = "http://doc.servo.org/gleam/"
 repository = "https://github.com/servo/gleam"
 description = "Generated OpenGL bindings and wrapper for Servo."
 
 [build-dependencies]
--- a/third_party/rust/gleam/build.rs
+++ b/third_party/rust/gleam/build.rs
@@ -14,17 +14,21 @@ fn main() {
 
     // OpenGL 3.3 bindings
     let gl_extensions = ["GL_ARB_texture_rectangle", "GL_EXT_debug_marker"];
     let gl_reg = Registry::new(Api::Gl, (3, 3), Profile::Core, Fallbacks::All, gl_extensions);
     gl_reg.write_bindings(gl_generator::StructGenerator, &mut file_gl)
           .unwrap();
 
     // GLES 2.0 bindings
-    let gles_extensions = ["GL_EXT_texture_format_BGRA8888", "GL_OES_EGL_image"];
+    let gles_extensions = [
+        "GL_EXT_texture_format_BGRA8888",
+        "GL_OES_EGL_image",
+        "GL_OES_EGL_image_external",
+    ];
     let gles_reg = Registry::new(Api::Gles2, (3, 0), Profile::Core, Fallbacks::All, gles_extensions);
     gles_reg.write_bindings(gl_generator::StructGenerator, &mut file_gles)
             .unwrap();
 
     // OpenGL 3.3 + GLES 2.0 bindings. Used to get all enums
     let gl_reg = gl_reg + gles_reg;
     gl_reg.write_bindings(gl_generator::StructGenerator, &mut file_gl_and_gles)
           .unwrap();
--- a/third_party/rust/gleam/src/gl.rs
+++ b/third_party/rust/gleam/src/gl.rs
@@ -352,16 +352,20 @@ pub trait Gl {
     fn get_program_info_log(&self, program: GLuint) -> String;
     fn get_program_iv(&self, program: GLuint, pname: GLenum) -> GLint;
     fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum) -> GLint;
     fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum) -> Vec<GLfloat>;
     fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint;
     fn get_shader_info_log(&self, shader: GLuint) -> String;
     fn get_string(&self, which: GLenum) -> String;
     fn get_shader_iv(&self, shader: GLuint, pname: GLenum) -> GLint;
+    fn get_shader_precision_format(&self,
+                                   shader_type: GLuint,
+                                   precision_type: GLuint)
+                                   -> (GLint, GLint, GLint);
     fn compile_shader(&self, shader: GLuint);
     fn create_program(&self) -> GLuint;
     fn delete_program(&self, program: GLuint);
     fn create_shader(&self, shader_type: GLenum) -> GLuint;
     fn delete_shader(&self, shader: GLuint);
     fn detach_shader(&self, program: GLuint, shader: GLuint);
     fn link_program(&self, program: GLuint);
     fn clear_color(&self, r: f32, g: f32, b: f32, a: f32);
--- a/third_party/rust/gleam/src/gl_fns.rs
+++ b/third_party/rust/gleam/src/gl_fns.rs
@@ -1152,16 +1152,38 @@ impl Gl for GlFns {
     fn get_shader_iv(&self, shader: GLuint, pname: GLenum) -> GLint {
         unsafe {
             let mut result: GLint = 0 as GLint;
             self.ffi_gl_.GetShaderiv(shader, pname, &mut result);
             return result;
         }
     }
 
+    fn get_shader_precision_format(&self, _shader_type: GLuint, precision_type: GLuint) -> (GLint, GLint, GLint) {
+        // gl.GetShaderPrecisionFormat is not available until OpenGL 4.1.
+        // Fallback to OpenGL standard precissions that most desktop hardware support.
+        match precision_type {
+            ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => {
+                // Fallback to IEEE 754 single precision
+                // Range: from -2^127 to 2^127
+                // Significand precision: 23 bits
+                (127, 127, 23)
+            },
+            ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => {
+                // Fallback to single precision integer
+                // Range: from -2^24 to 2^24
+                // Precision: For integer formats this value is always 0
+                (24, 24, 0)
+            },
+            _ => {
+                (0, 0, 0)
+            }
+        }
+    }
+
     fn compile_shader(&self, shader: GLuint) {
         unsafe {
             self.ffi_gl_.CompileShader(shader);
         }
     }
 
     fn create_program(&self) -> GLuint {
         unsafe {
--- a/third_party/rust/gleam/src/gles_fns.rs
+++ b/third_party/rust/gleam/src/gles_fns.rs
@@ -1126,16 +1126,31 @@ impl Gl for GlesFns {
     fn get_shader_iv(&self, shader: GLuint, pname: GLenum) -> GLint {
         unsafe {
             let mut result: GLint = 0 as GLint;
             self.ffi_gl_.GetShaderiv(shader, pname, &mut result);
             return result;
         }
     }
 
+    fn get_shader_precision_format(&self,
+                                   shader_type: GLuint,
+                                   precision_type: GLuint)
+                                   -> (GLint, GLint, GLint) {
+        let mut range = [0 as GLint, 0];
+        let mut precision = 0 as GLint;
+        unsafe {
+            self.ffi_gl_.GetShaderPrecisionFormat(shader_type,
+                                                  precision_type,
+                                                  range.as_mut_ptr(),
+                                                  &mut precision);
+        }
+        (range[0], range[1], precision)
+    }
+
     fn compile_shader(&self, shader: GLuint) {
         unsafe {
             self.ffi_gl_.CompileShader(shader);
         }
     }
 
     fn create_program(&self) -> GLuint {
         unsafe {
@@ -1260,23 +1275,16 @@ impl Gl for GlesFns {
                            sfail: GLenum,
                            dpfail: GLenum,
                            dppass: GLenum) {
         unsafe {
             self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass)
         }
     }
 
-    #[allow(unused_variables)]
-    #[cfg(not(target_os="android"))]
-    fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
-        panic!("not supported")
-    }
-
-    #[cfg(target_os="android")]
     fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
         unsafe {
             self.ffi_gl_.EGLImageTargetTexture2DOES(target, image);
         }
     }
 
     fn generate_mipmap(&self, target: GLenum) {
         unsafe {
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -315,17 +315,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gleam"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "glob"
@@ -962,64 +962,66 @@ source = "registry+https://github.com/ru
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
-version = "0.32.0"
+version = "0.35.0"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0-alpha6 (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.7.0 (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.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gamma-lut 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.33.0",
+ "webrender_traits 0.35.0",
 ]
 
 [[package]]
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender 0.32.0",
- "webrender_traits 0.33.0",
+ "gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webrender 0.35.0",
+ "webrender_traits 0.35.0",
 ]
 
 [[package]]
 name = "webrender_traits"
-version = "0.33.0"
+version = "0.35.0"
 dependencies = [
  "app_units 0.4.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.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1063,17 +1065,17 @@ dependencies = [
 "checksum dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74114b6b49d6731835da7a28a3642651451e315f7f9b9d04e907e65a45681796"
 "checksum env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03"
 "checksum euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34559b159306de36203986eff799f83ef2bfb301a29fad333883f1a74a4cc6b0"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fde23272c687e4570aefec06cb71174ec0f5284b725deac4e77ba2665d635faf"
 "checksum gamma-lut 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8728df930776135895cbb25cbdd17791cde7d4285d53cf58fe6ee2e6412455"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55"
-"checksum gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3232655dbe4fc5ab688c05024f2c816b5d20c19ad8216d5c7d85cf915b24e005"
+"checksum gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9c46ff982a2e6abed1f50b3077d3176836875d9720906b248335f4c93827a345"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5a376f7402b85be6e0ba504243ecbc0709c48019ecc6286d0540c2e359050c88"
 "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -313,17 +313,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gleam"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "glob"
@@ -949,64 +949,66 @@ source = "registry+https://github.com/ru
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
-version = "0.32.0"
+version = "0.35.0"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0-alpha6 (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.7.0 (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.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gamma-lut 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.33.0",
+ "webrender_traits 0.35.0",
 ]
 
 [[package]]
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender 0.32.0",
- "webrender_traits 0.33.0",
+ "gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webrender 0.35.0",
+ "webrender_traits 0.35.0",
 ]
 
 [[package]]
 name = "webrender_traits"
-version = "0.33.0"
+version = "0.35.0"
 dependencies = [
  "app_units 0.4.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.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1050,17 +1052,17 @@ dependencies = [
 "checksum dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74114b6b49d6731835da7a28a3642651451e315f7f9b9d04e907e65a45681796"
 "checksum env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03"
 "checksum euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34559b159306de36203986eff799f83ef2bfb301a29fad333883f1a74a4cc6b0"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fde23272c687e4570aefec06cb71174ec0f5284b725deac4e77ba2665d635faf"
 "checksum gamma-lut 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8728df930776135895cbb25cbdd17791cde7d4285d53cf58fe6ee2e6412455"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55"
-"checksum gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3232655dbe4fc5ab688c05024f2c816b5d20c19ad8216d5c7d85cf915b24e005"
+"checksum gleam 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9c46ff982a2e6abed1f50b3077d3176836875d9720906b248335f4c93827a345"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5a376f7402b85be6e0ba504243ecbc0709c48019ecc6286d0540c2e359050c88"
 "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"