Bug 1349692 - Update webrender to dafe3579e8dc886e6584116dc52a9362b543c169. r=jrmuizel
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 28 Mar 2017 17:49:11 -0400
changeset 350399 843561af313ae9d0c9661d63718d53ef4e084885
parent 350398 a82772358806e8fccdb8b9aa0545548932943868
child 350400 e0e0b41946f231db12a8d9584f7961022d96f8b9
push id88627
push userkwierso@gmail.com
push dateWed, 29 Mar 2017 22:48:01 +0000
treeherdermozilla-inbound@83d25c5fdde7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1349692
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 1349692 - Update webrender to dafe3579e8dc886e6584116dc52a9362b543c169. r=jrmuizel In addition to updating gfx/webrender and gfx/webrender_traits, this updates gfx/webrender_bindings for: - API changes to update_image and push_stacking_context. - Version bumps needed in Cargo.toml Also, since offscreen_gl_context is no longer a dependency, this patch removes that crate and various other crates it depends on.
gfx/doc/README.webrender
gfx/webrender/Cargo.toml
gfx/webrender/res/cs_blur.fs.glsl
gfx/webrender/res/cs_blur.vs.glsl
gfx/webrender/res/cs_box_shadow.fs.glsl
gfx/webrender/res/prim_shared.glsl
gfx/webrender/res/ps_angle_gradient.fs.glsl
gfx/webrender/res/ps_angle_gradient.vs.glsl
gfx/webrender/res/ps_blend.fs.glsl
gfx/webrender/res/ps_blend.vs.glsl
gfx/webrender/res/ps_border.fs.glsl
gfx/webrender/res/ps_box_shadow.fs.glsl
gfx/webrender/res/ps_box_shadow.vs.glsl
gfx/webrender/res/ps_cache_image.fs.glsl
gfx/webrender/res/ps_cache_image.vs.glsl
gfx/webrender/res/ps_composite.fs.glsl
gfx/webrender/res/ps_composite.vs.glsl
gfx/webrender/res/ps_gradient.fs.glsl
gfx/webrender/res/ps_gradient.vs.glsl
gfx/webrender/res/ps_hardware_composite.fs.glsl
gfx/webrender/res/ps_hardware_composite.vs.glsl
gfx/webrender/res/ps_radial_gradient.fs.glsl
gfx/webrender/res/ps_radial_gradient.vs.glsl
gfx/webrender/res/shared.glsl
gfx/webrender/src/clip_scroll_node.rs
gfx/webrender/src/device.rs
gfx/webrender/src/frame.rs
gfx/webrender/src/frame_builder.rs
gfx/webrender/src/gpu_store.rs
gfx/webrender/src/internal_types.rs
gfx/webrender/src/lib.rs
gfx/webrender/src/prim_store.rs
gfx/webrender/src/profiler.rs
gfx/webrender/src/render_backend.rs
gfx/webrender/src/render_task.rs
gfx/webrender/src/renderer.rs
gfx/webrender/src/resource_cache.rs
gfx/webrender/src/texture_cache.rs
gfx/webrender/src/tiling.rs
gfx/webrender/src/webgl_stubs.rs
gfx/webrender/src/webgl_types.rs
gfx/webrender_bindings/Cargo.toml
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_traits/Cargo.toml
gfx/webrender_traits/src/api.rs
gfx/webrender_traits/src/display_item.rs
gfx/webrender_traits/src/display_list.rs
gfx/webrender_traits/src/lib.rs
third_party/rust/cgl/.cargo-checksum.json
third_party/rust/cgl/.cargo-ok
third_party/rust/cgl/.gitignore
third_party/rust/cgl/.travis.yml
third_party/rust/cgl/COPYING
third_party/rust/cgl/Cargo.toml
third_party/rust/cgl/LICENSE-APACHE
third_party/rust/cgl/LICENSE-MIT
third_party/rust/cgl/README.md
third_party/rust/cgl/src/cgl.rs
third_party/rust/cgl/src/lib.rs
third_party/rust/error-chain/.cargo-checksum.json
third_party/rust/error-chain/.cargo-ok
third_party/rust/error-chain/.gitignore
third_party/rust/error-chain/.travis.yml
third_party/rust/error-chain/CHANGELOG.md
third_party/rust/error-chain/Cargo.toml
third_party/rust/error-chain/README.md
third_party/rust/error-chain/examples/all.rs
third_party/rust/error-chain/examples/doc.rs
third_party/rust/error-chain/examples/quickstart.rs
third_party/rust/error-chain/examples/size.rs
third_party/rust/error-chain/src/error_chain.rs
third_party/rust/error-chain/src/example_generated.rs
third_party/rust/error-chain/src/lib.rs
third_party/rust/error-chain/src/quick_error.rs
third_party/rust/error-chain/src/quick_main.rs
third_party/rust/error-chain/tests/quick_main.rs
third_party/rust/error-chain/tests/tests.rs
third_party/rust/metadeps/.cargo-checksum.json
third_party/rust/metadeps/.cargo-ok
third_party/rust/metadeps/.gitignore
third_party/rust/metadeps/Cargo.toml
third_party/rust/metadeps/README.md
third_party/rust/metadeps/src/lib.rs
third_party/rust/metadeps/tests/test.rs
third_party/rust/metadeps/tests/testdata.pc
third_party/rust/metadeps/tests/testlib.pc
third_party/rust/metadeps/tests/toml-missing-file/no-cargo-toml-here
third_party/rust/offscreen_gl_context/.cargo-checksum.json
third_party/rust/offscreen_gl_context/.cargo-ok
third_party/rust/offscreen_gl_context/.gitignore
third_party/rust/offscreen_gl_context/.travis.yml
third_party/rust/offscreen_gl_context/Cargo.toml
third_party/rust/offscreen_gl_context/Makefile
third_party/rust/offscreen_gl_context/README.md
third_party/rust/offscreen_gl_context/build.rs
third_party/rust/offscreen_gl_context/src/draw_buffer.rs
third_party/rust/offscreen_gl_context/src/gl_context.rs
third_party/rust/offscreen_gl_context/src/gl_context_attributes.rs
third_party/rust/offscreen_gl_context/src/gl_context_capabilities.rs
third_party/rust/offscreen_gl_context/src/gl_feature.rs
third_party/rust/offscreen_gl_context/src/gl_formats.rs
third_party/rust/offscreen_gl_context/src/gl_limits.rs
third_party/rust/offscreen_gl_context/src/lib.rs
third_party/rust/offscreen_gl_context/src/platform/mod.rs
third_party/rust/offscreen_gl_context/src/platform/not_implemented/mod.rs
third_party/rust/offscreen_gl_context/src/platform/not_implemented/native_gl_context.rs
third_party/rust/offscreen_gl_context/src/platform/with_cgl/mod.rs
third_party/rust/offscreen_gl_context/src/platform/with_cgl/native_gl_context.rs
third_party/rust/offscreen_gl_context/src/platform/with_egl/mod.rs
third_party/rust/offscreen_gl_context/src/platform/with_egl/native_gl_context.rs
third_party/rust/offscreen_gl_context/src/platform/with_egl/utils.rs
third_party/rust/offscreen_gl_context/src/platform/with_glx/mod.rs
third_party/rust/offscreen_gl_context/src/platform/with_glx/native_gl_context.rs
third_party/rust/offscreen_gl_context/src/platform/with_glx/utils.rs
third_party/rust/offscreen_gl_context/src/platform/with_osmesa/mod.rs
third_party/rust/offscreen_gl_context/src/platform/with_wgl/mod.rs
third_party/rust/offscreen_gl_context/src/platform/with_wgl/native_gl_context.rs
third_party/rust/offscreen_gl_context/src/platform/with_wgl/utils.rs
third_party/rust/offscreen_gl_context/src/platform/with_wgl/wgl_attributes.rs
third_party/rust/offscreen_gl_context/src/tests.rs
third_party/rust/osmesa-sys/.cargo-checksum.json
third_party/rust/osmesa-sys/.cargo-ok
third_party/rust/osmesa-sys/.gitignore
third_party/rust/osmesa-sys/Cargo.toml
third_party/rust/osmesa-sys/README.txt
third_party/rust/osmesa-sys/lib.rs
third_party/rust/shared_library/.cargo-checksum.json
third_party/rust/shared_library/.cargo-ok
third_party/rust/shared_library/.gitignore
third_party/rust/shared_library/.travis.yml
third_party/rust/shared_library/Cargo.toml
third_party/rust/shared_library/src/dynamic_library.rs
third_party/rust/shared_library/src/lib.rs
third_party/rust/toml/.cargo-checksum.json
third_party/rust/toml/.cargo-ok
third_party/rust/toml/.gitignore
third_party/rust/toml/.travis.yml
third_party/rust/toml/Cargo.toml
third_party/rust/toml/LICENSE-APACHE
third_party/rust/toml/LICENSE-MIT
third_party/rust/toml/README.md
third_party/rust/toml/examples/toml2json.rs
third_party/rust/toml/src/decoder/mod.rs
third_party/rust/toml/src/decoder/rustc_serialize.rs
third_party/rust/toml/src/decoder/serde.rs
third_party/rust/toml/src/display.rs
third_party/rust/toml/src/encoder/mod.rs
third_party/rust/toml/src/encoder/rustc_serialize.rs
third_party/rust/toml/src/encoder/serde.rs
third_party/rust/toml/src/lib.rs
third_party/rust/toml/src/parser.rs
third_party/rust/toml/tests/README.md
third_party/rust/toml/tests/formatting.rs
third_party/rust/toml/tests/invalid-encoder/array-mixed-types-ints-and-floats.json
third_party/rust/toml/tests/invalid.rs
third_party/rust/toml/tests/invalid/array-mixed-types-arrays-and-ints.toml
third_party/rust/toml/tests/invalid/array-mixed-types-ints-and-floats.toml
third_party/rust/toml/tests/invalid/array-mixed-types-strings-and-ints.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-leads.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-secs.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-t.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-z.toml
third_party/rust/toml/tests/invalid/datetime-malformed-with-milli.toml
third_party/rust/toml/tests/invalid/duplicate-key-table.toml
third_party/rust/toml/tests/invalid/duplicate-keys.toml
third_party/rust/toml/tests/invalid/duplicate-tables.toml
third_party/rust/toml/tests/invalid/empty-implicit-table.toml
third_party/rust/toml/tests/invalid/empty-table.toml
third_party/rust/toml/tests/invalid/float-no-leading-zero.toml
third_party/rust/toml/tests/invalid/float-no-trailing-digits.toml
third_party/rust/toml/tests/invalid/key-after-array.toml
third_party/rust/toml/tests/invalid/key-after-table.toml
third_party/rust/toml/tests/invalid/key-empty.toml
third_party/rust/toml/tests/invalid/key-hash.toml
third_party/rust/toml/tests/invalid/key-newline.toml
third_party/rust/toml/tests/invalid/key-open-bracket.toml
third_party/rust/toml/tests/invalid/key-single-open-bracket.toml
third_party/rust/toml/tests/invalid/key-space.toml
third_party/rust/toml/tests/invalid/key-start-bracket.toml
third_party/rust/toml/tests/invalid/key-two-equals.toml
third_party/rust/toml/tests/invalid/string-bad-byte-escape.toml
third_party/rust/toml/tests/invalid/string-bad-escape.toml
third_party/rust/toml/tests/invalid/string-byte-escapes.toml
third_party/rust/toml/tests/invalid/string-no-close.toml
third_party/rust/toml/tests/invalid/table-array-implicit.toml
third_party/rust/toml/tests/invalid/table-array-malformed-bracket.toml
third_party/rust/toml/tests/invalid/table-array-malformed-empty.toml
third_party/rust/toml/tests/invalid/table-empty.toml
third_party/rust/toml/tests/invalid/table-nested-brackets-close.toml
third_party/rust/toml/tests/invalid/table-nested-brackets-open.toml
third_party/rust/toml/tests/invalid/table-whitespace.toml
third_party/rust/toml/tests/invalid/table-with-pound.toml
third_party/rust/toml/tests/invalid/text-after-array-entries.toml
third_party/rust/toml/tests/invalid/text-after-integer.toml
third_party/rust/toml/tests/invalid/text-after-string.toml
third_party/rust/toml/tests/invalid/text-after-table.toml
third_party/rust/toml/tests/invalid/text-before-array-separator.toml
third_party/rust/toml/tests/invalid/text-in-array.toml
third_party/rust/toml/tests/valid.rs
third_party/rust/toml/tests/valid/array-empty.json
third_party/rust/toml/tests/valid/array-empty.toml
third_party/rust/toml/tests/valid/array-nospaces.json
third_party/rust/toml/tests/valid/array-nospaces.toml
third_party/rust/toml/tests/valid/arrays-hetergeneous.json
third_party/rust/toml/tests/valid/arrays-hetergeneous.toml
third_party/rust/toml/tests/valid/arrays-nested.json
third_party/rust/toml/tests/valid/arrays-nested.toml
third_party/rust/toml/tests/valid/arrays.json
third_party/rust/toml/tests/valid/arrays.toml
third_party/rust/toml/tests/valid/bool.json
third_party/rust/toml/tests/valid/bool.toml
third_party/rust/toml/tests/valid/comments-everywhere.json
third_party/rust/toml/tests/valid/comments-everywhere.toml
third_party/rust/toml/tests/valid/datetime.json
third_party/rust/toml/tests/valid/datetime.toml
third_party/rust/toml/tests/valid/empty.json
third_party/rust/toml/tests/valid/empty.toml
third_party/rust/toml/tests/valid/example-bom.toml
third_party/rust/toml/tests/valid/example-v0.3.0.json
third_party/rust/toml/tests/valid/example-v0.3.0.toml
third_party/rust/toml/tests/valid/example-v0.4.0.json
third_party/rust/toml/tests/valid/example-v0.4.0.toml
third_party/rust/toml/tests/valid/example.json
third_party/rust/toml/tests/valid/example.toml
third_party/rust/toml/tests/valid/example2.json
third_party/rust/toml/tests/valid/example2.toml
third_party/rust/toml/tests/valid/float.json
third_party/rust/toml/tests/valid/float.toml
third_party/rust/toml/tests/valid/hard_example.json
third_party/rust/toml/tests/valid/hard_example.toml
third_party/rust/toml/tests/valid/implicit-and-explicit-after.json
third_party/rust/toml/tests/valid/implicit-and-explicit-after.toml
third_party/rust/toml/tests/valid/implicit-and-explicit-before.json
third_party/rust/toml/tests/valid/implicit-and-explicit-before.toml
third_party/rust/toml/tests/valid/implicit-groups.json
third_party/rust/toml/tests/valid/implicit-groups.toml
third_party/rust/toml/tests/valid/integer.json
third_party/rust/toml/tests/valid/integer.toml
third_party/rust/toml/tests/valid/key-equals-nospace.json
third_party/rust/toml/tests/valid/key-equals-nospace.toml
third_party/rust/toml/tests/valid/key-space.json
third_party/rust/toml/tests/valid/key-space.toml
third_party/rust/toml/tests/valid/key-special-chars.json
third_party/rust/toml/tests/valid/key-special-chars.toml
third_party/rust/toml/tests/valid/key-with-pound.json
third_party/rust/toml/tests/valid/key-with-pound.toml
third_party/rust/toml/tests/valid/long-float.json
third_party/rust/toml/tests/valid/long-float.toml
third_party/rust/toml/tests/valid/long-integer.json
third_party/rust/toml/tests/valid/long-integer.toml
third_party/rust/toml/tests/valid/multiline-string.json
third_party/rust/toml/tests/valid/multiline-string.toml
third_party/rust/toml/tests/valid/raw-multiline-string.json
third_party/rust/toml/tests/valid/raw-multiline-string.toml
third_party/rust/toml/tests/valid/raw-string.json
third_party/rust/toml/tests/valid/raw-string.toml
third_party/rust/toml/tests/valid/string-empty.json
third_party/rust/toml/tests/valid/string-empty.toml
third_party/rust/toml/tests/valid/string-escapes.json
third_party/rust/toml/tests/valid/string-escapes.toml
third_party/rust/toml/tests/valid/string-simple.json
third_party/rust/toml/tests/valid/string-simple.toml
third_party/rust/toml/tests/valid/string-with-pound.json
third_party/rust/toml/tests/valid/string-with-pound.toml
third_party/rust/toml/tests/valid/table-array-implicit.json
third_party/rust/toml/tests/valid/table-array-implicit.toml
third_party/rust/toml/tests/valid/table-array-many.json
third_party/rust/toml/tests/valid/table-array-many.toml
third_party/rust/toml/tests/valid/table-array-nest.json
third_party/rust/toml/tests/valid/table-array-nest.toml
third_party/rust/toml/tests/valid/table-array-one.json
third_party/rust/toml/tests/valid/table-array-one.toml
third_party/rust/toml/tests/valid/table-empty.json
third_party/rust/toml/tests/valid/table-empty.toml
third_party/rust/toml/tests/valid/table-sub-empty.json
third_party/rust/toml/tests/valid/table-sub-empty.toml
third_party/rust/toml/tests/valid/table-whitespace.json
third_party/rust/toml/tests/valid/table-whitespace.toml
third_party/rust/toml/tests/valid/table-with-pound.json
third_party/rust/toml/tests/valid/table-with-pound.toml
third_party/rust/toml/tests/valid/unicode-escape.json
third_party/rust/toml/tests/valid/unicode-escape.toml
third_party/rust/toml/tests/valid/unicode-literal.json
third_party/rust/toml/tests/valid/unicode-literal.toml
third_party/rust/user32-sys/.cargo-checksum.json
third_party/rust/user32-sys/.cargo-ok
third_party/rust/user32-sys/Cargo.toml
third_party/rust/user32-sys/README.md
third_party/rust/user32-sys/build.rs
third_party/rust/user32-sys/src/lib.rs
third_party/rust/x11/.cargo-checksum.json
third_party/rust/x11/.cargo-ok
third_party/rust/x11/Cargo.toml
third_party/rust/x11/build.rs
third_party/rust/x11/examples/hello-world.rs
third_party/rust/x11/examples/input.rs
third_party/rust/x11/examples/xrecord.rs
third_party/rust/x11/src/dpms.rs
third_party/rust/x11/src/glx.rs
third_party/rust/x11/src/internal.rs
third_party/rust/x11/src/keysym.rs
third_party/rust/x11/src/lib.rs
third_party/rust/x11/src/link.rs
third_party/rust/x11/src/xcursor.rs
third_party/rust/x11/src/xf86vmode.rs
third_party/rust/x11/src/xfixes.rs
third_party/rust/x11/src/xft.rs
third_party/rust/x11/src/xinerama.rs
third_party/rust/x11/src/xinput.rs
third_party/rust/x11/src/xinput2.rs
third_party/rust/x11/src/xlib.rs
third_party/rust/x11/src/xlib_xcb.rs
third_party/rust/x11/src/xmd.rs
third_party/rust/x11/src/xmu.rs
third_party/rust/x11/src/xrandr.rs
third_party/rust/x11/src/xrecord.rs
third_party/rust/x11/src/xrender.rs
third_party/rust/x11/src/xss.rs
third_party/rust/x11/src/xt.rs
third_party/rust/x11/src/xtest.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: 0794911f97cae92496fca992d7430da696fa24eb
+Latest Commit: dafe3579e8dc886e6584116dc52a9362b543c169
--- a/gfx/webrender/Cargo.toml
+++ b/gfx/webrender/Cargo.toml
@@ -1,33 +1,34 @@
 [package]
 name = "webrender"
-version = "0.25.0"
+version = "0.26.0"
 authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
 license = "MPL-2.0"
 repository = "https://github.com/servo/webrender"
 build = "build.rs"
 
 [features]
-default = ["freetype-lib"]
+default = ["freetype-lib", "webgl"]
 freetype-lib = ["freetype/servo-freetype-sys"]
 profiler = ["thread_profiler/thread_profiler"]
+webgl = ["offscreen_gl_context", "webrender_traits/webgl"]
 
 [dependencies]
 app_units = "0.4"
 bincode = "1.0.0-alpha2"
 bit-set = "0.4"
 byteorder = "1.0"
 euclid = "0.11"
 fnv = "1.0"
 gleam = "0.4.1"
 lazy_static = "0.2"
 log = "0.3"
 num-traits = "0.1.32"
-offscreen_gl_context = {version = "0.8.0", features = ["serde", "osmesa"]}
+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"
 gamma-lut = "0.1"
 thread_profiler = "0.1.1"
 
 [dev-dependencies]
--- a/gfx/webrender/res/cs_blur.fs.glsl
+++ b/gfx/webrender/res/cs_blur.fs.glsl
@@ -10,31 +10,31 @@
 // TODO(gw): Make use of the bilinear sampling trick to reduce
 //           the number of texture fetches needed for a gaussian blur.
 
 float gauss(float x, float sigma) {
     return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
 }
 
 void main(void) {
-    vec4 cache_sample = texture(sCache, vUv);
+    vec4 cache_sample = texture(sCacheRGBA8, vUv);
     vec4 color = vec4(cache_sample.rgb, 1.0) * (cache_sample.a * gauss(0.0, vSigma));
 
     for (int i=1 ; i < vBlurRadius ; ++i) {
         vec2 offset = vec2(float(i)) * vOffsetScale;
 
         vec2 st0 = clamp(vUv.xy + offset, vUvRect.xy, vUvRect.zw);
-        vec4 color0 = texture(sCache, vec3(st0, vUv.z));
+        vec4 color0 = texture(sCacheRGBA8, vec3(st0, vUv.z));
 
         vec2 st1 = clamp(vUv.xy - offset, vUvRect.xy, vUvRect.zw);
-        vec4 color1 = texture(sCache, vec3(st1, vUv.z));
+        vec4 color1 = texture(sCacheRGBA8, vec3(st1, vUv.z));
 
         // Alpha must be premultiplied in order to properly blur the alpha channel.
         float weight = gauss(float(i), vSigma);
         color += vec4(color0.rgb * color0.a, color0.a) * weight;
         color += vec4(color1.rgb * color1.a, color1.a) * weight;
     }
 
     // Unpremultiply the alpha.
     color.rgb /= color.a;
 
-    oFragColor = color;
+    oFragColor = dither(color);
 }
