servo: Merge #20423 - Use ByteBuf for the canvas messages (from servo:bytes); r=emilio
authorAnthony Ramine <n.oxyde@gmail.com>
Mon, 26 Mar 2018 14:49:16 -0400
changeset 466061 f3db418c3e5f75655af1bd39b89cb31debb60b85
parent 466060 e7de3b21524c2d56a5c82ecde470b43f3ddb2d87
child 466062 3d1f7f7dd0334b166c115430020388d20fec7278
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #20423 - Use ByteBuf for the canvas messages (from servo:bytes); r=emilio Source-Repo: https://github.com/servo/servo Source-Revision: 9c5bdd932e4ce8720e25241cb1bbdd85be3c92a5
servo/Cargo.lock
servo/components/canvas/Cargo.toml
servo/components/canvas/canvas_paint_thread.rs
servo/components/canvas/lib.rs
servo/components/canvas/webgl_thread.rs
servo/components/canvas_traits/Cargo.toml
servo/components/canvas_traits/canvas.rs
servo/components/canvas_traits/lib.rs
servo/components/canvas_traits/webgl.rs
servo/components/malloc_size_of/Cargo.toml
servo/components/malloc_size_of/lib.rs
servo/components/script/Cargo.toml
servo/components/script/dom/canvasrenderingcontext2d.rs
servo/components/script/dom/htmlcanvaselement.rs
servo/components/script/dom/vrdisplay.rs
servo/components/script/dom/webglbuffer.rs
servo/components/script/dom/webglrenderingcontext.rs
servo/components/script/lib.rs
servo/components/webvr/webvr_thread.rs
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -269,16 +269,17 @@ dependencies = [
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "webrender 0.57.0 (git+https://github.com/servo/webrender)",
  "webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "canvas_traits"
 version = "0.0.1"
@@ -287,16 +288,17 @@ dependencies = [
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
  "nonzero 0.0.1",
  "offscreen_gl_context 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "caseless"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1623,16 +1625,17 @@ name = "malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "mozjs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
+ "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
  "smallbitvec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
  "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2504,16 +2507,17 @@ dependencies = [
  "ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "ref_slice 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "script_layout_interface 0.0.1",
  "script_plugins 0.0.1",
  "script_traits 0.0.1",
  "selectors 0.19.0",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_allocator 0.0.1",
  "servo_arc 0.1.1",
  "servo_atoms 0.0.1",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_rand 0.0.1",
  "servo_url 0.0.1",
--- a/servo/components/canvas/Cargo.toml
+++ b/servo/components/canvas/Cargo.toml
@@ -16,11 +16,12 @@ compositing = {path = "../compositing"}
 cssparser = "0.23.0"
 euclid = "0.17"
 fnv = "1.0"
 gleam = "0.4.29"
 ipc-channel = "0.10"
 log = "0.3.5"
 num-traits = "0.1.32"
 offscreen_gl_context = { version = "0.15", features = ["serde", "osmesa"] }
+serde_bytes = "0.10"
 servo_config = {path = "../config"}
 webrender = {git = "https://github.com/servo/webrender"}
 webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/canvas/canvas_paint_thread.rs
+++ b/servo/components/canvas/canvas_paint_thread.rs
@@ -8,16 +8,17 @@ use azure::azure_hl::{BackendType, DrawO
 use azure::azure_hl::{Color, ColorPattern, DrawSurfaceOptions, Filter, PathBuilder};
 use azure::azure_hl::{ExtendMode, GradientStop, LinearGradientPattern, RadialGradientPattern};
 use azure::azure_hl::SurfacePattern;
 use canvas_traits::canvas::*;
 use cssparser::RGBA;
 use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D};
 use ipc_channel::ipc::{self, IpcSender};
 use num_traits::ToPrimitive;
+use serde_bytes::ByteBuf;
 use std::borrow::ToOwned;
 use std::mem;
 use std::sync::Arc;
 use std::thread;
 use webrender_api;
 
 impl<'a> CanvasPaintThread<'a> {
     /// It reads image data from the canvas
@@ -140,19 +141,30 @@ impl<'a> CanvasPaintThread<'a> {
                             Canvas2dMsg::BeginPath => painter.begin_path(),
                             Canvas2dMsg::ClosePath => painter.close_path(),
                             Canvas2dMsg::Fill => painter.fill(),
                             Canvas2dMsg::Stroke => painter.stroke(),
                             Canvas2dMsg::Clip => painter.clip(),
                             Canvas2dMsg::IsPointInPath(x, y, fill_rule, chan) => {
                                 painter.is_point_in_path(x, y, fill_rule, chan)
                             },
-                            Canvas2dMsg::DrawImage(imagedata, image_size, dest_rect, source_rect,
-                                                   smoothing_enabled) => {
-                                painter.draw_image(imagedata, image_size, dest_rect, source_rect, smoothing_enabled)
+                            Canvas2dMsg::DrawImage(
+                                imagedata,
+                                image_size,
+                                dest_rect,
+                                source_rect,
+                                smoothing_enabled,
+                            ) => {
+                                painter.draw_image(
+                                    imagedata.into(),
+                                    image_size,
+                                    dest_rect,
+                                    source_rect,
+                                    smoothing_enabled,
+                                )
                             }
                             Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled) => {
                                 painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled)
                             }
                             Canvas2dMsg::DrawImageInOther(
                                 renderer, image_size, dest_rect, source_rect, smoothing, sender
                             ) => {
                                 painter.draw_image_in_other(
@@ -184,18 +196,29 @@ impl<'a> CanvasPaintThread<'a> {
                             Canvas2dMsg::SetLineCap(cap) => painter.set_line_cap(cap),
                             Canvas2dMsg::SetLineJoin(join) => painter.set_line_join(join),
                             Canvas2dMsg::SetMiterLimit(limit) => painter.set_miter_limit(limit),
                             Canvas2dMsg::SetTransform(ref matrix) => painter.set_transform(matrix),
                             Canvas2dMsg::SetGlobalAlpha(alpha) => painter.set_global_alpha(alpha),
                             Canvas2dMsg::SetGlobalComposition(op) => painter.set_global_composition(op),
                             Canvas2dMsg::GetImageData(dest_rect, canvas_size, chan)
                                 => painter.image_data(dest_rect, canvas_size, chan),
-                            Canvas2dMsg::PutImageData(imagedata, offset, image_data_size, dirty_rect)
-                                => painter.put_image_data(imagedata, offset, image_data_size, dirty_rect),
+                            Canvas2dMsg::PutImageData(
+                                imagedata,
+                                offset,
+                                image_data_size,
+                                dirty_rect,
+                            ) => {
+                                painter.put_image_data(
+                                    imagedata.into(),
+                                    offset,
+                                    image_data_size,
+                                    dirty_rect,
+                                )
+                            }
                             Canvas2dMsg::SetShadowOffsetX(value) => painter.set_shadow_offset_x(value),
                             Canvas2dMsg::SetShadowOffsetY(value) => painter.set_shadow_offset_y(value),
                             Canvas2dMsg::SetShadowBlur(value) => painter.set_shadow_blur(value),
                             Canvas2dMsg::SetShadowColor(ref color) => painter.set_shadow_color(color.to_azure_style()),
                         }
                     },
                     CanvasMsg::Close => break,
                     CanvasMsg::Recreate(size) => painter.recreate(size),
@@ -397,17 +420,22 @@ impl<'a> CanvasPaintThread<'a> {
                            source_rect: Rect<f64>,
                            smoothing_enabled: bool,
                            sender: IpcSender<()>) {
         let mut image_data = self.read_pixels(source_rect.to_i32(), image_size);
         // TODO: avoid double byte_swap.
         byte_swap(&mut image_data);
 
         let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage(
-            image_data, source_rect.size, dest_rect, source_rect, smoothing_enabled));
+            image_data.into(),
+            source_rect.size,
+            dest_rect,
+            source_rect,
+            smoothing_enabled,
+        ));
         renderer.send(msg).unwrap();
         // We acknowledge to the caller here that the data was sent to the
         // other canvas so that if JS immediately afterwards try to get the
         // pixels of the other one, it won't retrieve the other values.
         sender.send(()).unwrap();
     }
 
     fn move_to(&self, point: &Point2D<AzFloat>) {
@@ -573,19 +601,19 @@ impl<'a> CanvasPaintThread<'a> {
         if let Some(image_key) = self.image_key.take() {
             // If this executes, then we are in a new epoch since we last recreated the canvas,
             // so `old_image_key` must be `None`.
             debug_assert!(self.old_image_key.is_none());
             self.old_image_key = Some(image_key);
         }
     }
 
-    fn send_pixels(&mut self, chan: IpcSender<Option<Vec<u8>>>) {
+    fn send_pixels(&mut self, chan: IpcSender<Option<ByteBuf>>) {
         self.drawtarget.snapshot().get_data_surface().with_data(|element| {
-            chan.send(Some(element.into())).unwrap();
+            chan.send(Some(Vec::from(element).into())).unwrap();
         })
     }
 
     fn send_data(&mut self, chan: IpcSender<CanvasImageData>) {
         self.drawtarget.snapshot().get_data_surface().with_data(|element| {
             let size = self.drawtarget.get_size();
 
             let descriptor = webrender_api::ImageDescriptor {
@@ -627,22 +655,27 @@ impl<'a> CanvasPaintThread<'a> {
 
             let data = CanvasImageData {
                 image_key: self.image_key.unwrap(),
             };
             chan.send(data).unwrap();
         })
     }
 
-    fn image_data(&self, dest_rect: Rect<i32>, canvas_size: Size2D<f64>, chan: IpcSender<Vec<u8>>) {
+    fn image_data(
+        &self,
+        dest_rect: Rect<i32>,
+        canvas_size: Size2D<f64>,
+        chan: IpcSender<ByteBuf>,
+    ) {
         let mut dest_data = self.read_pixels(dest_rect, canvas_size);
 
         // bgra -> rgba
         byte_swap(&mut dest_data);
-        chan.send(dest_data).unwrap();
+        chan.send(dest_data.into()).unwrap();
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
     fn put_image_data(&mut self, imagedata: Vec<u8>,
                       offset: Vector2D<f64>,
                       image_data_size: Size2D<f64>,
                       mut dirty_rect: Rect<f64>) {
         if image_data_size.width <= 0.0 || image_data_size.height <= 0.0 {
--- a/servo/components/canvas/lib.rs
+++ b/servo/components/canvas/lib.rs
@@ -10,16 +10,17 @@ extern crate compositing;
 extern crate cssparser;
 extern crate euclid;
 extern crate fnv;
 extern crate gleam;
 extern crate ipc_channel;
 #[macro_use] extern crate log;
 extern crate num_traits;
 extern crate offscreen_gl_context;
+extern crate serde_bytes;
 extern crate servo_config;
 extern crate webrender;
 extern crate webrender_api;
 
 pub mod canvas_paint_thread;
 pub mod gl_context;
 mod webgl_mode;
 pub mod webgl_thread;
--- a/servo/components/canvas/webgl_thread.rs
+++ b/servo/components/canvas/webgl_thread.rs
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use canvas_traits::canvas::byte_swap;
 use canvas_traits::webgl::*;
 use euclid::Size2D;
 use fnv::FnvHashMap;
 use gleam::gl;
 use offscreen_gl_context::{GLContext, GLContextAttributes, GLLimits, NativeGLContextMethods};
+use serde_bytes::ByteBuf;
 use std::thread;
 use super::gl_context::{GLContextFactory, GLContextWrapper};
 use webrender;
 use webrender_api;
 
 /// WebGL Threading API entry point that lives in the constellation.
 /// It allows to get a WebGLThread handle for each script pipeline.
 pub use ::webgl_mode::WebGLThreads;
@@ -899,20 +900,28 @@ impl WebGLImpl {
 
         // TODO: update test expectations in order to enable debug assertions
         //if cfg!(debug_assertions) {
             let error = ctx.gl().get_error();
             assert_eq!(error, gl::NO_ERROR, "Unexpected WebGL error: 0x{:x} ({})", error, error);
         //}
     }
 
-    fn read_pixels(gl: &gl::Gl, x: i32, y: i32, width: i32, height: i32, format: u32, pixel_type: u32,
-                   chan: WebGLSender<Vec<u8>>) {
+    fn read_pixels(
+        gl: &gl::Gl,
+        x: i32,
+        y: i32,
+        width: i32,
+        height: i32,
+        format: u32,
+        pixel_type: u32,
+        chan: WebGLSender<ByteBuf>,
+    ) {
       let result = gl.read_pixels(x, y, width, height, format, pixel_type);
-      chan.send(result).unwrap()
+      chan.send(result.into()).unwrap()
     }
 
     fn active_attrib(gl: &gl::Gl,
                      program_id: WebGLProgramId,
                      index: u32,
                      chan: WebGLSender<WebGLResult<(i32, u32, String)>>) {
         let result = if index >= gl.get_program_iv(program_id.get(), gl::ACTIVE_ATTRIBUTES) as u32 {
             Err(WebGLError::InvalidValue)
--- a/servo/components/canvas_traits/Cargo.toml
+++ b/servo/components/canvas_traits/Cargo.toml
@@ -14,10 +14,11 @@ cssparser = "0.23.0"
 euclid = "0.17"
 ipc-channel = "0.10"
 lazy_static = "1"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = { path = "../malloc_size_of_derive" }
 nonzero = {path = "../nonzero"}
 offscreen_gl_context = { version = "0.15", features = ["serde"] }
 serde = "1.0"
+serde_bytes = "0.10"
 servo_config = {path = "../config"}
 webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/canvas_traits/canvas.rs
+++ b/servo/components/canvas_traits/canvas.rs
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use cssparser::RGBA;
 use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D};
 use ipc_channel::ipc::IpcSender;
+use serde_bytes::ByteBuf;
 use std::default::Default;
 use std::str::FromStr;
 use webrender_api;
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum FillRule {
     Nonzero,
     Evenodd,
@@ -28,34 +29,34 @@ pub enum CanvasMsg {
 pub struct CanvasImageData {
     pub image_key: webrender_api::ImageKey,
 }
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum Canvas2dMsg {
     Arc(Point2D<f32>, f32, f32, f32, bool),
     ArcTo(Point2D<f32>, Point2D<f32>, f32),
-    DrawImage(Vec<u8>, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
+    DrawImage(ByteBuf, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
     DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool),
     DrawImageInOther(
         IpcSender<CanvasMsg>, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>),
     BeginPath,
     BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>),
     ClearRect(Rect<f32>),
     Clip,
     ClosePath,
     Ellipse(Point2D<f32>, f32, f32, f32, f32, f32, bool),
     Fill,
     FillText(String, f64, f64, Option<f64>),
     FillRect(Rect<f32>),
-    GetImageData(Rect<i32>, Size2D<f64>, IpcSender<Vec<u8>>),
+    GetImageData(Rect<i32>, Size2D<f64>, IpcSender<ByteBuf>),
     IsPointInPath(f64, f64, FillRule, IpcSender<bool>),
     LineTo(Point2D<f32>),
     MoveTo(Point2D<f32>),
-    PutImageData(Vec<u8>, Vector2D<f64>, Size2D<f64>, Rect<f64>),
+    PutImageData(ByteBuf, Vector2D<f64>, Size2D<f64>, Rect<f64>),
     QuadraticCurveTo(Point2D<f32>, Point2D<f32>),
     Rect(Rect<f32>),
     RestoreContext,
     SaveContext,
     StrokeRect(Rect<f32>),
     Stroke,
     SetFillStyle(FillOrStrokeStyle),
     SetStrokeStyle(FillOrStrokeStyle),
@@ -74,17 +75,17 @@ pub enum Canvas2dMsg {
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum FromLayoutMsg {
     SendData(IpcSender<CanvasImageData>),
 }
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum FromScriptMsg {
-    SendPixels(IpcSender<Option<Vec<u8>>>),
+    SendPixels(IpcSender<Option<ByteBuf>>),
 }
 
 #[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
 pub struct CanvasGradientStop {
     pub offset: f64,
     pub color: RGBA,
 }
 
@@ -133,30 +134,34 @@ impl RadialGradientStyle {
             r1: r1,
             stops: stops,
         }
     }
 }
 
 #[derive(Clone, Deserialize, Serialize)]
 pub struct SurfaceStyle {
-    pub surface_data: Vec<u8>,
+    pub surface_data: ByteBuf,
     pub surface_size: Size2D<i32>,
     pub repeat_x: bool,
     pub repeat_y: bool,
 }
 
 impl SurfaceStyle {
-    pub fn new(surface_data: Vec<u8>, surface_size: Size2D<i32>, repeat_x: bool, repeat_y: bool)
-        -> SurfaceStyle {
-        SurfaceStyle {
-            surface_data: surface_data,
-            surface_size: surface_size,
-            repeat_x: repeat_x,
-            repeat_y: repeat_y,
+    pub fn new(
+        surface_data: Vec<u8>,
+        surface_size: Size2D<i32>,
+        repeat_x: bool,
+        repeat_y: bool,
+    ) -> Self {
+        Self {
+            surface_data: surface_data.into(),
+            surface_size,
+            repeat_x,
+            repeat_y,
         }
     }
 }
 
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum FillOrStrokeStyle {
     Color(RGBA),
--- a/servo/components/canvas_traits/lib.rs
+++ b/servo/components/canvas_traits/lib.rs
@@ -11,14 +11,15 @@ extern crate cssparser;
 extern crate euclid;
 extern crate ipc_channel;
 #[macro_use] extern crate lazy_static;
 extern crate malloc_size_of;
 #[macro_use] extern crate malloc_size_of_derive;
 extern crate nonzero;
 extern crate offscreen_gl_context;
 #[macro_use] extern crate serde;
+extern crate serde_bytes;
 extern crate servo_config;
 extern crate webrender_api;
 
 pub mod canvas;
 pub mod webgl;
 mod webgl_channel;
--- a/servo/components/canvas_traits/webgl.rs
+++ b/servo/components/canvas_traits/webgl.rs
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use euclid::Size2D;
 use nonzero::NonZero;
 use offscreen_gl_context::{GLContextAttributes, GLLimits};
+use serde_bytes::ByteBuf;
 use std::fmt;
 use webrender_api::{DocumentId, ImageKey, PipelineId};
 
 /// Sender type used in WebGLCommands.
 pub use ::webgl_channel::WebGLSender;
 /// Receiver type used in WebGLCommands.
 pub use ::webgl_channel::WebGLReceiver;
 /// Result type for send()/recv() calls in in WebGLCommands.
@@ -160,18 +161,18 @@ pub enum WebGLCommand {
     BlendColor(f32, f32, f32, f32),
     BlendEquation(u32),
     BlendEquationSeparate(u32, u32),
     BlendFunc(u32, u32),
     BlendFuncSeparate(u32, u32, u32, u32),
     AttachShader(WebGLProgramId, WebGLShaderId),
     DetachShader(WebGLProgramId, WebGLShaderId),
     BindAttribLocation(WebGLProgramId, u32, String),
-    BufferData(u32, Vec<u8>, u32),
-    BufferSubData(u32, isize, Vec<u8>),
+    BufferData(u32, ByteBuf, u32),
+    BufferSubData(u32, isize, ByteBuf),
     Clear(u32),
     ClearColor(f32, f32, f32, f32),
     ClearDepth(f64),
     ClearStencil(i32),
     ColorMask(bool, bool, bool, bool),
     CullFace(u32),
     FrontFace(u32),
     DepthFunc(u32),
@@ -217,17 +218,17 @@ pub enum WebGLCommand {
     GetUniformLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
     GetVertexAttrib(u32, u32, WebGLSender<WebGLResult<WebGLParameter>>),
     GetVertexAttribOffset(u32, u32, WebGLSender<isize>),
     GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
     GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
     GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender<i32>),
     PolygonOffset(f32, f32),
     RenderbufferStorage(u32, u32, i32, i32),
-    ReadPixels(i32, i32, i32, i32, u32, u32, WebGLSender<Vec<u8>>),
+    ReadPixels(i32, i32, i32, i32, u32, u32, WebGLSender<ByteBuf>),
     SampleCoverage(f32, bool),
     Scissor(i32, i32, i32, i32),
     StencilFunc(u32, i32, u32),
     StencilFuncSeparate(u32, u32, i32, u32),
     StencilMask(u32),
     StencilMaskSeparate(u32, u32),
     StencilOp(u32, u32, u32),
     StencilOpSeparate(u32, u32, u32, u32),
@@ -257,20 +258,20 @@ pub enum WebGLCommand {
     UniformMatrix4fv(i32, bool, Vec<f32>),
     UseProgram(WebGLProgramId),
     ValidateProgram(WebGLProgramId),
     VertexAttrib(u32, f32, f32, f32, f32),
     VertexAttribPointer(u32, i32, u32, bool, i32, u32),
     VertexAttribPointer2f(u32, i32, bool, i32, u32),
     GetViewport(WebGLSender<(i32, i32, i32, i32)>),
     SetViewport(i32, i32, i32, i32),
-    TexImage2D(u32, i32, i32, i32, i32, u32, u32, Vec<u8>),
+    TexImage2D(u32, i32, i32, i32, i32, u32, u32, ByteBuf),
     TexParameteri(u32, u32, i32),
     TexParameterf(u32, u32, f32),
-    TexSubImage2D(u32, i32, i32, i32, i32, i32, u32, u32, Vec<u8>),
+    TexSubImage2D(u32, i32, i32, i32, i32, i32, u32, u32, ByteBuf),
     DrawingBufferWidth(WebGLSender<i32>),
     DrawingBufferHeight(WebGLSender<i32>),
     Finish(WebGLSender<()>),
     Flush,
     GenerateMipmap(u32),
     CreateVertexArray(WebGLSender<Option<WebGLVertexArrayId>>),
     DeleteVertexArray(WebGLVertexArrayId),
     BindVertexArray(Option<WebGLVertexArrayId>),
@@ -396,17 +397,17 @@ pub enum WebGLShaderParameter {
 pub type WebVRDeviceId = u32;
 
 // WebVR commands that must be called in the WebGL render thread.
 #[derive(Clone, Deserialize, Serialize)]
 pub enum WebVRCommand {
     /// Start presenting to a VR device.
     Create(WebVRDeviceId),
     /// Synchronize the pose information to be used in the frame.
-    SyncPoses(WebVRDeviceId, f64, f64, WebGLSender<Result<Vec<u8>, ()>>),
+    SyncPoses(WebVRDeviceId, f64, f64, WebGLSender<Result<ByteBuf, ()>>),
     /// Submit the frame to a VR device using the specified texture coordinates.
     SubmitFrame(WebVRDeviceId, [f32; 4], [f32; 4]),
     /// Stop presenting to a VR device
     Release(WebVRDeviceId)
 }
 
 // Trait object that handles WebVR commands.
 // Receives the texture id and size associated to the WebGLContext.
--- a/servo/components/malloc_size_of/Cargo.toml
+++ b/servo/components/malloc_size_of/Cargo.toml
@@ -4,25 +4,33 @@ version = "0.0.1"
 authors = ["The Servo Project Developers"]
 license = "MIT/Apache-2.0"
 publish = false
 
 [lib]
 path = "lib.rs"
 
 [features]
-servo = ["mozjs", "string_cache", "url", "webrender_api", "xml5ever"]
+servo = [
+    "mozjs",
+    "serde_bytes",
+    "string_cache",
+    "url",
+    "webrender_api",
+    "xml5ever",
+]
 
 [dependencies]
 app_units = "0.6"
 cssparser = "0.23.0"
 euclid = "0.17"
 hashglobe = { path = "../hashglobe" }
 mozjs = { version = "0.4", features = ["promises"], optional = true }
 selectors = { path = "../selectors" }
+serde_bytes = { version = "0.10", optional = true }
 servo_arc = { path = "../servo_arc" }
 smallbitvec = "1.0.3"
 smallvec = "0.6"
 string_cache = { version = "0.7", optional = true }
 url = { version = "1.2", optional = true }
 webrender_api = { git = "https://github.com/servo/webrender", features = ["ipc"], optional = true }
 xml5ever = { version = "0.12", optional = true }
 void = "1.0.2"
--- a/servo/components/malloc_size_of/lib.rs
+++ b/servo/components/malloc_size_of/lib.rs
@@ -45,29 +45,33 @@
 
 extern crate app_units;
 extern crate cssparser;
 extern crate euclid;
 extern crate hashglobe;
 #[cfg(feature = "servo")]
 extern crate mozjs as js;
 extern crate selectors;
+#[cfg(feature = "servo")]
+extern crate serde_bytes;
 extern crate servo_arc;
 extern crate smallbitvec;
 extern crate smallvec;
 #[cfg(feature = "servo")]
 extern crate string_cache;
 #[cfg(feature = "url")]
 extern crate url;
 extern crate void;
 #[cfg(feature = "webrender_api")]
 extern crate webrender_api;
 #[cfg(feature = "servo")]
 extern crate xml5ever;
 
+#[cfg(feature = "servo")]
+use serde_bytes::ByteBuf;
 use std::hash::{BuildHasher, Hash};
 use std::mem::size_of;
 use std::ops::Range;
 use std::os::raw::c_void;
 use void::Void;
 
 /// A C function that takes a pointer to a heap allocation and returns its size.
 type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
@@ -295,16 +299,34 @@ impl<T: MallocSizeOf> MallocSizeOf for [
         let mut n = 0;
         for elem in self.iter() {
             n += elem.size_of(ops);
         }
         n
     }
 }
 
+#[cfg(feature = "servo")]
+impl MallocShallowSizeOf for ByteBuf {
+    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
+        unsafe { ops.malloc_size_of(self.as_ptr()) }
+    }
+}
+
+#[cfg(feature = "servo")]
+impl MallocSizeOf for ByteBuf {
+    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
+        let mut n = self.shallow_size_of(ops);
+        for elem in self.iter() {
+            n += elem.size_of(ops);
+        }
+        n
+    }
+}
+
 impl<T> MallocShallowSizeOf for Vec<T> {
     fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         unsafe { ops.malloc_size_of(self.as_ptr()) }
     }
 }
 
 impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
--- a/servo/components/script/Cargo.toml
+++ b/servo/components/script/Cargo.toml
@@ -73,16 +73,17 @@ profile_traits = {path = "../profile_tra
 ref_filter_map = "1.0.1"
 ref_slice = "1.0"
 regex = "0.2"
 script_layout_interface = {path = "../script_layout_interface"}
 script_plugins = {path = "../script_plugins"}
 script_traits = {path = "../script_traits"}
 selectors = { path = "../selectors" }
 serde = "1.0"
+serde_bytes = "0.10"
 servo_allocator = {path = "../allocator"}
 servo_arc = {path = "../servo_arc"}
 servo_atoms = {path = "../atoms"}
 servo_config = {path = "../config"}
 servo_geometry = {path = "../geometry" }
 servo_rand = {path = "../rand"}
 servo_url = {path = "../url"}
 smallvec = "0.6"
--- a/servo/components/script/dom/canvasrenderingcontext2d.rs
+++ b/servo/components/script/dom/canvasrenderingcontext2d.rs
@@ -448,23 +448,23 @@ impl CanvasRenderingContext2D {
                                                                      dw,
                                                                      dh);
 
         if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) {
             return Ok(());
         }
 
         let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
-        self.ipc_renderer
-            .send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage(image_data,
-                                                             image_size,
-                                                             dest_rect,
-                                                             source_rect,
-                                                             smoothing_enabled)))
-            .unwrap();
+        self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage(
+            image_data.into(),
+            image_size,
+            dest_rect,
+            source_rect,
+            smoothing_enabled,
+        ))).unwrap();
         self.mark_as_dirty();
         Ok(())
     }
 
     fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec<u8>, Size2D<i32>)> {
         let img = match self.request_image_from_cache(url) {
             ImageResponse::Loaded(img, _) => img,
             ImageResponse::PlaceholderLoaded(_, _) |
@@ -1122,25 +1122,25 @@ impl CanvasRenderingContext2DMethods for
         if sh < 0.0 {
             sh = -sh;
             sy -= sh;
         }
 
         let sh = cmp::max(1, sh.to_u32().unwrap());
         let sw = cmp::max(1, sw.to_u32().unwrap());
 
-        let (sender, receiver) = ipc::channel::<Vec<u8>>(self.global().time_profiler_chan().clone()).unwrap();
+        let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
         let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()),
                                   Size2D::new(sw as i32, sh as i32));
         let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero());
         let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
         self.ipc_renderer
             .send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)))
             .unwrap();
-        let mut data = receiver.recv().unwrap();
+        let mut data = Vec::from(receiver.recv().unwrap());
 
         // Un-premultiply alpha
         for chunk in data.chunks_mut(4) {
             let alpha = chunk[3] as usize;
             chunk[0] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[0] as usize];
             chunk[1] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[1] as usize];
             chunk[2] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[2] as usize];
         }
@@ -1169,20 +1169,22 @@ impl CanvasRenderingContext2DMethods for
                      dirty_width: Finite<f64>,
                      dirty_height: Finite<f64>) {
         let data = imagedata.get_data_array();
         let offset = Vector2D::new(*dx, *dy);
         let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64);
 
         let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y),
                                    Size2D::new(*dirty_width, *dirty_height));
