| author | Bert Peers <bpeers@mozilla.com> |
| Tue, 28 Jan 2020 20:05:38 +0000 | |
| changeset 512032 | 748cc6e57cd0b0fab4357ae38eb5bdae505afdac |
| parent 512031 | dd5f0e2d407e0f8481fe15739bad434ef0fb048b |
| child 512033 | b82950f789cdd7037e8616199dbb13f532cfdd29 |
| push id | 37066 |
| push user | shindli@mozilla.com |
| push date | Wed, 29 Jan 2020 03:50:12 +0000 |
| treeherder | mozilla-central@31e91b3d071e [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | gw, reland |
| bugs | 1605283 |
| milestone | 74.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
|
--- a/gfx/wr/Cargo.lock +++ b/gfx/wr/Cargo.lock @@ -1629,16 +1629,17 @@ dependencies = [ "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tileview" version = "0.1.0" dependencies = [ + "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "webrender 0.61.0", "webrender_api 0.61.0", ] [[package]] name = "time"
--- a/gfx/wr/tileview/Cargo.toml +++ b/gfx/wr/tileview/Cargo.toml @@ -7,8 +7,9 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] ron = "0.1.7" serde = {version = "1.0.88", features = ["derive"] } webrender = {path = "../webrender", features=["capture","replay","debugger","png","profiler","no_static_freetype", "leak_checks"]} webrender_api = {path = "../webrender_api", features=["serialize","deserialize"]} +euclid = { version = "0.20.0", features = ["serde"] }
--- a/gfx/wr/tileview/src/main.rs +++ b/gfx/wr/tileview/src/main.rs @@ -7,59 +7,65 @@ use webrender::{TileSerializer, TileCach use serde::Deserialize; //use ron::de::from_reader; use std::fs::File; use std::io::prelude::*; use std::path::Path; use std::ffi::OsString; use webrender::api::enumerate_interners; use webrender::UpdateKind; +use euclid::{Rect, Transform3D}; +use webrender_api::units::{PicturePoint, PictureSize, PicturePixel, WorldPixel}; + +static RES_JAVASCRIPT: &'static str = include_str!("tilecache.js"); +static RES_BASE_CSS: &'static str = include_str!("tilecache_base.css"); #[derive(Deserialize)] pub struct Slice { - pub x: f32, - pub y: f32, + pub transform: Transform3D<f32, PicturePixel, WorldPixel>, pub tile_cache: TileCacheInstanceSerializer } // invalidation reason CSS colors static CSS_FRACTIONAL_OFFSET: &str = "fill:#4040c0;fill-opacity:0.1;"; static CSS_BACKGROUND_COLOR: &str = "fill:#10c070;fill-opacity:0.1;"; static CSS_SURFACE_OPACITY_CHANNEL: &str = "fill:#c040c0;fill-opacity:0.1;"; static CSS_NO_TEXTURE: &str = "fill:#c04040;fill-opacity:0.1;"; static CSS_NO_SURFACE: &str = "fill:#40c040;fill-opacity:0.1;"; static CSS_PRIM_COUNT: &str = "fill:#40f0f0;fill-opacity:0.1;"; static CSS_CONTENT: &str = "fill:#f04040;fill-opacity:0.1;"; static CSS_COMPOSITOR_KIND_CHANGED: &str = "fill:#f0c070;fill-opacity:0.1;"; -fn tile_node_to_svg(node: &TileNode, x: f32, y: f32) -> String +fn tile_node_to_svg(node: &TileNode, transform: &Transform3D<f32, PicturePixel, WorldPixel>) -> String { match &node.kind { TileNodeKind::Leaf { .. } => { - format!("<rect x=\"{}\" y=\"{}\" width=\"{}\" height=\"{}\" />\n", - (node.rect.origin.x + x) as i32, - (node.rect.origin.y + y) as i32, - node.rect.size.width, node.rect.size.height) + let rect_world = transform.transform_rect(&node.rect).unwrap(); + format!("<rect x=\"{:.2}\" y=\"{:.2}\" width=\"{:.2}\" height=\"{:.2}\" />\n", + rect_world.origin.x, + rect_world.origin.y, + rect_world.size.width, + rect_world.size.height) }, TileNodeKind::Node { children } => { - children.iter().fold(String::new(), |acc, child| acc + &tile_node_to_svg(child, x, y) ) + children.iter().fold(String::new(), |acc, child| acc + &tile_node_to_svg(child, transform) ) } } } fn tile_to_svg(key: TileOffset, tile: &TileSerializer, slice: &Slice, prev_tile: Option<&TileSerializer>, tile_stroke: &str, prim_class: &str, invalidation_report: &mut String, svg_width: &mut i32, svg_height: &mut i32 ) -> String { - let mut svg = format!("\n<!-- tile key {},{} ; slice x {} y {}-->\n", key.x, key.y, slice.x, slice.y); + let mut svg = format!("\n<!-- tile key {},{} ; -->\n", key.x, key.y); let tile_fill = match tile.invalidation_reason { Some(InvalidationReason::FractionalOffset) => CSS_FRACTIONAL_OFFSET.to_string(), Some(InvalidationReason::BackgroundColor) => CSS_BACKGROUND_COLOR.to_string(), Some(InvalidationReason::SurfaceOpacityChanged) => CSS_SURFACE_OPACITY_CHANNEL.to_string(), Some(InvalidationReason::NoTexture) => CSS_NO_TEXTURE.to_string(), @@ -100,69 +106,68 @@ fn tile_to_svg(key: TileOffset, if let Some(reason) = tile.invalidation_reason { invalidation_report.push_str( &format!("\n<tspan x=\"0\" dy=\"16px\">slice {} tile key ({},{}) invalidated: {:?}</tspan>\n", slice.tile_cache.slice, key.x, key.y, reason)); } svg = format!(r#"{}<rect x="{}" y="{}" width="{}" height="{}" style="{}" ></rect>"#, svg, - //TODO --bpe are these in local space or screen space? tile.rect.origin.x, tile.rect.origin.y, tile.rect.size.width, tile.rect.size.height, tile_style); svg = format!("{}\n\n<g class=\"svg_quadtree\">\n{}</g>\n", svg, - //tile_node_to_svg(&tile.root, tile.rect.origin.x, tile.rect.origin.y)); - tile_node_to_svg(&tile.root, 0.0, 0.0)); + tile_node_to_svg(&tile.root, &slice.transform)); let right = (tile.rect.origin.x + tile.rect.size.width) as i32; let bottom = (tile.rect.origin.y + tile.rect.size.height) as i32; *svg_width = if right > *svg_width { right } else { *svg_width }; *svg_height = if bottom > *svg_height { bottom } else { *svg_height }; svg += "\n<!-- primitives -->\n"; svg = format!("{}<g id=\"{}\">\n\t", svg, prim_class); for prim in &tile.current_descriptor.prims { let rect = prim.prim_clip_rect; - //TODO proper positioning of prims, especially when scrolling - // this version seems closest, but introduces gaps (eg in about:config) - let x = (rect.x + slice.x) as i32; - let y = (rect.y + slice.y) as i32; - // this version is .. interesting: when scrolling, nothing moves in about:config, - // instead the searchbox shifts down.. hmm.. - //let x = rect.x as i32; - //let y = rect.y as i32; - let w = rect.w as i32; - let h = rect.h as i32; + + // the transform could also be part of the CSS, let the browser do it; + // might be a bit faster and also enable actual 3D transforms. + let rect_pixel = Rect { + origin: PicturePoint::new(rect.x, rect.y), + size: PictureSize::new(rect.w, rect.h), + }; + let rect_world = slice.transform.transform_rect(&rect_pixel).unwrap(); let style = if let Some(prev_tile) = prev_tile { // when this O(n^2) gets too slow, stop brute-forcing and use a set or something if prev_tile.current_descriptor.prims.iter().find(|&prim| prim.prim_clip_rect == rect).is_some() { "" } else { "class=\"svg_changed_prim\" " } } else { "class=\"svg_changed_prim\" " }; - svg = format!(r#"{}<rect x="{}" y="{}" width="{}" height="{}" {}/>"#, - svg, - x, y, w, h, - style); + svg += &format!("<rect x=\"{:.2}\" y=\"{:.2}\" width=\"{:.2}\" height=\"{:.2}\" {}/>", + svg, + rect_world.origin.x, + rect_world.origin.y, + rect_world.size.width, + rect_world.size.height, + style); svg += "\n\t"; } svg += "\n</g>\n"; // nearly invisible, all we want is the toolip really let style = "style=\"fill-opacity:0.001;"; @@ -177,17 +182,18 @@ fn tile_to_svg(key: TileOffset, svg } fn slices_to_svg(slices: &[Slice], prev_slices: Option<Vec<Slice>>, svg_width: &mut i32, svg_height: &mut i32, max_slice_index: &mut usize) -> String { - let svg_begin = "<?xml\u{2d}stylesheet type\u{3d}\"text/css\" href\u{3d}\"tilecache.css\" ?>\n"; + let svg_begin = "<?xml\u{2d}stylesheet type\u{3d}\"text/css\" href\u{3d}\"tilecache_base.css\" ?>\n\ + <?xml\u{2d}stylesheet type\u{3d}\"text/css\" href\u{3d}\"tilecache.css\" ?>\n"; let mut svg = String::new(); let mut invalidation_report = String::new(); for slice in slices { let tile_cache = &slice.tile_cache; *max_slice_index = if tile_cache.slice > *max_slice_index { tile_cache.slice } else { *max_slice_index }; @@ -236,16 +242,17 @@ fn slices_to_svg(slices: &[Slice], prev_ + "\n</svg>\n" } fn write_html(output_dir: &Path, svg_files: &[String], intern_files: &[String]) { let html_head = "<!DOCTYPE html>\n\ <html>\n\ <head>\n\ <meta charset=\"UTF-8\">\n\ + <link rel=\"stylesheet\" type=\"text/css\" href=\"tilecache_base.css\"></link>\n\ <link rel=\"stylesheet\" type=\"text/css\" href=\"tilecache.css\"></link>\n\ </head>\n" .to_string(); let html_body = "<body bgcolor=\"#000000\" onload=\"load()\">\n" .to_string(); @@ -300,120 +307,75 @@ fn write_html(output_dir: &Path, svg_fil let html = format!("{}{}{}{}", html_head, html_body, script, html_end); let output_file = output_dir.join("index.html"); let mut html_output = File::create(output_file).unwrap(); html_output.write_all(html.as_bytes()).unwrap(); } fn write_css(output_dir: &Path, max_slice_index: usize) { - let mut css = ".tile_svg {\n\ - float: left;\n\ - }\n\ - \n\ - .split {\n\ - position: fixed;\n\ - z-index: 1;\n\ - top: 0;\n\ - padding-top: 20px;\n\ - }\n\ - \n\ - .left {\n\ - left: 0;\n\ - }\n\ - \n\ - .right {\n\ - right: 0;\n\ - width: 20%;\n\ - height: 100%;\n\ - opacity: 90%;\n\ - }\n\ - \n\ - #intern {\n\ - position:relative;\n\ - top:60px;\n\ - width: 100%;\n\ - height: 100%;\n\ - color: orange;\n\ - background-color:white;\n\ - }\n\ - .svg_invalidated {\n\ - fill: white;\n\ - font-family:monospace;\n\ - }\n\n\n\ - #svg_ui_overlay {\n\ - position:absolute;\n\ - right:0; \n\ - top:0; \n\ - z-index:70; \n\ - color: rgb(255,255,100);\n\ - font-family:monospace;\n\ - background-color: #404040a0;\n\ - }\n\n\n\ - .svg_quadtree {\n\ - fill: none;\n\ - stroke-width: 1;\n\ - stroke: orange;\n\ - }\n\n\n\ - .svg_changed_prim {\n\ - stroke: red;\n\ - stroke-width: 2.0;\n\ - }\n\n\n\ - #svg_ui_slider {\n\ - width:90%;\n\ - }\n\n".to_string(); + let mut css = String::new(); for ix in 0..max_slice_index + 1 { let color = ( ix % 7 ) + 1; let rgb = format!("rgb({},{},{})", if color & 2 != 0 { 205 } else { 90 }, if color & 4 != 0 { 205 } else { 90 }, if color & 1 != 0 { 225 } else { 90 }); let prim_class = format!("tile_slice{}", ix); - css = format!("{}\n\ - #{} {{\n\ + css += &format!("#{} {{\n\ fill: {};\n\ fill-opacity: 0.03;\n\ stroke-width: 0.8;\n\ stroke: {};\n\ - }}\n\n", - css, - prim_class, - //rgb, - "none", - rgb); + }}\n\n", + prim_class, + //rgb, + "none", + rgb); } let output_file = output_dir.join("tilecache.css"); let mut css_output = File::create(output_file).unwrap(); css_output.write_all(css.as_bytes()).unwrap(); } macro_rules! updatelist_to_html_macro { ( $( $name:ident: $ty:ty, )+ ) => { fn updatelist_to_html(update_lists: &TileCacheLoggerUpdateLists) -> String { - let mut html = String::new(); + let mut html = "\ + <!DOCTYPE html>\n\ + <html> <head> <meta charset=\"UTF-8\">\n\ + <link rel=\"stylesheet\" type=\"text/css\" href=\"tilecache_base.css\"></link>\n\ + <link rel=\"stylesheet\" type=\"text/css\" href=\"tilecache.css\"></link>\n\ + </head> <body>\n".to_string(); + $( - html += &format!("<h4 style=\"margin:5px;\">{}</h4>\n<font color=\"green\">\n", stringify!($name)); - let mut was_insert = true; - for update in &update_lists.$name.1 { - let is_insert = match update.kind { - UpdateKind::Insert => true, - _ => false + html += &format!("<div class=\"intern_header\">{}</div>\n<div class=\"intern_data\">\n", + stringify!($name)); + let mut insert_count = 0; + for update in &update_lists.$name.1.updates { + match update.kind { + UpdateKind::Insert => { + html += &format!("<div class=\"insert\">{} {}</div>\n", + update.index, + format!("({:?})", update_lists.$name.1.data[insert_count])); + insert_count = insert_count + 1; + } + _ => { + html += &format!("<div class=\"remove\">{}</div>\n", + update.index); + } }; - if was_insert != is_insert { - html += &format!("</font><font color=\"{}\">", if is_insert { "green" } else { "red" }); - } - html += &format!("{}, \n", update.index); - was_insert = is_insert; } - html += &"</font><hr/>\n"; + html += "</div><br/>\n"; )+ + html += "</body> </html>\n"; html } } } enumerate_interners!(updatelist_to_html_macro); fn write_tile_cache_visualizer_svg(entry: &std::fs::DirEntry, output_dir: &Path, slices: &[Slice], prev_slices: Option<Vec<Slice>>, @@ -504,10 +466,13 @@ fn main() { print!("\r"); prev_slices = Some(slices); } write_html(output_dir, &svg_files, &intern_files); write_css(output_dir, max_slice_index); - println!("OK. For now, manually copy tilecache.js to the output folder please. "); + std::fs::write(output_dir.join("tilecache.js"), RES_JAVASCRIPT).unwrap(); + std::fs::write(output_dir.join("tilecache_base.css"), RES_BASE_CSS).unwrap(); + + println!("\n"); }
new file mode 100644 --- /dev/null +++ b/gfx/wr/tileview/src/tilecache_base.css @@ -0,0 +1,94 @@ +.tile_svg { + float: left; +} + +#intern { + position:relative; + top:60px; + width: 100%; + height: 100%; + color: orange; + border: 0px; + overflow: auto; + background: white; +} + +.intern_header { + color: blue; + font-family: Arial; + font-weight: bold; + line-height: 200%; + background-color: lightgrey; + margin-top: 5px; + margin-bottom: 5px; +} + +.intern_data { + font-family: monospace; + font-size: small; +} + +.intern_data .insert:nth-child(even) { + background: #FFFFFF; +} +.intern_data .insert:nth-child(odd) { + background: #EFEFEF; +} + +.intern_data .insert { + color: #008000; +} + +.intern_data .remove { + color: #800000; +} + + + +.split { + position: fixed; + z-index: 1; + top: 0; + padding-top: 14px; +} + +.left { + left: 0; +} + +.right { + right: 0; + width: 25%; + height: 90%; +} + +#svg_ui_overlay { + position:absolute; + right:0; + top:0; + z-index:70; + color: rgb(255,255,100); + font-family:monospace; + background-color: #404040a0; +} + +#svg_ui_slider { + width:90%; +} + +.svg_invalidated { + fill: white; + font-family:monospace; +} + +.svg_quadtree { + fill: none; + stroke-width: 1; + stroke: orange; +} + +.svg_changed_prim { + stroke: red; + stroke-width: 2.0; +} +
--- a/gfx/wr/webrender/src/intern.rs +++ b/gfx/wr/webrender/src/intern.rs @@ -45,21 +45,23 @@ use crate::util::VecHelper; #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)] struct Epoch(u64); /// A list of updates to be applied to the data store, /// provided by the interning structure. +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] pub struct UpdateList<S> { /// The additions and removals to apply. pub updates: Vec<Update>, /// Actual new data to insert. - data: Vec<S>, + pub data: Vec<S>, } lazy_static! { static ref NEXT_UID: AtomicUsize = AtomicUsize::new(0); } /// A globally, unique identifier #[cfg_attr(feature = "capture", derive(Serialize))]
--- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -75,17 +75,17 @@ use api::{DebugFlags, RasterSpace, Image use api::units::*; use crate::box_shadow::{BLUR_SAMPLE_SCALE}; use crate::clip::{ClipStore, ClipChainInstance, ClipDataHandle, ClipChainId}; use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace }; use crate::composite::{CompositorKind, CompositeState, NativeSurfaceId, NativeTileId}; use crate::debug_colors; -use euclid::{vec3, Point2D, Scale, Size2D, Vector2D, Rect}; +use euclid::{vec3, Point2D, Scale, Size2D, Vector2D, Rect, Transform3D}; use euclid::approxeq::ApproxEq; use crate::filterdata::SFilterData; use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState}; use crate::intern::ItemUid; use crate::internal_types::{FastHashMap, FastHashSet, PlaneSplitter, Filter, PlaneSplitAnchor, TextureSource}; use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext}; use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle}; use crate::gpu_types::UvRectKind; @@ -107,18 +107,33 @@ use std::sync::atomic::{AtomicUsize, Ord use crate::texture_cache::TextureCacheHandle; use crate::util::{TransformedRectKind, MatrixHelpers, MaxRect, scale_factors, VecHelper, RectHelpers}; use crate::filterdata::{FilterDataHandle}; #[cfg(any(feature = "capture", feature = "replay"))] use ron; #[cfg(feature = "capture")] use crate::scene_builder_thread::InternerUpdates; #[cfg(any(feature = "capture", feature = "replay"))] -use crate::intern::Update; - +use crate::intern::{Internable, UpdateList}; +#[cfg(any(feature = "capture", feature = "replay"))] +use api::{ClipIntern, FilterDataIntern, PrimitiveKeyKind}; +#[cfg(any(feature = "capture", feature = "replay"))] +use crate::prim_store::backdrop::Backdrop; +#[cfg(any(feature = "capture", feature = "replay"))] +use crate::prim_store::borders::{ImageBorder, NormalBorderPrim}; +#[cfg(any(feature = "capture", feature = "replay"))] +use crate::prim_store::gradient::{LinearGradient, RadialGradient}; +#[cfg(any(feature = "capture", feature = "replay"))] +use crate::prim_store::image::{Image, YuvImage}; +#[cfg(any(feature = "capture", feature = "replay"))] +use crate::prim_store::line_dec::LineDecoration; +#[cfg(any(feature = "capture", feature = "replay"))] +use crate::prim_store::picture::Picture; +#[cfg(any(feature = "capture", feature = "replay"))] +use crate::prim_store::text_run::TextRun; #[cfg(feature = "capture")] use std::fs::File; #[cfg(feature = "capture")] use std::io::prelude::*; #[cfg(feature = "capture")] use std::path::PathBuf; @@ -1488,17 +1503,17 @@ impl BackdropInfo { }, } } } #[derive(Clone)] pub struct TileCacheLoggerSlice { pub serialized_slice: String, - pub local_to_world_transform: DeviceRect + pub local_to_world_transform: Transform3D<f32, PicturePixel, WorldPixel>, } #[cfg(any(feature = "capture", feature = "replay"))] macro_rules! declare_tile_cache_logger_updatelists { ( $( $name:ident : $ty:ty, )+ ) => { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct TileCacheLoggerUpdateListsSerializer { @@ -1509,37 +1524,37 @@ macro_rules! declare_tile_cache_logger_u $( /// Generate storage, one per interner. /// the tuple is a workaround to avoid the need for multiple /// fields that start with $name (macro concatenation). /// the string is .ron serialized updatelist at capture time; /// the updates is the list of DataStore updates (avoid UpdateList /// due to Default() requirements on the Keys) reconstructed at /// load time. - pub $name: (String, Vec<Update>), + pub $name: (String, UpdateList<<$ty as Internable>::Key>), )+ } impl TileCacheLoggerUpdateLists { pub fn new() -> Self { TileCacheLoggerUpdateLists { $( - $name : ( String::new(), Vec::<Update>::new() ), + $name : ( String::new(), UpdateList{ updates: Vec::new(), data: Vec::new()} ), )+ } } /// serialize all interners in updates to .ron #[cfg(feature = "capture")] fn serialize_updates( &mut self, updates: &InternerUpdates ) { $( - self.$name.0 = ron::ser::to_string_pretty(&updates.$name.updates, Default::default()).unwrap(); + self.$name.0 = ron::ser::to_string_pretty(&updates.$name, Default::default()).unwrap(); )+ } fn is_empty(&self) -> bool { $( if !self.$name.0.is_empty() { return false; } )+ true @@ -1547,27 +1562,27 @@ macro_rules! declare_tile_cache_logger_u #[cfg(feature = "capture")] fn to_ron(&self) -> String { let mut serializer = TileCacheLoggerUpdateListsSerializer { ron_string: Vec::new() }; $( serializer.ron_string.push( if self.$name.0.is_empty() { - "[]".to_string() + "( updates: [], data: [] )".to_string() } else { self.$name.0.clone() }); )+ ron::ser::to_string_pretty(&serializer, Default::default()).unwrap() } #[cfg(feature = "replay")] pub fn from_ron(&mut self, text: &str) { - let serializer : TileCacheLoggerUpdateListsSerializer = + let serializer : TileCacheLoggerUpdateListsSerializer = match ron::de::from_str(&text) { Ok(data) => { data } Err(e) => { println!("ERROR: failed to deserialize updatelist: {:?}\n{:?}", &text, e); return; } }; let mut index = 0; @@ -1641,17 +1656,21 @@ impl TileCacheLogger { } } pub fn is_enabled(&self) -> bool { !self.frames.is_empty() } #[cfg(feature = "capture")] - pub fn add(&mut self, serialized_slice: String, local_to_world_transform: DeviceRect) { + pub fn add( + &mut self, + serialized_slice: String, + local_to_world_transform: Transform3D<f32, PicturePixel, WorldPixel> + ) { if !self.is_enabled() { return; } self.frames[self.write_index].slices.push( TileCacheLoggerSlice { serialized_slice, local_to_world_transform }); } @@ -1704,21 +1723,22 @@ impl TileCacheLogger { continue; } let filename = path_tile_cache.join(format!("frame{:05}.ron", files_written)); let mut output = File::create(filename).unwrap(); output.write_all(b"// slice data\n").unwrap(); output.write_all(b"[\n").unwrap(); for item in &self.frames[index].slices { - output.write_all(format!("( x: {}, y: {},\n", - item.local_to_world_transform.origin.x, - item.local_to_world_transform.origin.y) - .as_bytes()).unwrap(); - output.write_all(b"tile_cache:\n").unwrap(); + output.write_all(b"( transform:\n").unwrap(); + let transform = + ron::ser::to_string_pretty( + &item.local_to_world_transform, Default::default()).unwrap(); + output.write_all(transform.as_bytes()).unwrap(); + output.write_all(b",\n tile_cache:\n").unwrap(); output.write_all(item.serialized_slice.as_bytes()).unwrap(); output.write_all(b"\n),\n").unwrap(); } output.write_all(b"]\n\n").unwrap(); output.write_all(b"// @@@ chunk @@@\n\n").unwrap(); output.write_all(b"// interning data\n").unwrap(); @@ -3701,17 +3721,16 @@ impl PicturePrimitive { Picture3DContext::In { root_data: Some(_), .. } => { Some(PlaneSplitter::new()) } Picture3DContext::In { root_data: None, .. } => { None } }; - let unclipped = match self.raster_config { Some(ref raster_config) => { let pic_rect = PictureRect::from_untyped(&self.precise_local_rect.to_untyped()); let device_pixel_scale = frame_state .surfaces[raster_config.surface_index.0] .device_pixel_scale; @@ -4292,20 +4311,18 @@ impl PicturePrimitive { port, }); frame_state.render_tasks.add_dependency( frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port, root, ); } - - unclipped } - None => DeviceRect::zero() + None => {} }; #[cfg(feature = "capture")] { if frame_context.debug_flags.contains(DebugFlags::TILE_CACHE_LOGGING_DBG) { if let Some(ref tile_cache) = self.tile_cache { // extract just the fields that we're interested in @@ -4322,24 +4339,23 @@ impl PicturePrimitive { fract_offset: tile.fract_offset, id: tile.id, root: tile.root.clone(), background_color: tile.background_color, invalidation_reason: tile.invalidation_reason.clone() }); } let text = ron::ser::to_string_pretty(&tile_cache_tiny, Default::default()).unwrap(); - tile_cache_logger.add(text, unclipped); + tile_cache_logger.add(text, map_pic_to_world.get_transform()); } } } #[cfg(not(feature = "capture"))] { let _tile_cache_logger = tile_cache_logger; // unused variable fix - let _unclipped = unclipped; } let state = PictureState { //TODO: check for MAX_CACHE_SIZE here? map_local_to_pic, map_pic_to_world, map_pic_to_raster, map_raster_to_world,