--- a/gfx/webrender/res/cs_blur.vs.glsl
+++ b/gfx/webrender/res/cs_blur.vs.glsl
@@ -35,17 +35,17 @@ void main(void) {
     RenderTaskData src_task = fetch_render_task(cmd.src_task_id);
 
     vec4 local_rect = task.data0;
 
     vec2 pos = mix(local_rect.xy,
                    local_rect.xy + local_rect.zw,
                    aPosition.xy);
 
-    vec2 texture_size = vec2(textureSize(sCache, 0).xy);
+    vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0).xy);
     vUv.z = src_task.data1.x;
     vBlurRadius = int(task.data1.y);
     vSigma = task.data1.y * 0.5;
 
     switch (cmd.dir) {
         case DIR_HORIZONTAL:
             vOffsetScale = vec2(1.0 / texture_size.x, 0.0);
             break;
--- a/gfx/webrender/res/cs_box_shadow.fs.glsl
+++ b/gfx/webrender/res/cs_box_shadow.fs.glsl
@@ -139,10 +139,10 @@ float color(vec2 pos, vec2 p0Rect, vec2 
 void main(void) {
     vec2 pos = vPos.xy;
     vec2 p0Rect = vBoxShadowRect.xy, p1Rect = vBoxShadowRect.zw;
     vec2 radii = vBorderRadii.xy;
     float sigma = vBlurRadius / 2.0;
     float value = color(pos, p0Rect, p1Rect, radii, sigma);
 
     value = max(value, 0.0);
-    oFragColor = vec4(1.0, 1.0, 1.0, vInverted == 1.0 ? 1.0 - value : value);
+    oFragColor = dither(vec4(1.0, 1.0, 1.0, vInverted == 1.0 ? 1.0 - value : value));
 }
--- a/gfx/webrender/res/prim_shared.glsl
+++ b/gfx/webrender/res/prim_shared.glsl
@@ -28,17 +28,18 @@
 #define BORDER_BOTTOM    3
 
 #define UV_NORMALIZED    uint(0)
 #define UV_PIXEL         uint(1)
 
 #define EXTEND_MODE_CLAMP  0
 #define EXTEND_MODE_REPEAT 1
 
-uniform sampler2DArray sCache;
+uniform sampler2DArray sCacheA8;
+uniform sampler2DArray sCacheRGBA8;
 
 flat varying vec4 vClipMaskUvBounds;
 varying vec3 vClipMaskUv;
 
 #ifdef WR_VERTEX_SHADER
 
 #define VECS_PER_LAYER             13
 #define VECS_PER_RENDER_TASK        3
@@ -702,17 +703,17 @@ BoxShadow fetch_boxshadow(int index) {
     bs.bs_rect = texelFetchOffset(sData64, uv, 0, ivec2(1, 0));
     bs.color = texelFetchOffset(sData64, uv, 0, ivec2(2, 0));
     bs.border_radius_edge_size_blur_radius_inverted = texelFetchOffset(sData64, uv, 0, ivec2(3, 0));
 
     return bs;
 }
 
 void write_clip(vec2 global_pos, ClipArea area) {
-    vec2 texture_size = vec2(textureSize(sCache, 0).xy);
+    vec2 texture_size = vec2(textureSize(sCacheA8, 0).xy);
     vec2 uv = global_pos + area.task_bounds.xy - area.screen_origin_target_index.xy;
     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) {
@@ -750,11 +751,20 @@ vec2 init_transform_fs(vec3 local_pos, v
 
 float do_clip() {
     // anything outside of the mask is considered transparent
     bvec4 inside = lessThanEqual(
         vec4(vClipMaskUvBounds.xy, vClipMaskUv.xy),
         vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw));
     // check for the dummy bounds, which are given to the opaque objects
     return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0:
-        all(inside) ? textureLod(sCache, vClipMaskUv, 0.0).r : 0.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_factor = 4.0 / 255.0;
+    float noise = texelFetch(sDither, pos, 0).r * noise_factor;
+    return color + vec4(noise, noise, noise, 0);
 }
 #endif //WR_FRAGMENT_SHADER
--- a/gfx/webrender/res/ps_angle_gradient.fs.glsl
+++ b/gfx/webrender/res/ps_angle_gradient.fs.glsl
@@ -6,16 +6,15 @@ uniform sampler2D sGradients;
 
 void main(void) {
     vec2 texture_size = vec2(textureSize(sGradients, 0));
 
     // Either saturate or modulo the offset depending on repeat mode, then scale to number of
     // gradient color entries (texture width / 2).
     float x = mix(clamp(vOffset, 0.0, 1.0), fract(vOffset), vGradientRepeat) * 0.5 * texture_size.x;
 
-    // Start at the center of first color in the nearest 2-color entry, then offset with the
-    // fractional remainder to interpolate between the colors. Rely on texture clamping when
-    // outside of valid range.
     x = 2.0 * floor(x) + 0.5 + fract(x);
 
-    // Normalize the texture coordates so we can use texture() for bilinear filtering.
-    oFragColor = texture(sGradients, vec2(x, vGradientIndex) / texture_size);
+    // Use linear filtering to mix in the low bits (vGradientIndex + 1) with the high
+    // bits (vGradientIndex)
+    float y = vGradientIndex * 2.0 + 0.5 + 1.0 / 256.0;
+    oFragColor = dither(texture(sGradients, vec2(x, y) / texture_size));
 }
--- a/gfx/webrender/res/ps_angle_gradient.vs.glsl
+++ b/gfx/webrender/res/ps_angle_gradient.vs.glsl
@@ -22,13 +22,13 @@ void main(void) {
     vec2 start_point = floor(0.5 + gradient.start_end_point.xy * uDevicePixelRatio) / uDevicePixelRatio;
     vec2 end_point = floor(0.5 + gradient.start_end_point.zw * uDevicePixelRatio) / uDevicePixelRatio;
 
     vec2 dir = end_point - start_point;
     // Normalized offset of this vertex within the gradient, before clamp/repeat.
     vOffset = dot(vi.local_pos - start_point, dir) / dot(dir, dir);
 
     // V coordinate of gradient row in lookup texture.
-    vGradientIndex = float(prim.sub_index) + 0.5;
+    vGradientIndex = float(prim.sub_index);
 
     // Whether to repeat the gradient instead of clamping.
     vGradientRepeat = float(int(gradient.extend_mode.x) == EXTEND_MODE_REPEAT);
 }
--- a/gfx/webrender/res/ps_blend.fs.glsl
+++ b/gfx/webrender/res/ps_blend.fs.glsl
@@ -94,17 +94,17 @@ vec4 Brightness(vec4 Cs, float amount) {
     return vec4(Cs.rgb * amount, Cs.a);
 }
 
 vec4 Opacity(vec4 Cs, float amount) {
     return vec4(Cs.rgb, Cs.a * amount);
 }
 
 void main(void) {
-    vec4 Cs = texture(sCache, vUv);
+    vec4 Cs = texture(sCacheRGBA8, vUv);
 
     if (Cs.a == 0.0) {
         discard;
     }
 
     switch (vOp) {
         case 0:
             // Gaussian blur is specially handled:
--- a/gfx/webrender/res/ps_blend.vs.glsl
+++ b/gfx/webrender/res/ps_blend.vs.glsl
@@ -11,17 +11,17 @@ void main(void) {
     vec2 dest_origin = dest_task.render_target_origin -
                        dest_task.screen_space_origin +
                        src_task.screen_space_origin;
 
     vec2 local_pos = mix(dest_origin,
                          dest_origin + src_task.size,
                          aPosition.xy);
 
-    vec2 texture_size = vec2(textureSize(sCache, 0));
+    vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
     vec2 st0 = src_task.render_target_origin / texture_size;
     vec2 st1 = (src_task.render_target_origin + src_task.size) / texture_size;
     vUv = vec3(mix(st0, st1, aPosition.xy), src_task.render_target_layer_index);
 
     vOp = pi.sub_index;
     vAmount = float(pi.user_data.y) / 65535.0;
 
     gl_Position = uTransform * vec4(local_pos, pi.z, 1.0);
--- a/gfx/webrender/res/ps_border.fs.glsl
+++ b/gfx/webrender/res/ps_border.fs.glsl
@@ -361,20 +361,34 @@ void draw_mixed_border(float distanceFro
     case PST_TOP_LEFT:
     case PST_TOP_RIGHT:
     case PST_BOTTOM_LEFT:
     case PST_BOTTOM_RIGHT: {
       // This is the conversion factor for transformations and device pixel scaling.
       float pixelsPerFragment = length(fwidth(localPos.xy));
       vec4 color = get_fragment_color(distanceFromMixLine, pixelsPerFragment);
 
-      float distance = distance(vRefPoint, localPos) - vRadii.z;
-      float length = vRadii.x - vRadii.z;
-      if (distanceFromMiddle < 0.0) {
-        distance = length - distance;
+      if (vRadii.x > 0.0) {
+        float distance = distance(vRefPoint, localPos) - vRadii.z;
+        float length = vRadii.x - vRadii.z;
+        if (distanceFromMiddle < 0.0) {
+          distance = length - distance;
+        }
+
+        oFragColor = 0.0 <= distance && distance <= length ?
+          draw_mixed_edge(distance, length, color, brightness_mod) : vec4(0.0, 0.0, 0.0, 0.0);
+        break;
+      }
+
+      bool is_vertical = (vBorderPart == PST_TOP_LEFT) ? distanceFromMixLine < 0.0 :
+                                                         distanceFromMixLine >= 0.0;
+      float distance = is_vertical ? abs(localPos.x - vRefPoint.x) : abs(localPos.y - vRefPoint.y);
+      float length = is_vertical ? abs(vPieceRect.z) : abs(vPieceRect.w);
+      if (distanceFromMiddle > 0.0) {
+          distance = length - distance;
       }
 
       oFragColor = 0.0 <= distance && distance <= length ?
         draw_mixed_edge(distance, length, color, brightness_mod) : vec4(0.0, 0.0, 0.0, 0.0);
       break;
     }
     case PST_BOTTOM:
     case PST_TOP: {
--- a/gfx/webrender/res/ps_box_shadow.fs.glsl
+++ b/gfx/webrender/res/ps_box_shadow.fs.glsl
@@ -11,10 +11,10 @@ void main(void) {
     // shadow corner. This can happen, for example, when
     // drawing the outer parts of an inset box shadow.
     uv = clamp(uv, vec2(0.0), vec2(1.0));
 
     // Map the unit UV to the actual UV rect in the cache.
     uv = mix(vCacheUvRectCoords.xy, vCacheUvRectCoords.zw, uv);
 
     // Modulate the box shadow by the color.
-    oFragColor = vColor * texture(sCache, vec3(uv, vUv.z));
+    oFragColor = dither(vColor * texture(sCacheRGBA8, vec3(uv, vUv.z)));
 }
--- a/gfx/webrender/res/ps_box_shadow.vs.glsl
+++ b/gfx/webrender/res/ps_box_shadow.vs.glsl
@@ -20,13 +20,13 @@ void main(void) {
     // Constant offsets to inset from bilinear filtering border.
     vec2 patch_origin = child_task.data0.xy + vec2(1.0);
     vec2 patch_size_device_pixels = child_task.data0.zw - vec2(2.0);
     vec2 patch_size = patch_size_device_pixels / uDevicePixelRatio;
 
     vUv.xy = (vi.local_pos - prim.local_rect.p0) / patch_size;
     vMirrorPoint = 0.5 * prim.local_rect.size / patch_size;
 
-    vec2 texture_size = vec2(textureSize(sCache, 0));
+    vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
     vCacheUvRectCoords = vec4(patch_origin, patch_origin + patch_size_device_pixels) / texture_size.xyxy;
 
     vColor = bs.color;
 }
--- a/gfx/webrender/res/ps_cache_image.fs.glsl
+++ b/gfx/webrender/res/ps_cache_image.fs.glsl
@@ -1,7 +1,7 @@
 /* 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 main(void) {
-    oFragColor = texture(sCache, vUv);
+    oFragColor = texture(sCacheRGBA8, vUv);
 }
--- a/gfx/webrender/res/ps_cache_image.vs.glsl
+++ b/gfx/webrender/res/ps_cache_image.vs.glsl
@@ -13,16 +13,16 @@ void main(void) {
                                  prim.local_clip_rect,
                                  prim.z,
                                  prim.layer,
                                  prim.task);
 
     RenderTaskData child_task = fetch_render_task(prim.user_data.x);
     vUv.z = child_task.data1.x;
 
-    vec2 texture_size = vec2(textureSize(sCache, 0));
+    vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
     vec2 uv0 = child_task.data0.xy / texture_size;
     vec2 uv1 = (child_task.data0.xy + child_task.data0.zw) / texture_size;
 
     vec2 f = (vi.local_pos - prim.local_rect.p0) / prim.local_rect.size;
 
     vUv.xy = mix(uv0, uv1, f);
 }
--- a/gfx/webrender/res/ps_composite.fs.glsl
+++ b/gfx/webrender/res/ps_composite.fs.glsl
@@ -163,18 +163,18 @@ const int MixBlendMode_SoftLight   = 9;
 const int MixBlendMode_Difference  = 10;
 const int MixBlendMode_Exclusion   = 11;
 const int MixBlendMode_Hue         = 12;
 const int MixBlendMode_Saturation  = 13;
 const int MixBlendMode_Color       = 14;
 const int MixBlendMode_Luminosity  = 15;
 
 void main(void) {
-    vec4 Cb = texture(sCache, vUv0);
-    vec4 Cs = texture(sCache, vUv1);
+    vec4 Cb = texture(sCacheRGBA8, vUv0);
+    vec4 Cs = texture(sCacheRGBA8, vUv1);
 
     // Return yellow if none of the branches match (shouldn't happen).
     vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
 
     switch (vOp) {
         case MixBlendMode_Multiply:
             result.rgb = Multiply(Cb.rgb, Cs.rgb);
             break;
--- a/gfx/webrender/res/ps_composite.vs.glsl
+++ b/gfx/webrender/res/ps_composite.vs.glsl
@@ -12,17 +12,17 @@ void main(void) {
     vec2 dest_origin = dest_task.render_target_origin -
                        dest_task.screen_space_origin +
                        src_task.screen_space_origin;
 
     vec2 local_pos = mix(dest_origin,
                          dest_origin + src_task.size,
                          aPosition.xy);
 
-    vec2 texture_size = vec2(textureSize(sCache, 0));
+    vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
 
     vec2 st0 = backdrop_task.render_target_origin / texture_size;
     vec2 st1 = (backdrop_task.render_target_origin + backdrop_task.size) / texture_size;
     vUv0 = vec3(mix(st0, st1, aPosition.xy), backdrop_task.render_target_layer_index);
 
     st0 = src_task.render_target_origin / texture_size;
     st1 = (src_task.render_target_origin + src_task.size) / texture_size;
     vUv1 = vec3(mix(st0, st1, aPosition.xy), src_task.render_target_layer_index);
--- a/gfx/webrender/res/ps_gradient.fs.glsl
+++ b/gfx/webrender/res/ps_gradient.fs.glsl
@@ -7,10 +7,10 @@ void main(void) {
     float alpha = 0.0;
     vec2 local_pos = init_transform_fs(vLocalPos, vLocalRect, alpha);
 #else
     float alpha = 1.0;
     vec2 local_pos = vPos;
 #endif
 
     alpha = min(alpha, do_clip());
-    oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha);
+    oFragColor = dither(vColor * vec4(1.0, 1.0, 1.0, alpha));
 }
--- a/gfx/webrender/res/ps_gradient.vs.glsl
+++ b/gfx/webrender/res/ps_gradient.vs.glsl
@@ -10,41 +10,53 @@ void main(void) {
     GradientStop g0 = fetch_gradient_stop(prim.sub_index + 0);
     GradientStop g1 = fetch_gradient_stop(prim.sub_index + 1);
 
     RectWithSize segment_rect;
     vec2 axis;
     vec4 adjusted_color_g0 = g0.color;
     vec4 adjusted_color_g1 = g1.color;
     if (gradient.start_end_point.y == gradient.start_end_point.w) {
-        vec2 x = mix(gradient.start_end_point.xx, gradient.start_end_point.zz,
-                     vec2(g0.offset.x, g1.offset.x));
+        // Calculate the x coord of the gradient stops
+        vec2 g01_x = mix(gradient.start_end_point.xx, gradient.start_end_point.zz,
+                         vec2(g0.offset.x, g1.offset.x));
+
         // The start and end point of gradient might exceed the geometry rect. So clamp
         // it to the geometry rect.
-        x = clamp(x, prim.local_rect.p0.xx, prim.local_rect.p0.xx + prim.local_rect.size.xx);
+        g01_x = clamp(g01_x, prim.local_rect.p0.xx, prim.local_rect.p0.xx + prim.local_rect.size.xx);
+
+        // Calculate the rect using the clamped coords
+        segment_rect.p0 = vec2(g01_x.x, prim.local_rect.p0.y);
+        segment_rect.size = vec2(g01_x.y - g01_x.x, prim.local_rect.size.y);
+        axis = vec2(1.0, 0.0);
+
+        // We need to adjust the colors of the stops because they may have been clamped
         vec2 adjusted_offset =
-            (x - gradient.start_end_point.xx) / (gradient.start_end_point.zz - gradient.start_end_point.xx);
+            (g01_x - segment_rect.p0.xx) / segment_rect.size.xx;
         adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
         adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
-        segment_rect.p0 = vec2(x.x, prim.local_rect.p0.y);
-        segment_rect.size = vec2(x.y - x.x, prim.local_rect.size.y);
-        axis = vec2(1.0, 0.0);
     } else {
-        vec2 y = mix(gradient.start_end_point.yy, gradient.start_end_point.ww,
-                     vec2(g0.offset.x, g1.offset.x));
+        // Calculate the y coord of the gradient stops
+        vec2 g01_y = mix(gradient.start_end_point.yy, gradient.start_end_point.ww,
+                         vec2(g0.offset.x, g1.offset.x));
+
         // The start and end point of gradient might exceed the geometry rect. So clamp
         // it to the geometry rect.
-        y = clamp(y, prim.local_rect.p0.yy, prim.local_rect.p0.yy + prim.local_rect.size.yy);
+        g01_y = clamp(g01_y, prim.local_rect.p0.yy, prim.local_rect.p0.yy + prim.local_rect.size.yy);
+
+        // Calculate the rect using the clamped coords
+        segment_rect.p0 = vec2(prim.local_rect.p0.x, g01_y.x);
+        segment_rect.size = vec2(prim.local_rect.size.x, g01_y.y - g01_y.x);
+        axis = vec2(0.0, 1.0);
+
+        // We need to adjust the colors of the stops because they may have been clamped
         vec2 adjusted_offset =
-            (y - gradient.start_end_point.yy) / (gradient.start_end_point.ww - gradient.start_end_point.yy);
+            (g01_y - segment_rect.p0.yy) / segment_rect.size.yy;
         adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
         adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
-        segment_rect.p0 = vec2(prim.local_rect.p0.x, y.x);
-        segment_rect.size = vec2(prim.local_rect.size.x, y.y - y.x);
-        axis = vec2(0.0, 1.0);
     }
 
 #ifdef WR_FEATURE_TRANSFORM
     TransformVertexInfo vi = write_transform_vertex(segment_rect,
                                                     prim.local_clip_rect,
                                                     prim.z,
                                                     prim.layer,
                                                     prim.task);
--- a/gfx/webrender/res/ps_hardware_composite.fs.glsl
+++ b/gfx/webrender/res/ps_hardware_composite.fs.glsl
@@ -1,7 +1,7 @@
 /* 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 main(void) {
-    oFragColor = texture(sCache, vUv);
+    oFragColor = texture(sCacheRGBA8, vUv);
 }
--- a/gfx/webrender/res/ps_hardware_composite.vs.glsl
+++ b/gfx/webrender/res/ps_hardware_composite.vs.glsl
@@ -11,15 +11,15 @@ void main(void) {
     vec2 dest_origin = dest_task.render_target_origin -
                        dest_task.screen_space_origin +
                        src_task.screen_space_origin;
 
     vec2 local_pos = mix(dest_origin,
                          dest_origin + src_task.size,
                          aPosition.xy);
 
-    vec2 texture_size = vec2(textureSize(sCache, 0));
+    vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
     vec2 st0 = src_task.render_target_origin / texture_size;
     vec2 st1 = (src_task.render_target_origin + src_task.size) / texture_size;
     vUv = vec3(mix(st0, st1, aPosition.xy), src_task.render_target_layer_index);
 
     gl_Position = uTransform * vec4(local_pos, pi.z, 1.0);
 }
--- a/gfx/webrender/res/ps_radial_gradient.fs.glsl
+++ b/gfx/webrender/res/ps_radial_gradient.fs.glsl
@@ -45,16 +45,15 @@ void main(void) {
     }
 
     vec2 texture_size = vec2(textureSize(sGradients, 0));
 
     // Either saturate or modulo the offset depending on repeat mode, then scale to number of
     // gradient color entries (texture width / 2).
     x = mix(clamp(x, 0.0, 1.0), fract(x), vGradientRepeat) * 0.5 * texture_size.x;
 
-    // Start at the center of first color in the nearest 2-color entry, then offset with the
-    // fractional remainder to interpolate between the colors. Rely on texture clamping when
-    // outside of valid range.
     x = 2.0 * floor(x) + 0.5 + fract(x);
 
-    // Normalize the texture coordates so we can use texture() for bilinear filtering.
-    oFragColor = texture(sGradients, vec2(x, vGradientIndex) / texture_size);
+    // Use linear filtering to mix in the low bits (vGradientIndex + 1) with the high
+    // bits (vGradientIndex)
+    float y = vGradientIndex * 2.0 + 0.5 + 1.0 / 256.0;
+    oFragColor = dither(texture(sGradients, vec2(x, y) / texture_size));
 }
--- a/gfx/webrender/res/ps_radial_gradient.vs.glsl
+++ b/gfx/webrender/res/ps_radial_gradient.vs.glsl
@@ -22,13 +22,13 @@ void main(void) {
     // be better to fix this higher up in DL construction
     // and not snap here?
     vStartCenter = floor(0.5 + gradient.start_end_center.xy * uDevicePixelRatio) / uDevicePixelRatio;
     vEndCenter = floor(0.5 + gradient.start_end_center.zw * uDevicePixelRatio) / uDevicePixelRatio;
     vStartRadius = gradient.start_end_radius_extend_mode.x;
     vEndRadius = gradient.start_end_radius_extend_mode.y;
 
     // V coordinate of gradient row in lookup texture.
-    vGradientIndex = float(prim.sub_index) + 0.5;
+    vGradientIndex = float(prim.sub_index);
 
     // Whether to repeat the gradient instead of clamping.
     vGradientRepeat = float(int(gradient.start_end_radius_extend_mode.z) == EXTEND_MODE_REPEAT);
 }
--- a/gfx/webrender/res/shared.glsl
+++ b/gfx/webrender/res/shared.glsl
@@ -31,16 +31,17 @@
 #endif
 
 //======================================================================================
 // Shared shader uniforms
 //======================================================================================
 uniform sampler2D sColor0;
 uniform sampler2D sColor1;
 uniform sampler2D sColor2;
+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
@@ -243,19 +243,23 @@ impl ClipScrollNode {
             inv_transform.pre_translated(-parent_accumulated_scroll_offset.x,
                                          -parent_accumulated_scroll_offset.y,
                                          0.0)
                          .transform_rect(parent_combined_viewport_rect);
 
         // Now that we have the combined viewport rectangle of the parent nodes in local space,
         // we do the intersection and get our combined viewport rect in the coordinate system
         // starting from our origin.
-        self.combined_local_viewport_rect =
-            parent_combined_viewport_in_local_space.intersection(&self.local_clip_rect)
-                                                    .unwrap_or(LayerRect::zero());
+        self.combined_local_viewport_rect = match self.node_type {
+            NodeType::Clip(_) => {
+                parent_combined_viewport_in_local_space.intersection(&self.local_clip_rect)
+                                                       .unwrap_or(LayerRect::zero())
+            }
+            NodeType::ReferenceFrame(_) => parent_combined_viewport_in_local_space,
+        };
 
         // The transformation for this viewport in world coordinates is the transformation for
         // our parent reference frame, plus any accumulated scrolling offsets from nodes
         // between our reference frame and this node. For reference frames, we also include
         // whatever local transformation this reference frame provides. This can be combined
         // with the local_viewport_rect to get its position in world space.
         self.world_viewport_transform =
             parent_reference_frame_transform
--- a/gfx/webrender/src/device.rs
+++ b/gfx/webrender/src/device.rs
@@ -1542,24 +1542,32 @@ impl Device {
         let u_color1 = self.gl.get_uniform_location(program.id, "sColor1");
         if u_color1 != -1 {
             self.gl.uniform_1i(u_color1, TextureSampler::Color1 as i32);
         }
         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 = self.gl.get_uniform_location(program.id, "sCache");
-        if u_cache != -1 {
-            self.gl.uniform_1i(u_cache, TextureSampler::Cache 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);
         }
 
         let u_layers = self.gl.get_uniform_location(program.id, "sLayers");
         if u_layers != -1 {
             self.gl.uniform_1i(u_layers, TextureSampler::Layers as i32);
         }
 
         let u_tasks = self.gl.get_uniform_location(program.id, "sRenderTasks");
--- a/gfx/webrender/src/frame.rs
+++ b/gfx/webrender/src/frame.rs
@@ -11,19 +11,20 @@ use internal_types::{RendererFrame};
 use frame_builder::{FrameBuilder, FrameBuilderConfig};
 use clip_scroll_tree::{ClipScrollTree, ScrollStates};
 use profiler::TextureCacheProfileCounters;
 use resource_cache::ResourceCache;
 use scene::{Scene, SceneProperties};
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
 use tiling::{AuxiliaryListsMap, CompositeOps, PrimitiveFlags};
+use util::subtract_rect;
 use webrender_traits::{AuxiliaryLists, ClipDisplayItem, ClipRegion, ColorF, DeviceUintRect};
 use webrender_traits::{DeviceUintSize, DisplayItem, Epoch, FilterOp, ImageDisplayItem, LayerPoint};
-use webrender_traits::{LayerRect, LayerSize, LayerToScrollTransform, LayoutTransform};
+use webrender_traits::{LayerRect, LayerSize, LayerToScrollTransform, LayoutRect, LayoutTransform};
 use webrender_traits::{MixBlendMode, PipelineId, ScrollEventPhase, ScrollLayerId};
 use webrender_traits::{ScrollLayerState, ScrollLocation, ScrollPolicy, SpecificDisplayItem};
 use webrender_traits::{StackingContext, TileOffset, WorldPoint};
 
 #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
 pub struct FrameId(pub u32);
 
 static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { r: 0.3, g: 0.3, b: 0.3, a: 0.6 };
@@ -62,24 +63,24 @@ pub struct Frame {
     pub pipeline_epoch_map: HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>>,
     pub pipeline_auxiliary_lists: AuxiliaryListsMap,
     id: FrameId,
     frame_builder_config: FrameBuilderConfig,
     frame_builder: Option<FrameBuilder>,
 }
 
 trait DisplayListHelpers {
-    fn starting_stacking_context<'a>(&'a self) -> Option<(&'a StackingContext, &'a ClipRegion)>;
+    fn starting_stacking_context<'a>(&'a self) -> Option<(&'a StackingContext, &'a LayoutRect)>;
 }
 
 impl DisplayListHelpers for Vec<DisplayItem> {
-    fn starting_stacking_context<'a>(&'a self) -> Option<(&'a StackingContext, &'a ClipRegion)> {
+    fn starting_stacking_context<'a>(&'a self) -> Option<(&'a StackingContext, &'a LayoutRect)> {
         self.first().and_then(|item| match item.item {
             SpecificDisplayItem::PushStackingContext(ref specific_item) => {
-                Some((&specific_item.stacking_context, &item.clip))
+                Some((&specific_item.stacking_context, &item.rect))
             },
             _ => None,
         })
     }
 }
 
 trait StackingContextHelpers {
     fn mix_blend_mode_for_compositing(&self) -> Option<MixBlendMode>;
@@ -200,16 +201,32 @@ impl<'a> Iterator for DisplayListTravers
         }
 
         let item = &self.display_list[self.next_item_index];
         self.next_item_index += 1;
         Some(item)
     }
 }
 
+fn clip_intersection(original_rect: &LayerRect,
+                     region: &ClipRegion,
+                     aux_lists: &AuxiliaryLists)
+                     -> Option<LayerRect> {
+    if region.image_mask.is_some() {
+        return None;
+    }
+    let clips = aux_lists.complex_clip_regions(&region.complex);
+    let base_rect = region.main.intersection(original_rect);
+    clips.iter().fold(base_rect, |inner_combined, ccr| {
+        inner_combined.and_then(|combined| {
+            ccr.get_inner_rect().and_then(|ir| ir.intersection(&combined))
+        })
+    })
+}
+
 impl Frame {
     pub fn new(config: FrameBuilderConfig) -> Frame {
         Frame {
             pipeline_epoch_map: HashMap::with_hasher(Default::default()),
             pipeline_auxiliary_lists: HashMap::with_hasher(Default::default()),
             clip_scroll_tree: ClipScrollTree::new(),
             id: FrameId(0),
             frame_builder: None,
@@ -279,17 +296,17 @@ impl Frame {
             return;
         }
 
         let old_scrolling_states = self.reset();
         self.pipeline_auxiliary_lists = scene.pipeline_auxiliary_lists.clone();
 
         self.pipeline_epoch_map.insert(root_pipeline_id, root_pipeline.epoch);
 
-        let (root_stacking_context, root_clip) = match display_list.starting_stacking_context() {
+        let (root_stacking_context, root_bounds) = match display_list.starting_stacking_context() {
             Some(some) => some,
             None => {
                 warn!("Pipeline display list does not start with a stacking context.");
                 return;
             }
         };
 
         let background_color = root_pipeline.background_color.and_then(|color| {
@@ -304,33 +321,33 @@ impl Frame {
                                                   background_color,
                                                   self.frame_builder_config);
 
         {
             let mut context = FlattenContext::new(scene, &mut frame_builder, resource_cache);
 
             let scroll_layer_id = context.builder.push_root(root_pipeline_id,
                                                             &root_pipeline.viewport_size,
-                                                            &root_clip.main.size,
+                                                            &root_bounds.size,
                                                             &mut self.clip_scroll_tree);
 
             context.builder.setup_viewport_offset(window_size,
                                                   inner_rect,
                                                   device_pixel_ratio,
                                                   &mut self.clip_scroll_tree);
 
             let mut traversal = DisplayListTraversal::new_skipping_first(display_list);
             self.flatten_stacking_context(&mut traversal,
                                           root_pipeline_id,
                                           &mut context,
                                           scroll_layer_id,
                                           LayerPoint::zero(),
                                           0,
-                                          &root_stacking_context,
-                                          root_clip);
+                                          &root_bounds,
+                                          &root_stacking_context);
         }
 
         self.frame_builder = Some(frame_builder);
         self.clip_scroll_tree.finalize_and_apply_pending_scroll_offsets(old_scrolling_states);
     }
 
     fn flatten_clip<'a>(&mut self,
                         context: &mut FlattenContext,
@@ -352,18 +369,18 @@ impl Frame {
 
     fn flatten_stacking_context<'a>(&mut self,
                                     traversal: &mut DisplayListTraversal<'a>,
                                     pipeline_id: PipelineId,
                                     context: &mut FlattenContext,
                                     context_scroll_layer_id: ScrollLayerId,
                                     mut reference_frame_relative_offset: LayerPoint,
                                     level: i32,
-                                    stacking_context: &StackingContext,
-                                    clip_region: &ClipRegion) {
+                                    bounds: &LayerRect,
+                                    stacking_context: &StackingContext) {
         // Avoid doing unnecessary work for empty stacking contexts.
         if traversal.current_stacking_context_empty() {
             traversal.skip_current_stacking_context();
             return;
         }
 
         let composition_operations = {
             let auxiliary_lists = self.pipeline_auxiliary_lists
@@ -395,50 +412,48 @@ impl Frame {
             let transform = stacking_context.transform.as_ref();
             let transform = context.scene.properties.resolve_layout_transform(transform);
             let perspective =
                 stacking_context.perspective.unwrap_or_else(LayoutTransform::identity);
             let transform =
                 LayerToScrollTransform::create_translation(reference_frame_relative_offset.x,
                                                            reference_frame_relative_offset.y,
                                                            0.0)
-                                        .pre_translated(stacking_context.bounds.origin.x,
-                                                        stacking_context.bounds.origin.y,
-                                                        0.0)
+                                        .pre_translated(bounds.origin.x, bounds.origin.y, 0.0)
                                         .pre_mul(&transform)
                                         .pre_mul(&perspective);
 
+            let reference_frame_bounds = LayerRect::new(LayerPoint::zero(), bounds.size);
             scroll_layer_id = context.builder.push_reference_frame(Some(scroll_layer_id),
                                                                    pipeline_id,
-                                                                   &clip_region.main,
+                                                                   &reference_frame_bounds,
                                                                    &transform,
                                                                    &mut self.clip_scroll_tree);
             context.replacements.push((context_scroll_layer_id, scroll_layer_id));
             reference_frame_relative_offset = LayerPoint::zero();
         } else {
             reference_frame_relative_offset = LayerPoint::new(
-                reference_frame_relative_offset.x + stacking_context.bounds.origin.x,
-                reference_frame_relative_offset.y + stacking_context.bounds.origin.y);
+                reference_frame_relative_offset.x + bounds.origin.x,
+                reference_frame_relative_offset.y + bounds.origin.y);
         }
 
         // TODO(gw): Int with overflow etc
-        context.builder.push_stacking_context(reference_frame_relative_offset,
-                                              clip_region.main,
+        context.builder.push_stacking_context(&reference_frame_relative_offset,
                                               pipeline_id,
                                               level == 0,
                                               composition_operations);
 
         if level == 0 {
             if let Some(pipeline) = context.scene.pipeline_map.get(&pipeline_id) {
                 if let Some(bg_color) = pipeline.background_color {
                     // Note: we don't use the original clip region here,
                     // it's already processed by the node we just pushed.
-                    let background_rect = LayerRect::new(LayerPoint::zero(), clip_region.main.size);
+                    let background_rect = LayerRect::new(LayerPoint::zero(), bounds.size);
                     context.builder.add_solid_rectangle(scroll_layer_id,
-                                                        &clip_region.main,
+                                                        &bounds,
                                                         &ClipRegion::simple(&background_rect),
                                                         &bg_color,
                                                         PrimitiveFlags::None);
                 }
             }
         }
 
         self.flatten_items(traversal,
@@ -482,17 +497,18 @@ impl Frame {
         };
 
         let display_list = context.scene.display_lists.get(&pipeline_id);
         let display_list = match display_list {
             Some(display_list) => display_list,
             None => return,
         };
 
-        let (iframe_stacking_context, iframe_clip) = match display_list.starting_stacking_context() {
+        let (iframe_stacking_context,
+             iframe_stacking_context_bounds) = match display_list.starting_stacking_context() {
             Some(some) => some,
             None => {
                 warn!("Pipeline display list does not start with a stacking context.");
                 return;
             }
         };
 
         self.pipeline_epoch_map.insert(pipeline_id, pipeline.epoch);
@@ -511,29 +527,29 @@ impl Frame {
                                                  &mut self.clip_scroll_tree);
 
         let iframe_scroll_layer_id = ScrollLayerId::root_scroll_layer(pipeline_id);
         context.builder.add_clip_scroll_node(
             iframe_scroll_layer_id,
             iframe_reference_frame_id,
             pipeline_id,
             &LayerRect::new(LayerPoint::zero(), iframe_rect.size),
-            &iframe_clip.main.size,
-            iframe_clip,
+            &iframe_stacking_context_bounds.size,
+            &ClipRegion::simple(&iframe_stacking_context_bounds),
             &mut self.clip_scroll_tree);
 
         let mut traversal = DisplayListTraversal::new_skipping_first(display_list);
         self.flatten_stacking_context(&mut traversal,
                                       pipeline_id,
                                       context,
                                       iframe_scroll_layer_id,
                                       LayerPoint::zero(),
                                       0,
-                                      &iframe_stacking_context,
-                                      iframe_clip);
+                                      &iframe_stacking_context_bounds,
+                                      &iframe_stacking_context);
 
         context.builder.pop_reference_frame();
     }
 
     fn flatten_items<'a>(&mut self,
                          traversal: &mut DisplayListTraversal<'a>,
                          pipeline_id: PipelineId,
                          context: &mut FlattenContext,
@@ -589,21 +605,44 @@ impl Frame {
                                              text_info.font_key,
                                              text_info.size,
                                              text_info.blur_radius,
                                              &text_info.color,
                                              text_info.glyphs,
                                              text_info.glyph_options);
                 }
                 SpecificDisplayItem::Rectangle(ref info) => {
-                    context.builder.add_solid_rectangle(scroll_layer_id,
-                                                        &item.rect,
-                                                        &item.clip,
-                                                        &info.color,
-                                                        PrimitiveFlags::None);
+                    let auxiliary_lists = self.pipeline_auxiliary_lists
+                                              .get(&pipeline_id)
+                                              .expect("No auxiliary lists?!");
+                    // Try to extract the opaque inner rectangle out of the clipped primitive.
+                    if let Some(opaque_rect) = clip_intersection(&item.rect, &item.clip, &auxiliary_lists) {
+                        let mut results = Vec::new();
+                        subtract_rect(&item.rect, &opaque_rect, &mut results);
+                        // The inner rectangle is considered opaque within this layer.
+                        // It may still inherit some masking from the clip stack.
+                        context.builder.add_solid_rectangle(scroll_layer_id,
+                                                            &opaque_rect,
+                                                            &ClipRegion::simple(&item.clip.main),
+                                                            &info.color,
+                                                            PrimitiveFlags::None);
+                        for transparent_rect in &results {
+                            context.builder.add_solid_rectangle(scroll_layer_id,
+                                                                transparent_rect,
+                                                                &item.clip,
+                                                                &info.color,
+                                                                PrimitiveFlags::None);
+                        }
+                    } else {
+                        context.builder.add_solid_rectangle(scroll_layer_id,
+                                                            &item.rect,
+                                                            &item.clip,
+                                                            &info.color,
+                                                            PrimitiveFlags::None);
+                    }
                 }
                 SpecificDisplayItem::Gradient(ref info) => {
                     context.builder.add_gradient(scroll_layer_id,
                                                  item.rect,
                                                  &item.clip,
                                                  info.gradient.start_point,
                                                  info.gradient.end_point,
                                                  info.gradient.stops,
@@ -639,18 +678,18 @@ impl Frame {
                 }
                 SpecificDisplayItem::PushStackingContext(ref info) => {
                     self.flatten_stacking_context(traversal,
                                                   pipeline_id,
                                                   context,
                                                   item.scroll_layer_id,
                                                   reference_frame_relative_offset,
                                                   level + 1,
-                                                  &info.stacking_context,
-                                                  &item.clip);
+                                                  &item.rect,
+                                                  &info.stacking_context);
                 }
                 SpecificDisplayItem::Iframe(ref info) => {
                     self.flatten_iframe(info.pipeline_id,
                                         scroll_layer_id,
                                         &item.rect,
                                         context,
                                         reference_frame_relative_offset);
                 }
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -206,36 +206,34 @@ impl FrameBuilder {
             packed_layer_index: packed_layer_index,
             xf_rect: None,
          });
 
         ClipScrollGroupIndex(self.clip_scroll_group_store.len() - 1, scroll_layer_id)
     }
 
     pub fn push_stacking_context(&mut self,
-                                 reference_frame_offset: LayerPoint,
-                                 rect: LayerRect,
+                                 reference_frame_offset: &LayerPoint,
                                  pipeline_id: PipelineId,
                                  is_page_root: bool,
                                  composite_ops: CompositeOps) {
         if let Some(parent_index) = self.stacking_context_stack.last() {
             let parent_is_root = self.stacking_context_store[parent_index.0].is_page_root;
 
             if composite_ops.mix_blend_mode.is_some() && !parent_is_root {
                 // the parent stacking context of a stacking context with mix-blend-mode
                 // must be drawn with a transparent background, unless the parent stacking context
                 // is the root of the page
                 self.stacking_context_store[parent_index.0].should_isolate = true;
             }
         }
 
         let stacking_context_index = StackingContextIndex(self.stacking_context_store.len());
         self.stacking_context_store.push(StackingContext::new(pipeline_id,
-                                                              reference_frame_offset,
-                                                              rect,
+                                                              *reference_frame_offset,
                                                               is_page_root,
                                                               composite_ops));
         self.cmds.push(PrimitiveRunCmd::PushStackingContext(stacking_context_index));
         self.stacking_context_stack.push(stacking_context_index);
     }
 
     pub fn pop_stacking_context(&mut self) {
         self.cmds.push(PrimitiveRunCmd::PopStackingContext);
@@ -1327,17 +1325,18 @@ impl FrameBuilder {
                 clip_scroll_group_store: &self.clip_scroll_group_store,
                 prim_store: &self.prim_store,
                 resource_cache: resource_cache,
             };
 
             pass.build(&ctx, &mut render_tasks);
 
             profile_counters.passes.inc();
-            profile_counters.targets.add(pass.targets.len());
+            profile_counters.color_targets.add(pass.color_targets.target_count());
+            profile_counters.alpha_targets.add(pass.alpha_targets.target_count());
         }
 
         resource_cache.end_frame();
 
         Frame {
             device_pixel_ratio: device_pixel_ratio,
             background_color: self.background_color,
             window_size: self.screen_size,
@@ -1441,17 +1440,17 @@ 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(Some(local_viewport_rect),
+            node_clip_info.xf_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,
             };
 
@@ -1488,26 +1487,23 @@ impl<'a> LayerRectCalculationAndCullingP
                                                 stacking_context.reference_frame_offset.y,
                                                 0.0);
             packed_layer.set_transform(transform);
 
             if !stacking_context.can_contribute_to_scene() {
                 return;
             }
 
-            // Here we want to find the intersection between the clipping region and the
-            // stacking context content, so we move the viewport rectangle into the coordinate
-            // system of the stacking context content.
+            // 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);
-            let intersected_rect = stacking_context.local_rect.intersection(viewport_rect);
-
-            group.xf_rect = packed_layer.set_rect(intersected_rect,
+            group.xf_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 = {
--- a/gfx/webrender/src/gpu_store.rs
+++ b/gfx/webrender/src/gpu_store.rs
@@ -40,16 +40,20 @@ pub trait GpuStoreLayout {
         let texel_size = Self::texel_size();
         debug_assert!(item_size % texel_size == 0);
         item_size / texel_size
     }
 
     fn items_per_row<T>() -> usize {
         Self::texture_width::<T>() / Self::texels_per_item::<T>()
     }
+
+    fn rows_per_item<T>() -> usize {
+        Self::texels_per_item::<T>() / Self::texture_width::<T>()
+    }
 }
 
 /// A CPU-side buffer storing content to be uploaded to the GPU.
 pub struct GpuStore<T, L> {
     data: Vec<T>,
     layout: PhantomData<L>,
     // TODO(gw): Could store this intrusively inside
     // the data array free slots.
@@ -76,18 +80,20 @@ impl<T: Clone + Default, L: GpuStoreLayo
     pub fn build(&self) -> Vec<T> {
         let items_per_row = L::items_per_row::<T>();
 
         let mut items = self.data.clone();
 
         // Extend the data array to be a multiple of the row size.
         // This ensures memory safety when the array is passed to
         // OpenGL to upload to the GPU.
-        while items.len() % items_per_row != 0 {
-            items.push(T::default());
+        if items_per_row != 0 {
+            while items_per_row != 0 && items.len() % items_per_row != 0 {
+                items.push(T::default());
+            }
         }
 
         items
     }
 
     pub fn alloc(&mut self, count: usize) -> GpuStoreAddress {
         let address = self.get_next_address();
 
--- a/gfx/webrender/src/internal_types.rs
+++ b/gfx/webrender/src/internal_types.rs
@@ -1,33 +1,28 @@
 /* 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 euclid::{TypedPoint2D, UnknownUnit};
 use fnv::FnvHasher;
-use gleam::gl;
-use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle};
-use offscreen_gl_context::{GLContext, NativeGLContextMethods, GLContextDispatcher};
-use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle};
-use offscreen_gl_context::{ColorAttachmentType, GLContextAttributes, GLLimits};
 use profiler::BackendProfileCounters;
 use std::collections::{HashMap, HashSet};
 use std::f32;
 use std::hash::BuildHasherDefault;
 use std::{i32, usize};
 use std::path::PathBuf;
 use std::sync::Arc;
 use tiling;
 use renderer::BlendMode;
-use webrender_traits::{Epoch, ColorF, PipelineId, DeviceIntSize};
+use webrender_traits::{Epoch, ColorF, PipelineId};
 use webrender_traits::{ImageFormat, NativeFontHandle};
-use webrender_traits::{ExternalImageId, ScrollLayerId, WebGLCommand};
+use webrender_traits::{ExternalImageId, ScrollLayerId};
 use webrender_traits::{ImageData};
 use webrender_traits::{DeviceUintRect};
 
 // An ID for a texture that is owned by the
 // texture cache module. This can include atlases
 // or standalone textures allocated via the
 // texture cache (e.g. if an image is too large
 // to be added to an atlas). The texture cache
@@ -43,138 +38,25 @@ pub struct CacheTextureId(pub usize);
 // pipeline until they reach the rendering
 // thread, where they are resolved to a
 // native texture ID.
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 pub enum SourceTexture {
     Invalid,
     TextureCache(CacheTextureId),
-    WebGL(u32),                         // Is actually a gl::GLuint
     External(ExternalImageId),
-}
-
-pub enum GLContextHandleWrapper {
-    Native(NativeGLContextHandle),
-    OSMesa(OSMesaContextHandle),
-}
-
-impl GLContextHandleWrapper {
-    pub fn current_native_handle() -> Option<GLContextHandleWrapper> {
-        NativeGLContext::current_handle().map(GLContextHandleWrapper::Native)
-    }
-
-    pub fn current_osmesa_handle() -> Option<GLContextHandleWrapper> {
-        OSMesaContext::current_handle().map(GLContextHandleWrapper::OSMesa)
-    }
-
-    pub fn new_context(&self,
-                       size: DeviceIntSize,
-                       attributes: GLContextAttributes,
-                       dispatcher: Option<Box<GLContextDispatcher>>) -> Result<GLContextWrapper, &'static str> {
-        match *self {
-            GLContextHandleWrapper::Native(ref handle) => {
-                let ctx = GLContext::<NativeGLContext>::new_shared_with_dispatcher(size.to_untyped(),
-                                                                                   attributes,
-                                                                                   ColorAttachmentType::Texture,
-                                                                                   gl::GlType::default(),
-                                                                                   Some(handle),
-                                                                                   dispatcher);
-                ctx.map(GLContextWrapper::Native)
-            }
-            GLContextHandleWrapper::OSMesa(ref handle) => {
-                let ctx = GLContext::<OSMesaContext>::new_shared_with_dispatcher(size.to_untyped(),
-                                                                                 attributes,
-                                                                                 ColorAttachmentType::Texture,
-                                                                                 gl::GlType::default(),
-                                                                                 Some(handle),
-                                                                                 dispatcher);
-                ctx.map(GLContextWrapper::OSMesa)
-            }
-        }
-    }
-}
-
-pub enum GLContextWrapper {
-    Native(GLContext<NativeGLContext>),
-    OSMesa(GLContext<OSMesaContext>),
-}
-
-impl GLContextWrapper {
-    pub fn make_current(&self) {
-        match *self {
-            GLContextWrapper::Native(ref ctx) => {
-                ctx.make_current().unwrap();
-            }
-            GLContextWrapper::OSMesa(ref ctx) => {
-                ctx.make_current().unwrap();
-            }
-        }
-    }
-
-    pub fn unbind(&self) {
-        match *self {
-            GLContextWrapper::Native(ref ctx) => {
-                ctx.unbind().unwrap();
-            }
-            GLContextWrapper::OSMesa(ref ctx) => {
-                ctx.unbind().unwrap();
-            }
-        }
-    }
-
-    pub fn apply_command(&self, cmd: WebGLCommand) {
-        match *self {
-            GLContextWrapper::Native(ref ctx) => {
-                cmd.apply(ctx);
-            }
-            GLContextWrapper::OSMesa(ref ctx) => {
-                cmd.apply(ctx);
-            }
-        }
-    }
-
-    pub fn get_info(&self) -> (DeviceIntSize, u32, GLLimits) {
-        match *self {
-            GLContextWrapper::Native(ref ctx) => {
-                let (real_size, texture_id) = {
-                    let draw_buffer = ctx.borrow_draw_buffer().unwrap();
-                    (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap())
-                };
-
-                let limits = ctx.borrow_limits().clone();
-
-                (DeviceIntSize::from_untyped(&real_size), texture_id, limits)
-            }
-            GLContextWrapper::OSMesa(ref ctx) => {
-                let (real_size, texture_id) = {
-                    let draw_buffer = ctx.borrow_draw_buffer().unwrap();
-                    (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap())
-                };
-
-                let limits = ctx.borrow_limits().clone();
-
-                (DeviceIntSize::from_untyped(&real_size), texture_id, limits)
-            }
-        }
-    }
-
-    pub fn resize(&mut self, size: &DeviceIntSize) -> Result<(), &'static str> {
-        match *self {
-            GLContextWrapper::Native(ref mut ctx) => {
-                ctx.resize(size.to_untyped())
-            }
-            GLContextWrapper::OSMesa(ref mut ctx) => {
-                ctx.resize(size.to_untyped())
-            }
-        }
-    }
+    #[cfg_attr(not(feature = "webgl"), allow(dead_code))]
+    /// This is actually a gl::GLuint, with the shared texture id between the
+    /// main context and the WebGL context.
+    WebGL(u32),
 }
 
 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>>),
@@ -182,26 +64,28 @@ pub enum FontTemplate {
 }
 
 #[derive(Debug, PartialEq, Eq)]
 pub enum TextureSampler {
     Color0,
     Color1,
     Color2,
     Mask,
-    Cache,
+    CacheA8,
+    CacheRGBA8,
     Data16,
     Data32,
     Data64,
     Data128,
     Layers,
     RenderTasks,
     Geometry,
     ResourceRects,
     Gradients,
+    Dither,
 }
 
 impl TextureSampler {
     pub fn color(n: usize) -> TextureSampler {
         match n {
             0 => TextureSampler::Color0,
             1 => TextureSampler::Color1,
             2 => TextureSampler::Color2,
@@ -307,22 +191,30 @@ impl PackedColor {
 pub struct PackedTexel {
     pub b: u8,
     pub g: u8,
     pub r: u8,
     pub a: u8,
 }
 
 impl PackedTexel {
-    pub fn from_color(color: &ColorF) -> PackedTexel {
+    pub fn high_bytes(color: &ColorF) -> PackedTexel {
+        Self::extract_bytes(color, COLOR_FLOAT_TO_FIXED)
+    }
+
+    pub fn low_bytes(color: &ColorF) -> PackedTexel {
+        Self::extract_bytes(color, COLOR_FLOAT_TO_FIXED_WIDE)
+    }
+
+    fn extract_bytes(color: &ColorF, multiplier: f32) -> PackedTexel {
         PackedTexel {
-            b: (0.5 + color.b * COLOR_FLOAT_TO_FIXED).floor() as u8,
-            g: (0.5 + color.g * COLOR_FLOAT_TO_FIXED).floor() as u8,
-            r: (0.5 + color.r * COLOR_FLOAT_TO_FIXED).floor() as u8,
-            a: (0.5 + color.a * COLOR_FLOAT_TO_FIXED).floor() as u8,
+            b: ((0.5 + color.b * multiplier).floor() as u32 & 0xff) as u8,
+            g: ((0.5 + color.g * multiplier).floor() as u32 & 0xff) as u8,
+            r: ((0.5 + color.r * multiplier).floor() as u32 & 0xff) as u8,
+            a: ((0.5 + color.a * multiplier).floor() as u32 & 0xff) as u8,
         }
     }
 }
 
 #[derive(Debug, Clone, Copy)]
 #[repr(C)]
 pub struct PackedVertex {
     pub pos: [f32; 2],
--- a/gfx/webrender/src/lib.rs
+++ b/gfx/webrender/src/lib.rs
@@ -72,16 +72,23 @@ mod render_backend;
 mod render_task;
 mod resource_cache;
 mod scene;
 mod spring;
 mod texture_cache;
 mod tiling;
 mod util;
 
+#[cfg(feature = "webgl")]
+mod webgl_types;
+
+#[cfg(not(feature = "webgl"))]
+#[path = "webgl_stubs.rs"]
+mod webgl_types;
+
 mod shader_source {
     include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
 }
 
 pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};
 
 mod platform {
     #[cfg(target_os="macos")]
@@ -122,16 +129,17 @@ extern crate app_units;
 extern crate bincode;
 extern crate euclid;
 extern crate fnv;
 extern crate gleam;
 extern crate num_traits;
 //extern crate notify;
 extern crate time;
 extern crate webrender_traits;
+#[cfg(feature = "webgl")]
 extern crate offscreen_gl_context;
 extern crate byteorder;
 extern crate threadpool;
 
 #[cfg(any(target_os="macos", target_os="windows"))]
 extern crate gamma_lut;
 
 pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -275,31 +275,34 @@ pub struct GradientDataEntry {
 // A table of gradient entries, with two colors per entry, that specify the start and end color
 // within the segment of the gradient space represented by that entry. To lookup a gradient result,
 // first the entry index is calculated to determine which two colors to interpolate between, then
 // the offset within that entry bucket is used to interpolate between the two colors in that entry.
 // This layout preserves hard stops, as the end color for a given entry can differ from the start
 // color for the following entry, despite them being adjacent. Colors are stored within in BGRA8
 // format for texture upload.
 pub struct GradientData {
-    pub colors: [GradientDataEntry; GRADIENT_DATA_RESOLUTION],
+    pub colors_high: [GradientDataEntry; GRADIENT_DATA_RESOLUTION],
+    pub colors_low: [GradientDataEntry; GRADIENT_DATA_RESOLUTION],
 }
 
 impl Default for GradientData {
     fn default() -> GradientData {
         GradientData {
-            colors: unsafe { mem::uninitialized() }
+            colors_high: unsafe { mem::uninitialized() },
+            colors_low: unsafe { mem::uninitialized() }
         }
     }
 }
 
 impl Clone for GradientData {
     fn clone(&self) -> GradientData {
         GradientData {
-            colors: self.colors,
+            colors_high: self.colors_high,
+            colors_low: self.colors_low,
         }
     }
 }
 
 impl GradientData {
     // Generate a color ramp between the start and end indexes from a start color to an end color.
     fn fill_colors(&mut self, start_idx: usize, end_idx: usize, start_color: &ColorF, end_color: &ColorF) -> usize {
         if start_idx >= end_idx {
@@ -309,28 +312,34 @@ impl GradientData {
         // Calculate the color difference for individual steps in the ramp.
         let inv_steps = 1.0 / (end_idx - start_idx) as f32;
         let step_r = (end_color.r - start_color.r) * inv_steps;
         let step_g = (end_color.g - start_color.g) * inv_steps;
         let step_b = (end_color.b - start_color.b) * inv_steps;
         let step_a = (end_color.a - start_color.a) * inv_steps;
 
         let mut cur_color = *start_color;
-        let mut cur_packed_color = PackedTexel::from_color(&cur_color);
+        let mut cur_color_high = PackedTexel::high_bytes(&cur_color);
+        let mut cur_color_low = PackedTexel::low_bytes(&cur_color);
 
         // Walk the ramp writing start and end colors for each entry.
-        for entry in &mut self.colors[start_idx..end_idx] {
-            entry.start_color = cur_packed_color;
+        for index in start_idx..end_idx {
+            let high_byte_entry = &mut self.colors_high[index];
+            let low_byte_entry = &mut self.colors_low[index];
 
+            high_byte_entry.start_color = cur_color_high;
+            low_byte_entry.start_color = cur_color_low;
             cur_color.r += step_r;
             cur_color.g += step_g;
             cur_color.b += step_b;
             cur_color.a += step_a;
-            cur_packed_color = PackedTexel::from_color(&cur_color);
-            entry.end_color = cur_packed_color;
+            cur_color_high = PackedTexel::high_bytes(&cur_color);
+            cur_color_low = PackedTexel::low_bytes(&cur_color);
+            high_byte_entry.end_color = cur_color_high;
+            low_byte_entry.end_color = cur_color_low;
         }
 
         end_idx
     }
 
     // Compute an entry index based on a gradient stop offset.
     #[inline]
     fn get_index(offset: f32) -> usize {
--- a/gfx/webrender/src/profiler.rs
+++ b/gfx/webrender/src/profiler.rs
@@ -245,26 +245,28 @@ impl ProfileCounter for AverageTimeProfi
         }
     }
 }
 
 pub struct FrameProfileCounters {
     pub total_primitives: IntProfileCounter,
     pub visible_primitives: IntProfileCounter,
     pub passes: IntProfileCounter,
-    pub targets: IntProfileCounter,
+    pub color_targets: IntProfileCounter,
+    pub alpha_targets: IntProfileCounter,
 }
 
 impl FrameProfileCounters {
     pub fn new() -> FrameProfileCounters {
         FrameProfileCounters {
             total_primitives: IntProfileCounter::new("Total Primitives"),
             visible_primitives: IntProfileCounter::new("Visible Primitives"),
             passes: IntProfileCounter::new("Passes"),
-            targets: IntProfileCounter::new("Render Targets"),
+            color_targets: IntProfileCounter::new("Color Targets"),
+            alpha_targets: IntProfileCounter::new("Alpha Targets"),
         }
     }
 }
 
 #[derive(Clone)]
 pub struct TextureCacheProfileCounters {
     pub pages_a8: ResourceProfileCounter,
     pub pages_rgb8: ResourceProfileCounter,
@@ -656,17 +658,18 @@ impl Profiler {
             &renderer_profile.frame_counter,
             &renderer_profile.frame_time,
         ], debug_renderer, true);
 
         self.draw_counters(&[
             &frame_profile.total_primitives,
             &frame_profile.visible_primitives,
             &frame_profile.passes,
-            &frame_profile.targets,
+            &frame_profile.color_targets,
+            &frame_profile.alpha_targets,
         ], debug_renderer, true);
 
         self.draw_counters(&[
             &backend_profile.font_templates,
             &backend_profile.image_templates,
         ], debug_renderer, true);
 
         self.draw_counters(&[
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -1,34 +1,37 @@
 /* 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 byteorder::{LittleEndian, ReadBytesExt};
 use frame::Frame;
 use frame_builder::FrameBuilderConfig;
-use internal_types::{FontTemplate, GLContextHandleWrapper, GLContextWrapper};
-use internal_types::{SourceTexture, ResultMsg, RendererFrame};
+use internal_types::{FontTemplate, SourceTexture, ResultMsg, RendererFrame};
 use profiler::{BackendProfileCounters, TextureCacheProfileCounters};
 use record::ApiRecordingReceiver;
 use resource_cache::ResourceCache;
 use scene::Scene;
 use std::collections::HashMap;
 use std::io::{Cursor, Read};
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::Sender;
 use texture_cache::TextureCache;
 use thread_profiler::register_thread_with_profiler;
 use threadpool::ThreadPool;
+use webgl_types::{GLContextHandleWrapper, GLContextWrapper};
 use webrender_traits::{DeviceIntPoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize, LayerPoint};
 use webrender_traits::{ApiMsg, AuxiliaryLists, BuiltDisplayList, IdNamespace, ImageData};
 use webrender_traits::{PipelineId, RenderNotifier, RenderDispatcher, WebGLCommand, WebGLContextId};
 use webrender_traits::channel::{PayloadHelperMethods, PayloadReceiver, PayloadSender, MsgReceiver};
 use webrender_traits::{BlobImageRenderer, VRCompositorCommand, VRCompositorHandler};
+#[cfg(feature = "webgl")]
 use offscreen_gl_context::GLContextDispatcher;
+#[cfg(not(feature = "webgl"))]
+use webgl_types::GLContextDispatcher;
 
 /// The render backend is responsible for transforming high level display lists into
 /// GPU-friendly work which is then submitted to the renderer in the form of a frame::Frame.
 ///
 /// The render backend operates on its own thread.
 pub struct RenderBackend {
     api_rx: MsgReceiver<ApiMsg>,
     payload_rx: PayloadReceiver,
@@ -142,18 +145,18 @@ impl RenderBackend {
                             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());
                             }
                             self.resource_cache.add_image_template(id, descriptor, data, tiling);
                         }
-                        ApiMsg::UpdateImage(id, descriptor, bytes) => {
-                            self.resource_cache.update_image_template(id, descriptor, bytes);
+                        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);
                         }
                         ApiMsg::SetPageZoom(factor) => {
                             self.page_zoom_factor = factor.get();
                         }
                         ApiMsg::SetPinchZoom(factor) => {
--- a/gfx/webrender/src/render_task.rs
+++ b/gfx/webrender/src/render_task.rs
@@ -2,17 +2,17 @@
  * 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 internal_types::{HardwareCompositeOp, LowLevelFilterOp};
 use mask_cache::MaskCacheInfo;
 use prim_store::{PrimitiveCacheKey, PrimitiveIndex};
 use std::{cmp, f32, i32, mem, usize};
 use tiling::{ClipScrollGroupIndex, PackedLayerIndex, RenderPass, RenderTargetIndex};
-use tiling::{StackingContextIndex};
+use tiling::{RenderTargetKind, StackingContextIndex};
 use webrender_traits::{DeviceIntLength, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
 use webrender_traits::{MixBlendMode, ScrollLayerId};
 
 const FLOATS_PER_RENDER_TASK_INFO: usize = 12;
 
 #[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
 pub struct RenderTaskIndex(pub usize);
 
@@ -434,9 +434,20 @@ impl RenderTask {
 
     pub fn max_depth(&self, depth: usize, max_depth: &mut usize) {
         let depth = depth + 1;
         *max_depth = cmp::max(*max_depth, depth);
         for child in &self.children {
             child.max_depth(depth, max_depth);
         }
     }
+
+    pub fn target_kind(&self) -> RenderTargetKind {
+        match self.kind {
+            RenderTaskKind::Alpha(..) |
+            RenderTaskKind::CachePrimitive(..) |
+            RenderTaskKind::VerticalBlur(..) |
+            RenderTaskKind::Readback(..) |
+            RenderTaskKind::HorizontalBlur(..) => RenderTargetKind::Color,
+            RenderTaskKind::CacheMask(..) => RenderTargetKind::Alpha,
+        }
+    }
 }
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -16,17 +16,17 @@ use device::{GpuSample, TextureFilter, V
 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::{ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE, SourceTexture};
-use internal_types::{BatchTextures, TextureSampler, GLContextHandleWrapper};
+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;
 use std;
 use std::cmp;
@@ -38,20 +38,21 @@ use std::mem;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::thread;
 use texture_cache::TextureCache;
 use threadpool::ThreadPool;
 use tiling::{AlphaBatchKind, BlurCommand, Frame, PrimitiveBatch, PrimitiveBatchData};
-use tiling::{CacheClipInstance, PrimitiveInstance, RenderTarget};
+use tiling::{AlphaRenderTarget, CacheClipInstance, PrimitiveInstance, ColorRenderTarget, RenderTargetKind};
 use time::precise_time_ns;
 use thread_profiler::{register_thread_with_profiler, write_profile};
 use util::TransformedRectKind;
+use webgl_types::GLContextHandleWrapper;
 use webrender_traits::{ColorF, Epoch, PipelineId, RenderNotifier, RenderDispatcher};
 use webrender_traits::{ExternalImageId, ImageData, ImageFormat, RenderApiSender};
 use webrender_traits::{DeviceIntRect, DevicePoint, DeviceIntPoint, DeviceIntSize, DeviceUintSize};
 use webrender_traits::{ImageDescriptor, BlobImageRenderer};
 use webrender_traits::channel;
 use webrender_traits::VRCompositorHandler;
 
 pub const GPU_DATA_TEXTURE_POOL: usize = 5;
@@ -149,25 +150,32 @@ impl<L: GpuStoreLayout> GpuDataTexture<L
     fn init<T: Default>(&mut self,
                         device: &mut Device,
                         data: &mut Vec<T>) {
         if data.is_empty() {
             return;
         }
 
         let items_per_row = L::items_per_row::<T>();
+        let rows_per_item = L::rows_per_item::<T>();
 
         // Extend the data array to be a multiple of the row size.
         // This ensures memory safety when the array is passed to
         // OpenGL to upload to the GPU.
-        while data.len() % items_per_row != 0 {
-            data.push(T::default());
+        if items_per_row != 0 {
+            while data.len() % items_per_row != 0 {
+                data.push(T::default());
+            }
         }
 
-        let height = data.len() / items_per_row;
+        let height = if items_per_row != 0 {
+            data.len() / items_per_row
+        } else {
+            data.len() * rows_per_item
+        };
 
         device.init_texture(self.id,
                             L::texture_width::<T>() as u32,
                             height as u32,
                             L::image_format(),
                             L::texture_filter(),
                             RenderTargetMode::None,
                             Some(unsafe { mem::transmute(data.as_slice()) } ));
@@ -196,17 +204,17 @@ pub type VertexDataStore<T> = GpuStore<T
 pub struct GradientDataTextureLayout {}
 
 impl GpuStoreLayout for GradientDataTextureLayout {
     fn image_format() -> ImageFormat {
         ImageFormat::RGBA8
     }
 
     fn texture_width<T>() -> usize {
-        mem::size_of::<GradientData>() / Self::texel_size()
+        mem::size_of::<GradientData>() / Self::texel_size() / 2
     }
 
     fn texture_filter() -> TextureFilter {
         TextureFilter::Linear
     }
 }
 
 type GradientDataTexture = GpuDataTexture<GradientDataTextureLayout>;
@@ -477,17 +485,18 @@ pub struct Renderer {
     clear_color: ColorF,
     debug: DebugRenderer,
     render_target_debug: bool,
     backend_profile_counters: BackendProfileCounters,
     profile_counters: RendererProfileCounters,
     profiler: Profiler,
     last_time: u64,
 
-    render_targets: Vec<TextureId>,
+    color_render_targets: Vec<TextureId>,
+    alpha_render_targets: Vec<TextureId>,
 
     gpu_profile: GpuProfiler<GpuProfileTag>,
     prim_vao_id: VAOId,
     blur_vao_id: VAOId,
     clip_vao_id: VAOId,
 
     gdt_index: usize,
     gpu_data_textures: [GpuDataTextures; GPU_DATA_TEXTURE_POOL],
@@ -507,16 +516,18 @@ pub struct Renderer {
     /// use a hashmap, and allows a flat vector for performance.
     cache_texture_id_map: Vec<TextureId>,
 
     /// A special 1x1 dummy cache texture used for shaders that expect to work
     /// with the cache but are actually running in the first pass
     /// when no target is yet provided as a cache texture input.
     dummy_cache_texture_id: TextureId,
 
+    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>>,
 
     // Optional trait object that handles WebVR commands.
@@ -743,16 +754,28 @@ impl Renderer {
             0xff, 0xff, 0xff, 0xff,
             0xff, 0xff, 0xff, 0xff,
             0xff, 0xff, 0xff, 0xff,
         ];
         let mask_pixels: Vec<u8> = vec![
             0xff, 0xff,
             0xff, 0xff,
         ];
+
+        let dither_matrix: [u8; 64] = [
+            00, 48, 12, 60, 03, 51, 15, 63,
+            32, 16, 44, 28, 35, 19, 47, 31,
+            08, 56, 04, 52, 11, 59, 07, 55,
+            40, 24, 36, 20, 43, 27, 39, 23,
+            02, 50, 14, 62, 01, 49, 13, 61,
+            34, 18, 46, 30, 33, 17, 45, 29,
+            10, 58, 06, 54, 09, 57, 05, 53,
+            42, 26, 38, 22, 41, 25, 37, 21
+        ];
+
         // 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);
 
@@ -767,16 +790,25 @@ impl Renderer {
         device.init_texture(dummy_cache_texture_id,
                             1,
                             1,
                             ImageFormat::RGBA8,
                             TextureFilter::Linear,
                             RenderTargetMode::LayerRenderTarget(1),
                             None);
 
+        let dither_matrix_texture_id = device.create_texture_ids(1, TextureTarget::Default)[0];
+        device.init_texture(dither_matrix_texture_id,
+                            8,
+                            8,
+                            ImageFormat::A8,
+                            TextureFilter::Nearest,
+                            RenderTargetMode::None,
+                            Some(&dither_matrix));
+
         let debug_renderer = DebugRenderer::new(&mut device);
 
         let gpu_data_textures = [
             GpuDataTextures::new(&mut device),
             GpuDataTextures::new(&mut device),
             GpuDataTextures::new(&mut device),
             GpuDataTextures::new(&mut device),
             GpuDataTextures::new(&mut device),
@@ -896,27 +928,29 @@ impl Renderer {
             backend_profile_counters: BackendProfileCounters::new(),
             profile_counters: RendererProfileCounters::new(),
             profiler: Profiler::new(),
             enable_profiler: options.enable_profiler,
             max_recorded_profiles: options.max_recorded_profiles,
             clear_framebuffer: options.clear_framebuffer,
             clear_color: options.clear_color,
             last_time: 0,
-            render_targets: Vec::new(),
+            color_render_targets: Vec::new(),
+            alpha_render_targets: Vec::new(),
             gpu_profile: gpu_profile,
             prim_vao_id: prim_vao_id,
             blur_vao_id: blur_vao_id,
             clip_vao_id: clip_vao_id,
             gdt_index: 0,
             gpu_data_textures: gpu_data_textures,
             pipeline_epoch_map: HashMap::with_hasher(Default::default()),
             main_thread_dispatcher: main_thread_dispatcher,
             cache_texture_id_map: Vec::new(),
             dummy_cache_texture_id: dummy_cache_texture_id,
+            dither_matrix_texture_id: dither_matrix_texture_id,
             external_image_handler: None,
             external_images: HashMap::with_hasher(Default::default()),
             vr_compositor_handler: vr_compositor,
             cpu_profiles: VecDeque::new(),
             gpu_profiles: VecDeque::new(),
         };
 
         let sender = RenderApiSender::new(api_tx, payload_tx);
@@ -1247,16 +1281,19 @@ impl Renderer {
         self.device.bind_vao(vao);
         self.device.bind_program(shader, projection);
 
         for i in 0..textures.colors.len() {
             let texture_id = self.resolve_source_texture(&textures.colors[i]);
             self.device.bind_texture(TextureSampler::color(i), texture_id);
         }
 
+        // TODO: this probably isn't the best place for this.
+        self.device.bind_texture(TextureSampler::Dither, self.dither_matrix_texture_id);
+
         self.device.update_vao_instances(vao, data, VertexUsageHint::Stream);
         self.device.draw_indexed_triangles_instanced_u16(6, data.len() as i32);
         self.profile_counters.vertices.add(6 * data.len());
         self.profile_counters.draw_calls.inc();
     }
 
     fn submit_batch(&mut self,
                     batch: &PrimitiveBatch,
@@ -1402,85 +1439,40 @@ impl Renderer {
                                           vao,
                                           shader,
                                           &batch.key.textures,
                                           projection);
             }
         }
     }
 
-    fn draw_target(&mut self,
-                   render_target: Option<(TextureId, i32)>,
-                   target: &RenderTarget,
-                   target_size: DeviceUintSize,
-                   cache_texture: TextureId,
-                   should_clear: bool,
-                   background_color: Option<ColorF>,
-                   render_task_data: &Vec<RenderTaskData>) {
-        self.device.disable_depth();
-        self.device.enable_depth_write();
-
-        let projection = {
+    fn draw_color_target(&mut self,
+                         render_target: Option<(TextureId, i32)>,
+                         target: &ColorRenderTarget,
+                         target_size: DeviceUintSize,
+                         color_cache_texture: TextureId,
+                         clear_color: Option<[f32; 4]>,
+                         render_task_data: &Vec<RenderTaskData>,
+                         projection: &Matrix4D<f32>) {
+        {
             let _gm = self.gpu_profile.add_marker(GPU_TAG_SETUP_TARGET);
             self.device.bind_draw_target(render_target, Some(target_size));
-
+            self.device.disable_depth();
+            self.device.enable_depth_write();
             self.device.set_blend(false);
             self.device.set_blend_mode_alpha();
-            self.device.bind_texture(TextureSampler::Cache, cache_texture);
-
-            let (color, projection) = match render_target {
-                Some(..) => (
-                    // The clear color here is chosen specifically such that:
-                    // - The red channel is cleared to 1, so that the clip mask
-                    //   generation (which reads/writes the red channel) can
-                    //   assume that each allocated rect is opaque / non-clipped
-                    //   initially.
-                    // - The alpha channel is cleared to 0, so that visual render
-                    //   tasks can assume that pixels are transparent if not
-                    //   rendered. (This is relied on by the compositing support
-                    //   for mix-blend-mode etc).
-                    [1.0, 1.0, 1.0, 0.0],
-                    Matrix4D::ortho(0.0,
-                                   target_size.width as f32,
-                                   0.0,
-                                   target_size.height as f32,
-                                   ORTHO_NEAR_PLANE,
-                                   ORTHO_FAR_PLANE)
-                ),
-                None => (
-                    background_color.map_or(self.clear_color.to_array(), |color| {
-                        color.to_array()
-                    }),
-                    Matrix4D::ortho(0.0,
-                                   target_size.width as f32,
-                                   target_size.height as f32,
-                                   0.0,
-                                   ORTHO_NEAR_PLANE,
-                                   ORTHO_FAR_PLANE)
-                ),
-            };
-
-            let clear_depth = Some(1.0);
-            let clear_color = if should_clear {
-                Some(color)
-            } else {
-                None
-            };
-
-            self.device.clear_target(clear_color, clear_depth);
+            self.device.clear_target(clear_color, Some(1.0));
 
             let isolate_clear_color = Some([0.0, 0.0, 0.0, 0.0]);
             for isolate_clear in &target.isolate_clears {
                 self.device.clear_target_rect(isolate_clear_color, None, *isolate_clear);
             }
 
-            projection
-        };
-
-        self.device.disable_depth_write();
+            self.device.disable_depth_write();
+        }
 
         // Draw any blurs for this target.
         // Blurs are rendered as a standard 2-pass
         // separable implementation.
         // TODO(gw): In the future, consider having
         //           fast path blur shaders for common
         //           blur radii with fixed weights.
         if !target.vertical_blurs.is_empty() || !target.horizontal_blurs.is_empty() {
@@ -1510,47 +1502,16 @@ impl Renderer {
             let shader = self.cs_box_shadow.get(&mut self.device).unwrap();
             self.draw_instanced_batch(&target.box_shadow_cache_prims,
                                       vao,
                                       shader,
                                       &BatchTextures::no_texture(),
                                       &projection);
         }
 
-        // Draw the clip items into the tiled alpha mask.
-        {
-            let _gm = self.gpu_profile.add_marker(GPU_TAG_CACHE_CLIP);
-            let vao = self.clip_vao_id;
-            // switch to multiplicative blending
-            self.device.set_blend(true);
-            self.device.set_blend_mode_multiply();
-            // draw rounded cornered rectangles
-            if !target.clip_batcher.rectangles.is_empty() {
-                let _gm2 = GpuMarker::new(self.device.rc_gl(), "clip rectangles");
-                let shader = self.cs_clip_rectangle.get(&mut self.device).unwrap();
-                self.draw_instanced_batch(&target.clip_batcher.rectangles,
-                                          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 shader = self.cs_clip_image.get(&mut self.device).unwrap();
-                self.draw_instanced_batch(items,
-                                          vao,
-                                          shader,
-                                          &BatchTextures::no_texture(),
-                                          &projection);
-            }
-        }
-
         // Draw any textrun caches for this target. For now, this
         // is only used to cache text runs that are to be blurred
         // for text-shadow support. In the future it may be worth
         // considering using this for (some) other text runs, since
         // it removes the overhead of submitting many small glyphs
         // to multiple tiles in the normal text run case.
         if !target.text_run_cache_prims.is_empty() {
             self.device.set_blend(true);
@@ -1574,17 +1535,17 @@ impl Renderer {
         self.device.set_depth_func(DepthFunction::Less);
         self.device.enable_depth();
         self.device.enable_depth_write();
 
         for batch in &target.alpha_batcher.opaque_batches {
             self.submit_batch(batch,
                               &projection,
                               render_task_data,
-                              cache_texture,
+                              color_cache_texture,
                               render_target,
                               target_size);
         }
 
         self.device.disable_depth_write();
 
         for batch in &target.alpha_batcher.alpha_batches {
             if batch.key.blend_mode != prev_blend_mode {
@@ -1606,25 +1567,73 @@ impl Renderer {
                     }
                 }
                 prev_blend_mode = batch.key.blend_mode;
             }
 
             self.submit_batch(batch,
                               &projection,
                               render_task_data,
-                              cache_texture,
+                              color_cache_texture,
                               render_target,
                               target_size);
         }
 
         self.device.disable_depth();
         self.device.set_blend(false);
     }
 
+    fn draw_alpha_target(&mut self,
+                         render_target: (TextureId, i32),
+                         target: &AlphaRenderTarget,
+                         target_size: DeviceUintSize,
+                         projection: &Matrix4D<f32>) {
+        {
+            let _gm = self.gpu_profile.add_marker(GPU_TAG_SETUP_TARGET);
+            self.device.bind_draw_target(Some(render_target), Some(target_size));
+            self.device.disable_depth();
+            self.device.disable_depth_write();
+
+            let clear_color = [1.0, 1.0, 1.0, 0.0];
+            self.device.clear_target(Some(clear_color), None);
+        }
+
+        // Draw the clip items into the tiled alpha mask.
+        {
+            let _gm = self.gpu_profile.add_marker(GPU_TAG_CACHE_CLIP);
+            let vao = self.clip_vao_id;
+            // switch to multiplicative blending
+            self.device.set_blend(true);
+            self.device.set_blend_mode_multiply();
+
+            // draw rounded cornered rectangles
+            if !target.clip_batcher.rectangles.is_empty() {
+                let _gm2 = GpuMarker::new(self.device.rc_gl(), "clip rectangles");
+                let shader = self.cs_clip_rectangle.get(&mut self.device).unwrap();
+                self.draw_instanced_batch(&target.clip_batcher.rectangles,
+                                          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 shader = self.cs_clip_image.get(&mut self.device).unwrap();
+                self.draw_instanced_batch(items,
+                                          vao,
+                                          shader,
+                                          &BatchTextures::no_texture(),
+                                          &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
         // custom item. Then we patch the resource_rects structure
         // here before it's uploaded to the GPU.
         if !frame.deferred_resolves.is_empty() {
             let handler = self.external_image_handler
                               .as_mut()
@@ -1689,72 +1698,143 @@ impl Renderer {
 
         self.device.disable_depth_write();
         self.device.disable_stencil();
         self.device.set_blend(false);
 
         if frame.passes.is_empty() {
             self.device.clear_target(Some(self.clear_color.to_array()), Some(1.0));
         } else {
-            // Add new render targets to the pool if required.
-            let needed_targets = frame.passes.len() - 1;     // framebuffer doesn't need a target!
-            let current_target_count = self.render_targets.len();
-            if needed_targets > current_target_count {
-                let new_target_count = needed_targets - current_target_count;
-                let new_targets = self.device.create_texture_ids(new_target_count as i32,
-                                                                 TextureTarget::Array);
-                self.render_targets.extend_from_slice(&new_targets);
+            // Assign render targets to the passes.
+            for pass in &mut frame.passes {
+                debug_assert!(pass.color_texture_id.is_none());
+                debug_assert!(pass.alpha_texture_id.is_none());
+
+                if pass.needs_render_target_kind(RenderTargetKind::Color) {
+                    pass.color_texture_id = Some(self.color_render_targets
+                                                     .pop()
+                                                     .unwrap_or_else(|| {
+                                                         self.device
+                                                             .create_texture_ids(1, TextureTarget::Array)[0]
+                                                      }));
+                }
+
+                if pass.needs_render_target_kind(RenderTargetKind::Alpha) {
+                    pass.alpha_texture_id = Some(self.alpha_render_targets
+                                                     .pop()
+                                                     .unwrap_or_else(|| {
+                                                         self.device
+                                                             .create_texture_ids(1, TextureTarget::Array)[0]
+                                                      }));
+                }
             }
 
             // Init textures and render targets to match this scene.
-            for (pass, texture_id) in frame.passes.iter().zip(self.render_targets.iter()) {
-                self.device.init_texture(*texture_id,
-                                         frame.cache_size.width as u32,
-                                         frame.cache_size.height as u32,
-                                         ImageFormat::RGBA8,
-                                         TextureFilter::Linear,
-                                         RenderTargetMode::LayerRenderTarget(pass.targets.len() as i32),
-                                         None);
+            for pass in &frame.passes {
+                if let Some(texture_id) = pass.color_texture_id {
+                    let target_count = pass.required_target_count(RenderTargetKind::Color);
+                    self.device.init_texture(texture_id,
+                                             frame.cache_size.width as u32,
+                                             frame.cache_size.height as u32,
+                                             ImageFormat::RGBA8,
+                                             TextureFilter::Linear,
+                                             RenderTargetMode::LayerRenderTarget(target_count as i32),
+                                             None);
+                }
+                if let Some(texture_id) = pass.alpha_texture_id {
+                    let target_count = pass.required_target_count(RenderTargetKind::Alpha);
+                    self.device.init_texture(texture_id,
+                                             frame.cache_size.width as u32,
+                                             frame.cache_size.height as u32,
+                                             ImageFormat::A8,
+                                             TextureFilter::Nearest,
+                                             RenderTargetMode::LayerRenderTarget(target_count as i32),
+                                             None);
+                }
             }
 
             // TODO(gw): This is a hack / workaround for #728.
             // We should find a better way to implement these updates rather
             // than wasting this extra memory, but for now it removes a large
             // number of driver stalls.
             self.gpu_data_textures[self.gdt_index].init_frame(&mut self.device, frame);
             self.gdt_index = (self.gdt_index + 1) % GPU_DATA_TEXTURE_POOL;
 
-            let mut src_id = self.dummy_cache_texture_id;
+            let mut src_color_id = self.dummy_cache_texture_id;
+            let mut src_alpha_id = self.dummy_cache_texture_id;
+
+            for pass in &mut frame.passes {
+                let size;
+                let clear_color;
+                let projection;
 
-            for (pass_index, pass) in frame.passes.iter().enumerate() {
-                let (do_clear, size, target_id) = if pass.is_framebuffer {
-                    (self.clear_framebuffer || needs_clear,
-                     framebuffer_size,
-                     None)
+                if pass.is_framebuffer {
+                    clear_color = if self.clear_framebuffer || needs_clear {
+                        Some(frame.background_color.map_or(self.clear_color.to_array(), |color| {
+                            color.to_array()
+                        }))
+                    } else {
+                        None
+                    };
+                    size = framebuffer_size;
+                    projection = Matrix4D::ortho(0.0,
+                                                 size.width as f32,
+                                                 size.height as f32,
+                                                 0.0,
+                                                 ORTHO_NEAR_PLANE,
+                                                 ORTHO_FAR_PLANE)
                 } else {
-                    (true, &frame.cache_size, Some(self.render_targets[pass_index]))
-                };
+                    size = &frame.cache_size;
+                    clear_color = Some([1.0, 1.0, 1.0, 0.0]);
+                    projection = Matrix4D::ortho(0.0,
+                                                 size.width as f32,
+                                                 0.0,
+                                                 size.height as f32,
+                                                 ORTHO_NEAR_PLANE,
+                                                 ORTHO_FAR_PLANE);
+                }
 
-                for (target_index, target) in pass.targets.iter().enumerate() {
-                    let render_target = target_id.map(|texture_id| {
+                self.device.bind_texture(TextureSampler::CacheA8, src_alpha_id);
+                self.device.bind_texture(TextureSampler::CacheRGBA8, src_color_id);
+
+                for (target_index, target) in pass.alpha_targets.targets.iter().enumerate() {
+                    self.draw_alpha_target((pass.alpha_texture_id.unwrap(), target_index as i32),
+                                           target,
+                                           *size,
+                                           &projection);
+                }
+
+                for (target_index, target) in pass.color_targets.targets.iter().enumerate() {
+                    let render_target = pass.color_texture_id.map(|texture_id| {
                         (texture_id, target_index as i32)
                     });
-                    self.draw_target(render_target,
-                                     target,
-                                     *size,
-                                     src_id,
-                                     do_clear,
-                                     frame.background_color,
-                                     &frame.render_task_data);
+                    self.draw_color_target(render_target,
+                                           target,
+                                           *size,
+                                           src_color_id,
+                                           clear_color,
+                                           &frame.render_task_data,
+                                           &projection);
 
                 }
 
-                src_id = target_id.unwrap_or(self.dummy_cache_texture_id);
+                src_color_id = pass.color_texture_id.unwrap_or(self.dummy_cache_texture_id);
+                src_alpha_id = pass.alpha_texture_id.unwrap_or(self.dummy_cache_texture_id);
+
+                // Return the texture IDs to the pool for next frame.
+                if let Some(texture_id) = pass.color_texture_id.take() {
+                    self.color_render_targets.push(texture_id);
+                }
+                if let Some(texture_id) = pass.alpha_texture_id.take() {
+                    self.alpha_render_targets.push(texture_id);
+                }
             }
 
+            self.color_render_targets.reverse();
+            self.alpha_render_targets.reverse();
             self.draw_render_target_debug(framebuffer_size);
         }
 
         self.unlock_external_images();
     }
 
     pub fn debug_renderer<'a>(&'a mut self) -> &'a mut DebugRenderer {
         &mut self.debug
@@ -1779,17 +1859,17 @@ impl Renderer {
             // Right now, it just draws them in one row at the bottom of the screen,
             // with a fixed size.
             let rt_debug_x0 = 16;
             let rt_debug_y0 = 16;
             let rt_debug_spacing = 16;
             let rt_debug_size = 512;
             let mut current_target = 0;
 
-            for texture_id in &self.render_targets {
+            for texture_id in self.color_render_targets.iter().chain(self.alpha_render_targets.iter()) {
                 let layer_count = self.device.get_render_target_layer_count(*texture_id);
                 for layer_index in 0..layer_count {
                     let x0 = rt_debug_x0 + (rt_debug_spacing + rt_debug_size) * current_target;
                     let y0 = rt_debug_y0;
 
                     // If we have more targets than fit on one row in screen, just early exit.
                     if x0 > framebuffer_size.width as i32 {
                         return;
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.rs
@@ -18,17 +18,17 @@ use std::hash::Hash;
 use std::mem;
 use std::sync::{Arc, Barrier, Mutex};
 use std::sync::mpsc::{channel, Receiver, Sender};
 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, ImageDescriptor, ColorF};
+use webrender_traits::{DevicePoint, DeviceIntSize, DeviceUintRect, ImageDescriptor, ColorF};
 use webrender_traits::{ExternalImageId, GlyphOptions, GlyphInstance, TileOffset, TileSize};
 use webrender_traits::{BlobImageRenderer, BlobImageDescriptor, BlobImageError};
 use threadpool::ThreadPool;
 use euclid::Point2D;
 
 thread_local!(pub static FONT_CONTEXT: RefCell<FontContext> = RefCell::new(FontContext::new()));
 
 type GlyphCache = ResourceClassCache<RenderedGlyphKey, Option<TextureCacheItemId>>;
@@ -105,16 +105,17 @@ enum State {
     QueryResources,
 }
 
 struct ImageResource {
     data: ImageData,
     descriptor: ImageDescriptor,
     epoch: Epoch,
     tiling: Option<TileSize>,
+    dirty_rect: Option<DeviceUintRect>
 }
 
 struct CachedImageInfo {
     texture_cache_id: TextureCacheItemId,
     epoch: Epoch,
 }
 
 pub struct ResourceClassCache<K,V> {
@@ -280,48 +281,55 @@ impl ResourceCache {
             tiling = Some(512);
         }
 
         let resource = ImageResource {
             descriptor: descriptor,
             data: data,
             epoch: Epoch(0),
             tiling: tiling,
+            dirty_rect: None,
         };
 
         self.image_templates.insert(image_key, resource);
     }
 
     pub fn update_image_template(&mut self,
                                  image_key: ImageKey,
                                  descriptor: ImageDescriptor,
-                                 bytes: Vec<u8>) {
-        let next_epoch = match self.image_templates.get(&image_key) {
+                                 bytes: Vec<u8>,
+                                 dirty_rect: Option<DeviceUintRect>) {
+        let (next_epoch, prev_dirty_rect) = match self.image_templates.get(&image_key) {
             Some(image) => {
                 // This image should not be an external image.
                 match image.data {
                     ImageData::ExternalHandle(id) => {
                         panic!("Update an external image with buffer, id={} image_key={:?}", id.0, image_key);
                     },
                     _ => {},
                 }
 
                 let Epoch(current_epoch) = image.epoch;
-                Epoch(current_epoch + 1)
+                (Epoch(current_epoch + 1), image.dirty_rect)
             }
             None => {
-                Epoch(0)
+                (Epoch(0), None)
             }
         };
 
         let resource = ImageResource {
             descriptor: descriptor,
             data: ImageData::new(bytes),
             epoch: next_epoch,
             tiling: None,
+            dirty_rect: match (dirty_rect, prev_dirty_rect) {
+                (Some(rect), Some(prev_rect)) => Some(rect.union(&prev_rect)),
+                (Some(rect), None) => Some(rect),
+                _ => None,
+            },
         };
 
         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);
 
@@ -643,17 +651,17 @@ impl ResourceCache {
             }
         }
     }
 
     fn finalize_image_request(&mut self,
                               request: ImageRequest,
                               image_data: Option<ImageData>,
                               texture_cache_profile: &mut TextureCacheProfileCounters) {
-        let image_template = &self.image_templates[&request.key];
+        let image_template = self.image_templates.get_mut(&request.key).unwrap();
         let image_data = image_data.unwrap_or_else(||{
             image_template.data.clone()
         });
 
         match image_template.data {
             ImageData::ExternalHandle(..) => {
                 // external handle doesn't need to update the texture_cache.
             }
@@ -695,23 +703,25 @@ impl ResourceCache {
 
                 match self.cached_images.entry(request.clone(), self.current_frame_id) {
                     Occupied(entry) => {
                         let image_id = entry.get().texture_cache_id;
 
                         if entry.get().epoch != image_template.epoch {
                             self.texture_cache.update(image_id,
                                                       descriptor,
-                                                      image_data);
+                                                      image_data,
+                                                      image_template.dirty_rect);
 
                             // Update the cached epoch
                             *entry.into_mut() = CachedImageInfo {
                                 texture_cache_id: image_id,
                                 epoch: image_template.epoch,
                             };
+                            image_template.dirty_rect = None;
                         }
                     }
                     Vacant(entry) => {
                         let image_id = self.texture_cache.new_item_id();
 
                         let filter = match request.rendering {
                             ImageRendering::Pixelated => TextureFilter::Nearest,
                             ImageRendering::Auto | ImageRendering::CrispEdges => TextureFilter::Linear,
--- a/gfx/webrender/src/texture_cache.rs
+++ b/gfx/webrender/src/texture_cache.rs
@@ -701,39 +701,54 @@ impl TextureCache {
             item: cache_item,
             kind: AllocationKind::TexturePage,
         }
     }
 
     pub fn update(&mut self,
                   image_id: TextureCacheItemId,
                   descriptor: ImageDescriptor,
-                  data: ImageData) {
+                  data: ImageData,
+                  dirty_rect: Option<DeviceUintRect>) {
         let existing_item = self.items.get(image_id);
 
         // TODO(gw): Handle updates to size/format!
         debug_assert_eq!(existing_item.allocated_rect.size.width, descriptor.width);
         debug_assert_eq!(existing_item.allocated_rect.size.height, descriptor.height);
 
         let op = match data {
             ImageData::ExternalHandle(..) | ImageData::ExternalBuffer(..)=> {
                 panic!("Doesn't support Update() for external image.");
             }
             ImageData::Blob(..) => {
                 panic!("The vector image should have been rasterized into a raw image.");
             }
             ImageData::Raw(bytes) => {
-                TextureUpdateOp::Update {
-                    page_pos_x: existing_item.allocated_rect.origin.x,
-                    page_pos_y: existing_item.allocated_rect.origin.y,
-                    width: descriptor.width,
-                    height: descriptor.height,
-                    data: bytes,
-                    stride: descriptor.stride,
-                    offset: descriptor.offset,
+                if let Some(dirty) = dirty_rect {
+                    let stride = descriptor.compute_stride();
+                    let offset = descriptor.offset + dirty.origin.y * stride + dirty.origin.x;
+                    TextureUpdateOp::Update {
+                        page_pos_x: existing_item.allocated_rect.origin.x + dirty.origin.x,
+                        page_pos_y: existing_item.allocated_rect.origin.y + dirty.origin.y,
+                        width: dirty.size.width,
+                        height: dirty.size.height,
+                        data: bytes,
+                        stride: Some(stride),
+                        offset: offset,
+                    }
+                } else {
+                    TextureUpdateOp::Update {
+                        page_pos_x: existing_item.allocated_rect.origin.x,
+                        page_pos_y: existing_item.allocated_rect.origin.y,
+                        width: descriptor.width,
+                        height: descriptor.height,
+                        data: bytes,
+                        stride: descriptor.stride,
+                        offset: descriptor.offset,
+                    }
                 }
             }
         };
 
         let update_op = TextureUpdate {
             id: existing_item.texture_id,
             op: op,
         };
--- a/gfx/webrender/src/tiling.rs
+++ b/gfx/webrender/src/tiling.rs
@@ -1,13 +1,14 @@
 /* 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::TextureId;
 use fnv::FnvHasher;
 use gpu_store::GpuStoreAddress;
 use internal_types::{ANGLE_FLOAT_TO_FIXED, BatchTextures, CacheTextureId, LowLevelFilterOp};
 use internal_types::SourceTexture;
 use mask_cache::MaskCacheInfo;
 use prim_store::{CLIP_DATA_GPU_SIZE, DeferredResolve, GpuBlock128, GpuBlock16, GpuBlock32};
 use prim_store::{GpuBlock64, GradientData, PrimitiveCacheKey, PrimitiveGeometry, PrimitiveIndex};
 use prim_store::{PrimitiveKind, PrimitiveMetadata, PrimitiveStore, TexelRect};
@@ -123,17 +124,20 @@ impl AlphaBatchHelpers for PrimitiveStor
                         FontRenderMode::Subpixel => BlendMode::Subpixel(text_run_cpu.color),
                         FontRenderMode::Alpha | FontRenderMode::Mono => BlendMode::Alpha,
                     }
                 } else {
                     // Text runs drawn to blur never get drawn with subpixel AA.
                     BlendMode::Alpha
                 }
             }
-            PrimitiveKind::Image => {
+            PrimitiveKind::Image |
+            PrimitiveKind::AlignedGradient |
+            PrimitiveKind::AngleGradient |
+            PrimitiveKind::RadialGradient => {
                 if needs_blending {
                     BlendMode::PremultipliedAlpha
                 } else {
                     BlendMode::None
                 }
             }
             _ => {
                 if needs_blending {
@@ -408,28 +412,21 @@ pub enum PrimitiveRunCmd {
 }
 
 #[derive(Debug, Copy, Clone)]
 pub enum PrimitiveFlags {
     None,
     Scrollbar(ScrollLayerId, f32)
 }
 
-// TODO(gw): I've had to make several of these types below public
-//           with the changes for text-shadow. The proper solution
-//           is to split the render task and render target code into
-//           its own module. However, I'm avoiding that for now since
-//           this PR is large enough already, and other people are working
-//           on PRs that make use of render tasks.
-
 #[derive(Debug, Copy, Clone)]
 pub struct RenderTargetIndex(pub usize);
 
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-struct RenderPassIndex(isize);
+pub struct RenderPassIndex(isize);
 
 struct DynamicTaskInfo {
     index: RenderTaskIndex,
     rect: DeviceIntRect,
 }
 
 pub struct RenderTaskCollection {
     pub render_task_data: Vec<RenderTaskData>,
@@ -852,20 +849,99 @@ impl ClipBatcher {
 
 pub struct RenderTargetContext<'a> {
     pub stacking_context_store: &'a [StackingContext],
     pub clip_scroll_group_store: &'a [ClipScrollGroup],
     pub prim_store: &'a PrimitiveStore,
     pub resource_cache: &'a ResourceCache,
 }
 
+pub trait RenderTarget {
+    fn new(size: DeviceUintSize) -> Self;
+    fn allocate(&mut self, size: DeviceUintSize) -> Option<DeviceUintPoint>;
+    fn build(&mut self,
+             _ctx: &RenderTargetContext,
+             _render_tasks: &mut RenderTaskCollection,
+             _child_pass_index: RenderPassIndex) {}
+    fn add_task(&mut self,
+                task: RenderTask,
+                ctx: &RenderTargetContext,
+                render_tasks: &RenderTaskCollection,
+                pass_index: RenderPassIndex);
+}
+
+#[derive(Debug, Copy, Clone)]
+pub enum RenderTargetKind {
+    Color,   // RGBA32
+    Alpha,   // R8
+}
+
+pub struct RenderTargetList<T> {
+    target_size: DeviceUintSize,
+    pub targets: Vec<T>,
+}
+
+impl<T: RenderTarget> RenderTargetList<T> {
+    fn new(target_size: DeviceUintSize, create_initial_target: bool) -> RenderTargetList<T> {
+        let mut targets = Vec::new();
+        if create_initial_target {
+            targets.push(T::new(target_size));
+        }
+
+        RenderTargetList {
+            targets: targets,
+            target_size: target_size,
+        }
+    }
+
+    pub fn target_count(&self) -> usize {
+        self.targets.len()
+    }
+
+    fn build(&mut self,
+             ctx: &RenderTargetContext,
+             render_tasks: &mut RenderTaskCollection,
+             pass_index: RenderPassIndex) {
+        for target in &mut self.targets {
+            let child_pass_index = RenderPassIndex(pass_index.0 - 1);
+            target.build(ctx, render_tasks, child_pass_index);
+        }
+    }
+
+    fn add_task(&mut self,
+                task: RenderTask,
+                ctx: &RenderTargetContext,
+                render_tasks: &mut RenderTaskCollection,
+                pass_index: RenderPassIndex) {
+        self.targets.last_mut().unwrap().add_task(task, ctx, render_tasks, pass_index);
+    }
+
+    fn allocate(&mut self, alloc_size: DeviceUintSize) -> (DeviceUintPoint, RenderTargetIndex) {
+        let existing_origin = self.targets
+                                  .last_mut()
+                                  .and_then(|target| target.allocate(alloc_size));
+
+        let origin = match existing_origin {
+            Some(origin) => origin,
+            None => {
+                let mut new_target = T::new(self.target_size);
+                let origin = new_target.allocate(alloc_size)
+                                       .expect(&format!("Each render task must allocate <= size of one target! ({:?})", alloc_size));
+                self.targets.push(new_target);
+                origin
+            }
+        };
+
+        (origin, RenderTargetIndex(self.targets.len() - 1))
+    }
+}
+
 /// A render target represents a number of rendering operations on a surface.
-pub struct RenderTarget {
+pub struct ColorRenderTarget {
     pub alpha_batcher: AlphaBatcher,
-    pub clip_batcher: ClipBatcher,
     pub box_shadow_cache_prims: Vec<PrimitiveInstance>,
     // List of text runs to be cached to this render target.
     // TODO(gw): For now, assume that these all come from
     //           the same source texture id. This is almost
     //           always true except for pathological test
     //           cases with more than 4k x 4k of unique
     //           glyphs visible. Once the future glyph / texture
     //           cache changes land, this restriction will
@@ -875,21 +951,24 @@ pub struct RenderTarget {
     // List of blur operations to apply for this render target.
     pub vertical_blurs: Vec<BlurCommand>,
     pub horizontal_blurs: Vec<BlurCommand>,
     pub readbacks: Vec<DeviceIntRect>,
     pub isolate_clears: Vec<DeviceIntRect>,
     page_allocator: TexturePage,
 }
 
-impl RenderTarget {
-    fn new(size: DeviceUintSize) -> RenderTarget {
-        RenderTarget {
+impl RenderTarget for ColorRenderTarget {
+    fn allocate(&mut self, size: DeviceUintSize) -> Option<DeviceUintPoint> {
+        self.page_allocator.allocate(&size)
+    }
+
+    fn new(size: DeviceUintSize) -> ColorRenderTarget {
+        ColorRenderTarget {
             alpha_batcher: AlphaBatcher::new(),
-            clip_batcher: ClipBatcher::new(),
             box_shadow_cache_prims: Vec::new(),
             text_run_cache_prims: Vec::new(),
             text_run_textures: BatchTextures::no_texture(),
             vertical_blurs: Vec::new(),
             horizontal_blurs: Vec::new(),
             readbacks: Vec::new(),
             isolate_clears: Vec::new(),
             page_allocator: TexturePage::new(CacheTextureId(0), size),
@@ -1003,84 +1082,142 @@ impl RenderTarget {
                         }
                     }
                     _ => {
                         // No other primitives make use of primitive caching yet!
                         unreachable!()
                     }
                 }
             }
+            RenderTaskKind::CacheMask(..) => {
+                panic!("Should not be added to color target!");
+            }
+            RenderTaskKind::Readback(device_rect) => {
+                self.readbacks.push(device_rect);
+            }
+        }
+    }
+}
+
+pub struct AlphaRenderTarget {
+    pub clip_batcher: ClipBatcher,
+    page_allocator: TexturePage,
+}
+
+impl RenderTarget for AlphaRenderTarget {
+    fn allocate(&mut self, size: DeviceUintSize) -> Option<DeviceUintPoint> {
+        self.page_allocator.allocate(&size)
+    }
+
+    fn new(size: DeviceUintSize) -> AlphaRenderTarget {
+        AlphaRenderTarget {
+            clip_batcher: ClipBatcher::new(),
+            page_allocator: TexturePage::new(CacheTextureId(0), size),
+        }
+    }
+
+    fn add_task(&mut self,
+                task: RenderTask,
+                ctx: &RenderTargetContext,
+                render_tasks: &RenderTaskCollection,
+                pass_index: RenderPassIndex) {
+        match task.kind {
+            RenderTaskKind::Alpha(..) |
+            RenderTaskKind::VerticalBlur(..) |
+            RenderTaskKind::HorizontalBlur(..) |
+            RenderTaskKind::CachePrimitive(..) |
+            RenderTaskKind::Readback(..) => {
+                panic!("Should not be added to alpha target!");
+            }
             RenderTaskKind::CacheMask(ref task_info) => {
                 let task_index = render_tasks.get_task_index(&task.id, pass_index);
                 self.clip_batcher.add(task_index,
                                       &task_info.clips,
                                       &ctx.resource_cache,
                                       task_info.geometry_kind);
             }
-            RenderTaskKind::Readback(device_rect) => {
-                self.readbacks.push(device_rect);
-            }
         }
     }
 }
 
 /// A render pass represents a set of rendering operations that don't depend on one
 /// another.
 ///
 /// A render pass can have several render targets if there wasn't enough space in one
 /// target to do all of the rendering for that pass.
 pub struct RenderPass {
     pass_index: RenderPassIndex,
     pub is_framebuffer: bool,
     tasks: Vec<RenderTask>,
-    pub targets: Vec<RenderTarget>,
-    size: DeviceUintSize,
+    pub color_targets: RenderTargetList<ColorRenderTarget>,
+    pub alpha_targets: RenderTargetList<AlphaRenderTarget>,
+    pub color_texture_id: Option<TextureId>,
+    pub alpha_texture_id: Option<TextureId>,
 }
 
 impl RenderPass {
     pub fn new(pass_index: isize, is_framebuffer: bool, size: DeviceUintSize) -> RenderPass {
         RenderPass {
             pass_index: RenderPassIndex(pass_index),
             is_framebuffer: is_framebuffer,
-            targets: vec![ RenderTarget::new(size) ],
+            color_targets: RenderTargetList::new(size, is_framebuffer),
+            alpha_targets: RenderTargetList::new(size, false),
             tasks: vec![],
-            size: size,
+            color_texture_id: None,
+            alpha_texture_id: None,
         }
     }
 
     pub fn add_render_task(&mut self, task: RenderTask) {
         self.tasks.push(task);
     }
 
-    fn allocate_target(&mut self, alloc_size: DeviceUintSize) -> DeviceUintPoint {
-        let existing_origin = self.targets
-                                  .last_mut()
-                                  .unwrap()
-                                  .page_allocator
-                                  .allocate(&alloc_size);
-        match existing_origin {
-            Some(origin) => origin,
-            None => {
-                let mut new_target = RenderTarget::new(self.size);
-                let origin = new_target.page_allocator
-                                       .allocate(&alloc_size)
-                                       .expect(&format!("Each render task must allocate <= size of one target! ({:?})", alloc_size));
-                self.targets.push(new_target);
-                origin
-            }
+    fn add_task(&mut self,
+                task: RenderTask,
+                ctx: &RenderTargetContext,
+                render_tasks: &mut RenderTaskCollection) {
+        match task.target_kind() {
+            RenderTargetKind::Color => self.color_targets.add_task(task, ctx, render_tasks, self.pass_index),
+            RenderTargetKind::Alpha => self.alpha_targets.add_task(task, ctx, render_tasks, self.pass_index),
         }
     }
 
+    fn allocate_target(&mut self,
+                       kind: RenderTargetKind,
+                       alloc_size: DeviceUintSize) -> (DeviceUintPoint, RenderTargetIndex) {
+        match kind {
+            RenderTargetKind::Color => self.color_targets.allocate(alloc_size),
+            RenderTargetKind::Alpha => self.alpha_targets.allocate(alloc_size),
+        }
+    }
+
+    pub fn needs_render_target_kind(&self, kind: RenderTargetKind) -> bool {
+        if self.is_framebuffer {
+            false
+        } else {
+            self.required_target_count(kind) > 0
+        }
+    }
+
+    pub fn required_target_count(&self, kind: RenderTargetKind) -> usize {
+        debug_assert!(!self.is_framebuffer);        // framebuffer never needs targets
+        match kind {
+            RenderTargetKind::Color => self.color_targets.target_count(),
+            RenderTargetKind::Alpha => self.alpha_targets.target_count(),
+        }
+    }
 
     pub fn build(&mut self, ctx: &RenderTargetContext, render_tasks: &mut RenderTaskCollection) {
         profile_scope!("RenderPass::build");
 
         // Step through each task, adding to batches as appropriate.
         let tasks = mem::replace(&mut self.tasks, Vec::new());
         for mut task in tasks {
+            let target_kind = task.target_kind();
+
             // Find a target to assign this task to, or create a new
             // one if required.
             match task.location {
                 RenderTaskLocation::Fixed => {}
                 RenderTaskLocation::Dynamic(ref mut origin, ref size) => {
                     // See if this task is a duplicate.
                     // If so, just skip adding it!
                     match task.id {
@@ -1093,35 +1230,30 @@ impl RenderPass {
                             if let Some(rect) = render_tasks.get_dynamic_allocation(self.pass_index, key) {
                                 debug_assert_eq!(rect.size, *size);
                                 continue;
                             }
                         }
                     }
 
                     let alloc_size = DeviceUintSize::new(size.width as u32, size.height as u32);
-                    let alloc_origin = self.allocate_target(alloc_size);
+                    let (alloc_origin, target_index) = self.allocate_target(target_kind, alloc_size);
 
                     *origin = Some((DeviceIntPoint::new(alloc_origin.x as i32,
-                                                     alloc_origin.y as i32),
-                                    RenderTargetIndex(self.targets.len() - 1)));
+                                                        alloc_origin.y as i32),
+                                    target_index));
                 }
             }
 
             render_tasks.add(&task, self.pass_index);
-            self.targets.last_mut().unwrap().add_task(task,
-                                                      ctx,
-                                                      render_tasks,
-                                                      self.pass_index);
+            self.add_task(task, ctx, render_tasks);
         }
 
-        for target in &mut self.targets {
-            let child_pass_index = RenderPassIndex(self.pass_index.0 - 1);
-            target.build(ctx, render_tasks, child_pass_index);
-        }
+        self.color_targets.build(ctx, render_tasks, self.pass_index);
+        self.alpha_targets.build(ctx, render_tasks, self.pass_index);
     }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[repr(u8)]
 pub enum AlphaBatchKind {
     Composite = 0,
     HardwareComposite,
@@ -1319,46 +1451,46 @@ pub struct StackingContextIndex(pub usiz
 #[derive(Debug)]
 pub struct StackingContext {
     pub pipeline_id: PipelineId,
 
     // Offset in the parent reference frame to the origin of this stacking
     // context's coordinate system.
     pub reference_frame_offset: LayerPoint,
 
-    // Bounds of this stacking context in its own coordinate system.
-    pub local_rect: LayerRect,
+    // Bounding rectangle for this stacking context calculated based on the size
+    // and position of all its children.
+    pub bounding_rect: DeviceIntRect,
 
-    pub bounding_rect: DeviceIntRect,
     pub composite_ops: CompositeOps,
     pub clip_scroll_groups: Vec<ClipScrollGroupIndex>,
 
     // Signifies that this stacking context should be drawn in a separate render pass
     // with a transparent background and then composited back to its parent. Used to
     // support mix-blend-mode in certain cases.
     pub should_isolate: bool,
 
     // Set for the root stacking context of a display list or an iframe. Used for determining
     // when to isolate a mix-blend-mode composite.
     pub is_page_root: bool,
 
+    // Wehther or not this stacking context has any visible components, calculated
+    // based on the size and position of all children and how they are clipped.
     pub is_visible: bool,
 }
 
 impl StackingContext {
     pub fn new(pipeline_id: PipelineId,
                reference_frame_offset: LayerPoint,
-               local_rect: LayerRect,
                is_page_root: bool,
                composite_ops: CompositeOps)
                -> StackingContext {
         StackingContext {
             pipeline_id: pipeline_id,
             reference_frame_offset: reference_frame_offset,
-            local_rect: local_rect,
             bounding_rect: DeviceIntRect::zero(),
             composite_ops: composite_ops,
             clip_scroll_groups: Vec::new(),
             should_isolate: false,
             is_page_root: is_page_root,
             is_visible: false,
         }
     }
@@ -1427,32 +1559,27 @@ impl PackedLayer {
     }
 
     pub fn set_transform(&mut self, transform: LayerToWorldTransform) {
         self.transform = transform;
         self.inv_transform = self.transform.inverse().unwrap();
     }
 
     pub fn set_rect(&mut self,
-                    local_rect: Option<LayerRect>,
+                    local_rect: &LayerRect,
                     screen_rect: &DeviceIntRect,
                     device_pixel_ratio: f32)
                     -> Option<TransformedRect> {
-        let local_rect = match local_rect {
-            Some(rect) if !rect.is_empty() => rect,
-            _ => return None,
-        };
-
         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;
+        self.local_clip_rect = *local_rect;
         Some(xf_rect)
     }
 }
 
 #[derive(Debug, Clone)]
 pub struct CompositeOps {
     // Requires only a single texture as input (e.g. most filters)
     pub filters: Vec<LowLevelFilterOp>,
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/src/webgl_stubs.rs
@@ -0,0 +1,59 @@
+/* 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/. */
+
+//! Stubs for the types contained in webgl_types.rs
+//!
+//! The API surface provided here should be roughly the same to the one provided
+//! in webgl_types, modulo completely compiled-out stuff.
+
+use webrender_traits::DeviceIntSize;
+use webrender_traits::{GLContextAttributes, GLLimits};
+use webrender_traits::WebGLCommand;
+
+pub struct GLContextHandleWrapper;
+
+impl GLContextHandleWrapper {
+    pub fn new_context(&self,
+                       _: DeviceIntSize,
+                       _: GLContextAttributes,
+                       _: Option<Box<GLContextDispatcher>>) -> Result<GLContextWrapper, &'static str> {
+        unreachable!()
+    }
+
+    pub fn current_native_handle() -> Option<GLContextHandleWrapper> {
+        None
+    }
+
+    pub fn current_osmesa_handle() -> Option<GLContextHandleWrapper> {
+        None
+    }
+}
+
+pub struct GLContextWrapper;
+
+impl GLContextWrapper {
+    pub fn make_current(&self) {
+        unreachable!()
+    }
+
+    pub fn unbind(&self) {
+        unreachable!()
+    }
+
+    pub fn apply_command(&self, _: WebGLCommand) {
+        unreachable!()
+    }
+
+    pub fn get_info(&self) -> (DeviceIntSize, u32, GLLimits) {
+        unreachable!()
+    }
+
+    pub fn resize(&mut self, _: &DeviceIntSize) -> Result<(), &'static str> {
+        unreachable!()
+    }
+}
+
+pub trait GLContextDispatcher {
+    fn dispatch(&self, Box<Fn() + Send>);
+}
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/src/webgl_types.rs
@@ -0,0 +1,130 @@
+/* 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/. */
+
+//! A set of WebGL-related types, in their own module so it's easy to
+//! compile it off.
+
+use gleam::gl;
+use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle};
+use offscreen_gl_context::{GLContext, NativeGLContextMethods, GLContextDispatcher};
+use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle};
+use offscreen_gl_context::{ColorAttachmentType, GLContextAttributes, GLLimits};
+use webrender_traits::{WebGLCommand, DeviceIntSize};
+
+pub enum GLContextHandleWrapper {
+    Native(NativeGLContextHandle),
+    OSMesa(OSMesaContextHandle),
+}
+
+impl GLContextHandleWrapper {
+    pub fn current_native_handle() -> Option<GLContextHandleWrapper> {
+        NativeGLContext::current_handle().map(GLContextHandleWrapper::Native)
+    }
+
+    pub fn current_osmesa_handle() -> Option<GLContextHandleWrapper> {
+        OSMesaContext::current_handle().map(GLContextHandleWrapper::OSMesa)
+    }
+
+    pub fn new_context(&self,
+                       size: DeviceIntSize,
+                       attributes: GLContextAttributes,
+                       dispatcher: Option<Box<GLContextDispatcher>>) -> Result<GLContextWrapper, &'static str> {
+        match *self {
+            GLContextHandleWrapper::Native(ref handle) => {
+                let ctx = GLContext::<NativeGLContext>::new_shared_with_dispatcher(size.to_untyped(),
+                                                                                   attributes,
+                                                                                   ColorAttachmentType::Texture,
+                                                                                   gl::GlType::default(),
+                                                                                   Some(handle),
+                                                                                   dispatcher);
+                ctx.map(GLContextWrapper::Native)
+            }
+            GLContextHandleWrapper::OSMesa(ref handle) => {
+                let ctx = GLContext::<OSMesaContext>::new_shared_with_dispatcher(size.to_untyped(),
+                                                                                 attributes,
+                                                                                 ColorAttachmentType::Texture,
+                                                                                 gl::GlType::default(),
+                                                                                 Some(handle),
+                                                                                 dispatcher);
+                ctx.map(GLContextWrapper::OSMesa)
+            }
+        }
+    }
+}
+
+pub enum GLContextWrapper {
+    Native(GLContext<NativeGLContext>),
+    OSMesa(GLContext<OSMesaContext>),
+}
+
+impl GLContextWrapper {
+    pub fn make_current(&self) {
+        match *self {
+            GLContextWrapper::Native(ref ctx) => {
+                ctx.make_current().unwrap();
+            }
+            GLContextWrapper::OSMesa(ref ctx) => {
+                ctx.make_current().unwrap();
+            }
+        }
+    }
+
+    pub fn unbind(&self) {
+        match *self {
+            GLContextWrapper::Native(ref ctx) => {
+                ctx.unbind().unwrap();
+            }
+            GLContextWrapper::OSMesa(ref ctx) => {
+                ctx.unbind().unwrap();
+            }
+        }
+    }
+
+    pub fn apply_command(&self, cmd: WebGLCommand) {
+        match *self {
+            GLContextWrapper::Native(ref ctx) => {
+                cmd.apply(ctx);
+            }
+            GLContextWrapper::OSMesa(ref ctx) => {
+                cmd.apply(ctx);
+            }
+        }
+    }
+
+    pub fn get_info(&self) -> (DeviceIntSize, u32, GLLimits) {
+        match *self {
+            GLContextWrapper::Native(ref ctx) => {
+                let (real_size, texture_id) = {
+                    let draw_buffer = ctx.borrow_draw_buffer().unwrap();
+                    (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap())
+                };
+
+                let limits = ctx.borrow_limits().clone();
+
+                (DeviceIntSize::from_untyped(&real_size), texture_id, limits)
+            }
+            GLContextWrapper::OSMesa(ref ctx) => {
+                let (real_size, texture_id) = {
+                    let draw_buffer = ctx.borrow_draw_buffer().unwrap();
+                    (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap())
+                };
+
+                let limits = ctx.borrow_limits().clone();
+
+                (DeviceIntSize::from_untyped(&real_size), texture_id, limits)
+            }
+        }
+    }
+
+    pub fn resize(&mut self, size: &DeviceIntSize) -> Result<(), &'static str> {
+        match *self {
+            GLContextWrapper::Native(ref mut ctx) => {
+                ctx.resize(size.to_untyped())
+            }
+            GLContextWrapper::OSMesa(ref mut ctx) => {
+                ctx.resize(size.to_untyped())
+            }
+        }
+    }
+}
--- 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.26.0"}
+webrender_traits = {path = "../webrender_traits", version = "0.27.0"}
 euclid = "0.11"
 app_units = "0.4"
 gleam = "0.4"
 
 [dependencies.webrender]
 path = "../webrender"
-version = "0.25.0"
+version = "0.26.0"
 default-features = false
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -849,17 +849,17 @@ pub extern "C" fn wr_api_add_external_im
 #[no_mangle]
 pub extern "C" fn wr_api_update_image(api: &mut RenderApi,
                                       key: ImageKey,
                                       descriptor: &WrImageDescriptor,
                                       bytes: ByteSlice) {
     assert!(unsafe { is_in_compositor_thread() });
     let copied_bytes = bytes.as_slice().to_owned();
 
-    api.update_image(key, descriptor.to_descriptor(), copied_bytes);
+    api.update_image(key, descriptor.to_descriptor(), copied_bytes, None);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_delete_image(api: &mut RenderApi, key: ImageKey) {
     assert!(unsafe { is_in_compositor_thread() });
     api.delete_image(key)
 }
 
@@ -1022,17 +1022,16 @@ pub extern "C" fn wr_dp_begin(state: &mu
 
     let bounds = LayoutRect::new(LayoutPoint::new(0.0, 0.0),
                                  LayoutSize::new(width as f32, height as f32));
 
     state.frame_builder
         .dl_builder
         .push_stacking_context(webrender_traits::ScrollPolicy::Scrollable,
                                bounds,
-                               ClipRegion::simple(&bounds),
                                0,
                                None,
                                None,
                                webrender_traits::MixBlendMode::Normal,
                                Vec::new());
 }
 
 #[no_mangle]
@@ -1083,29 +1082,27 @@ pub extern "C" fn wr_dp_push_stacking_co
             ImageMask {
                 image: image,
                 rect: rect.to_rect(),
                 repeat: repeat,
             }
         })
     };
 
-    let clip_region2 = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], None);
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], mask);
 
     let mut filters: Vec<FilterOp> = Vec::new();
     if opacity < 1.0 {
         filters.push(FilterOp::Opacity(PropertyBinding::Value(opacity)));
     }
 
     state.frame_builder
         .dl_builder
         .push_stacking_context(webrender_traits::ScrollPolicy::Scrollable,
                                bounds,
-                               clip_region2,
                                state.z_index,
                                Some(PropertyBinding::Value(*transform)),
                                None,
                                mix_blend_mode,
                                filters);
     state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, None);
 }
 