-        let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(data,
-                                                                offset,
-                                                                image_data_size,
-                                                                dirty_rect));
+        let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(
+            data.into(),
+            offset,
+            image_data_size,
+            dirty_rect,
+        ));
         self.ipc_renderer.send(msg).unwrap();
         self.mark_as_dirty();
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient
     fn CreateLinearGradient(&self,
                             x0: Finite<f64>,
                             y0: Finite<f64>,
--- a/servo/components/script/dom/htmlcanvaselement.rs
+++ b/servo/components/script/dom/htmlcanvaselement.rs
@@ -258,17 +258,17 @@ impl HTMLCanvasElement {
         }
 
         let data = match self.context.borrow().as_ref() {
             Some(&CanvasContext::Context2d(ref context)) => {
                 let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
                 let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender));
                 context.get_ipc_renderer().send(msg).unwrap();
 
-                receiver.recv().unwrap()?
+                receiver.recv().unwrap()?.into()
             },
             Some(&CanvasContext::WebGL(_)) => {
                 // TODO: add a method in WebGLRenderingContext to get the pixels.
                 return None;
             },
             Some(&CanvasContext::WebGL2(_)) => {
                 // TODO: add a method in WebGL2RenderingContext to get the pixels.
                 return None;
--- a/servo/components/script/dom/vrdisplay.rs
+++ b/servo/components/script/dom/vrdisplay.rs
@@ -30,16 +30,17 @@ use dom::vrframedata::VRFrameData;
 use dom::vrpose::VRPose;
 use dom::vrstageparameters::VRStageParameters;
 use dom::webglrenderingcontext::WebGLRenderingContext;
 use dom_struct::dom_struct;
 use ipc_channel::ipc::IpcSender;
 use profile_traits::ipc;
 use script_runtime::CommonScriptMsg;
 use script_runtime::ScriptThreadEventCategory::WebVREvent;
+use serde_bytes::ByteBuf;
 use std::cell::Cell;
 use std::mem;
 use std::ops::Deref;
 use std::rc::Rc;
 use std::sync::mpsc;
 use std::thread;
 use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVRFrameData, WebVRLayer, WebVRMsg};
 
