From f754a15d43c0ce7e25571819065f68c63ae4370f Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 13 Apr 2017 14:50:57 -0400 Subject: [PATCH 1/2] Add profiling for IPC overhead Note: this adds a dependency on `time` to `webrender_traits`. The purpose of this is to evaluate the overhead of different IPC implementations and serialization strategies. In particular, we need to replace the current implementation, as it is unsound; it just blindly transmutes, leaving room for a malicious process to create Undefined representations of e.g. enums. We take 4 time stamps: * before serialization to `Vec` happens * after serialization * before deserialization * after deserialization Because some of these time stamps happen in webrender_traits and cross-process, we need to take them manually and send the first two over IPC. Currently I'm just stuffing them in one of the descriptors, since that's easy and minimally invasive (but Firefox's headers will need to be updated, I think). We consider the time to perform the message send cross-process to be the time between serialization ending and deserialization starting. Overall IPC overhead is the whole process. We also record how large the two sent buffers are, as this may change significantly with a Proper Serialization Mechanism. In my preliminary testing basically all overhead is currently in the actual message send process (about 0.5ms on Mac in Servo). There's sometimes some overhead from deserialization, which is probably stuffing the auxlist in a map. About 200k is being sent for the display list, and 100k for the aux list. --- webrender/src/profiler.rs | 40 ++++++++++++++++++++++++++++ webrender/src/render_backend.rs | 9 ++++--- webrender/src/scene.rs | 18 ++++++++++++- webrender_traits/Cargo.toml | 1 + webrender_traits/src/display_list.rs | 20 +++++++++++--- webrender_traits/src/lib.rs | 1 + 6 files changed, 82 insertions(+), 7 deletions(-) diff --git a/webrender/src/profiler.rs b/webrender/src/profiler.rs index a1376e1fa6..9e0362189d 100644 --- a/webrender/src/profiler.rs +++ b/webrender/src/profiler.rs @@ -289,6 +289,12 @@ pub struct BackendProfileCounters { pub image_templates: ResourceProfileCounter, pub total_time: TimeProfileCounter, pub texture_cache: TextureCacheProfileCounters, + pub ipc_serialize_time: TimeProfileCounter, + pub ipc_deserialize_time: TimeProfileCounter, + pub ipc_send_time: TimeProfileCounter, + pub ipc_total_time: TimeProfileCounter, + pub ipc_display_len: IntProfileCounter, + pub ipc_aux_len: IntProfileCounter, } impl BackendProfileCounters { @@ -298,9 +304,26 @@ impl BackendProfileCounters { image_templates: ResourceProfileCounter::new("Image Templates"), total_time: TimeProfileCounter::new("Backend CPU Time", false), texture_cache: TextureCacheProfileCounters::new(), + ipc_serialize_time: TimeProfileCounter::new("IPC Serialize Time", false), + ipc_deserialize_time: TimeProfileCounter::new("IPC Deserialize Time", false), + ipc_send_time: TimeProfileCounter::new("IPC Send Time", false), + ipc_total_time: TimeProfileCounter::new("IPC Time", false), + ipc_display_len: IntProfileCounter::new("IPC Display List Len"), + ipc_aux_len: IntProfileCounter::new("IPC Aux List Len"), } } + pub fn set_ipc(&mut self, serial_start: u64, serial_end: u64, + deserial_start: u64, deserial_end: u64, + display_len: usize, aux_len: usize) { + self.ipc_serialize_time.set(serial_end - serial_start); + self.ipc_deserialize_time.set(deserial_end - deserial_start); + self.ipc_send_time.set(deserial_start - serial_end); + self.ipc_total_time.set(deserial_end - serial_start); + self.ipc_display_len.set(display_len); + self.ipc_aux_len.set(aux_len); + } + pub fn reset(&mut self) { self.total_time.reset(); } @@ -560,6 +583,7 @@ pub struct Profiler { compositor_time: ProfileGraph, gpu_time: ProfileGraph, gpu_frames: GpuFrameCollection, + ipc_time: ProfileGraph, } impl Profiler { @@ -573,6 +597,7 @@ impl Profiler { compositor_time: ProfileGraph::new(600), gpu_time: ProfileGraph::new(600), gpu_frames: GpuFrameCollection::new(), + ipc_time: ProfileGraph::new(600), } } @@ -685,6 +710,15 @@ impl Profiler { &backend_profile.texture_cache.pages_rgba8, ], debug_renderer, true); + self.draw_counters(&[ + &backend_profile.ipc_serialize_time, + &backend_profile.ipc_send_time, + &backend_profile.ipc_deserialize_time, + &backend_profile.ipc_total_time, + &backend_profile.ipc_display_len, + &backend_profile.ipc_aux_len, + ], debug_renderer, true); + self.draw_counters(&[ &renderer_profile.draw_calls, &renderer_profile.vertices, @@ -695,17 +729,23 @@ impl Profiler { &renderer_timers.cpu_time, &renderer_timers.gpu_time, ], debug_renderer, false); + + self.backend_time.push(backend_profile.total_time.nanoseconds); self.compositor_time.push(renderer_timers.cpu_time.nanoseconds); + self.ipc_time.push(backend_profile.ipc_total_time.nanoseconds); self.gpu_time.push(gpu_time); self.gpu_frames.push(gpu_time, gpu_samples); + let rect = self.backend_time.draw_graph(self.x_left, self.y_left, "CPU (backend)", debug_renderer); self.y_left += rect.size.height + PROFILE_PADDING; let rect = self.compositor_time.draw_graph(self.x_left, self.y_left, "CPU (compositor)", debug_renderer); self.y_left += rect.size.height + PROFILE_PADDING; + let rect = self.ipc_time.draw_graph(self.x_left, self.y_left, "DisplayList IPC", debug_renderer); + self.y_left += rect.size.height + PROFILE_PADDING; let rect = self.gpu_time.draw_graph(self.x_left, self.y_left, "GPU", debug_renderer); self.y_left += rect.size.height + PROFILE_PADDING; let rect = self.gpu_frames.draw(self.x_left, diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index 3f9b778f9a..4c5de9962c 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -212,15 +212,18 @@ impl RenderBackend { if !preserve_frame_state { self.discard_frame_state_for_pipeline(pipeline_id); } - profile_counters.total_time.profile(|| { + let mut total_time = profile_counters.total_time.clone(); + total_time.profile(|| { self.scene.set_display_list(pipeline_id, epoch, built_display_list, background_color, viewport_size, - auxiliary_lists); + auxiliary_lists, + &mut profile_counters); self.build_scene(); - }) + }); + profile_counters.total_time = total_time; } ApiMsg::SetRootPipeline(pipeline_id) => { profile_scope!("SetRootPipeline"); diff --git a/webrender/src/scene.rs b/webrender/src/scene.rs index 611b708635..96481b9634 100644 --- a/webrender/src/scene.rs +++ b/webrender/src/scene.rs @@ -3,9 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use fnv::FnvHasher; +use profiler::BackendProfileCounters; use std::collections::HashMap; use std::hash::BuildHasherDefault; use tiling::AuxiliaryListsMap; +use time::precise_time_ns; use webrender_traits::{AuxiliaryLists, BuiltDisplayList, PipelineId, Epoch, ColorF}; use webrender_traits::{DisplayItem, DynamicProperties, LayerSize, LayoutTransform}; use webrender_traits::{PropertyBinding, PropertyBindingId}; @@ -119,10 +121,24 @@ impl Scene { built_display_list: BuiltDisplayList, background_color: Option, viewport_size: LayerSize, - auxiliary_lists: AuxiliaryLists) { + auxiliary_lists: AuxiliaryLists, + profile_counters: &mut BackendProfileCounters) { + + let display_list_len = built_display_list.data().len(); + let aux_list_len = auxiliary_lists.data().len(); + let (serial_start_time, serial_end_time) = built_display_list.serialization_times(); + + let deserial_start_time = precise_time_ns(); + self.pipeline_auxiliary_lists.insert(pipeline_id, auxiliary_lists); self.display_lists.insert(pipeline_id, built_display_list.into_display_items()); + let deserial_end_time = precise_time_ns(); + + profile_counters.set_ipc(serial_start_time, serial_end_time, + deserial_start_time, deserial_end_time, + display_list_len, aux_list_len); + let new_pipeline = ScenePipeline { pipeline_id: pipeline_id, epoch: epoch, diff --git a/webrender_traits/Cargo.toml b/webrender_traits/Cargo.toml index f5c73991d0..a04bbb7690 100644 --- a/webrender_traits/Cargo.toml +++ b/webrender_traits/Cargo.toml @@ -20,6 +20,7 @@ ipc-channel = {version = "0.7", optional = true} offscreen_gl_context = {version = "0.8", features = ["serde"], optional = true} serde = "0.9" serde_derive = "0.9" +time = "0.1" [target.'cfg(target_os = "macos")'.dependencies] core-graphics = "0.7" diff --git a/webrender_traits/src/display_list.rs b/webrender_traits/src/display_list.rs index 9d58b3dc94..2c38b7b673 100644 --- a/webrender_traits/src/display_list.rs +++ b/webrender_traits/src/display_list.rs @@ -5,6 +5,7 @@ use app_units::Au; use std::mem; use std::slice; +use time::precise_time_ns; use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem}; use {ClipDisplayItem, ClipId, ClipRegion, ColorF, ComplexClipRegion, DisplayItem, ExtendMode}; use {FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem, GradientStop}; @@ -51,6 +52,10 @@ pub struct BuiltDisplayList { pub struct BuiltDisplayListDescriptor { /// The size in bytes of the display list items in this display list. display_list_items_size: usize, + /// The first IPC time stamp: before any work has been done + serialization_start_time: u64, + /// The second IPC time stamp: after serialization + serialization_end_time: u64, } impl BuiltDisplayListDescriptor { @@ -91,6 +96,9 @@ impl BuiltDisplayList { } } + pub fn serialization_times(&self) -> (u64, u64) { + (self.descriptor.serialization_start_time, self.descriptor.serialization_end_time) + } } #[derive(Clone)] @@ -542,17 +550,23 @@ impl DisplayListBuilder { pub fn finalize(self) -> (PipelineId, BuiltDisplayList, AuxiliaryLists) { unsafe { + let serialization_start_time = precise_time_ns(); + let blob = convert_vec_pod_to_blob(self.list); - let display_list_items_size = blob.len(); + let aux_list = self.auxiliary_lists_builder.finalize(); + + let serialization_end_time = precise_time_ns(); (self.pipeline_id, BuiltDisplayList { descriptor: BuiltDisplayListDescriptor { - display_list_items_size: display_list_items_size, + display_list_items_size: blob.len(), + serialization_start_time: serialization_start_time, + serialization_end_time: serialization_end_time, }, data: blob, }, - self.auxiliary_lists_builder.finalize()) + aux_list) } } } diff --git a/webrender_traits/src/lib.rs b/webrender_traits/src/lib.rs index 710824cb6f..f81a15dabb 100644 --- a/webrender_traits/src/lib.rs +++ b/webrender_traits/src/lib.rs @@ -20,6 +20,7 @@ extern crate offscreen_gl_context; extern crate serde; #[macro_use] extern crate serde_derive; +extern crate time; #[cfg(target_os = "macos")] extern crate core_graphics; From 0b6be1f62a9c912a9bcfbf9e8847ce0b770e8da9 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sat, 15 Apr 2017 19:11:38 -0400 Subject: [PATCH 2/2] WIP bincode IPC --- Cargo.lock | 2 + webrender/src/render_backend.rs | 6 +- webrender/src/scene.rs | 6 +- webrender_traits/Cargo.toml | 1 + webrender_traits/src/api.rs | 4 +- webrender_traits/src/display_list.rs | 171 ++++++++++----------------- webrender_traits/src/lib.rs | 1 + wrench/src/json_frame_writer.rs | 4 +- wrench/src/scene.rs | 6 +- wrench/src/yaml_frame_writer.rs | 8 +- 10 files changed, 83 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c933979630..da3e540abe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -892,6 +892,7 @@ name = "webrender_traits" version = "0.33.0" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -902,6 +903,7 @@ dependencies = [ "offscreen_gl_context 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index 4c5de9962c..839c957db5 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -17,7 +17,7 @@ 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::{ApiMsg, BuiltAuxiliaryLists, BuiltDisplayList, IdNamespace, ImageData}; use webrender_traits::{PipelineId, RenderNotifier, RenderDispatcher, WebGLCommand, WebGLContextId}; use webrender_traits::channel::{PayloadSenderHelperMethods, PayloadReceiverHelperMethods, PayloadReceiver, PayloadSender, MsgReceiver}; use webrender_traits::{BlobImageRenderer, VRCompositorCommand, VRCompositorHandler}; @@ -206,8 +206,8 @@ impl RenderBackend { BuiltDisplayList::from_data(auxiliary_data.display_list_data, display_list_descriptor); let auxiliary_lists = - AuxiliaryLists::from_data(auxiliary_data.auxiliary_lists_data, - auxiliary_lists_descriptor); + BuiltAuxiliaryLists::from_data(auxiliary_data.auxiliary_lists_data, + auxiliary_lists_descriptor); if !preserve_frame_state { self.discard_frame_state_for_pipeline(pipeline_id); diff --git a/webrender/src/scene.rs b/webrender/src/scene.rs index 96481b9634..c7a6a5f3c8 100644 --- a/webrender/src/scene.rs +++ b/webrender/src/scene.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; use std::hash::BuildHasherDefault; use tiling::AuxiliaryListsMap; use time::precise_time_ns; -use webrender_traits::{AuxiliaryLists, BuiltDisplayList, PipelineId, Epoch, ColorF}; +use webrender_traits::{BuiltAuxiliaryLists, BuiltDisplayList, PipelineId, Epoch, ColorF}; use webrender_traits::{DisplayItem, DynamicProperties, LayerSize, LayoutTransform}; use webrender_traits::{PropertyBinding, PropertyBindingId}; @@ -121,7 +121,7 @@ impl Scene { built_display_list: BuiltDisplayList, background_color: Option, viewport_size: LayerSize, - auxiliary_lists: AuxiliaryLists, + auxiliary_lists: BuiltAuxiliaryLists, profile_counters: &mut BackendProfileCounters) { let display_list_len = built_display_list.data().len(); @@ -130,7 +130,7 @@ impl Scene { let deserial_start_time = precise_time_ns(); - self.pipeline_auxiliary_lists.insert(pipeline_id, auxiliary_lists); + self.pipeline_auxiliary_lists.insert(pipeline_id, auxiliary_lists.into_auxiliary_lists()); self.display_lists.insert(pipeline_id, built_display_list.into_display_items()); let deserial_end_time = precise_time_ns(); diff --git a/webrender_traits/Cargo.toml b/webrender_traits/Cargo.toml index a04bbb7690..3aedfb0790 100644 --- a/webrender_traits/Cargo.toml +++ b/webrender_traits/Cargo.toml @@ -12,6 +12,7 @@ webgl = ["offscreen_gl_context"] [dependencies] app_units = "0.4" +bincode = "1.0.0-alpha2" byteorder = "1.0" euclid = "0.11" gleam = "0.4" diff --git a/webrender_traits/src/api.rs b/webrender_traits/src/api.rs index 9de96ecb67..998b4731bd 100644 --- a/webrender_traits/src/api.rs +++ b/webrender_traits/src/api.rs @@ -8,7 +8,7 @@ use offscreen_gl_context::{GLContextAttributes, GLLimits}; use std::cell::Cell; use std::fmt; use std::marker::PhantomData; -use {AuxiliaryLists, AuxiliaryListsDescriptor, BuiltDisplayList, BuiltDisplayListDescriptor}; +use {BuiltAuxiliaryLists, AuxiliaryListsDescriptor, BuiltDisplayList, BuiltDisplayListDescriptor}; use {ClipId, ColorF, DeviceIntPoint, DeviceIntSize, DeviceUintRect, DeviceUintSize, FontKey}; use {GlyphDimensions, GlyphKey, ImageData, ImageDescriptor, ImageKey, LayoutPoint, LayoutSize}; use {LayoutTransform, NativeFontHandle, WorldPoint}; @@ -304,7 +304,7 @@ impl RenderApi { background_color: Option, epoch: Epoch, viewport_size: LayoutSize, - (pipeline_id, display_list, auxiliary_lists): (PipelineId, BuiltDisplayList, AuxiliaryLists), + (pipeline_id, display_list, auxiliary_lists): (PipelineId, BuiltDisplayList, BuiltAuxiliaryLists), preserve_frame_state: bool) { let (dl_data, dl_desc) = display_list.into_data(); let (aux_data, aux_desc) = auxiliary_lists.into_data(); diff --git a/webrender_traits/src/display_list.rs b/webrender_traits/src/display_list.rs index 2c38b7b673..ae94098681 100644 --- a/webrender_traits/src/display_list.rs +++ b/webrender_traits/src/display_list.rs @@ -3,8 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use app_units::Au; -use std::mem; -use std::slice; +use bincode; use time::precise_time_ns; use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem}; use {ClipDisplayItem, ClipId, ClipRegion, ColorF, ComplexClipRegion, DisplayItem, ExtendMode}; @@ -19,6 +18,12 @@ use {TransformStyle, WebGLContextId, WebGLDisplayItem, YuvColorSpace, YuvImageDi pub struct AuxiliaryLists { /// The concatenation of: gradient stops, complex clip regions, filters, and glyph instances, /// in that order. + data: AuxiliaryListsBuilder, + descriptor: AuxiliaryListsDescriptor, +} + +pub struct BuiltAuxiliaryLists { + /// A serialized data: Vec, descriptor: AuxiliaryListsDescriptor, } @@ -30,10 +35,7 @@ pub struct AuxiliaryLists { #[repr(C)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub struct AuxiliaryListsDescriptor { - gradient_stops_size: usize, - complex_clip_regions_size: usize, - filters_size: usize, - glyph_instances_size: usize, + size: usize } /// A display list. @@ -84,16 +86,8 @@ impl BuiltDisplayList { &self.descriptor } - pub fn all_display_items(&self) -> &[DisplayItem] { - unsafe { - convert_blob_to_pod(&self.data) - } - } - pub fn into_display_items(self) -> Vec { - unsafe { - convert_vec_blob_to_pod(self.data) - } + bincode::deserialize(&self.data).expect("TODO: OH NO MALICIOUS PROCESS") } pub fn serialization_times(&self) -> (u64, u64) { @@ -505,6 +499,7 @@ impl DisplayListBuilder { self.push_item(item, rect, clip); } +/* // Don't use this function. It will go away. // We're using it as a hack in Gecko to retain parts sub-parts of display lists so that // we can regenerate them without building Gecko display items. @@ -539,6 +534,7 @@ impl DisplayListBuilder { self.list.push(i); } } +*/ pub fn new_clip_region(&mut self, rect: &LayoutRect, @@ -548,26 +544,25 @@ impl DisplayListBuilder { ClipRegion::new(rect, complex, image_mask, &mut self.auxiliary_lists_builder) } - pub fn finalize(self) -> (PipelineId, BuiltDisplayList, AuxiliaryLists) { - unsafe { - let serialization_start_time = precise_time_ns(); + pub fn finalize(self) -> (PipelineId, BuiltDisplayList, BuiltAuxiliaryLists) { + let serialization_start_time = precise_time_ns(); - let blob = convert_vec_pod_to_blob(self.list); - let aux_list = self.auxiliary_lists_builder.finalize(); + // let blob = convert_vec_pod_to_blob(self.list); + let blob = bincode::serialize(&self.list, bincode::Infinite).expect("TODO: ran out of space?"); + let aux_list = self.auxiliary_lists_builder.finalize(); - let serialization_end_time = precise_time_ns(); + let serialization_end_time = precise_time_ns(); - (self.pipeline_id, - BuiltDisplayList { - descriptor: BuiltDisplayListDescriptor { - display_list_items_size: blob.len(), - serialization_start_time: serialization_start_time, - serialization_end_time: serialization_end_time, - }, - data: blob, - }, - aux_list) - } + (self.pipeline_id, + BuiltDisplayList { + descriptor: BuiltDisplayListDescriptor { + display_list_items_size: blob.len(), + serialization_start_time: serialization_start_time, + serialization_end_time: serialization_end_time, + }, + data: blob, + }, + aux_list) } } @@ -597,7 +592,7 @@ impl ItemRange { } } -#[derive(Clone, Default)] +#[derive(Clone, Default, Serialize, Deserialize)] pub struct AuxiliaryListsBuilder { gradient_stops: Vec, complex_clip_regions: Vec, @@ -615,7 +610,7 @@ impl AuxiliaryListsBuilder { } pub fn gradient_stops(&self, gradient_stops_range: &ItemRange) -> &[GradientStop] { - gradient_stops_range.get(&self.gradient_stops[..]) + gradient_stops_range.get(&self.gradient_stops) } pub fn add_complex_clip_regions(&mut self, complex_clip_regions: &[ComplexClipRegion]) @@ -625,7 +620,7 @@ impl AuxiliaryListsBuilder { pub fn complex_clip_regions(&self, complex_clip_regions_range: &ItemRange) -> &[ComplexClipRegion] { - complex_clip_regions_range.get(&self.complex_clip_regions[..]) + complex_clip_regions_range.get(&self.complex_clip_regions) } pub fn add_filters(&mut self, filters: &[FilterOp]) -> ItemRange { @@ -633,7 +628,7 @@ impl AuxiliaryListsBuilder { } pub fn filters(&self, filters_range: &ItemRange) -> &[FilterOp] { - filters_range.get(&self.filters[..]) + filters_range.get(&self.filters) } pub fn add_glyph_instances(&mut self, glyph_instances: &[GlyphInstance]) -> ItemRange { @@ -641,45 +636,31 @@ 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_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); - - AuxiliaryLists { - data: blob, - descriptor: AuxiliaryListsDescriptor { - gradient_stops_size: gradient_stops_size, - complex_clip_regions_size: complex_clip_regions_size, - filters_size: filters_size, - glyph_instances_size: glyph_instances_size, - }, - } + glyph_instances_range.get(&self.glyph_instances) + } + + pub fn finalize(self) -> BuiltAuxiliaryLists { + let blob = bincode::serialize(&self, bincode::Infinite).expect("TODO: ran out of space?"); + let size = blob.len(); + + BuiltAuxiliaryLists { + data: blob, + descriptor: AuxiliaryListsDescriptor { + size: size + }, } } } impl AuxiliaryListsDescriptor { pub fn size(&self) -> usize { - self.gradient_stops_size + self.complex_clip_regions_size + self.filters_size + - self.glyph_instances_size + self.size } } -impl AuxiliaryLists { - /// Creates a new `AuxiliaryLists` instance from a descriptor and data received over a channel. - pub fn from_data(data: Vec, descriptor: AuxiliaryListsDescriptor) -> AuxiliaryLists { - AuxiliaryLists { +impl BuiltAuxiliaryLists { + pub fn from_data(data: Vec, descriptor: AuxiliaryListsDescriptor) -> BuiltAuxiliaryLists { + BuiltAuxiliaryLists { data: data, descriptor: descriptor, } @@ -690,69 +671,41 @@ impl AuxiliaryLists { } pub fn data(&self) -> &[u8] { - &self.data[..] + &self.data } + pub fn into_auxiliary_lists(self) -> AuxiliaryLists { + let data = bincode::deserialize(&self.data).expect("TODO: OH NO MALICIOUS PROCESS"); + AuxiliaryLists { + data: data, + descriptor: self.descriptor + } + } +} + +impl AuxiliaryLists { pub fn descriptor(&self) -> &AuxiliaryListsDescriptor { &self.descriptor } /// Returns the gradient stops described by `gradient_stops_range`. pub fn gradient_stops(&self, gradient_stops_range: &ItemRange) -> &[GradientStop] { - unsafe { - let end = self.descriptor.gradient_stops_size; - gradient_stops_range.get(convert_blob_to_pod(&self.data[0..end])) - } + gradient_stops_range.get(&self.data.gradient_stops) } /// Returns the complex clipping regions described by `complex_clip_regions_range`. pub fn complex_clip_regions(&self, complex_clip_regions_range: &ItemRange) -> &[ComplexClipRegion] { - let start = self.descriptor.gradient_stops_size; - let end = start + self.descriptor.complex_clip_regions_size; - unsafe { - complex_clip_regions_range.get(convert_blob_to_pod(&self.data[start..end])) - } + complex_clip_regions_range.get(&self.data.complex_clip_regions) } /// Returns the filters described by `filters_range`. pub fn filters(&self, filters_range: &ItemRange) -> &[FilterOp] { - let start = self.descriptor.gradient_stops_size + - self.descriptor.complex_clip_regions_size; - let end = start + self.descriptor.filters_size; - unsafe { - filters_range.get(convert_blob_to_pod(&self.data[start..end])) - } + filters_range.get(&self.data.filters) } /// Returns the glyph instances described by `glyph_instances_range`. pub fn glyph_instances(&self, glyph_instances_range: &ItemRange) -> &[GlyphInstance] { - let start = self.descriptor.gradient_stops_size + - self.descriptor.complex_clip_regions_size + self.descriptor.filters_size; - unsafe { - glyph_instances_range.get(convert_blob_to_pod(&self.data[start..])) - } + glyph_instances_range.get(&self.data.glyph_instances) } } - -unsafe fn convert_pod_to_blob(data: &[T]) -> &[u8] where T: Copy + 'static { - slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * mem::size_of::()) -} - -// this variant of the above lets us convert without needing to make a copy -unsafe fn convert_vec_pod_to_blob(mut data: Vec) -> Vec where T: Copy + 'static { - let v = Vec::from_raw_parts(data.as_mut_ptr() as *mut u8, data.len() * mem::size_of::(), data.capacity() * mem::size_of::()); - mem::forget(data); - v -} - -unsafe fn convert_blob_to_pod(blob: &[u8]) -> &[T] where T: Copy + 'static { - slice::from_raw_parts(blob.as_ptr() as *const T, blob.len() / mem::size_of::()) -} - -// this variant of the above lets us convert without needing to make a copy -unsafe fn convert_vec_blob_to_pod(mut data: Vec) -> Vec where T: Copy + 'static { - let v = Vec::from_raw_parts(data.as_mut_ptr() as *mut T, data.len() / mem::size_of::(), data.capacity() / mem::size_of::()); - mem::forget(data); - v -} diff --git a/webrender_traits/src/lib.rs b/webrender_traits/src/lib.rs index f81a15dabb..924e5bfb5b 100644 --- a/webrender_traits/src/lib.rs +++ b/webrender_traits/src/lib.rs @@ -6,6 +6,7 @@ #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, float_cmp))] extern crate app_units; +extern crate bincode; extern crate byteorder; #[cfg(feature = "nightly")] extern crate core; diff --git a/wrench/src/json_frame_writer.rs b/wrench/src/json_frame_writer.rs index 89f51ed027..61c7524937 100644 --- a/wrench/src/json_frame_writer.rs +++ b/wrench/src/json_frame_writer.rs @@ -104,7 +104,7 @@ impl JsonFrameWriter { let aux_data = data[dl_desc.size() + 4..].to_vec(); let dl = BuiltDisplayList::from_data(dl_data, dl_desc); - let aux = AuxiliaryLists::from_data(aux_data, aux_desc); + let aux = BuiltAuxiliaryLists::from_data(aux_data, aux_desc); let mut frame_file_name = self.frame_base.clone(); let current_shown_frame = unsafe { CURRENT_FRAME_NUMBER }; @@ -112,7 +112,7 @@ impl JsonFrameWriter { let mut file = File::create(&frame_file_name).unwrap(); - let items: Vec<&DisplayItem> = dl.all_display_items().iter().collect(); + let items: Vec = dl.into_display_items(); let s = serde_json::to_string_pretty(&items).unwrap(); file.write_all(&s.into_bytes()).unwrap(); file.write_all(b"\n").unwrap(); diff --git a/wrench/src/scene.rs b/wrench/src/scene.rs index d205c38efb..f3c692a30d 100644 --- a/wrench/src/scene.rs +++ b/wrench/src/scene.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use std::collections::HashMap; -use webrender_traits::{AuxiliaryLists, BuiltDisplayList, ColorF, DisplayItem, Epoch}; +use webrender_traits::{AuxiliaryLists, ColorF, DisplayItem, Epoch}; use webrender_traits::{LayerSize, PipelineId}; /// A representation of the layout within the display port for a given document or iframe. @@ -52,9 +52,9 @@ impl Scene { pub fn finish_display_list(&mut self, pipeline_id: PipelineId, - built_display_list: BuiltDisplayList, + display_list: Vec, auxiliary_lists: AuxiliaryLists) { self.pipeline_auxiliary_lists.insert(pipeline_id, auxiliary_lists); - self.display_lists.insert(pipeline_id, built_display_list.all_display_items().to_vec()); + self.display_lists.insert(pipeline_id, display_list); } } diff --git a/wrench/src/yaml_frame_writer.rs b/wrench/src/yaml_frame_writer.rs index e5edf9578a..68ea48b704 100644 --- a/wrench/src/yaml_frame_writer.rs +++ b/wrench/src/yaml_frame_writer.rs @@ -314,12 +314,12 @@ impl YamlFrameWriter { let dl_data = data[4..dl_desc.size() + 4].to_vec(); let aux_data = data[dl_desc.size() + 4..].to_vec(); - let dl = BuiltDisplayList::from_data(dl_data, dl_desc); - let aux = AuxiliaryLists::from_data(aux_data, aux_desc); + let dl = BuiltDisplayList::from_data(dl_data, dl_desc).into_display_items(); + let aux = BuiltAuxiliaryLists::from_data(aux_data, aux_desc).into_auxiliary_lists(); let mut root_dl_table = new_table(); { - let mut iter = dl.all_display_items().iter(); + let mut iter = dl.iter(); self.write_display_list(&mut root_dl_table, &mut iter, &aux, &mut ClipIdMapper::new()); } @@ -328,7 +328,7 @@ impl YamlFrameWriter { if let Some(root_pipeline_id) = scene.root_pipeline_id { u32_vec_node(&mut root_dl_table, "id", &[root_pipeline_id.0, root_pipeline_id.1]); - let referenced_pipeline_ids = dl.all_display_items().iter() + let referenced_pipeline_ids = dl.iter() .flat_map(|base| { if let SpecificDisplayItem::Iframe(k) = base.item { Some(k.pipeline_id)