--- a/gfx/webrender_traits/Cargo.toml
+++ b/gfx/webrender_traits/Cargo.toml
@@ -1,27 +1,28 @@
 [package]
 name = "webrender_traits"
-version = "0.26.0"
+version = "0.27.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"]
 
 [dependencies]
 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"]}
+offscreen_gl_context = {version = "0.8", features = ["serde"], optional = true}
 serde = "0.9"
 serde_derive = "0.9"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 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
@@ -1,36 +1,39 @@
 /* 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 byteorder::{LittleEndian, WriteBytesExt};
 use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
+#[cfg(feature = "webgl")]
 use offscreen_gl_context::{GLContextAttributes, GLLimits};
 use std::cell::Cell;
 use std::fmt;
 use std::marker::PhantomData;
 use {AuxiliaryLists, AuxiliaryListsDescriptor, BuiltDisplayList, BuiltDisplayListDescriptor};
 use {ColorF, DeviceIntPoint, DeviceIntSize, DeviceUintRect, DeviceUintSize, FontKey};
 use {GlyphDimensions, GlyphKey, ImageData, ImageDescriptor, ImageKey, LayoutPoint, LayoutSize};
-use {LayoutTransform, NativeFontHandle, ScrollLayerId, WebGLCommand, WebGLContextId, WorldPoint};
+use {LayoutTransform, NativeFontHandle, ScrollLayerId, WorldPoint};
+#[cfg(feature = "webgl")]
+use {WebGLCommand, WebGLContextId};
 
 pub type TileSize = u16;
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum ApiMsg {
     AddRawFont(FontKey, Vec<u8>),
     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, Vec<u8>),
+    UpdateImage(ImageKey, ImageDescriptor, Vec<u8>, Option<DeviceUintRect>),
     /// Drops an image from the resource cache.
     DeleteImage(ImageKey),
     CloneApi(MsgSender<IdNamespace>),
     /// Supplies a new frame to WebRender.
     ///
     /// After receiving this message, WebRender will read the display list, followed by the
     /// auxiliary lists, from the payload channel.
     SetRootDisplayList(Option<ColorF>,
@@ -95,16 +98,34 @@ impl fmt::Debug for ApiMsg {
         }
     }
 }
 
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
 pub struct Epoch(pub u32);
 
+#[cfg(not(feature = "webgl"))]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
+pub struct WebGLContextId(pub usize);
+
+#[cfg(not(feature = "webgl"))]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct GLContextAttributes([u8; 0]);
+
+#[cfg(not(feature = "webgl"))]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct GLLimits([u8; 0]);
+
+#[cfg(not(feature = "webgl"))]
+#[derive(Clone, Deserialize, Serialize)]
+pub enum WebGLCommand {
+    Flush,
+}
+
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub struct PipelineId(pub u32, pub u32);
 
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
 pub struct IdNamespace(pub u32);
 
@@ -224,18 +245,19 @@ impl RenderApi {
 
     /// Updates a specific image.
     ///
     /// Currently doesn't support changing dimensions or format by updating.
     // TODO: Support changing dimensions (and format) during image update?
     pub fn update_image(&self,
                         key: ImageKey,
                         descriptor: ImageDescriptor,
-                        bytes: Vec<u8>) {
-        let msg = ApiMsg::UpdateImage(key, descriptor, bytes);
+                        bytes: Vec<u8>,
+                        dirty_rect: Option<DeviceUintRect>) {
+        let msg = ApiMsg::UpdateImage(key, descriptor, bytes, dirty_rect);
         self.api_sender.send(msg).unwrap();
     }
 
     /// Deletes the specific image.
     pub fn delete_image(&self, key: ImageKey) {
         let msg = ApiMsg::DeleteImage(key);
         self.api_sender.send(msg).unwrap();
     }
--- a/gfx/webrender_traits/src/display_item.rs
+++ b/gfx/webrender_traits/src/display_item.rs
@@ -239,17 +239,16 @@ pub struct RadialGradientDisplayItem {
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct PushStackingContextDisplayItem {
     pub stacking_context: StackingContext,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct StackingContext {
     pub scroll_policy: ScrollPolicy,
-    pub bounds: LayoutRect,
     pub z_index: i32,
     pub transform: Option<PropertyBinding<LayoutTransform>>,
     pub perspective: Option<LayoutTransform>,
     pub mix_blend_mode: MixBlendMode,
     pub filters: ItemRange,
 }
 
 #[repr(u32)]
@@ -351,27 +350,25 @@ pub struct ComplexClipRegion {
     /// The boundaries of the rectangle.
     pub rect: LayoutRect,
     /// Border radii of this rectangle.
     pub radii: BorderRadius,
 }
 
 impl StackingContext {
     pub fn new(scroll_policy: ScrollPolicy,
-               bounds: LayoutRect,
                z_index: i32,
                transform: Option<PropertyBinding<LayoutTransform>>,
                perspective: Option<LayoutTransform>,
                mix_blend_mode: MixBlendMode,
                filters: Vec<FilterOp>,
                auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
                -> StackingContext {
         StackingContext {
             scroll_policy: scroll_policy,
-            bounds: bounds,
             z_index: z_index,
             transform: transform,
             perspective: perspective,
             mix_blend_mode: mix_blend_mode,
             filters: auxiliary_lists_builder.add_filters(&filters),
         }
     }
 }
--- a/gfx/webrender_traits/src/display_list.rs
+++ b/gfx/webrender_traits/src/display_list.rs
@@ -63,16 +63,20 @@ impl BuiltDisplayListDescriptor {
 impl BuiltDisplayList {
     pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> BuiltDisplayList {
         BuiltDisplayList {
             data: data,
             descriptor: descriptor,
         }
     }
 
+    pub fn into_data(self) -> (Vec<u8>, BuiltDisplayListDescriptor) {
+        (self.data, self.descriptor)
+    }
+
     pub fn data(&self) -> &[u8] {
         &self.data[..]
     }
 
     pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
         &self.descriptor
     }
 
@@ -308,35 +312,33 @@ impl DisplayListBuilder {
         });
 
         self.push_item(item, rect, clip);
     }
 
     pub fn push_stacking_context(&mut self,
                                  scroll_policy: ScrollPolicy,
                                  bounds: LayoutRect,
-                                 clip: ClipRegion,
                                  z_index: i32,
                                  transform: Option<PropertyBinding<LayoutTransform>>,
                                  perspective: Option<LayoutTransform>,
                                  mix_blend_mode: MixBlendMode,
                                  filters: Vec<FilterOp>) {
         let item = SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem {
             stacking_context: StackingContext {
                 scroll_policy: scroll_policy,
-                bounds: bounds,
                 z_index: z_index,
                 transform: transform,
                 perspective: perspective,
                 mix_blend_mode: mix_blend_mode,
                 filters: self.auxiliary_lists_builder.add_filters(&filters),
             }
         });
 
-        self.push_item(item, LayoutRect::zero(), clip);
+        self.push_item(item, bounds, ClipRegion::simple(&LayoutRect::zero()));
     }
 
     pub fn pop_stacking_context(&mut self) {
         self.push_new_empty_item(SpecificDisplayItem::PopStackingContext);
     }
 
     pub fn define_clip(&mut self,
                        clip: ClipRegion,
@@ -427,17 +429,17 @@ 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 blob = convert_pod_to_blob(&self.list).to_vec();
+            let blob = convert_vec_pod_to_blob(self.list);
             let display_list_items_size = blob.len();
 
             (self.pipeline_id,
              BuiltDisplayList {
                  descriptor: BuiltDisplayListDescriptor {
                      display_list_items_size: display_list_items_size,
                  },
                  data: blob,
@@ -522,17 +524,17 @@ impl AuxiliaryListsBuilder {
     }
 
     pub fn glyph_instances(&self, glyph_instances_range: &ItemRange) -> &[GlyphInstance] {
         glyph_instances_range.get(&self.glyph_instances[..])
     }
 
     pub fn finalize(self) -> AuxiliaryLists {
         unsafe {
-            let mut blob = convert_pod_to_blob(&self.gradient_stops).to_vec();
+            let mut blob = convert_vec_pod_to_blob(self.gradient_stops);
             let gradient_stops_size = blob.len();
             blob.extend_from_slice(convert_pod_to_blob(&self.complex_clip_regions));
             let complex_clip_regions_size = blob.len() - gradient_stops_size;
             blob.extend_from_slice(convert_pod_to_blob(&self.filters));
             let filters_size = blob.len() - (complex_clip_regions_size + gradient_stops_size);
             blob.extend_from_slice(convert_pod_to_blob(&self.glyph_instances));
             let glyph_instances_size = blob.len() -
                 (complex_clip_regions_size + gradient_stops_size + filters_size);
@@ -561,16 +563,20 @@ impl AuxiliaryLists {
     /// Creates a new `AuxiliaryLists` instance from a descriptor and data received over a channel.
     pub fn from_data(data: Vec<u8>, descriptor: AuxiliaryListsDescriptor) -> AuxiliaryLists {
         AuxiliaryLists {
             data: data,
             descriptor: descriptor,
         }
     }
 
+    pub fn into_data(self) -> (Vec<u8>, AuxiliaryListsDescriptor) {
+        (self.data, self.descriptor)
+    }
+
     pub fn data(&self) -> &[u8] {
         &self.data[..]
     }
 
     pub fn descriptor(&self) -> &AuxiliaryListsDescriptor {
         &self.descriptor
     }
 
@@ -611,12 +617,19 @@ impl AuxiliaryLists {
         }
     }
 }
 
 unsafe fn convert_pod_to_blob<T>(data: &[T]) -> &[u8] where T: Copy + 'static {
     slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * mem::size_of::<T>())
 }
 
+// this variant of the above lets us convert without needing to make a copy
+unsafe fn convert_vec_pod_to_blob<T>(mut data: Vec<T>) -> Vec<u8> where T: Copy + 'static {
+    let v = Vec::from_raw_parts(data.as_mut_ptr() as *mut u8, data.len() * mem::size_of::<T>(), data.capacity() * mem::size_of::<T>());
+    mem::forget(data);
+    v
+}
+
 unsafe fn convert_blob_to_pod<T>(blob: &[u8]) -> &[T] where T: Copy + 'static {
     slice::from_raw_parts(blob.as_ptr() as *const T, blob.len() / mem::size_of::<T>())
 }
 
--- a/gfx/webrender_traits/src/lib.rs
+++ b/gfx/webrender_traits/src/lib.rs
@@ -9,16 +9,17 @@ extern crate byteorder;
 #[cfg(feature = "nightly")]
 extern crate core;
 extern crate euclid;
 extern crate gleam;
 #[macro_use]
 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;
 
 #[cfg(target_os = "macos")]
 extern crate core_graphics;
 
@@ -28,18 +29,20 @@ extern crate dwrote;
 mod units;
 mod api;
 mod color;
 pub mod channel;
 mod display_item;
 mod display_list;
 mod font;
 mod image;
+#[cfg(feature = "webgl")]
 mod webgl;
 
 pub use api::*;
 pub use color::*;
 pub use display_item::*;
 pub use display_list::*;
 pub use font::*;
 pub use image::*;
 pub use units::*;
+#[cfg(feature = "webgl")]
 pub use webgl::*;
deleted file mode 100644
--- a/third_party/rust/cgl/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"944bf600c6230664922a011cbca026699969f2f89f6c7ff689835836ccd7b1de",".travis.yml":"ea512c9287deceaab4ee436a1246874c84e7a422a90cd3aa3e8f9d3121824674","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"95753be1a55ae87129e69f594f2dc3f14a4f6df4401296aad9fde35b40177814","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"5b2cad1e1bd53b9f986974a23dbcbd951270a567d6c661f3584707d7ad198e82","src/cgl.rs":"d41fea7f18c07912f485d041baeb99010023084b449af69c6c92dfdcaf1c96e8","src/lib.rs":"8a86ac23aaea868d951a1c51300670d1eda525681d0b144964a6c81737f485e6"},"package":"86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/cgl/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Cargo.lock
-target
deleted file mode 100644
--- a/third_party/rust/cgl/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-os: osx
-language: rust
-sudo: false
-branches:
-  except:
-    - master
-notifications:
-  webhooks: http://build.servo.org:54856/travis
deleted file mode 100644
--- a/third_party/rust/cgl/COPYING
+++ /dev/null
@@ -1,5 +0,0 @@
-Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-option. All files in the project carrying such notice may not be
-copied, modified, or distributed except according to those terms.
deleted file mode 100644
--- a/third_party/rust/cgl/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "cgl"
-license = "MIT / Apache-2.0"
-version = "0.2.1"
-authors = ["The Servo Project Developers"]
-description = "Rust bindings for CGL on Mac"
-repository = "https://github.com/servo/cgl-rs"
-
-[dependencies]
-libc = "0.2"
-gleam = "0.4"
deleted file mode 100644
--- a/third_party/rust/cgl/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
deleted file mode 100644
--- a/third_party/rust/cgl/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2012-2013 Mozilla Foundation
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
deleted file mode 100644
--- a/third_party/rust/cgl/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-rust-cgl
-========
-
-Rust bindings for CGL on Mac
deleted file mode 100644
--- a/third_party/rust/cgl/src/cgl.rs
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Mac-specific OpenGL bindings.
-
-#![allow(non_upper_case_globals)]
-
-use gleam::gl::{GLenum, GLint, GLsizei, GLuint};
-use libc::{c_void, c_int, c_char};
-
-pub type CGLPixelFormatAttribute = c_int;
-pub type CGLContextParameter = c_int;
-pub type CGLContextEnable = c_int;
-pub type CGLGlobalOption = c_int;
-pub type CGLError = c_int;
-
-pub type CGLPixelFormatObj = *mut c_void;
-pub type CGLContextObj = *mut c_void;
-pub type CGLShareGroupObj = *mut c_void;
-pub type IOSurfaceRef = *mut c_void;
-
-pub const kCGLNoError: CGLError = 0;
-
-pub const kCGLPFAAllRenderers: CGLPixelFormatAttribute = 1;
-pub const kCGLPFADoubleBuffer: CGLPixelFormatAttribute = 5;
-pub const kCGLPFAStereo: CGLPixelFormatAttribute = 6;
-pub const kCGLPFAAuxBuffers: CGLPixelFormatAttribute = 7;
-pub const kCGLPFAColorSize: CGLPixelFormatAttribute = 8;
-pub const kCGLPFAAlphaSize: CGLPixelFormatAttribute = 11;
-pub const kCGLPFADepthSize: CGLPixelFormatAttribute = 12;
-pub const kCGLPFAStencilSize: CGLPixelFormatAttribute = 13;
-pub const kCGLPFAAccumSize: CGLPixelFormatAttribute = 14;
-pub const kCGLPFAMinimumPolicy: CGLPixelFormatAttribute = 51;
-pub const kCGLPFAMaximumPolicy: CGLPixelFormatAttribute = 52;
-pub const kCGLPFAOffScreen: CGLPixelFormatAttribute = 53;
-pub const kCGLPFAFullScreen: CGLPixelFormatAttribute = 54;
-pub const kCGLPFASampleBuffers: CGLPixelFormatAttribute = 55;
-pub const kCGLPFASamples: CGLPixelFormatAttribute = 56;
-pub const kCGLPFAAuxDepthStencil: CGLPixelFormatAttribute = 57;
-pub const kCGLPFAColorFloat: CGLPixelFormatAttribute = 58;
-pub const kCGLPFAMultisample: CGLPixelFormatAttribute = 59;
-pub const kCGLPFASupersample: CGLPixelFormatAttribute = 60;
-pub const kCGLPFASampleAlpha: CGLPixelFormatAttribute = 61;
-pub const kCGLPFARendererID: CGLPixelFormatAttribute = 70;
-pub const kCGLPFASingleRenderer: CGLPixelFormatAttribute = 71;
-pub const kCGLPFANoRecovery: CGLPixelFormatAttribute = 72;
-pub const kCGLPFAAccelerated: CGLPixelFormatAttribute = 73;
-pub const kCGLPFAClosestPolicy: CGLPixelFormatAttribute = 74;
-pub const kCGLPFARobust: CGLPixelFormatAttribute = 75;
-pub const kCGLPFABackingStore: CGLPixelFormatAttribute = 76;
-pub const kCGLPFAMPSafe: CGLPixelFormatAttribute = 78;
-pub const kCGLPFAWindow: CGLPixelFormatAttribute = 80;
-pub const kCGLPFAMultiScreen: CGLPixelFormatAttribute = 81;
-pub const kCGLPFACompliant: CGLPixelFormatAttribute = 83;
-pub const kCGLPFADisplayMask: CGLPixelFormatAttribute = 84;
-pub const kCGLPFAPBuffer: CGLPixelFormatAttribute = 90;
-pub const kCGLPFARemotePBuffer: CGLPixelFormatAttribute = 91;
-pub const kCGLPFAAllowOfflineRenderers: CGLPixelFormatAttribute = 96;
-pub const kCGLPFAAcceleratedCompute: CGLPixelFormatAttribute = 97;
-pub const kCGLPFAOpenGLProfile: CGLPixelFormatAttribute = 99;
-pub const kCGLPFAVirtualScreenCount: CGLPixelFormatAttribute = 128;
-
-pub const kCGLCESwapRectangle: CGLContextEnable = 201;
-pub const kCGLCESwapLimit: CGLContextEnable = 203;
-pub const kCGLCERasterization: CGLContextEnable = 221;
-pub const kCGLCEStateValidation: CGLContextEnable = 301;
-pub const kCGLCESurfaceBackingSize: CGLContextEnable = 305;
-pub const kCGLCEDisplayListOptimization: CGLContextEnable = 307;
-pub const kCGLCEMPEngine: CGLContextEnable = 313;
-pub const kCGLCECrashOnRemovedFunctions: CGLContextEnable = 316;
-
-pub const kCGLCPSwapRectangle: CGLContextParameter = 200;
-pub const kCGLCPSwapInterval: CGLContextParameter = 222;
-pub const kCGLCPDispatchTableSize: CGLContextParameter = 224;
-pub const kCGLCPClientStorage: CGLContextParameter = 226;
-pub const kCGLCPSurfaceTexture: CGLContextParameter = 228;
-pub const kCGLCPSurfaceOrder: CGLContextParameter = 235;
-pub const kCGLCPSurfaceOpacity: CGLContextParameter = 236;
-pub const kCGLCPSurfaceBackingSize: CGLContextParameter = 304;
-pub const kCGLCPSurfaceSurfaceVolatile: CGLContextParameter = 306;
-pub const kCGLCPReclaimResources: CGLContextParameter = 308;
-pub const kCGLCPCurrentRendererID: CGLContextParameter = 309;
-pub const kCGLCPGPUVertexProcessing: CGLContextParameter = 310;
-pub const kCGLCPGPUFragmentProcessing: CGLContextParameter = 311;
-pub const kCGLCPHasDrawable: CGLContextParameter = 314;
-pub const kCGLCPMPSwapsInFlight: CGLContextParameter = 315;
-
-pub const kCGLGOFormatCacheSize: CGLGlobalOption = 501;
-pub const kCGLGOClearFormatCache: CGLGlobalOption = 502;
-pub const kCGLGORetainRenderers: CGLGlobalOption = 503;
-pub const kCGLGOResetLibrary: CGLGlobalOption = 504;
-pub const kCGLGOUseErrorHandler: CGLGlobalOption = 505;
-pub const kCGLGOUseBuildCache: CGLGlobalOption = 506;
-
-pub const CORE_BOOLEAN_ATTRIBUTES: &'static [CGLPixelFormatAttribute] =
-    &[kCGLPFAAllRenderers,
-      kCGLPFADoubleBuffer,
-      kCGLPFAStereo,
-      kCGLPFAAuxBuffers,
-      kCGLPFAMinimumPolicy,
-      kCGLPFAMaximumPolicy,
-      kCGLPFAOffScreen,
-      kCGLPFAFullScreen,
-      kCGLPFAAuxDepthStencil,
-      kCGLPFAColorFloat,
-      kCGLPFAMultisample,
-      kCGLPFASupersample,
-      kCGLPFASampleAlpha,
-      kCGLPFASingleRenderer,
-      kCGLPFANoRecovery,
-      kCGLPFAAccelerated,
-      kCGLPFAClosestPolicy,
-      kCGLPFARobust,
-      kCGLPFABackingStore,
-      kCGLPFAMPSafe,
-      kCGLPFAWindow,
-      kCGLPFAMultiScreen,
-      kCGLPFACompliant,
-      kCGLPFAPBuffer,
-      kCGLPFARemotePBuffer,
-      kCGLPFAAllowOfflineRenderers,
-      kCGLPFAAcceleratedCompute];
-
-pub const CORE_INTEGER_ATTRIBUTES: &'static [CGLPixelFormatAttribute] =
-    &[kCGLPFAColorSize,
-      kCGLPFAAlphaSize,
-      kCGLPFADepthSize,
-      kCGLPFAStencilSize,
-      kCGLPFAAccumSize,
-      kCGLPFASampleBuffers,
-      kCGLPFASamples,
-      kCGLPFARendererID,
-      kCGLPFADisplayMask,
-      kCGLPFAOpenGLProfile,
-      kCGLPFAVirtualScreenCount];
-
-#[link(name = "OpenGL", kind = "framework")]
-extern {
-    // CGLCurrent.h
-
-    pub fn CGLSetCurrentContext(ctx: CGLContextObj) -> CGLError;
-    pub fn CGLGetCurrentContext() -> CGLContextObj;
-    pub fn CGLGetShareGroup(context: CGLContextObj) -> CGLShareGroupObj;
-
-    // OpenGL.h
-
-    // Pixel format functions
-    pub fn CGLChoosePixelFormat(attribs: *const CGLPixelFormatAttribute,
-                                pix: *mut CGLPixelFormatObj,
-                                npix: *mut GLint) -> CGLError;
-    pub fn CGLDescribePixelFormat(pix: CGLPixelFormatObj,
-                                  pix_num: GLint,
-                                  attrib: CGLPixelFormatAttribute,
-                                  value: *mut GLint) -> CGLError;
-    pub fn CGLDestroyPixelFormat(pix: CGLPixelFormatObj) -> CGLError;
-
-    // Context functions
-    pub fn CGLCreateContext(pix: CGLPixelFormatObj, share: CGLContextObj, ctx: *mut CGLContextObj) ->
-                            CGLError;
-    pub fn CGLDestroyContext(ctx: CGLContextObj) -> CGLError;
-    pub fn CGLGetPixelFormat(ctx: CGLContextObj) -> CGLPixelFormatObj;
-
-    // Getting and Setting Context Options
-    pub fn CGLEnable(ctx: CGLContextObj, pname: CGLContextEnable) -> CGLError;
-    pub fn CGLDisable(ctx: CGLContextObj, pname: CGLContextEnable) -> CGLError;
-    pub fn CGLIsEnabled(ctx: CGLContextObj, pname: CGLContextEnable, enable: &mut GLint) -> CGLError;
-    pub fn CGLSetParameter(ctx: CGLContextObj, pname: CGLContextParameter, params: &GLint) -> CGLError;
-    pub fn CGLGetParameter(ctx: CGLContextObj, pname: CGLContextParameter, params: &mut GLint) -> CGLError;
-
-    // Locking functions
-    pub fn CGLLockContext(ctx: CGLContextObj) -> CGLError;
-    pub fn CGLUnlockContext(ctx: CGLContextObj) -> CGLError;
-
-    // Getting and Setting Global Information
-    pub fn CGLSetOption(pname: CGLGlobalOption, param: &GLint) -> CGLError;
-    pub fn CGLGetOption(pname: CGLGlobalOption, param: &mut GLint) -> CGLError;
-    pub fn CGLSetGlobalOption(pname: CGLGlobalOption, param: &GLint) -> CGLError;
-    pub fn CGLGetGlobalOption(pname: CGLGlobalOption, param: &mut GLint) -> CGLError;
-    pub fn CGLGetVersion (major: &mut GLint, minor: &mut GLint) -> CGLError;
-
-    // CGLIOSurface.h
-
-    pub fn CGLTexImageIOSurface2D(ctx: CGLContextObj, target: GLenum, internal_format: GLenum,
-                                  width: GLsizei, height: GLsizei, format: GLenum, ty: GLenum,
-                                  ioSurface: IOSurfaceRef, plane: GLuint) -> CGLError;
-
-    // https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGL_OpenGL/#//apple_ref/c/func/CGLErrorString
-
-    pub fn CGLErrorString(error: CGLError) -> *const c_char;
-}
deleted file mode 100644
--- a/third_party/rust/cgl/src/lib.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_name = "cgl"]
-#![crate_type = "lib"]
-
-extern crate libc;
-extern crate gleam;
-
-pub use cgl::*;
-
-mod cgl;
deleted file mode 100644
--- a/third_party/rust/error-chain/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"ed8bb3864902ddf6322e6b1d6358bcaec9b51382a5216b9526ad0987ae430b0d",".travis.yml":"d56246d6c8796c638b5012c2d7a91d9b6ec101b6a47128e2d4bfa957c1c784e8","CHANGELOG.md":"8eb613d4a417752d4d1c81e065853e5ba0a21530e0881886c2ae4ffbf0ce57cd","Cargo.toml":"9e551bbef17e031db548e1a81f52d249c94db73a194daf0fe2906bc9404b9805","README.md":"6771ca940645b2f7e7a018c8cd25b25f8bf35786e229b54fa2fded1f2d0ae411","examples/all.rs":"2e6d530e95907bde1e49bda7fde7167568d08a370ade44a153612e2d1cb899d7","examples/doc.rs":"574948eb776c3d363f5cff9a48015bab6c17828c7306dc3eb8818afa90a31a83","examples/quickstart.rs":"0cd227741ed3559c0ead90dcc643cef30b73255d9c9f15c2ee20c4a1085d6f5c","examples/size.rs":"7922acd891dfd06f1d36308a3ccdf03def2646b2f39bfd1b15cf2896247bad8f","src/error_chain.rs":"236c4feead97661b33541434ae71f32c279738a81d0d4b7ce9c50550d5d6a662","src/example_generated.rs":"edaead3c4911afd0a0870cfcab11f8835eb17447031d227bbb5d17210379f778","src/lib.rs":"14ce5d1e76185e762db2414b51411095ddd38207a6f4d9dd50d4a041e7b77d88","src/quick_error.rs":"1889b9ca1f7a5e9124275fd5da81e709d0d6bd3b06915bf320c23d4c4f083301","src/quick_main.rs":"755028c2b4305482a1ab86f8b1b68a95eac22b331c94e14d29777dc69dad1bf4","tests/quick_main.rs":"1d6a726856b954d4cffddab00602583921972ceeeb2bf7ba9ebbac6a51584b53","tests/tests.rs":"2f7ceee2f9808d0985c848d99fe967e8f0b549cf144d4d692a5c5d1c2ba7d660"},"package":"318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/error-chain/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*~
-target/
-Cargo.lock
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/error-chain/.travis.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-language: rust
-rust:
-- stable
-- beta
-- nightly
-# Oldest supported version for all features.
-# Use of https://github.com/rust-lang/rfcs/pull/16
-- 1.13.0
-# Oldest supported version as dependency, with no features, tests, or examples.
-- 1.10.0
-
-sudo: false
-cache: cargo
-addons:
-  apt:
-    packages:
-    - libcurl4-openssl-dev
-    - libelf-dev
-    - libdw-dev
-
-before_script:
-- |
-  pip install 'travis-cargo<0.2' --user &&
-  export PATH=$HOME/.local/bin:$PATH
-
-script:
-- travis-cargo build -- $FEATURES
-- travis-cargo --skip 1.10.0 test -- $FEATURES
-
-after_success:
-- travis-cargo --only stable doc
-- travis-cargo --only stable doc-upload
-
-env:
-  global:
-  - secure: ncxJbvJM1vCZfcEftjsFKJMxxhKLgWKaR8Go9AMo0VB5fB2XVW/6NYO5bQEEYpOf1Nc/+2FbI2+Dkz0S/mJpUcNSfBgablCHgwU2sHse7KsoaqfHj2mf1E3exjzSHoP96hPGicC5zAjSXFjCgJPOUSGqqRaJ7z5AsJLhJT6LuK7QpvwPBZzklUN8T+n1sVmws8TNmRIbaniq/q6wYHANHcy6Dl59dx4sKwniUGiZdUhCiddVpoxbECSxc0A8mN2pk7/aW+WGxK3goBs5ZF7+JXF318F62pDcXQmR5CX6WdpenIcJ25g1Vg1WhQ4Ifpe17CN0bfxV8ShuzrQUThCDMffZCo9XySBtODdEowwK1UIpjnFLfIxjOs45Cd8o3tM2j0CfvtnjOz6BCdUU0qiwNPPNx0wFkx3ZiOfSh+FhBhvyPM12HN2tdN0esgVBItFmEci+sSIIXqjVL6DNiu5zTjbu0bs6COwlUWdmL6vmsZtq5tl7Cno9+C3szxRVAkShGydd04l9NYjqNEzTa1EPG50OsnVRKGdRiFzSxhc3BWExNKvcQ4v867t6/PpPkW6s4oXmYI3+De+8O7ExWc6a4alcrDXKlMs5fCb5Pcd4Ju9kowcjkoJo5yf2wW3Ox5R8SJpaEEpvyhx5O/qtIxjhHNzeo8Wsr/6gdNDv20r91TI=
-  - TRAVIS_CARGO_NIGHTLY_FEATURE=""
-  matrix:
-  - FEATURES=--features=backtrace
-  - FEATURES=--no-default-features
-
-matrix:
-  exclude:
-  - env: FEATURES=--features=backtrace
-    rust: 1.10.0
deleted file mode 100644
--- a/third_party/rust/error-chain/CHANGELOG.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# Unreleased
-
-# 0.7.2
-
-- Add `quick_main!` (#88).
-- `allow(unused)` for the `Result` wrapper.
-- Minimum rust version supported is not 1.10 on some conditions (#103).
-
-# 0.7.1
-
-- [Add the `bail!` macro](https://github.com/brson/error-chain/pull/76)
-
-# 0.7.0
-
-- [Rollback several design changes to fix regressions](https://github.com/brson/error-chain/pull/75)
-- New `Variant(Error) #[attrs]` for `links` and `foreign_links`.
-- Hide implementation details from the doc.
-- Always generate `Error::backtrace`.
-
-# 0.6.2
-
-- Allow dead code.
-
-# 0.6.1
-
-- Fix wrong trait constraint in ResultExt implementation (#66).
-
-# 0.6.0
-
-- Conditional compilation for error variants.
-- Backtrace generation is now a feature.
-- More standard trait implementations for extra convenience.
-- Remove ChainErr.
-- Remove need to specify `ErrorKind` in `links {}`.
-- Add ResultExt trait.
-- Error.1 is a struct instead of a tuple.
-- Error is now a struct.
-- The declarations order is more flexible.
-- Way better error reporting when there is a syntax error in the macro call.
-- `Result` generation can be disabled.
-- At most one declaration of each type can be present.
-
-# 0.5.0
-
-- [Only generate backtraces with RUST_BACKTRACE set](https://github.com/brson/error-chain/pull/27)
-- [Fixup matching, disallow repeating "types" section](https://github.com/brson/error-chain/pull/26)
-- [Fix tests on stable/beta](https://github.com/brson/error-chain/pull/28)
-- [Only deploy docs when tagged](https://github.com/brson/error-chain/pull/30)
-
-Contributors: benaryorg, Brian Anderson, Georg Brandl
-
-# 0.4.2
-
-- [Fix the resolution of the ErrorKind description method](https://github.com/brson/error-chain/pull/24)
-
-Contributors: Brian Anderson
-
-# 0.4.1 (yanked)
-
-- [Fix a problem with resolving methods of the standard Error type](https://github.com/brson/error-chain/pull/22)
-
-Contributors: Brian Anderson
-
-# 0.4.0 (yanked)
-
-- [Remove the foreign link description and forward to the foreign error](https://github.com/brson/error-chain/pull/19)
-- [Allow missing sections](https://github.com/brson/error-chain/pull/17)
-
-Contributors: Brian Anderson, Taylor Cramer
-
-# 0.3.0
-
-- [Forward Display implementation for foreign errors](https://github.com/brson/error-chain/pull/13)
-
-Contributors: Brian Anderson, Taylor Cramer
-
-# 0.2.2
-
-- [Don't require `types` section in macro invocation](https://github.com/brson/error-chain/pull/8)
-- [Add "quick start" to README](https://github.com/brson/error-chain/pull/9)
-
-Contributors: Brian Anderson, Jake Shadle, Nate Mara
deleted file mode 100644
--- a/third_party/rust/error-chain/Cargo.toml
+++ /dev/null
@@ -1,22 +0,0 @@
-[package]
-
-name = "error-chain"
-version = "0.7.2"
-authors = [ "Brian Anderson <banderson@mozilla.com>",
-            "Paul Colomiets <paul@colomiets.name>",
-            "Colin Kiegel <kiegel@gmx.de>",
-            "Yamakaky <yamakaky@yamaworld.fr>"]
-description = "Yet another error boilerplate library."
-
-documentation = "https://docs.rs/error-chain"
-homepage = "https://github.com/brson/error-chain"
-repository = "https://github.com/brson/error-chain"
-
-license = "MIT/Apache-2.0"
-
-[features]
-default = ["backtrace", "example_generated"]
-example_generated = []
-
-[dependencies]
-backtrace = { version = "0.3", optional = true }
deleted file mode 100644
--- a/third_party/rust/error-chain/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# error-chain - Consistent error handling for Rust
-
-[![Build Status](https://api.travis-ci.org/brson/error-chain.svg?branch=master)](https://travis-ci.org/brson/error-chain)
-[![Latest Version](https://img.shields.io/crates/v/error-chain.svg)](https://crates.io/crates/error-chain)
-[![License](https://img.shields.io/github/license/brson/error-chain.svg)](https://github.com/brson/error-chain)
-
-`error-chain` makes it easy to take full advantage of Rust's error
-handling features without the overhead of maintaining boilerplate
-error types and conversions. It implements an opinionated strategy for
-defining your own error types, as well as conversions from others'
-error types.
-
-[Documentation (crates.io)](https://docs.rs/error-chain).
-
-[Documentation (master)](https://brson.github.io/error-chain).
-
-## Quick start
-
-If you just want to set up your new project with error-chain,
-follow the [quickstart.rs] template, and read this [intro]
-to error-chain.
-
-[quickstart.rs]: https://github.com/brson/error-chain/blob/master/examples/quickstart.rs
-[intro]: http://brson.github.io/2016/11/30/starting-with-error-chain
-
-## Supported Rust version
-
-Please view the beginning of the [Travis configuration file](.travis.yml)
-to see the oldest supported Rust version.
-
-Note that `error-chain` supports older versions of Rust when built with
-`default-features = false`.
-
-## License
-
-MIT/Apache-2.0
deleted file mode 100644
--- a/third_party/rust/error-chain/examples/all.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-#[macro_use]
-extern crate error_chain;
-
-pub mod inner {
-    error_chain! {}
-}
-
-#[cfg(feature = "a_feature")]
-pub mod feature {
-    error_chain! {}
-}
-
-error_chain! {
-    // Types generated by the macro. If empty of absent, it defaults to
-    //     Error, ErrorKind, Result;
-    types {
-        // With custom names:
-        MyError, MyErrorKind, MyResult;
-        // Without the `Result` wrapper:
-        //     Error, ErrorKind;
-    }
-
-    // Automatic bindings to others error types generated by `error_chain!`.
-    links {
-        Inner(inner::Error, inner::ErrorKind);
-        // Attributes can be added at the end of the declaration.
-        Feature(feature::Error, feature::ErrorKind) #[cfg(feature = "a_feature")];
-    }
-
-    // Bindings to types implementing std::error::Error.
-    foreign_links {
-        Io(::std::io::Error);
-    }
-}
-
-fn main() {}
deleted file mode 100644
--- a/third_party/rust/error-chain/examples/doc.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-#![deny(missing_docs)]
-
-//! This module is used to check that all generated items are documented.
-
-#[macro_use]
-extern crate error_chain;
-
-/// Inner module.
-pub mod inner {
-    error_chain! {
-    }
-}
-
-error_chain! {
-    links {
-        Inner(inner::Error, inner::ErrorKind) #[doc = "Doc"];
-    }
-    foreign_links {
-        Io(::std::io::Error) #[doc = "Io"];
-    }
-    errors {
-        /// Doc
-        Test2 {
-
-        }
-    }
-}
-
-fn main() {}
deleted file mode 100644
--- a/third_party/rust/error-chain/examples/quickstart.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Simple and robust error handling with error-chain!
-// Use this as a template for new projects.
-
-// `error_chain!` can recurse deeply
-#![recursion_limit = "1024"]
-
-// Import the macro. Don't forget to add `error-chain` in your
-// `Cargo.toml`!
-#[macro_use]
-extern crate error_chain;
-
-// We'll put our errors in an `errors` module, and other modules in
-// this crate will `use errors::*;` to get access to everything
-// `error_chain!` creates.
-mod errors {
-    // Create the Error, ErrorKind, ResultExt, and Result types
-    error_chain! { }
-}
-
-use errors::*;
-
-fn main() {
-    if let Err(ref e) = run() {
-        use ::std::io::Write;
-        let stderr = &mut ::std::io::stderr();
-        let errmsg = "Error writing to stderr";
-
-        writeln!(stderr, "error: {}", e).expect(errmsg);
-
-        for e in e.iter().skip(1) {
-            writeln!(stderr, "caused by: {}", e).expect(errmsg);
-        }
-
-        // The backtrace is not always generated. Try to run this example
-        // with `RUST_BACKTRACE=1`.
-        if let Some(backtrace) = e.backtrace() {
-            writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
-        }
-
-        ::std::process::exit(1);
-    }
-}
-
-// Use this macro to auto-generate the main above. You may want to
-// set the `RUST_BACKTRACE` env variable to see a backtrace.
-//quick_main!(run);
-
-
-// Most functions will return the `Result` type, imported from the
-// `errors` module. It is a typedef of the standard `Result` type
-// for which the error type is always our own `Error`.
-fn run() -> Result<()> {
-    use std::fs::File;
-
-    // This operation will fail
-    File::open("tretrete")
-        .chain_err(|| "unable to open tretrete file")?;
-
-    Ok(())
-}
-
deleted file mode 100644
--- a/third_party/rust/error-chain/examples/size.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-#[macro_use]
-extern crate error_chain;
-
-use std::mem::{size_of, size_of_val};
-
-error_chain! {
-    errors {
-        AVariant
-        Another
-    }
-}
-
-fn main() {
-    println!("Memory usage in bytes");
-    println!("---------------------");
-    println!("Result<()>: {}", size_of::<Result<()>>());
-    println!("  (): {}", size_of::<()>());
-    println!("  Error: {}", size_of::<Error>());
-    println!("    ErrorKind: {}", size_of::<ErrorKind>());
-    let msg = ErrorKind::Msg("test".into());
-    println!("      ErrorKind::Msg: {}", size_of_val(&msg));
-    println!("        String: {}", size_of::<String>());
-    println!("    State: {}", size_of::<error_chain::State>());
-    #[cfg(feature = "backtrace")]
-    {
-        let state = error_chain::State {
-            next_error: None,
-            backtrace: None,
-        };
-        println!("      State.next_error: {}", size_of_val(&state.next_error));
-        println!("      State.backtrace: {}", size_of_val(&state.backtrace));
-    }
-    #[cfg(not(feature = "backtrace"))]
-    {
-        let state = error_chain::State {
-            next_error: None,
-        };
-        println!("      State.next_error: {}", size_of_val(&state.next_error));
-    }
-}
deleted file mode 100644
--- a/third_party/rust/error-chain/src/error_chain.rs
+++ /dev/null
@@ -1,405 +0,0 @@
-/// Prefer to use `error_chain` instead of this macro.
-#[macro_export]
-macro_rules! error_chain_processed {
-    // Default values for `types`.
-    (
-        types {}
-        $( $rest: tt )*
-    ) => {
-        error_chain_processed! {
-            types {
-                Error, ErrorKind, ResultExt, Result;
-            }
-            $( $rest )*
-        }
-    };
-    // With `Result` wrapper.
-    (
-        types {
-            $error_name:ident, $error_kind_name:ident,
-            $result_ext_name:ident, $result_name:ident;
-        }
-        $( $rest: tt )*
-    ) => {
-        error_chain_processed! {
-            types {
-                $error_name, $error_kind_name,
-                $result_ext_name;
-            }
-            $( $rest )*
-        }
-        /// Convenient wrapper around `std::Result`.
-        #[allow(unused)]
-        pub type $result_name<T> = ::std::result::Result<T, $error_name>;
-    };
-    // Without `Result` wrapper.
-    (
-        types {
-            $error_name:ident, $error_kind_name:ident,
-            $result_ext_name:ident;
-        }
-
-        links {
-            $( $link_variant:ident ( $link_error_path:path, $link_kind_path:path )
-               $( #[$meta_links:meta] )*; ) *
-        }
-
-        foreign_links {
-            $( $foreign_link_variant:ident ( $foreign_link_error_path:path )
-               $( #[$meta_foreign_links:meta] )*; )*
-        }
-
-        errors {
-            $( $error_chunks:tt ) *
-        }
-
-    ) => {
-        /// The Error type.
-        ///
-        /// This struct is made of three things:
-        ///
-        /// - an `ErrorKind` which is used to determine the type of the error.
-        /// - a backtrace, generated when the error is created.
-        /// - an error chain, used for the implementation of `Error::cause()`.
-        #[derive(Debug)]
-        pub struct $error_name(
-            // The members must be `pub` for `links`.
-            /// The kind of the error.
-            #[doc(hidden)]
-            pub $error_kind_name,
-            /// Contains the error chain and the backtrace.
-            #[doc(hidden)]
-            pub $crate::State,
-        );
-
-        impl $crate::ChainedError for $error_name {
-            type ErrorKind = $error_kind_name;
-
-            fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
-                $error_name(kind, state)
-            }
-
-            fn from_kind(kind: Self::ErrorKind) -> Self {
-                Self::from_kind(kind)
-            }
-
-            fn kind(&self) -> &Self::ErrorKind {
-                self.kind()
-            }
-
-            fn iter(&self) -> $crate::ErrorChainIter {
-                $crate::ErrorChainIter(Some(self))
-            }
-
-            fn backtrace(&self) -> Option<&$crate::Backtrace> {
-                self.backtrace()
-            }
-
-            impl_extract_backtrace!($error_name
-                                    $error_kind_name
-                                    $([$link_error_path, $(#[$meta_links])*])*);
-        }
-
-        #[allow(dead_code)]
-        impl $error_name {
-            /// Constructs an error from a kind, and generates a backtrace.
-            pub fn from_kind(kind: $error_kind_name) -> $error_name {
-                $error_name(
-                    kind,
-                    $crate::State::default(),
-                )
-            }
-
-            /// Returns the kind of the error.
-            pub fn kind(&self) -> &$error_kind_name {
-                &self.0
-            }
-
-            /// Iterates over the error chain.
-            pub fn iter(&self) -> $crate::ErrorChainIter {
-                $crate::ChainedError::iter(self)
-            }
-
-            /// Returns the backtrace associated with this error.
-            pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
-                self.1.backtrace()
-            }
-        }
-
-        impl ::std::error::Error for $error_name {
-            fn description(&self) -> &str {
-                self.0.description()
-            }
-
-            fn cause(&self) -> Option<&::std::error::Error> {
-                match self.1.next_error {
-                    Some(ref c) => Some(&**c),
-                    None => {
-                        match self.0 {
-                            $(
-                                $(#[$meta_foreign_links])*
-                                $error_kind_name::$foreign_link_variant(ref foreign_err) => {
-                                    foreign_err.cause()
-                                }
-                            ) *
-                            _ => None
-                        }
-                    }
-                }
-            }
-        }
-
-        impl ::std::fmt::Display for $error_name {
-            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-                ::std::fmt::Display::fmt(&self.0, f)
-            }
-        }
-
-        $(
-            $(#[$meta_links])*
-            impl From<$link_error_path> for $error_name {
-                fn from(e: $link_error_path) -> Self {
-                    $error_name(
-                        $error_kind_name::$link_variant(e.0),
-                        e.1,
-                    )
-                }
-            }
-        ) *
-
-        $(
-            $(#[$meta_foreign_links])*
-            impl From<$foreign_link_error_path> for $error_name {
-                fn from(e: $foreign_link_error_path) -> Self {
-                    $error_name::from_kind(
-                        $error_kind_name::$foreign_link_variant(e)
-                    )
-                }
-            }
-        ) *
-
-        impl From<$error_kind_name> for $error_name {
-            fn from(e: $error_kind_name) -> Self {
-                $error_name::from_kind(e)
-            }
-        }
-
-        impl<'a> From<&'a str> for $error_name {
-            fn from(s: &'a str) -> Self {
-                $error_name::from_kind(s.into())
-            }
-        }
-
-        impl From<String> for $error_name {
-            fn from(s: String) -> Self {
-                $error_name::from_kind(s.into())
-            }
-        }
-
-        impl ::std::ops::Deref for $error_name {
-            type Target = $error_kind_name;
-
-            fn deref(&self) -> &Self::Target {
-                &self.0
-            }
-        }
-
-
-        // The ErrorKind type
-        // --------------
-
-        quick_error! {
-            /// The kind of an error.
-            #[derive(Debug)]
-            pub enum $error_kind_name {
-
-                /// A convenient variant for String.
-                Msg(s: String) {
-                    description(&s)
-                    display("{}", s)
-                }
-
-                $(
-                    $(#[$meta_links])*
-                    $link_variant(e: $link_kind_path) {
-                        description(e.description())
-                        display("{}", e)
-                    }
-                ) *
-
-                $(
-                    $(#[$meta_foreign_links])*
-                    $foreign_link_variant(err: $foreign_link_error_path) {
-                        description(::std::error::Error::description(err))
-                        display("{}", err)
-                    }
-                ) *
-
-                $($error_chunks)*
-            }
-        }
-
-        $(
-            $(#[$meta_links])*
-            impl From<$link_kind_path> for $error_kind_name {
-                fn from(e: $link_kind_path) -> Self {
-                    $error_kind_name::$link_variant(e)
-                }
-            }
-        ) *
-
-        impl<'a> From<&'a str> for $error_kind_name {
-            fn from(s: &'a str) -> Self {
-                $error_kind_name::Msg(s.to_string())
-            }
-        }
-
-        impl From<String> for $error_kind_name {
-            fn from(s: String) -> Self {
-                $error_kind_name::Msg(s)
-            }
-        }
-
-        impl From<$error_name> for $error_kind_name {
-            fn from(e: $error_name) -> Self {
-                e.0
-            }
-        }
-
-        // The ResultExt trait defines the `chain_err` method.
-
-        /// Additional methods for `Result`, for easy interaction with this crate.
-        pub trait $result_ext_name<T, E> {
-            /// If the `Result` is an `Err` then `chain_err` evaluates the closure,
-            /// which returns *some type that can be converted to `ErrorKind`*, boxes
-            /// the original error to store as the cause, then returns a new error
-            /// containing the original error.
-            fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
-                where F: FnOnce() -> EK,
-                      EK: Into<$error_kind_name>;
-        }
-
-        impl<T, E> $result_ext_name<T, E> for ::std::result::Result<T, E> where E: ::std::error::Error + Send + 'static {
-            fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
-                where F: FnOnce() -> EK,
-                      EK: Into<$error_kind_name> {
-                self.map_err(move |e| {
-                    let state = $crate::State::new::<$error_name>(Box::new(e), );
-                    $crate::ChainedError::new(callback().into(), state)
-                })
-            }
-        }
-
-
-    };
-}
-
-/// Internal macro used for reordering of the fields.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! error_chain_processing {
-    (
-        ({}, $b:tt, $c:tt, $d:tt)
-        types $content:tt
-        $( $tail:tt )*
-    ) => {
-        error_chain_processing! {
-            ($content, $b, $c, $d)
-            $($tail)*
-        }
-    };
-    (
-        ($a:tt, {}, $c:tt, $d:tt)
-        links $content:tt
-        $( $tail:tt )*
-    ) => {
-        error_chain_processing! {
-            ($a, $content, $c, $d)
-            $($tail)*
-        }
-    };
-    (
-        ($a:tt, $b:tt, {}, $d:tt)
-        foreign_links $content:tt
-        $( $tail:tt )*
-    ) => {
-        error_chain_processing! {
-            ($a, $b, $content, $d)
-            $($tail)*
-        }
-    };
-    (
-        ($a:tt, $b:tt, $c:tt, {})
-        errors $content:tt
-        $( $tail:tt )*
-    ) => {
-        error_chain_processing! {
-            ($a, $b, $c, $content)
-            $($tail)*
-        }
-    };
-    ( ($a:tt, $b:tt, $c:tt, $d:tt) ) => {
-        error_chain_processed! {
-            types $a
-            links $b
-            foreign_links $c
-            errors $d
-        }
-    };
-}
-
-/// This macro is used for handling of duplicated and out-of-order fields. For
-/// the exact rules, see `error_chain_processed`.
-#[macro_export]
-macro_rules! error_chain {
-    ( $( $block_name:ident { $( $block_content:tt )* } )* ) => {
-        error_chain_processing! {
-            ({}, {}, {}, {})
-            $($block_name { $( $block_content )* })*
-        }
-    };
-}
-
-/// Macro used to manage the `backtrace` feature.
-///
-/// See
-/// https://www.reddit.com/r/rust/comments/57virt/hey_rustaceans_got_an_easy_question_ask_here/da5r4ti/?context=3
-/// for more details.
-#[macro_export]
-#[doc(hidden)]
-#[cfg(feature = "backtrace")]
-macro_rules! impl_extract_backtrace {
-    ($error_name: ident
-     $error_kind_name: ident
-     $([$link_error_path: path, $(#[$meta_links: meta])*])*) => {
-        fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
-            -> Option<::std::sync::Arc<$crate::Backtrace>> {
-            if let Some(e) = e.downcast_ref::<$error_name>() {
-                return e.1.backtrace.clone();
-            }
-            $(
-                $( #[$meta_links] )*
-                {
-                    if let Some(e) = e.downcast_ref::<$link_error_path>() {
-                        return e.1.backtrace.clone();
-                    }
-                }
-            ) *
-            None
-        }
-    }
-}
-
-/// Macro used to manage the `backtrace` feature.
-///
-/// See
-/// https://www.reddit.com/r/rust/comments/57virt/hey_rustaceans_got_an_easy_question_ask_here/da5r4ti/?context=3
-/// for more details.
-#[macro_export]
-#[doc(hidden)]
-#[cfg(not(feature = "backtrace"))]
-macro_rules! impl_extract_backtrace {
-    ($error_name: ident
-     $error_kind_name: ident
-     $([$link_error_path: path, $(#[$meta_links: meta])*])*) => {}
-}
deleted file mode 100644
--- a/third_party/rust/error-chain/src/example_generated.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-//! This modules show an example of code generated by the macro. IT MUST NOT BE
-//! USED OUTSIDE THIS CRATE.
-//!
-//! This is the basic error structure. You can see that `ErrorKind`
-//! has been populated in a variety of ways. All `ErrorKind`s get a
-//! `Msg` variant for basic errors. When strings are converted to
-//! `ErrorKind`s they become `ErrorKind::Msg`. The "links" defined in
-//! the macro are expanded to the `Inner` variant, and the
-//! "foreign links" to the `Io` variant.
-//!
-//! Both types come with a variety of `From` conversions as well:
-//! `Error` can be created from `ErrorKind`, `&str` and `String`,
-//! and the `links` and `foreign_links` error types. `ErrorKind`
-//! can be created from the corresponding `ErrorKind`s of the link
-//! types, as well as from `&str` and `String`.
-//!
-//! `into()` and `From::from` are used heavily to massage types into
-//! the right shape. Which one to use in any specific case depends on
-//! the influence of type inference, but there are some patterns that
-//! arise frequently.
-
-/// Another code generated by the macro.
-pub mod inner {
-    error_chain! {}
-}
-
-error_chain! {
-    links {
-        Inner(inner::Error, inner::ErrorKind) #[doc = "Link to another `ErrorChain`."];
-    }
-    foreign_links {
-        Io(::std::io::Error) #[doc = "Link to a `std::error::Error` type."];
-    }
-    errors {
-        #[doc = "A custom error kind."]
-        Custom
-    }
-}
deleted file mode 100644
--- a/third_party/rust/error-chain/src/lib.rs
+++ /dev/null
@@ -1,581 +0,0 @@
-#![deny(missing_docs)]
-
-//! A library for consistent and reliable error handling
-//!
-//! error-chain makes it easy to take full advantage of Rust's
-//! powerful error handling features without the overhead of
-//! maintaining boilerplate error types and conversions. It implements
-//! an opinionated strategy for defining your own error types, as well
-//! as conversions from others' error types.
-//!
-//! ## Quick start
-//!
-//! If you just want to set up your new project with error-chain,
-//! follow the [quickstart.rs] template, and read this [intro]
-//! to error-chain.
-//!
-//! [quickstart.rs]: https://github.com/brson/error-chain/blob/master/examples/quickstart.rs
-//! [intro]: http://brson.github.io/2016/11/30/starting-with-error-chain
-//!
-//! ## Why error chain?
-//!
-//! * error-chain is easy to configure. Handle errors robustly with minimal
-//!   effort.
-//! * Basic error handling requires no maintenance of custom error types
-//!   nor the `From` conversions that make `?` work.
-//! * error-chain scales from simple error handling strategies to more
-//!   rigorous.  Return formatted strings for simple errors, only
-//!   introducing error variants and their strong typing as needed for
-//!   advanced error recovery.
-//! * error-chain makes it trivial to correctly manage the [cause] of
-//!   the errors generated by your own code. This is the "chaining"
-//!   in "error-chain".
-//!
-//! [cause]: https://doc.rust-lang.org/std/error/trait.Error.html#method.cause
-//!
-//! ## Principles of error-chain
-//!
-//! error-chain is based on the following principles:
-//!
-//! * No error should ever be discarded. This library primarily
-//!   makes it easy to "chain" errors with the `chain_err` method.
-//! * Introducing new errors is trivial. Simple errors can be introduced
-//!   at the error site with just a string.
-//! * Handling errors is possible with pattern matching.
-//! * Conversions between error types are done in an automatic and
-//!   consistent way - `From` conversion behavior is never specified
-//!   explicitly.
-//! * Errors implement Send.
-//! * Errors can carry backtraces.
-//!
-//! Similar to other libraries like [error-type] and [quick-error],
-//! this library introduces the error chaining mechanism originally
-//! employed by Cargo.  The `error_chain!` macro declares the types
-//! and implementation boilerplate necessary for fulfilling a
-//! particular error-handling strategy. Most importantly it defines a
-//! custom error type (called `Error` by convention) and the `From`
-//! conversions that let the `try!` macro and `?` operator work.
-//!
-//! This library differs in a few ways from previous error libs:
-//!
-//! * Instead of defining the custom `Error` type as an enum, it is a
-//!   struct containing an `ErrorKind` (which defines the
-//!   `description` and `display` methods for the error), an opaque,
-//!   optional, boxed `std::error::Error + Send + 'static` object
-//!   (which defines the `cause`, and establishes the links in the
-//!   error chain), and a `Backtrace`.
-//! * The macro also defines a `ResultExt` trait that defines a
-//!   `chain_err` method. This method on all `std::error::Error + Send + 'static`
-//!   types extends the error chain by boxing the current
-//!   error into an opaque object and putting it inside a new concrete
-//!   error.
-//! * It provides automatic `From` conversions between other error types
-//!   defined by the `error_chain!` that preserve type information,
-//!   and facilitate seamless error composition and matching of composed
-//!   errors.
-//! * It provides automatic `From` conversions between any other error
-//!   type that hides the type of the other error in the `cause` box.
-//! * If `RUST_BACKTRACE` is enabled, it collects a single backtrace at
-//!   the earliest opportunity and propagates it down the stack through
-//!   `From` and `ResultExt` conversions.
-//!
-//! To accomplish its goals it makes some tradeoffs:
-//!
-//! * The split between the `Error` and `ErrorKind` types can make it
-//!   slightly more cumbersome to instantiate new (unchained) errors,
-//!   requiring an `Into` or `From` conversion; as well as slightly
-//!   more cumbersome to match on errors with another layer of types
-//!   to match.
-//! * Because the error type contains `std::error::Error + Send + 'static` objects,
-//!   it can't implement `PartialEq` for easy comparisons.
-//!
-//! ## Declaring error types
-//!
-//! Generally, you define one family of error types per crate, though
-//! it's also perfectly fine to define error types on a finer-grained
-//! basis, such as per module.
-//!
-//! Assuming you are using crate-level error types, typically you will
-//! define an `errors` module and inside it call `error_chain!`:
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! mod other_error {
-//!     error_chain! {}
-//! }
-//!
-//! error_chain! {
-//!     // The type defined for this error. These are the conventional
-//!     // and recommended names, but they can be arbitrarily chosen.
-//!     // It is also possible to leave this block out entirely, or
-//!     // leave it empty, and these names will be used automatically.
-//!     types {
-//!         Error, ErrorKind, ResultExt, Result;
-//!     }
-//!
-//!     // Without the `Result` wrapper:
-//!     //
-//!     // types {
-//!     //     Error, ErrorKind, ResultExt;
-//!     // }
-//!
-//!     // Automatic conversions between this error chain and other
-//!     // error chains. In this case, it will e.g. generate an
-//!     // `ErrorKind` variant called `Dist` which in turn contains
-//!     // the `rustup_dist::ErrorKind`, with conversions from
-//!     // `rustup_dist::Error`.
-//!     //
-//!     // Optionally, some attributes can be added to a variant.
-//!     //
-//!     // This section can be empty.
-//!     links {
-//!         Another(other_error::Error, other_error::ErrorKind) #[cfg(unix)];
-//!     }
-//!
-//!     // Automatic conversions between this error chain and other
-//!     // error types not defined by the `error_chain!`. These will be
-//!     // wrapped in a new error with, in this case, the
-//!     // `ErrorKind::Temp` variant. The description and cause will
-//!     // forward to the description and cause of the original error.
-//!     //
-//!     // Optionally, some attributes can be added to a variant.
-//!     //
-//!     // This section can be empty.
-//!     foreign_links {
-//!         Fmt(::std::fmt::Error);
-//!         Io(::std::io::Error) #[cfg(unix)];
-//!     }
-//!
-//!     // Define additional `ErrorKind` variants. The syntax here is
-//!     // the same as `quick_error!`, but the `from()` and `cause()`
-//!     // syntax is not supported.
-//!     errors {
-//!         InvalidToolchainName(t: String) {
-//!             description("invalid toolchain name")
-//!             display("invalid toolchain name: '{}'", t)
-//!         }
-//!     }
-//! }
-//!
-//! # fn main() {}
-//! ```
-//!
-//! Each section, `types`, `links`, `foreign_links`, and `errors` may
-//! be omitted if it is empty.
-//!
-//! This populates the module with a number of definitions,
-//! the most important of which are the `Error` type
-//! and the `ErrorKind` type. An example of generated code can be found in the
-//! [example_generated](example_generated) module.
-//!
-//! ## Returning new errors
-//!
-//! Introducing new error chains, with a string message:
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! # fn main() {}
-//! # error_chain! {}
-//! fn foo() -> Result<()> {
-//!     Err("foo error!".into())
-//! }
-//! ```
-//!
-//! Introducing new error chains, with an `ErrorKind`:
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! # fn main() {}
-//! error_chain! {
-//!     errors { FooError }
-//! }
-//!
-//! fn foo() -> Result<()> {
-//!     Err(ErrorKind::FooError.into())
-//! }
-//! ```
-//!
-//! Note that the return type is the typedef `Result`, which is
-//! defined by the macro as `pub type Result<T> =
-//! ::std::result::Result<T, Error>`. Note that in both cases
-//! `.into()` is called to convert a type into the `Error` type; both
-//! strings and `ErrorKind` have `From` conversions to turn them into
-//! `Error`.
-//!
-//! When the error is emitted inside a `try!` macro or behind the
-//! `?` operator, the explicit conversion isn't needed; `try!` will
-//! automatically convert `Err(ErrorKind)` to `Err(Error)`. So the
-//! below is equivalent to the previous:
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! # fn main() {}
-//! # error_chain! { errors { FooError } }
-//! fn foo() -> Result<()> {
-//!     Ok(try!(Err(ErrorKind::FooError)))
-//! }
-//!
-//! fn bar() -> Result<()> {
-//!     Ok(try!(Err("bogus!")))
-//! }
-//! ```
-//!
-//! ## The `bail!` macro
-//!
-//! The above method of introducing new errors works but is a little
-//! verbose. Instead we can use the `bail!` macro, which, much like `try!`
-//! and `?`, performs an early return with conversions. With `bail!` the
-//! previous examples look like:
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! # fn main() {}
-//! # error_chain! { errors { FooError } }
-//! fn foo() -> Result<()> {
-//!     bail!(ErrorKind::FooError);
-//!
-//!     Ok(())
-//! }
-//!
-//! fn bar() -> Result<()> {
-//!     bail!("bogus!");
-//!
-//!     Ok(())
-//! }
-//! ```
-//!
-//! ## Chaining errors
-//!
-//! To extend the error chain:
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! # fn main() {}
-//! # error_chain! {}
-//! # fn do_something() -> Result<()> { unimplemented!() }
-//! # fn test() -> Result<()> {
-//! let res: Result<()> = do_something().chain_err(|| "something went wrong");
-//! # Ok(())
-//! # }
-//! ```
-//!
-//! `chain_err` can be called on any `Result` type where the contained
-//! error type implements `std::error::Error + Send + 'static`.  If
-//! the `Result` is an `Err` then `chain_err` evaluates the closure,
-//! which returns *some type that can be converted to `ErrorKind`*,
-//! boxes the original error to store as the cause, then returns a new
-//! error containing the original error.
-//!
-//! ## Matching errors
-//!
-//! error-chain error variants are matched with simple patterns.
-//! `Error` is a tuple struct and its first field is the `ErrorKind`,
-//! making dispatching on error kinds relatively compact:
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! # fn main() {
-//! error_chain! {
-//!     errors {
-//!         InvalidToolchainName(t: String) {
-//!             description("invalid toolchain name")
-//!             display("invalid toolchain name: '{}'", t)
-//!         }
-//!     }
-//! }
-//!
-//! match Error::from("error!") {
-//!     Error(ErrorKind::InvalidToolchainName(_), _) => { }
-//!     Error(ErrorKind::Msg(_), _) => { }
-//! }
-//! # }
-//! ```
-//!
-//! Chained errors are also matched with (relatively) compact syntax
-//!
-//! ```
-//! # #[macro_use] extern crate error_chain;
-//! mod utils {
-//!     error_chain! {
-//!         errors {
-//!             BadStuff {
-//!                 description("bad stuff")
-//!             }
-//!         }
-//!     }
-//! }
-//!
-//! mod app {
-//!     error_chain! {
-//!         links {
-//!             Utils(::utils::Error, ::utils::ErrorKind);
-//!         }
-//!     }
-//! }
-//!
-//!
-//! # fn main() {
-//! match app::Error::from("error!") {
-//!     app::Error(app::ErrorKind::Utils(utils::ErrorKind::BadStuff), _) => { }
-//!     _ => { }
-//! }
-//! # }
-//! ```
-//!
-//! ## Foreign links
-//!
-//! Errors that do not conform to the same conventions as this library
-//! can still be included in the error chain. They are considered "foreign
-//! errors", and are declared using the `foreign_links` block of the
-//! `error_chain!` macro. `Error`s are automatically created from
-//! foreign errors by the `try!` macro.
-//!
-//! Foreign links and regular links have one crucial difference:
-//! `From` conversions for regular links *do not introduce a new error
-//! into the error chain*, while conversions for foreign links *always
-//! introduce a new error into the error chain*. So for the example
-//! above all errors deriving from the `temp::Error` type will be
-//! presented to the user as a new `ErrorKind::Temp` variant, and the
-//! cause will be the original `temp::Error` error. In contrast, when
-//! `rustup_utils::Error` is converted to `Error` the two `ErrorKind`s
-//! are converted between each other to create a new `Error` but the
-//! old error is discarded; there is no "cause" created from the
-//! original error.
-//!
-//! ## Backtraces
-//!
-//! If the `RUST_BACKTRACE` environment variable is set to anything
-//! but ``0``, the earliest non-foreign error to be generated creates
-//! a single backtrace, which is passed through all `From` conversions
-//! and `chain_err` invocations of compatible types. To read the
-//! backtrace just call the `backtrace()` method.
-//!
-//! Backtrace generation can be disabled by turning off the `backtrace` feature.
-//!
-//! ## Iteration
-//!
-//! The `iter` method returns an iterator over the chain of error boxes.
-//!
-//! [error-type]: https://github.com/DanielKeep/rust-error-type
-//! [quick-error]: https://github.com/tailhook/quick-error
-
-
-#[cfg(feature = "backtrace")]
-extern crate backtrace;
-
-use std::error;
-use std::iter::Iterator;
-#[cfg(feature = "backtrace")]
-use std::sync::Arc;
-
-#[cfg(feature = "backtrace")]
-pub use backtrace::Backtrace;
-#[cfg(not(feature = "backtrace"))]
-/// Dummy type used when the `backtrace` feature is disabled.
-pub type Backtrace = ();
-
-#[macro_use]
-mod quick_error;
-#[macro_use]
-mod error_chain;
-#[macro_use]
-mod quick_main;
-pub use quick_main::ExitCode;
-#[cfg(feature = "example_generated")]
-pub mod example_generated;
-
-/// Iterator over the error chain using the `Error::cause()` method.
-pub struct ErrorChainIter<'a>(pub Option<&'a error::Error>);
-
-impl<'a> Iterator for ErrorChainIter<'a> {
-    type Item = &'a error::Error;
-
-    fn next<'b>(&'b mut self) -> Option<&'a error::Error> {
-        match self.0.take() {
-            Some(e) => {
-                self.0 = e.cause();
-                Some(e)
-            }
-            None => None,
-        }
-    }
-}
-
-/// Returns a backtrace of the current call stack if `RUST_BACKTRACE`
-/// is set to anything but ``0``, and `None` otherwise.  This is used
-/// in the generated error implementations.
-#[cfg(feature = "backtrace")]
-#[doc(hidden)]
-pub fn make_backtrace() -> Option<Arc<Backtrace>> {
-    match std::env::var_os("RUST_BACKTRACE") {
-        Some(ref val) if val != "0" => Some(Arc::new(Backtrace::new())),
-        _ => None,
-    }
-}
-
-/// This trait is implemented on all the errors generated by the `error_chain`
-/// macro.
-pub trait ChainedError: error::Error + Send + 'static {
-    /// Associated kind type.
-    type ErrorKind;
-
-    /// Constructs an error from a kind, and generates a backtrace.
-    fn from_kind(kind: Self::ErrorKind) -> Self where Self: Sized;
-
-    /// Returns the kind of the error.
-    fn kind(&self) -> &Self::ErrorKind;
-
-    /// Iterates over the error chain.
-    fn iter(&self) -> ErrorChainIter;
-
-    /// Returns the backtrace associated with this error.
-    fn backtrace(&self) -> Option<&Backtrace>;
-
-    /// Creates an error from its parts.
-    #[doc(hidden)]
-    fn new(kind: Self::ErrorKind, state: State) -> Self where Self: Sized;
-
-    /// Returns the first known backtrace, either from its State or from one
-    /// of the errors from `foreign_links`.
-    #[cfg(feature = "backtrace")]
-    #[doc(hidden)]
-    fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option<Arc<Backtrace>>
-        where Self: Sized;
-}
-
-/// Common state between errors.
-#[derive(Debug)]
-#[doc(hidden)]
-pub struct State {
-    /// Next error in the error chain.
-    pub next_error: Option<Box<error::Error + Send>>,
-    /// Backtrace for the current error.
-    #[cfg(feature = "backtrace")]
-    pub backtrace: Option<Arc<Backtrace>>,
-}
-
-impl Default for State {
-    #[cfg(feature = "backtrace")]
-    fn default() -> State {
-        State {
-            next_error: None,
-            backtrace: make_backtrace(),
-        }
-    }
-
-    #[cfg(not(feature = "backtrace"))]
-    fn default() -> State {
-        State { next_error: None }
-    }
-}
-
-impl State {
-    /// Creates a new State type
-    #[cfg(feature = "backtrace")]
-    pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State {
-        let backtrace = CE::extract_backtrace(&*e).or_else(make_backtrace);
-        State {
-            next_error: Some(e),
-            backtrace: backtrace,
-        }
-    }
-
-    /// Creates a new State type
-    #[cfg(not(feature = "backtrace"))]
-    pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State {
-        State { next_error: Some(e) }
-    }
-
-    /// Returns the inner backtrace if present.
-    #[cfg(feature = "backtrace")]
-    pub fn backtrace(&self) -> Option<&Backtrace> {
-        self.backtrace.as_ref().map(|v| &**v)
-    }
-
-    /// Returns the inner backtrace if present.
-    #[cfg(not(feature = "backtrace"))]
-    pub fn backtrace(&self) -> Option<&Backtrace> {
-        None
-    }
-}
-
-/// Exits a function early with an error
-///
-/// The `bail!` macro provides an easy way to exit a function.
-/// `bail!(expr)` is equivalent to writing.
-///
-/// ```
-/// # #[macro_use] extern crate error_chain;
-/// # error_chain! { }
-/// # fn main() { }
-/// # fn foo() -> Result<()> {
-/// # let expr = "";
-///     return Err(expr.into());
-/// # }
-/// ```
-///
-/// And as shorthand it takes a formatting string a la `println!`:
-///
-/// ```
-/// # #[macro_use] extern crate error_chain;
-/// # error_chain! { }
-/// # fn main() { }
-/// # fn foo() -> Result<()> {
-/// # let n = 0;
-/// bail!("bad number: {}", n);
-/// # }
-/// ```
-///
-/// # Examples
-///
-/// Bailing on a custom error:
-///
-/// ```
-/// # #[macro_use] extern crate error_chain;
-/// # fn main() {}
-/// error_chain! {
-///     errors { FooError }
-/// }
-///
-/// fn foo() -> Result<()> {
-///     if bad_condition() {
-///         bail!(ErrorKind::FooError);
-///     }
-///
-///     Ok(())
-/// }
-///
-/// # fn bad_condition() -> bool { true }
-/// ```
-///
-/// Bailing on a formatted string:
-///
-/// ```
-/// # #[macro_use] extern crate error_chain;
-/// # fn main() {}
-/// error_chain! { }
-///
-/// fn foo() -> Result<()> {
-///     if let Some(bad_num) = bad_condition() {
-///         bail!("so bad: {}", bad_num);
-///     }
-///
-///     Ok(())
-/// }
-///
-/// # fn bad_condition() -> Option<i8> { None }
-/// ```
-#[macro_export]
-macro_rules! bail {
-    ($e:expr) => {
-        return Err($e.into());
-    };
-    ($fmt:expr, $($arg:tt)+) => {
-        return Err(format!($fmt, $($arg)+).into());
-    };
-}
-
-#[doc(hidden)]
-pub mod mock {
-    error_chain!{}
-}
deleted file mode 100644
--- a/third_party/rust/error-chain/src/quick_error.rs
+++ /dev/null
@@ -1,529 +0,0 @@
-// From https://github.com/tailhook/quick-error
-// Changes:
-//   - replace `impl Error` by `impl Item::description`
-//   - $imeta
-
-#[macro_export]
-macro_rules! quick_error {
-    (   $(#[$meta:meta])*
-        pub enum $name:ident { $($chunks:tt)* }
-    ) => {
-        quick_error!(SORT [pub enum $name $(#[$meta])* ]
-            items [] buf []
-            queue [ $($chunks)* ]);
-    };
-    (   $(#[$meta:meta])*
-        enum $name:ident { $($chunks:tt)* }
-    ) => {
-        quick_error!(SORT [enum $name $(#[$meta])* ]
-            items [] buf []
-            queue [ $($chunks)* ]);
-    };
-    // Queue is empty, can do the work
-    (SORT [enum $name:ident $( #[$meta:meta] )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [ ]
-        queue [ ]
-    ) => {
-        quick_error!(ENUM_DEFINITION [enum $name $( #[$meta] )*]
-            body []
-            queue [$($( #[$imeta] )*
-                      => $iitem: $imode [$( $ivar: $ityp ),*] )*]
-        );
-        quick_error!(IMPLEMENTATIONS $name {$(
-           $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
-           )*});
-        $(
-            quick_error!(ERROR_CHECK $imode $($ifuncs)*);
-        )*
-    };
-    (SORT [pub enum $name:ident $( #[$meta:meta] )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [ ]
-        queue [ ]
-    ) => {
-        quick_error!(ENUM_DEFINITION [pub enum $name $( #[$meta] )*]
-            body []
-            queue [$($( #[$imeta] )*
-                      => $iitem: $imode [$( $ivar: $ityp ),*] )*]
-        );
-        quick_error!(IMPLEMENTATIONS $name {$(
-           $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
-           )*});
-        $(
-            quick_error!(ERROR_CHECK $imode $($ifuncs)*);
-        )*
-    };
-    // Add meta to buffer
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )*]
-        queue [ #[$qmeta:meta] $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* #[$qmeta] ]
-            queue [$( $tail )*]);
-    };
-    // Add ident to buffer
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )*]
-        queue [ $qitem:ident $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])*
-                      => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$(#[$bmeta])* => $qitem : UNIT [ ] ]
-            queue [$( $tail )*]);
-    };
-    // Flush buffer on meta after ident
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )*
-            => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
-        queue [ #[$qmeta:meta] $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
-                     $(#[$bmeta])* => $bitem: $bmode $(( $($btyp),* ))*]
-            items [$($( #[$imeta:meta] )*
-                      => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
-                     $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
-            buf [ #[$qmeta] ]
-            queue [$( $tail )*]);
-    };
-    // Add tuple enum-variant
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
-        queue [($( $qvar:ident: $qtyp:ty ),+) $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),*] ]
-            queue [$( $tail )*]
-        );
-    };
-    // Add struct enum-variant - e.g. { descr: &'static str }
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
-        queue [{ $( $qvar:ident: $qtyp:ty ),+} $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
-            queue [$( $tail )*]);
-    };
-    // Add struct enum-variant, with excess comma - e.g. { descr: &'static str, }
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
-        queue [{$( $qvar:ident: $qtyp:ty ),+ ,} $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
-            queue [$( $tail )*]);
-    };
-    // Add braces and flush always on braces
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )*
-                 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
-        queue [ {$( $qfuncs:tt )*} $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
-                      $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {$( $qfuncs )*} ]
-            buf [ ]
-            queue [$( $tail )*]);
-    };
-    // Flush buffer on double ident
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )*
-                 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
-        queue [ $qitem:ident $( $tail:tt )*]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
-                     $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
-            buf [ => $qitem : UNIT [ ] ]
-            queue [$( $tail )*]);
-    };
-    // Flush buffer on end
-    (SORT [$( $def:tt )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [$( #[$bmeta:meta] )*
-            => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
-        queue [ ]
-    ) => {
-        quick_error!(SORT [$( $def )*]
-            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
-                     $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
-            buf [ ]
-            queue [ ]);
-    };
-    // Public enum (Queue Empty)
-    (ENUM_DEFINITION [pub enum $name:ident $( #[$meta:meta] )*]
-        body [$($( #[$imeta:meta] )*
-            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
-        queue [ ]
-    ) => {
-        $(#[$meta])*
-        pub enum $name {
-            $(
-                $(#[$imeta])*
-                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
-            )*
-        }
-    };
-    // Private enum (Queue Empty)
-    (ENUM_DEFINITION [enum $name:ident $( #[$meta:meta] )*]
-        body [$($( #[$imeta:meta] )*
-            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
-        queue [ ]
-    ) => {
-        $(#[$meta])*
-        enum $name {
-            $(
-                $(#[$imeta])*
-                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
-            )*
-        }
-    };
-    // Unit variant
-    (ENUM_DEFINITION [$( $def:tt )*]
-        body [$($( #[$imeta:meta] )*
-            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
-        queue [$( #[$qmeta:meta] )*
-            => $qitem:ident: UNIT [ ] $( $queue:tt )*]
-    ) => {
-        quick_error!(ENUM_DEFINITION [ $($def)* ]
-            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
-                    $( #[$qmeta] )* => $qitem () {} ]
-            queue [ $($queue)* ]
-        );
-    };
-    // Tuple variant
-    (ENUM_DEFINITION [$( $def:tt )*]
-        body [$($( #[$imeta:meta] )*
-            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
-        queue [$( #[$qmeta:meta] )*
-            => $qitem:ident: TUPLE [$( $qvar:ident: $qtyp:ty ),+] $( $queue:tt )*]
-    ) => {
-        quick_error!(ENUM_DEFINITION [ $($def)* ]
-            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
-                    $( #[$qmeta] )* => $qitem (($( $qtyp ),*)) {} ]
-            queue [ $($queue)* ]
-        );
-    };
-    // Struct variant
-    (ENUM_DEFINITION [$( $def:tt )*]
-        body [$($( #[$imeta:meta] )*
-            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
-        queue [$( #[$qmeta:meta] )*
-            => $qitem:ident: STRUCT [$( $qvar:ident: $qtyp:ty ),*] $( $queue:tt )*]
-    ) => {
-        quick_error!(ENUM_DEFINITION [ $($def)* ]
-            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
-                    $( #[$qmeta] )* => $qitem () {{$( $qvar: $qtyp ),*}} ]
-            queue [ $($queue)* ]
-        );
-    };
-    (IMPLEMENTATIONS
-        $name:ident {$(
-            $item:ident: $imode:tt [$(#[$imeta:meta])*] [$( $var:ident: $typ:ty ),*] {$( $funcs:tt )*}
-        )*}
-    ) => {
-        #[allow(unused)]
-        impl ::std::fmt::Display for $name {
-            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
-                -> ::std::fmt::Result
-            {
-                match *self {
-                    $(
-                        $(#[$imeta])*
-                        quick_error!(ITEM_PATTERN
-                            $name $item: $imode [$( ref $var ),*]
-                        ) => {
-                            let display_fn = quick_error!(FIND_DISPLAY_IMPL
-                                $name $item: $imode
-                                {$( $funcs )*});
-
-                            display_fn(self, fmt)
-                        }
-                    )*
-                }
-            }
-        }
-        /*#[allow(unused)]
-        impl ::std::error::Error for $name {
-            fn description(&self) -> &str {
-                match *self {
-                    $(
-                        quick_error!(ITEM_PATTERN
-                            $name $item: $imode [$( ref $var ),*]
-                        ) => {
-                            quick_error!(FIND_DESCRIPTION_IMPL
-                                $item: $imode self fmt [$( $var ),*]
-                                {$( $funcs )*})
-                        }
-                    )*
-                }
-            }
-            fn cause(&self) -> Option<&::std::error::Error> {
-                match *self {
-                    $(
-                        quick_error!(ITEM_PATTERN
-                            $name $item: $imode [$( ref $var ),*]
-                        ) => {
-                            quick_error!(FIND_CAUSE_IMPL
-                                $item: $imode [$( $var ),*]
-                                {$( $funcs )*})
-                        }
-                    )*
-                }
-            }
-        }*/
-        #[allow(unused)]
-        impl $name {
-            /// A string describing the error kind.
-            pub fn description(&self) -> &str {
-                match *self {
-                    $(
-                        $(#[$imeta])*
-                        quick_error!(ITEM_PATTERN
-                            $name $item: $imode [$( ref $var ),*]
-                        ) => {
-                            quick_error!(FIND_DESCRIPTION_IMPL
-                                $item: $imode self fmt [$( $var ),*]
-                                {$( $funcs )*})
-                        }
-                    )*
-                }
-            }
-        }
-        $(
-            quick_error!(FIND_FROM_IMPL
-                $name $item: $imode [$( $var:$typ ),*]
-                {$( $funcs )*});
-        )*
-    };
-    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
-        { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*}
-    ) => {
-        |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| {
-            write!(f, $( $exprs )*)
-        }
-    };
-    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
-        { display($pattern:expr) $( $tail:tt )*}
-    ) => {
-        |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern) }
-    };
-    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
-        { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*}
-    ) => {
-        |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern, $( $exprs )*) }
-    };
-    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
-        { $t:tt $( $tail:tt )*}
-    ) => {
-        quick_error!(FIND_DISPLAY_IMPL
-            $name $item: $imode
-            {$( $tail )*})
-    };
-    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
-        { }
-    ) => {
-        |self_: &$name, f: &mut ::std::fmt::Formatter| {
-            write!(f, "{}", self_.description())
-        }
-    };
-    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
-        [$( $var:ident ),*]
-        { description($expr:expr) $( $tail:tt )*}
-    ) => {
-        $expr
-    };
-    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
-        [$( $var:ident ),*]
-        { $t:tt $( $tail:tt )*}
-    ) => {
-        quick_error!(FIND_DESCRIPTION_IMPL
-            $item: $imode $me $fmt [$( $var ),*]
-            {$( $tail )*})
-    };
-    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
-        [$( $var:ident ),*]
-        { }
-    ) => {
-        stringify!($item)
-    };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
-        [$( $var:ident ),*]
-        { cause($expr:expr) $( $tail:tt )*}
-    ) => {
-        Some($expr)
-    };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
-        [$( $var:ident ),*]
-        { $t:tt $( $tail:tt )*}
-    ) => {
-        quick_error!(FIND_CAUSE_IMPL
-            $item: $imode [$( $var ),*]
-            { $($tail)* })
-    };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
-        [$( $var:ident ),*]
-        { }
-    ) => {
-        None
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
-        [$( $var:ident: $typ:ty ),*]
-        { from() $( $tail:tt )*}
-    ) => {
-        $(
-            impl From<$typ> for $name {
-                fn from($var: $typ) -> $name {
-                    $name::$item($var)
-                }
-            }
-        )*
-        quick_error!(FIND_FROM_IMPL
-            $name $item: $imode [$( $var:$typ ),*]
-            {$( $tail )*});
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: UNIT
-        [ ]
-        { from($ftyp:ty) $( $tail:tt )*}
-    ) => {
-        impl From<$ftyp> for $name {
-            fn from(_discarded_error: $ftyp) -> $name {
-                $name::$item
-            }
-        }
-        quick_error!(FIND_FROM_IMPL
-            $name $item: UNIT [  ]
-            {$( $tail )*});
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: TUPLE
-        [$( $var:ident: $typ:ty ),*]
-        { from($fvar:ident: $ftyp:ty) -> ($( $texpr:expr ),*) $( $tail:tt )*}
-    ) => {
-        impl From<$ftyp> for $name {
-            fn from($fvar: $ftyp) -> $name {
-                $name::$item($( $texpr ),*)
-            }
-        }
-        quick_error!(FIND_FROM_IMPL
-            $name $item: TUPLE [$( $var:$typ ),*]
-            { $($tail)* });
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: STRUCT
-        [$( $var:ident: $typ:ty ),*]
-        { from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )*}
-    ) => {
-        impl From<$ftyp> for $name {
-            fn from($fvar: $ftyp) -> $name {
-                $name::$item {
-                    $( $tvar: $texpr ),*
-                }
-            }
-        }
-        quick_error!(FIND_FROM_IMPL
-            $name $item: STRUCT [$( $var:$typ ),*]
-            { $($tail)* });
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
-        [$( $var:ident: $typ:ty ),*]
-        { $t:tt $( $tail:tt )*}
-    ) => {
-        quick_error!(FIND_FROM_IMPL
-            $name $item: $imode [$( $var:$typ ),*]
-            {$( $tail )*}
-        );
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
-        [$( $var:ident: $typ:ty ),*]
-        { }
-    ) => {
-    };
-    (ITEM_BODY $(#[$imeta:meta])* $item:ident: UNIT
-    ) => { };
-    (ITEM_BODY $(#[$imeta:meta])* $item:ident: TUPLE
-        [$( $typ:ty ),*]
-    ) => {
-        ($( $typ ),*)
-    };
-    (ITEM_BODY $(#[$imeta:meta])* $item:ident: STRUCT
-        [$( $var:ident: $typ:ty ),*]
-    ) => {
-        {$( $var:$typ ),*}
-    };
-    (ITEM_PATTERN $name:ident $item:ident: UNIT []
-    ) => {
-        $name::$item
-    };
-    (ITEM_PATTERN $name:ident $item:ident: TUPLE
-        [$( ref $var:ident ),*]
-    ) => {
-        $name::$item ($( ref $var ),*)
-    };
-    (ITEM_PATTERN $name:ident $item:ident: STRUCT
-        [$( ref $var:ident ),*]
-    ) => {
-        $name::$item {$( ref $var ),*}
-    };
-    // This one should match all allowed sequences in "funcs" but not match
-    // anything else.
-    // This is to contrast FIND_* clauses which just find stuff they need and
-    // skip everything else completely
-    (ERROR_CHECK $imode:tt display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt display($pattern: expr) $( $tail:tt )*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt display($pattern: expr, $( $exprs:tt )*) $( $tail:tt )*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt description($expr:expr) $( $tail:tt )*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt cause($expr:expr) $($tail:tt)*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt from() $($tail:tt)*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt from($ftyp:ty) $($tail:tt)*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK TUPLE from($fvar:ident: $ftyp:ty) -> ($( $e:expr ),*) $( $tail:tt )*)
-    => { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
-    (ERROR_CHECK STRUCT from($fvar:ident: $ftyp:ty) -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
-    => { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
-    (ERROR_CHECK $imode:tt ) => {};
-    // Utility functions
-    (IDENT $ident:ident) => { $ident }
-}
deleted file mode 100644
--- a/third_party/rust/error-chain/src/quick_main.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-/// Convenient wrapper to be able to use `try!` and such in the main. You can
-/// use it with a separated function:
-///
-/// ```ignore
-/// # #[macro_use] extern crate error_chain;
-/// # error_chain! {}
-/// quick_main!(run);
-///
-/// fn run() -> Result<()> {
-///     Err("error".into())
-/// }
-/// ```
-///
-/// or with a closure:
-///
-/// ```ignore
-/// # #[macro_use] extern crate error_chain;
-/// # error_chain! {}
-/// quick_main!(|| -> Result<()> {
-///     Err("error".into())
-/// });
-/// ```
-///
-/// You can also set the exit value of the process by returning a type that implements [`ExitCode`](trait.ExitCode.html):
-///
-/// ```ignore
-/// # #[macro_use] extern crate error_chain;
-/// # error_chain! {}
-/// quick_main!(run);
-///
-/// fn run() -> Result<u32> {
-///     Err("error".into())
-/// }
-/// ```
-#[macro_export]
-macro_rules! quick_main {
-    ($main:expr) => {
-        fn main() {
-            use ::std::io::Write;
-            let stderr = &mut ::std::io::stderr();
-            let errmsg = "Error writing to stderr";
-
-            ::std::process::exit(match $main() {
-                Ok(ret) => $crate::ExitCode::code(ret),
-                Err(ref e) => {
-                    let e: &$crate::ChainedError<ErrorKind=_> = e;
-                    writeln!(stderr, "Error: {}", e).expect(errmsg);
-
-                    for e in e.iter().skip(1) {
-                        writeln!(stderr, "Caused by: {}", e).expect(errmsg);
-                    }
-
-                    if let Some(backtrace) = e.backtrace() {
-                        writeln!(stderr, "{:?}", backtrace).expect(errmsg);
-                    }
-
-                    1
-                }
-            });
-        }
-    };
-}
-
-/// Represents a value that can be used as the exit status of the process.
-/// See [`quick_main!`](macro.quick_main.html).
-pub trait ExitCode {
-    /// Returns the value to use as the exit status.
-    fn code(self) -> i32;
-}
-
-impl ExitCode for i32 {
-    fn code(self) -> i32 { self }
-}
-
-impl ExitCode for () {
-    fn code(self) -> i32 { 0 }
-}
deleted file mode 100644
--- a/third_party/rust/error-chain/tests/quick_main.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-#![allow(dead_code)]
-#[macro_use]
-extern crate error_chain;
-
-error_chain!();
-
-mod unit {
-    use super::*;
-    quick_main!(run);
-
-    fn run() -> Result<()> {
-        Ok(())
-    }
-}
-
-mod i32 {
-    use super::*;
-    quick_main!(run);
-
-    fn run() -> Result<i32> {
-        Ok(1)
-    }
-}
-
-mod closure {
-    use super::*;
-    quick_main!(|| -> Result<()> {
-        Ok(())
-    });
-}
deleted file mode 100644
--- a/third_party/rust/error-chain/tests/tests.rs
+++ /dev/null
@@ -1,543 +0,0 @@
-#![allow(dead_code)]
-//#![feature(trace_macros)]
-//
-//trace_macros!(true);
-
-#[macro_use]
-extern crate error_chain;
-
-#[test]
-fn smoke_test_1() {
-    error_chain! {
-        types {
-            Error, ErrorKind, ResultExt, Result;
-        }
-
-        links { }
-
-        foreign_links { }
-
-        errors { }
-    };
-}
-
-#[test]
-fn smoke_test_2() {
-    error_chain! {
-        types { }
-
-        links { }
-
-        foreign_links { }
-
-        errors { }
-    };
-}
-
-#[test]
-fn smoke_test_3() {
-    error_chain! {
-        links { }
-
-        foreign_links { }
-
-        errors { }
-    };
-}
-
-#[test]
-fn smoke_test_4() {
-    error_chain! {
-        links { }
-
-        foreign_links { }
-
-        errors {
-            HttpStatus(e: u32) {
-                description("http request returned an unsuccessful status code")
-                display("http request returned an unsuccessful status code: {}", e)
-            }
-        }
-    };
-}
-
-#[test]
-fn smoke_test_5() {
-    error_chain! {
-        types { }
-
-        links { }
-
-        foreign_links { }
-
-        errors {
-            HttpStatus(e: u32) {
-                description("http request returned an unsuccessful status code")
-                display("http request returned an unsuccessful status code: {}", e)
-            }
-        }
-    };
-}
-
-#[test]
-fn smoke_test_6() {
-    error_chain! {
-        errors {
-            HttpStatus(e: u32) {
-                description("http request returned an unsuccessful status code")
-                display("http request returned an unsuccessful status code: {}", e)
-            }
-        }
-    };
-}
-
-#[test]
-fn smoke_test_7() {
-    error_chain! {
-        types { }
-
-        foreign_links { }
-
-        errors {
-            HttpStatus(e: u32) {
-                description("http request returned an unsuccessful status code")
-                display("http request returned an unsuccessful status code: {}", e)
-            }
-        }
-    };
-}
-
-#[test]
-fn smoke_test_8() {
-    error_chain! {
-        types { }
-
-        links { }
-        links { }
-
-        foreign_links { }
-        foreign_links { }
-
-        errors {
-            FileNotFound
-            AccessDenied
-        }
-    };
-}
-
-#[test]
-fn order_test_1() {
-    error_chain! { types { } links { } foreign_links { } errors { } };
-}
-
-#[test]
-fn order_test_2() {
-    error_chain! { links { } types { } foreign_links { } errors { } };
-}
-
-#[test]
-fn order_test_3() {
-    error_chain! { foreign_links { }  links { }  errors { } types { } };
-}
-
-#[test]
-fn order_test_4() {
-    error_chain! { errors { } types { } foreign_links { } };
-}
-
-#[test]
-fn order_test_5() {
-    error_chain! { foreign_links { } types { }  };
-}
-
-#[test]
-fn order_test_6() {
-    error_chain! {
-        links { }
-
-        errors {
-            HttpStatus(e: u32) {
-                description("http request returned an unsuccessful status code")
-                display("http request returned an unsuccessful status code: {}", e)
-            }
-        }
-
-
-        foreign_links { }
-    };
-}
-
-#[test]
-fn order_test_7() {
-    error_chain! {
-        links { }
-
-        foreign_links { }
-
-        types {
-            Error, ErrorKind, ResultExt, Result;
-        }
-    };
-}
-
-
-#[test]
-fn order_test_8() {
-    error_chain! {
-        links { }
-
-        foreign_links { }
-        foreign_links { }
-
-        types {
-            Error, ErrorKind, ResultExt, Result;
-        }
-    };
-}
-
-#[test]
-fn empty() {
-    error_chain! { };
-}
-
-#[test]
-#[cfg(feature = "backtrace")]
-fn has_backtrace_depending_on_env() {
-    use std::env;
-
-    error_chain! {
-        types {}
-        links {}
-        foreign_links {}
-        errors {
-            MyError
-        }
-    }
-
-    let original_value = env::var_os("RUST_BACKTRACE");
-
-    // missing RUST_BACKTRACE and RUST_BACKTRACE=0
-    env::remove_var("RUST_BACKTRACE");
-    let err = Error::from(ErrorKind::MyError);
-    assert!(err.backtrace().is_none());
-    env::set_var("RUST_BACKTRACE", "0");
-    let err = Error::from(ErrorKind::MyError);
-    assert!(err.backtrace().is_none());
-
-    // RUST_BACKTRACE set to anything but 0
-    env::set_var("RUST_BACKTRACE", "yes");
-    let err = Error::from(ErrorKind::MyError);
-    assert!(err.backtrace().is_some());
-
-    if let Some(var) = original_value {
-        env::set_var("RUST_BACKTRACE", var);
-    }
-}
-
-#[test]
-fn chain_err() {
-    use std::fmt;
-
-    error_chain! {
-        foreign_links {
-            Fmt(fmt::Error);
-        }
-        errors {
-            Test
-        }
-    }
-
-    let _: Result<()> = Err(fmt::Error).chain_err(|| "");
-    let _: Result<()> = Err(Error::from_kind(ErrorKind::Test)).chain_err(|| "");
-}
-
-#[test]
-fn links() {
-    mod test {
-        error_chain! {}
-    }
-
-    error_chain! {
-        links {
-            Test(test::Error, test::ErrorKind);
-        }
-    }
-}
-
-#[cfg(test)]
-mod foreign_link_test {
-
-    use std::fmt;
-
-    // Note: foreign errors must be `pub` because they appear in the
-    // signature of the public foreign_link_error_path
-    #[derive(Debug)]
-    pub struct ForeignError {
-        cause: ForeignErrorCause
-    }
-
-    impl ::std::error::Error for ForeignError {
-        fn description(&self) -> &'static str {
-            "Foreign error description"
-        }
-
-        fn cause(&self) -> Option<&::std::error::Error> { Some(&self.cause) }
-    }
-
-    impl fmt::Display for ForeignError {
-        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-            write!(formatter, "Foreign error display")
-        }
-    }
-
-    #[derive(Debug)]
-    pub struct ForeignErrorCause {}
-
-    impl ::std::error::Error for ForeignErrorCause {
-        fn description(&self) -> &'static str {
-            "Foreign error cause description"
-        }
-
-        fn cause(&self) -> Option<&::std::error::Error> { None }
-    }
-
-    impl fmt::Display for ForeignErrorCause {
-        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-            write!(formatter, "Foreign error cause display")
-        }
-    }
-
-    error_chain! {
-        types{
-            Error, ErrorKind, ResultExt, Result;
-        }
-        links {}
-        foreign_links {
-            Foreign(ForeignError);
-            Io(::std::io::Error);
-        }
-        errors {}
-    }
-
-    #[test]
-    fn display_underlying_error() {
-        let chained_error = try_foreign_error().err().unwrap();
-        assert_eq!(
-            format!("{}", ForeignError{ cause: ForeignErrorCause{} }),
-            format!("{}", chained_error)
-        );
-    }
-
-    #[test]
-    fn finds_cause() {
-        let chained_error = try_foreign_error().err().unwrap();
-        assert_eq!(
-            format!("{}", ForeignErrorCause{}),
-            format!("{}", ::std::error::Error::cause(&chained_error).unwrap())
-        );
-    }
-
-    #[test]
-    fn iterates() {
-        let chained_error = try_foreign_error().err().unwrap();
-        let mut error_iter = chained_error.iter();
-        assert_eq!(
-            format!("{}", ForeignError{ cause: ForeignErrorCause{} }),
-            format!("{}", error_iter.next().unwrap())
-        );
-        assert_eq!(
-            format!("{}", ForeignErrorCause{}),
-            format!("{}", error_iter.next().unwrap())
-        );
-        assert_eq!(
-            format!("{:?}", None as Option<&::std::error::Error>),
-            format!("{:?}", error_iter.next())
-        );
-    }
-
-    fn try_foreign_error() -> Result<()> {
-        try!(Err(ForeignError{
-            cause: ForeignErrorCause{}
-        }));
-        Ok(())
-    }
-}
-
-#[cfg(test)]
-mod attributes_test {
-    #[allow(unused_imports)]
-    use std::io;
-
-    #[cfg(not(test))]
-    mod inner {
-        error_chain! {
-
-        }
-    }
-
-    error_chain! {
-        types {
-            Error, ErrorKind, ResultExt, Result;
-        }
-
-        links {
-            Inner(inner::Error, inner::ErrorKind) #[cfg(not(test))];
-        }
-
-        foreign_links {
-            Io(io::Error) #[cfg(not(test))];
-        }
-
-        errors {
-            #[cfg(not(test))]
-            AnError {
-
-            }
-        }
-    }
-}
-
-#[test]
-fn with_result() {
-    error_chain! {
-        types {
-            Error, ErrorKind, ResultExt, Result;
-        }
-    }
-    let _: Result<()> = Ok(());
-}
-
-#[test]
-fn without_result() {
-    error_chain! {
-        types {
-            Error, ErrorKind, ResultExt;
-        }
-    }
-    let _: Result<(), ()> = Ok(());
-}
-
-#[test]
-fn documentation() {
-    mod inner {
-        error_chain! {}
-    }
-
-    error_chain! {
-        links {
-            Inner(inner::Error, inner::ErrorKind) #[doc = "Doc"];
-        }
-        foreign_links {
-            Io(::std::io::Error) #[doc = "Doc"];
-        }
-        errors {
-            /// Doc
-            Variant
-        }
-    }
-}
-
-#[cfg(test)]
-mod multiple_error_same_mod {
-    error_chain! {
-        types {
-            MyError, MyErrorKind, MyResultExt, MyResult;
-        }
-    }
-    error_chain! {}
-}
-
-#[doc(test)]
-#[deny(dead_code)]
-mod allow_dead_code {
-    error_chain! {}
-}
-
-// Make sure links actually work!
-#[test]
-fn rustup_regression() {
-    error_chain! {
-        links {
-            Download(error_chain::mock::Error, error_chain::mock::ErrorKind);
-        }
-
-        foreign_links { }
-
-        errors {
-            LocatingWorkingDir {
-                description("could not locate working directory")
-            }
-        }
-    }
-}
-
-#[test]
-fn error_patterns() {
-    error_chain! {
-        links { }
-
-        foreign_links { }
-
-        errors { }
-    }
-
-    // Tuples look nice when matching errors
-    match Error::from("Test") {
-        Error(ErrorKind::Msg(_), _) => {
-        }
-    }
-}
-
-#[test]
-fn error_first() {
-    error_chain! {
-        errors {
-            LocatingWorkingDir {
-                description("could not locate working directory")
-            }
-        }
-
-        links {
-            Download(error_chain::mock::Error, error_chain::mock::ErrorKind);
-        }
-
-        foreign_links { }
-    }
-}
-
-#[test]
-fn bail() {
-    error_chain! {
-        errors { Foo }
-    }
-
-    fn foo() -> Result<()> {
-        bail!(ErrorKind::Foo)
-    }
-
-    fn bar() -> Result<()> {
-        bail!("bar")
-    }
-
-    fn baz() -> Result<()> {
-        bail!("{}", "baz")
-    }
-}
-
-/// Since the `types` declaration is a list of symbols, check if we
-/// don't change their meaning or order.
-#[test]
-fn types_declarations() {
-    error_chain! {
-        types {
-            MyError, MyErrorKind, MyResultExt, MyResult;
-        }
-    }
-
-    MyError::from_kind(MyErrorKind::Msg("".into()));
-
-    let err: Result<(), ::std::io::Error> = Ok(());
-    MyResultExt::chain_err(err, || "").unwrap();
-
-    let _: MyResult<()> = Ok(());
-}
deleted file mode 100644
--- a/third_party/rust/metadeps/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7fddeb99c2f6a8bf0c57f8ec992f4f3dd643174aaf358faaa704d9ae103eddda","Cargo.toml":"92121442fa4299ae532a607fa048008cabb3ff28434f89014be0763b971fe27c","README.md":"d9b95a8e3c7b120af66d04a2390e06cf784e5e29ad05e65877fa932602387fb5","src/lib.rs":"d03ec98e8c9aea41fecccc684564434e589200adad1363067a8f4297e0fa6531","tests/test.rs":"d7475de77f692d838605f9b9645993dbb8a7f8c4dc5fdfd41b8fa52d47f6352c","tests/testdata.pc":"43f481e989c03674fed5ef78c6420b3f8d36a2ce001928d86c418d1844acd5e7","tests/testlib.pc":"a6e8f05cbef472d36ebb4cbf00bd95410189ba8d41e5b2e974f53da4c62e2b60","tests/toml-missing-file/no-cargo-toml-here":"6ab4da4b56f15315df6538610cfcd2ba3d0f9a7a8414678ff00ab5a78f7d41fa"},"package":"829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/metadeps/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/Cargo.lock
-/target
deleted file mode 100644
--- a/third_party/rust/metadeps/Cargo.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-[package]
-name = "metadeps"
-version = "1.1.1"
-authors = ["Josh Triplett <josh@joshtriplett.org>"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/joshtriplett/metadeps"
-documentation = "http://docs.rs/metadeps"
-description = "Run pkg-config from declarative dependencies in Cargo.toml"
-keywords = ["pkg-config", "build-dependencies", "build-depends", "manifest", "metadata"]
-
-[dependencies]
-error-chain = { version = "0.7.1", default-features = false }
-pkg-config = "0.3.8"
-toml = { version = "0.2", default-features = false }
-
-[dev-dependencies]
-lazy_static = "0.2"
deleted file mode 100644
--- a/third_party/rust/metadeps/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-metadeps lets you write `pkg-config` dependencies in `Cargo.toml` metadata,
-rather than programmatically in `build.rs`.  This makes those dependencies
-declarative, so other tools can read them as well.
-
-# Usage
-
-In your `Cargo.toml`, add the following to your `[build-dependencies]`:
-
-```toml
-metadeps = "1.1"
-```
-
-Then, to declare a dependency on `testlib >= 1.2`, and a conditional dependency
-on `testdata >= 4.5`, add the following section:
-
-```toml
-[package.metadata.pkg-config]
-testlib = "1.2"
-testdata = { version = "4.5", feature = "use-testdata" }
-```
-
-In your `build.rs`, add:
-
-```rust
-extern crate metadeps;
-
-fn main() {
-    metadeps::probe().unwrap();
-}
-```
deleted file mode 100644
--- a/third_party/rust/metadeps/src/lib.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-//! metadeps lets you write `pkg-config` dependencies in `Cargo.toml` metadata,
-//! rather than programmatically in `build.rs`.  This makes those dependencies
-//! declarative, so other tools can read them as well.
-//!
-//! metadeps parses metadata like this in `Cargo.toml`:
-//!
-//! ```toml
-//! [package.metadata.pkg-config]
-//! testlib = "1.2"
-//! testdata = { version = "4.5", feature = "some-feature" }
-//! ```
-
-#![deny(missing_docs, warnings)]
-
-#[macro_use]
-extern crate error_chain;
-extern crate pkg_config;
-extern crate toml;
-
-use std::collections::HashMap;
-use std::env;
-use std::fs;
-use std::io::Read;
-use std::path::PathBuf;
-use pkg_config::{Config, Library};
-
-error_chain! {
-    foreign_links {
-        PkgConfig(pkg_config::Error) #[doc="pkg-config error"];
-    }
-}
-
-/// Probe all libraries configured in the Cargo.toml
-/// `[package.metadata.pkg-config]` section.
-pub fn probe() -> Result<HashMap<String, Library>> {
-    let dir = try!(env::var_os("CARGO_MANIFEST_DIR").ok_or("$CARGO_MANIFEST_DIR not set"));
-    let mut path = PathBuf::from(dir);
-    path.push("Cargo.toml");
-    let mut manifest = try!(fs::File::open(&path).chain_err(||
-        format!("Error opening {}", path.display())
-    ));
-    let mut manifest_str = String::new();
-    try!(manifest.read_to_string(&mut manifest_str).chain_err(||
-        format!("Error reading {}", path.display())
-    ));
-    let toml = try!(manifest_str.parse::<toml::Value>().map_err(|e|
-        format!("Error parsing TOML from {}: {:?}", path.display(), e)
-    ));
-    let key = "package.metadata.pkg-config";
-    let meta = try!(toml.lookup(key).ok_or(
-        format!("No {} in {}", key, path.display())
-    ));
-    let table = try!(meta.as_table().ok_or(
-        format!("{} not a table in {}", key, path.display())
-    ));
-    let mut libraries = HashMap::new();
-    for (name, value) in table {
-        let ref version = match value {
-            &toml::Value::String(ref s) => s,
-            &toml::Value::Table(ref t) => {
-                let mut feature = None;
-                let mut version = None;
-                for (tname, tvalue) in t {
-                    match (tname.as_str(), tvalue) {
-                        ("feature", &toml::Value::String(ref s)) => { feature = Some(s); }
-                        ("version", &toml::Value::String(ref s)) => { version = Some(s); }
-                        _ => bail!("Unexpected key {}.{}.{} type {}", key, name, tname, tvalue.type_str()),
-                    }
-                }
-                if let Some(feature) = feature {
-                    let var = format!("CARGO_FEATURE_{}", feature.to_uppercase().replace('-', "_"));
-                    if env::var_os(var).is_none() {
-                        continue;
-                    }
-                }
-                try!(version.ok_or(format!("No version in {}.{}", key, name)))
-            }
-            _ => bail!("{}.{} not a string or table", key, name),
-        };
-        let library = try!(Config::new().atleast_version(&version).probe(name));
-        libraries.insert(name.clone(), library);
-    }
-    Ok(libraries)
-}
deleted file mode 100644
--- a/third_party/rust/metadeps/tests/test.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-#[macro_use]
-extern crate lazy_static;
-extern crate metadeps;
-extern crate pkg_config;
-
-use std::env;
-use std::sync::Mutex;
-
-lazy_static! {
-    static ref LOCK: Mutex<()> = Mutex::new(());
-}
-
-fn toml(path: &str) -> metadeps::Result<std::collections::HashMap<String, pkg_config::Library>> {
-    let _l = LOCK.lock();
-    env::set_var("PKG_CONFIG_PATH", &env::current_dir().unwrap().join("tests"));
-    env::set_var("CARGO_MANIFEST_DIR", &env::current_dir().unwrap().join("tests").join(path));
-    env::set_var("CARGO_FEATURE_TEST_FEATURE", "");
-    metadeps::probe()
-}
-
-#[test]
-fn good() {
-    let libraries = toml("toml-good").unwrap();
-    let testlib = libraries.get("testlib").unwrap();
-    assert_eq!(testlib.version, "1.2.3");
-    let testdata = libraries.get("testdata").unwrap();
-    assert_eq!(testdata.version, "4.5.6");
-    assert!(libraries.get("testmore").is_none());
-}
-
-fn toml_err(path: &str, err_starts_with: &str) {
-    let err = toml(path).unwrap_err();
-    if !err.description().starts_with(err_starts_with) {
-        panic!("Expected error to start with: {:?}\nGot error: {:?}", err_starts_with, err);
-    }
-}
-
-#[test]
-fn missing_file() {
-    toml_err("toml-missing-file", "Error opening");
-}
-
-#[test]
-fn missing_key() {
-    toml_err("toml-missing-key", "No package.metadata.pkg-config in");
-}
-
-#[test]
-fn not_table() {
-    toml_err("toml-not-table", "package.metadata.pkg-config not a table in");
-}
-
-#[test]
-fn version_missing() {
-    toml_err("toml-version-missing", "No version in package.metadata.pkg-config.testlib");
-}
-
-#[test]
-fn version_not_string() {
-    toml_err("toml-version-not-string", "package.metadata.pkg-config.testlib not a string or table");
-}
-
-#[test]
-fn version_in_table_not_string() {
-    toml_err("toml-version-in-table-not-string", "Unexpected key package.metadata.pkg-config.testlib.version type integer");
-}
-
-#[test]
-fn feature_not_string() {
-    toml_err("toml-feature-not-string", "Unexpected key package.metadata.pkg-config.testlib.feature type integer");
-}
-
-#[test]
-fn unexpected_key() {
-    toml_err("toml-unexpected-key", "Unexpected key package.metadata.pkg-config.testlib.color type string");
-}
deleted file mode 100644
--- a/third_party/rust/metadeps/tests/testdata.pc
+++ /dev/null
@@ -1,8 +0,0 @@
-Name: Test Data
-Description: Fake data to test pkg-config.
-Version: 4.5.6
-
-prefix=/usr
-datarootdir=${prefix}/share
-datadir=${datarootdir}
-testdata=${datadir}/testdata/test.dat
deleted file mode 100644
--- a/third_party/rust/metadeps/tests/testlib.pc
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=/usr
-exec_prefix=${prefix}
-libdir=${exec_prefix}/lib/x86_64-linux-gnu
-includedir=${prefix}/include/testlib
-
-Name: Test Library
-Description: A fake library to test pkg-config.
-Version: 1.2.3
-Libs: L${libdir} -ltest
-Cflags: -I${includedir}
deleted file mode 100644
--- a/third_party/rust/metadeps/tests/toml-missing-file/no-cargo-toml-here
+++ /dev/null
@@ -1,1 +0,0 @@
-No Cargo.toml here
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7150ee9391a955b2ef7e0762fc61c0c1aab167620ca36d88d78062d93b8334ba",".travis.yml":"9b8376fc479996f32f8a690e6009fc2f7e9f6dc1b1224e0180a92ad65b0b2183","Cargo.toml":"c9adde499850222639dec26ff52a2f7c2285a970095a437231856bf3182eb3c6","Makefile":"85b6d903eecac170ac97f10d9d89b8366cd91f5ea2f7c6212704bc590b64cf50","README.md":"614cf0c6242be3e62e45a3d60ce9a2a1581bdc46b28b25d5f40caba558e4d615","build.rs":"95e0820ac2e24e0a4951b92454bbf4eb0967d389a4bc358a844156e5f425bd56","src/draw_buffer.rs":"4b3c61b230e4b4f025ec60b594489570b0ea159e1dada5910d3c0edadbaf6542","src/gl_context.rs":"633392d4b558d89877f70125f799a9c6f1788505d6837456e359198f028884d0","src/gl_context_attributes.rs":"8ddf99864f838ba847783d824e85eb71c8eea7d5dfb9950737dfb1472a33a4f6","src/gl_context_capabilities.rs":"9f665ad04d42d47d15ecbd430639d95da526ec5951f0b7abe2434adc1415c85d","src/gl_feature.rs":"b826884900c0e8d6317a41ebb6c30bdb468601bf1c030c376749bdb2ecd2f15a","src/gl_formats.rs":"d15a8e102ebac82c166be4ba2a6e6702a82d509ac61102157c26a0ae25f54ac7","src/gl_limits.rs":"a7837b11ded456ce454d9beb642359ac1ca755262654ac53bca371dd55b2d172","src/lib.rs":"9d66fc08d6fe533644e2f7dec11e3cdc6f2f237b2fb0bb1fc5996a933c87ab8e","src/platform/mod.rs":"29887128ed1e0c77b5b5dcd1bfc39ef0a53598db5325d76b71f5a772b480789b","src/platform/not_implemented/mod.rs":"d576e9fc3164f9e2a8ff9460a60eaa8ecada44c600de1a4d1bb5513ab93569af","src/platform/not_implemented/native_gl_context.rs":"fe018722b8bebbd59b6fae759dd78b0175d10bf110205b113ff155fd06d0f75d","src/platform/with_cgl/mod.rs":"b05dc146c9ba82d62410d9b0566a8aa70c77e7ec583ad4881c531d7118454543","src/platform/with_cgl/native_gl_context.rs":"c6271cfa96836d8f833f5efbc90352852557d582db41d2c513cc36c3f966ae88","src/platform/with_egl/mod.rs":"c52ac147eb051733070c36b2c62be8c57427f80999507f62a9ce801f4aac284c","src/platform/with_egl/native_gl_context.rs":"3a8342d53de9525a5478cc96b323dbad2b3628aa6655fe5f092834cc72256116","src/platform/with_egl/utils.rs":"508521e2bf3809ffe0dfea4fa4a358903f49c77a33aa42cc6c0e7458d992a2a7","src/platform/with_glx/mod.rs":"0e497f38b2071ed189995c91b27b0b199d31bfcc10836e2d26b55023d7aff503","src/platform/with_glx/native_gl_context.rs":"2c648ae18baac14290b2eca3581d474adfea00a29a7ad47a1100e564e74b9152","src/platform/with_glx/utils.rs":"eb81e0a4c62947fa5099c241cfe2e4dd075376d30b22864e042c0f536ac6be58","src/platform/with_osmesa/mod.rs":"995c1f1af7cb113e51f154796f65e95e145f4b25ea32354756f3380e9a7764b5","src/platform/with_wgl/mod.rs":"38f9b44b54c8a1bd4d25ae77a4ea6a2e5454a00b816764d7d74152c1f3c1b126","src/platform/with_wgl/native_gl_context.rs":"4aecd40a811cf38607b17db9724f79bb934e056f85c90c987b2aa82d637b7bb4","src/platform/with_wgl/utils.rs":"d9640c000dcb513cf0a13c4a0d35c423366b7d0894deff299affe0202bdeb770","src/platform/with_wgl/wgl_attributes.rs":"73b75da18519e048011e9c303e402cf7961e3652aa8f4d4ebf507b4ab83d06a3","src/tests.rs":"c0f7ab2584ee97691a9ab8cc00ebd725a040ef54ef56c285ed0cfbf84a7b0263"},"package":"cebfb377484b8fe608acabed968bc4108d44dcfa22318c2e8614eaffd8c5c5f8"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-target
-Cargo.lock
-*~
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/.travis.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-language: rust
-rust: nightly
-sudo: false
-
-addons:
-  apt:
-    sources:
-      - ubuntu-toolchain-r-test
-    packages:
-      - gcc-4.8
-      - g++-4.8
-      - libxxf86vm-dev
-      - libosmesa6-dev
-      - libgles2-mesa-dev
-
-before_install:
-  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then export CXX=g++-4.8; fi
-
-os:
-  - linux
-  - osx
-
-script:
-  - cargo build --verbose
-  # We cannot test egl nor glx in Travis' linux
-  # - cargo test --verbose
-  # - cargo test --verbose --features test_egl_in_linux
-  - if [ "$TRAVIS_OS_NAME" != "linux" ]; then cargo test --verbose; fi
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/Cargo.toml
+++ /dev/null
@@ -1,42 +0,0 @@
-[package]
-name = "offscreen_gl_context"
-license = "MIT / Apache-2.0"
-version = "0.8.2"
-authors = ["Emilio Cobos Álvarez <emilio@crisal.io>", "The Servo Project Developers"]
-description = "Creation and manipulation of HW accelerated offscreen rendering contexts in multiple platforms. Originally intended for the Servo project's WebGL implementation."
-repository = "https://github.com/emilio/rust-offscreen-rendering-context"
-build = "build.rs"
-
-[build-dependencies]
-gl_generator = "0.5"
-
-[features]
-default = ["x11"]
-osmesa = ["osmesa-sys"]
-# NOTE: Just for testing use, there are no other changes
-test_egl_in_linux = []
-
-[dependencies]
-log  = "0.3"
-gleam = "0.4"
-euclid = "0.11"
-serde = { version = "0.9", optional = true }
-osmesa-sys = { version = "0.1", optional = true }
-
-[target.x86_64-apple-darwin.dependencies]
-core-foundation = "0.3.0"
-cgl = "0.2"
-
-[target.'cfg(target_os = "linux")'.dependencies.x11]
-optional = true
-version = "2.3.0"
-features = ["xlib"]
-
-[target.'cfg(target_os = "windows")'.dependencies]
-winapi = "0.2"
-gdi32-sys = "0.2"
-user32-sys = "0.2"
-kernel32-sys = "0.2"
-
-[target.'cfg(any(target_os="macos", target_os="windows"))'.dependencies]
-lazy_static = "0.2"
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-.PHONY: all tests
-all:
-	@echo > /dev/null
-
-tests:
-	cargo test --verbose
-	cargo test --features texture_surface --verbose
-	cargo test --features "test_osmesa" --verbose
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Offscreen graphics library for Servo
-[![Build
-Status](https://travis-ci.org/emilio/rust-offscreen-rendering-context.svg?branch=master)](https://travis-ci.org/emilio/rust-offscreen-rendering-context)
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/build.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-extern crate gl_generator;
-
-use std::env;
-use std::fs::File;
-use std::path::PathBuf;
-use gl_generator::{Registry, Api, Profile, Fallbacks};
-
-fn main() {
-    let target = env::var("TARGET").unwrap();
-    let dest = PathBuf::from(&env::var("OUT_DIR").unwrap());
-
-    if target.contains("linux") && cfg!(feature = "x11") {
-        let mut file = File::create(&dest.join("glx_bindings.rs")).unwrap();
-        Registry::new(Api::Glx, (1, 4), Profile::Core, Fallbacks::All, [])
-            .write_bindings(gl_generator::StaticGenerator, &mut file).unwrap();
-        println!("cargo:rustc-link-lib=GL");
-    }
-
-    if target.contains("android") || (target.contains("linux") && cfg!(feature = "test_egl_in_linux")) {
-        let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
-        Registry::new(Api::Egl, (1, 4), Profile::Core, Fallbacks::All, [])
-            .write_bindings(gl_generator::StaticGenerator, &mut file).unwrap();
-        println!("cargo:rustc-link-lib=EGL");
-    }
-
-    if target.contains("windows") {
-        let mut file = File::create(&dest.join("wgl_bindings.rs")).unwrap();
-        Registry::new(Api::Wgl, (1, 0), Profile::Core, Fallbacks::All, [])
-            .write_bindings(gl_generator::StaticGenerator, &mut file)
-            .unwrap();
-
-        let mut file = File::create(&dest.join("wgl_extra_bindings.rs")).unwrap();
-        Registry::new(Api::Wgl, (1, 0), Profile::Core, Fallbacks::All, [
-                          "WGL_ARB_create_context",
-                          "WGL_ARB_create_context_profile",
-                          "WGL_ARB_create_context_robustness",
-                          "WGL_ARB_context_flush_control",
-                          "WGL_ARB_extensions_string",
-                          "WGL_ARB_framebuffer_sRGB",
-                          "WGL_ARB_multisample",
-                          "WGL_ARB_pixel_format",
-                          "WGL_ARB_pixel_format_float",
-                          "WGL_EXT_create_context_es2_profile",
-                          "WGL_EXT_extensions_string",
-                          "WGL_EXT_framebuffer_sRGB",
-                          "WGL_EXT_swap_control",
-                      ])
-            .write_bindings(gl_generator::StructGenerator, &mut file).unwrap();
-
-        println!("cargo:rustc-link-lib=opengl32");
-    }
-
-    if target.contains("darwin") {
-        println!("cargo:rustc-link-lib=framework=OpenGL");
-    }
-}
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/src/draw_buffer.rs
+++ /dev/null
@@ -1,281 +0,0 @@
-use euclid::Size2D;
-use gleam::gl;
-use gleam::gl::types::{GLuint, GLenum, GLint};
-use std::rc::Rc;
-
-use GLContext;
-use NativeGLContextMethods;
-
-#[derive(Debug)]
-pub enum ColorAttachmentType {
-    Texture,
-    Renderbuffer,
-}
-
-impl Default for ColorAttachmentType {
-    fn default() -> ColorAttachmentType {
-        ColorAttachmentType::Renderbuffer
-    }
-}
-
-
-/// We either have a color renderbuffer, or a surface bound to a texture bound
-/// to a framebuffer as a color attachment.
-///
-/// NB: The draw buffer manages it, and calls its destroy method on drop, this
-/// is just to avoid propagating the GL functions pointer further down.
-#[derive(Debug)]
-pub enum ColorAttachment {
-    Renderbuffer(GLuint),
-    Texture(GLuint),
-}
-
-impl ColorAttachment {
-    pub fn color_attachment_type(&self) -> ColorAttachmentType {
-        match *self {
-            ColorAttachment::Renderbuffer(_) => ColorAttachmentType::Renderbuffer,
-            ColorAttachment::Texture(_) => ColorAttachmentType::Texture,
-        }
-    }
-
-    fn destroy(self, gl: &gl::Gl) {
-        match self {
-            ColorAttachment::Renderbuffer(id) => gl.delete_renderbuffers(&[id]),
-            ColorAttachment::Texture(tex_id) => gl.delete_textures(&[tex_id]),
-        }
-    }
-}
-
-/// This structure represents an offscreen context
-/// draw buffer. It has a framebuffer, with at least
-/// color renderbuffer (alpha or not). It may also have
-/// a depth or stencil buffer, depending on context
-/// requirements.
-pub struct DrawBuffer {
-    gl_: Rc<gl::Gl>,
-    size: Size2D<i32>,
-    framebuffer: GLuint,
-    stencil_renderbuffer: GLuint,
-    depth_renderbuffer: GLuint,
-    color_attachment: Option<ColorAttachment>
-    // samples: GLsizei,
-}
-
-/// Helper function to create a render buffer
-/// TODO(emilio): We'll need to switch between `glRenderbufferStorage` and
-/// `glRenderbufferStorageMultisample` when we support antialising
-fn create_renderbuffer(gl_: &gl::Gl,
-                       format: GLenum,
-                       size: &Size2D<i32>) -> GLuint {
-    let ret = gl_.gen_renderbuffers(1)[0];
-    gl_.bind_renderbuffer(gl::RENDERBUFFER, ret);
-    gl_.renderbuffer_storage(gl::RENDERBUFFER, format, size.width, size.height);
-    gl_.bind_renderbuffer(gl::RENDERBUFFER, 0);
-
-    ret
-}
-
-impl DrawBuffer {
-    pub fn new<T: NativeGLContextMethods>(context: &GLContext<T>,
-                                          mut size: Size2D<i32>,
-                                          color_attachment_type: ColorAttachmentType)
-                                          -> Result<Self, &'static str>
-    {
-        const MIN_DRAWING_BUFFER_SIZE: i32 = 16;
-        use std::cmp;
-
-        let attrs = context.borrow_attributes();
-        let capabilities = context.borrow_capabilities();
-
-        debug!("Creating draw buffer {:?}, {:?}, attrs: {:?}, caps: {:?}",
-               size, color_attachment_type, attrs, capabilities);
-
-        if attrs.antialias && capabilities.max_samples == 0 {
-            return Err("The given GLContext doesn't support requested antialising");
-        }
-
-        if attrs.preserve_drawing_buffer {
-            return Err("preserveDrawingBuffer is not supported yet");
-        }
-
-        // See https://github.com/servo/servo/issues/12320
-        size.width = cmp::max(MIN_DRAWING_BUFFER_SIZE, size.width);
-        size.height = cmp::max(MIN_DRAWING_BUFFER_SIZE, size.height);
-
-        let mut draw_buffer = DrawBuffer {
-            gl_: context.clone_gl(),
-            size: size,
-            framebuffer: 0,
-            color_attachment: None,
-            stencil_renderbuffer: 0,
-            depth_renderbuffer: 0,
-            // samples: 0,
-        };
-
-        try!(context.make_current());
-
-        try!(draw_buffer.init(context, color_attachment_type));
-
-        debug_assert_eq!(draw_buffer.gl().check_frame_buffer_status(gl::FRAMEBUFFER),
-                         gl::FRAMEBUFFER_COMPLETE);
-        debug_assert_eq!(draw_buffer.gl().get_error(),
-                         gl::NO_ERROR);
-
-        Ok(draw_buffer)
-    }
-
-    #[inline(always)]
-    pub fn get_framebuffer(&self) -> GLuint {
-        self.framebuffer
-    }
-
-    #[inline(always)]
-    pub fn size(&self) -> Size2D<i32> {
-        self.size
-    }
-
-    #[inline(always)]
-    // NOTE: We unwrap here because after creation the draw buffer
-    // always have a color attachment
-    pub fn color_attachment_type(&self) -> ColorAttachmentType {
-        self.color_attachment.as_ref().unwrap().color_attachment_type()
-    }
-
-    pub fn get_bound_color_renderbuffer_id(&self) -> Option<GLuint> {
-        match self.color_attachment.as_ref().unwrap() {
-            &ColorAttachment::Renderbuffer(id) => Some(id),
-            _ => None,
-        }
-    }
-
-    pub fn get_bound_texture_id(&self) -> Option<GLuint> {
-        match self.color_attachment.as_ref().unwrap() {
-            &ColorAttachment::Renderbuffer(_) => None,
-            &ColorAttachment::Texture(id) => Some(id),
-        }
-    }
-
-    fn gl(&self) -> &gl::Gl {
-        &*self.gl_
-    }
-
-
-    fn init<T: NativeGLContextMethods>(&mut self,
-                                       context: &GLContext<T>,
-                                       color_attachment_type: ColorAttachmentType)
-        -> Result<(), &'static str> {
-        let attrs = context.borrow_attributes();
-        let formats = context.borrow_formats();
-
-        assert!(self.color_attachment.is_none(),
-                "Would leak color attachment!");
-        self.color_attachment = match color_attachment_type {
-            ColorAttachmentType::Renderbuffer => {
-                let color_renderbuffer =
-                    create_renderbuffer(self.gl(), formats.color_renderbuffer, &self.size);
-                debug_assert!(color_renderbuffer != 0);
-
-                Some(ColorAttachment::Renderbuffer(color_renderbuffer))
-            },
-
-            // TODO(ecoal95): Allow more customization of textures
-            ColorAttachmentType::Texture => {
-                let texture = self.gl().gen_textures(1)[0];
-                debug_assert!(texture != 0);
-
-                self.gl().bind_texture(gl::TEXTURE_2D, texture);
-                self.gl().tex_image_2d(gl::TEXTURE_2D, 0,
-                                 formats.texture_internal as GLint, self.size.width, self.size.height, 0, formats.texture, formats.texture_type, None);
-
-                // Low filtering to allow rendering
-                self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
-                self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
-
-                // TODO(emilio): Check if these two are neccessary, probably not
-                self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
-                self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
-
-                self.gl().bind_texture(gl::TEXTURE_2D, 0);
-
-                debug_assert_eq!(self.gl().get_error(), gl::NO_ERROR);
-
-                Some(ColorAttachment::Texture(texture))
-            },
-        };
-
-        // After this we check if we need stencil and depth buffers
-        if attrs.depth {
-            self.depth_renderbuffer = create_renderbuffer(self.gl(), formats.depth, &self.size);
-            debug_assert!(self.depth_renderbuffer != 0);
-        }
-
-        if attrs.stencil {
-            self.stencil_renderbuffer = create_renderbuffer(self.gl(), formats.stencil, &self.size);
-            debug_assert!(self.stencil_renderbuffer != 0);
-        }
-
-        self.framebuffer = self.gl().gen_framebuffers(1)[0];
-        debug_assert!(self.framebuffer != 0);
-
-        // Finally we attach them to the framebuffer
-        self.attach_to_framebuffer()
-    }
-
-    fn attach_to_framebuffer(&mut self) -> Result<(), &'static str> {
-        self.gl().bind_framebuffer(gl::FRAMEBUFFER, self.framebuffer);
-        // NOTE: The assertion fails if the framebuffer is not bound
-        debug_assert_eq!(self.gl().is_framebuffer(self.framebuffer), gl::TRUE);
-
-        match *self.color_attachment.as_ref().unwrap() {
-            ColorAttachment::Renderbuffer(color_renderbuffer) => {
-                self.gl().framebuffer_renderbuffer(gl::FRAMEBUFFER,
-                                                  gl::COLOR_ATTACHMENT0,
-                                                  gl::RENDERBUFFER,
-                                                  color_renderbuffer);
-                debug_assert_eq!(self.gl().is_renderbuffer(color_renderbuffer), gl::TRUE);
-            },
-            ColorAttachment::Texture(texture_id) => {
-                self.gl().framebuffer_texture_2d(gl::FRAMEBUFFER,
-                                                gl::COLOR_ATTACHMENT0,
-                                                gl::TEXTURE_2D,
-                                                texture_id, 0);
-            },
-        }
-
-        if self.depth_renderbuffer != 0 {
-            self.gl().framebuffer_renderbuffer(gl::FRAMEBUFFER,
-                                              gl::DEPTH_ATTACHMENT,
-                                              gl::RENDERBUFFER,
-                                              self.depth_renderbuffer);
-            debug_assert_eq!(self.gl().is_renderbuffer(self.depth_renderbuffer), gl::TRUE);
-        }
-
-        if self.stencil_renderbuffer != 0 {
-            self.gl().framebuffer_renderbuffer(gl::FRAMEBUFFER,
-                                              gl::STENCIL_ATTACHMENT,
-                                              gl::RENDERBUFFER,
-                                              self.stencil_renderbuffer);
-            debug_assert_eq!(self.gl().is_renderbuffer(self.stencil_renderbuffer), gl::TRUE);
-        }
-
-        Ok(())
-    }
-}
-
-// NOTE: The initially associated GLContext MUST be the current gl context
-// when drop is called. I know this is an important constraint.
-// Right now there are no problems, if not, consider using a pointer to a
-// parent with Rc<GLContext> and call make_current()
-impl Drop for DrawBuffer {
-    fn drop(&mut self) {
-        if let Some(att) = self.color_attachment.take() {
-            att.destroy(self.gl());
-        }
-
-        self.gl().delete_framebuffers(&[self.framebuffer]);
-
-        // NOTE: Color renderbuffer is destroyed on drop of
-        //   ColorAttachment
-        self.gl().delete_renderbuffers(&[self.stencil_renderbuffer, self.depth_renderbuffer]);
-    }
-}
deleted file mode 100644
--- a/third_party/rust/offscreen_gl_context/src/gl_context.rs
+++ /dev/null
@@ -1,231 +0,0 @@
-use euclid::Size2D;
-use gleam