@@ -63,17 +64,17 @@ pub struct VRDisplay {
     #[ignore_malloc_size_of = "Defined in rust-webvr"]
     next_raf_id: Cell<u32>,
     /// List of request animation frame callbacks
     #[ignore_malloc_size_of = "closures are hard"]
     raf_callback_list: DomRefCell<Vec<(u32, Option<Rc<FrameRequestCallback>>)>>,
     // Compositor VRFrameData synchonization
     frame_data_status: Cell<VRFrameDataStatus>,
     #[ignore_malloc_size_of = "closures are hard"]
-    frame_data_receiver: DomRefCell<Option<WebGLReceiver<Result<Vec<u8>, ()>>>>,
+    frame_data_receiver: DomRefCell<Option<WebGLReceiver<Result<ByteBuf, ()>>>>,
     running_display_raf: Cell<bool>,
     paused: Cell<bool>,
     stopped_on_pause: Cell<bool>,
 }
 
 unsafe_no_jsmanaged_fields!(WebVRDisplayData);
 unsafe_no_jsmanaged_fields!(WebVRFrameData);
 unsafe_no_jsmanaged_fields!(WebVRLayer);
--- a/servo/components/script/dom/webglbuffer.rs
+++ b/servo/components/script/dom/webglbuffer.rs
@@ -88,17 +88,21 @@ impl WebGLBuffer {
 
     pub fn buffer_data(&self, target: u32, data: &[u8], usage: u32) -> WebGLResult<()> {
         if let Some(previous_target) = self.target.get() {
             if target != previous_target {
                 return Err(WebGLError::InvalidOperation);
             }
         }
         self.capacity.set(data.len());
-        self.renderer.send(WebGLCommand::BufferData(target, data.to_vec(), usage)).unwrap();
+        self.renderer.send(WebGLCommand::BufferData(
+            target,
+            data.to_vec().into(),
+            usage,
+        )).unwrap();
 
         Ok(())
     }
 
     pub fn capacity(&self) -> usize {
         self.capacity.get()
     }
 
--- a/servo/components/script/dom/webglrenderingcontext.rs
+++ b/servo/components/script/dom/webglrenderingcontext.rs
@@ -1045,22 +1045,25 @@ impl WebGLRenderingContext {
         // will be 1.
         self.send_command(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32));
 
         let format = internal_format.as_gl_constant();
         let data_type = data_type.as_gl_constant();
         let internal_format = self.extension_manager.get_effective_tex_internal_format(format, data_type);
 
         // TODO(emilio): convert colorspace if requested
-        let msg = WebGLCommand::TexImage2D(target.as_gl_constant(), level as i32,
-                                           internal_format as i32,
-                                           width as i32, height as i32,
-                                           format,
-                                           data_type,
-                                           pixels);
+        let msg = WebGLCommand::TexImage2D(
+            target.as_gl_constant(),
+            level as i32,
+            internal_format as i32,
+            width as i32, height as i32,
+            format,
+            data_type,
+            pixels.into(),
+        );
 
         self.send_command(msg);
 
         if let Some(fb) = self.bound_framebuffer.get() {
             fb.invalidate_texture(&*texture);
         }
     }
 
@@ -1097,21 +1100,27 @@ impl WebGLRenderingContext {
         // Set the unpack alignment.  For textures coming from arrays,
         // this will be the current value of the context's
         // GL_UNPACK_ALIGNMENT, while for textures from images or
         // canvas (produced by rgba8_image_to_tex_image_data()), it
         // will be 1.
         self.send_command(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32));
 
         // TODO(emilio): convert colorspace if requested
-        let msg = WebGLCommand::TexSubImage2D(target.as_gl_constant(),
-                                              level as i32, xoffset, yoffset,
-                                              width as i32, height as i32,
-                                              format.as_gl_constant(),
-                                              data_type.as_gl_constant(), pixels);
+        let msg = WebGLCommand::TexSubImage2D(
+            target.as_gl_constant(),
+            level as i32,
+            xoffset,
+            yoffset,
+            width as i32,
+            height as i32,
+            format.as_gl_constant(),
+            data_type.as_gl_constant(),
+            pixels.into(),
+        );
 
         self.send_command(msg);
     }
 
     // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14
     fn validate_feature_enum(&self, cap: u32) -> bool {
         match cap {
             constants::BLEND | constants::CULL_FACE | constants::DEPTH_TEST | constants::DITHER |
@@ -1177,17 +1186,17 @@ impl WebGLRenderingContext {
             0,
             0,
             width as i32,
             height as i32,
             constants::RGBA,
             constants::UNSIGNED_BYTE,
             sender,
         ));
-        Some(receiver.recv().unwrap())
+        Some(receiver.recv().unwrap().into())
     }
 }
 
 impl Drop for WebGLRenderingContext {
     fn drop(&mut self) {
         self.webgl_sender.send_remove().unwrap();
     }
 }
@@ -1754,17 +1763,21 @@ impl WebGLRenderingContextMethods for We
 
         if offset < 0 {
             return self.webgl_error(InvalidValue);
         }
 
         if (offset as usize) + data_vec.len() > bound_buffer.capacity() {
             return self.webgl_error(InvalidValue);
         }
-        self.send_command(WebGLCommand::BufferSubData(target, offset as isize, data_vec));
+        self.send_command(WebGLCommand::BufferSubData(
+            target,
+            offset as isize,
+            data_vec.into(),
+        ));
     }
 
     // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
     fn CompressedTexImage2D(&self, _target: u32, _level: i32, _internal_format: u32,
                             _width: i32, _height: i32, _border: i32,
                             _data: CustomAutoRooterGuard<ArrayBufferView>) {
         // FIXME: No compressed texture format is currently supported, so error out as per
         // https://www.khronos.org/registry/webgl/specs/latest/1.0/#COMPRESSED_TEXTURE_SUPPORT
--- a/servo/components/script/lib.rs
+++ b/servo/components/script/lib.rs
@@ -76,16 +76,17 @@ extern crate phf;
 extern crate profile_traits;
 extern crate ref_filter_map;
 extern crate ref_slice;
 extern crate regex;
 extern crate script_layout_interface;
 extern crate script_traits;
 extern crate selectors;
 extern crate serde;
+extern crate serde_bytes;
 extern crate servo_allocator;
 extern crate servo_arc;
 #[macro_use] extern crate servo_atoms;
 extern crate servo_config;
 extern crate servo_geometry;
 extern crate servo_rand;
 extern crate servo_url;
 extern crate smallvec;
--- a/servo/components/webvr/webvr_thread.rs
+++ b/servo/components/webvr/webvr_thread.rs
@@ -339,17 +339,17 @@ impl webgl::WebVRRenderHandler for WebVR
                 self.create_compositor(compositor_id);
             }
             webgl::WebVRCommand::SyncPoses(compositor_id, near, far, sender) => {
                 if let Some(compositor) = self.compositors.get(&compositor_id) {
                     let pose = unsafe {
                         (*compositor.0).sync_poses();
                         (*compositor.0).synced_frame_data(near, far).to_bytes()
                     };
-                    let _ = sender.send(Ok(pose));
+                    let _ = sender.send(Ok(pose.into()));
                 } else {
                     let _ = sender.send(Err(()));
                 }
             }
             webgl::WebVRCommand::SubmitFrame(compositor_id, left_bounds, right_bounds) => {
                 if let Some(compositor) = self.compositors.get(&compositor_id) {
                     if let Some((texture_id, size)) = texture {
                         let layer = VRLayer {