| ☠☠ backed out by 65b1787817bd ☠ ☠ | |
| author | Miko Mynttinen <mikokm@gmail.com> |
| Wed, 22 Jan 2020 22:43:59 +0000 | |
| changeset 511696 | 92b415dac733b24ce8013e2ba6dd629c25c7af5c |
| parent 511695 | 30481c41873ab75cb2b0c49860d6b67ad7e38bf5 |
| child 511697 | 1865e6d29dcfdcc1ec7adb5a5fa8fa9df183083b |
| push id | 37054 |
| push user | btara@mozilla.com |
| push date | Sat, 25 Jan 2020 09:45:27 +0000 |
| treeherder | mozilla-central@f7f534f08b48 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| bugs | 1558926 |
| 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/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -1390,16 +1390,32 @@ void DisplayListBuilder::PushBoxShadow( const wr::BorderRadius& aBorderRadius, const wr::BoxShadowClipMode& aClipMode) { wr_dp_push_box_shadow(mWrState, aRect, MergeClipLeaf(aClip), aIsBackfaceVisible, &mCurrentSpaceAndClipChain, aBoxBounds, aOffset, aColor, aBlurRadius, aSpreadRadius, aBorderRadius, aClipMode); } +void DisplayListBuilder::ReuseItem(wr::ItemKey aKey) { + wr_dp_push_reuse_item(mWrState, aKey); +} + +void DisplayListBuilder::StartCachedItem(wr::ItemKey aKey) { + wr_dp_start_cached_item(mWrState, aKey); +} + +void DisplayListBuilder::EndCachedItem(wr::ItemKey aKey) { + wr_dp_end_cached_item(mWrState, aKey); +} + +void DisplayListBuilder::SetDisplayListCacheSize(const size_t aCacheSize) { + wr_dp_set_cache_size(mWrState, aCacheSize); +} + Maybe<layers::ScrollableLayerGuid::ViewID> DisplayListBuilder::GetContainingFixedPosScrollTarget( const ActiveScrolledRoot* aAsr) { return mActiveFixedPosTracker ? mActiveFixedPosTracker->GetScrollTargetForASR(aAsr) : Nothing(); }
--- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -395,16 +395,17 @@ class DisplayListBuilder final { RenderRoot aRenderRoot = RenderRoot::Default); DisplayListBuilder(DisplayListBuilder&&) = default; ~DisplayListBuilder(); void Save(); void Restore(); void ClearSave(); + usize Dump(usize aIndent, const Maybe<usize>& aStart, const Maybe<usize>& aEnd); void Finalize(wr::LayoutSize& aOutContentSizes, wr::BuiltDisplayList& aOutDisplayList); void Finalize(layers::RenderRootDisplayListData& aOutTransaction); RenderRoot GetRenderRoot() const { return mRenderRoot; } @@ -573,20 +574,31 @@ class DisplayListBuilder final { void PushBoxShadow(const wr::LayoutRect& aRect, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutRect& aBoxBounds, const wr::LayoutVector2D& aOffset, const wr::ColorF& aColor, const float& aBlurRadius, const float& aSpreadRadius, const wr::BorderRadius& aBorderRadius, const wr::BoxShadowClipMode& aClipMode); + void StartCachedItem(wr::ItemKey aKey); + void EndCachedItem(wr::ItemKey aKey); + void ReuseItem(wr::ItemKey aKey); + void SetDisplayListCacheSize(const size_t aCacheSize); + uint64_t CurrentClipChainId() const { return mCurrentSpaceAndClipChain.clip_chain; } + const wr::WrSpaceAndClipChain& CurrentSpaceAndClipChain() const { + return mCurrentSpaceAndClipChain; + } + + const wr::PipelineId& CurrentPipelineId() const { return mPipelineId; } + // Checks to see if the innermost enclosing fixed pos item has the same // ASR. If so, it returns the scroll target for that fixed-pos item. // Otherwise, it returns Nothing(). Maybe<layers::ScrollableLayerGuid::ViewID> GetContainingFixedPosScrollTarget( const ActiveScrolledRoot* aAsr); Maybe<SideBits> GetContainingFixedPosSideBits(const ActiveScrolledRoot* aAsr);
--- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -3479,16 +3479,54 @@ pub extern "C" fn wr_dp_push_box_shadow( color, blur_radius, spread_radius, border_radius, clip_mode); } #[no_mangle] +pub extern "C" fn wr_dp_start_cached_item(state: &mut WrState, + key: ItemKey) { + debug_assert!(state.current_item_key.is_none(), "Nested item keys"); + state.current_item_key = Some(key); + + state.frame_builder.dl_builder.start_extra_data_chunk(); +} + +#[no_mangle] +pub extern "C" fn wr_dp_end_cached_item(state: &mut WrState, + key: ItemKey) { + // Avoid pushing reuse item marker when no extra data was written. + if state.frame_builder.dl_builder.end_extra_data_chunk() > 0 { + state.frame_builder.dl_builder.push_reuse_item(key); + } + + debug_assert!(state.current_item_key.is_some(), "Nested item keys"); + state.current_item_key = None; +} + +#[no_mangle] +pub extern "C" fn wr_dp_push_reuse_item(state: &mut WrState, + key: ItemKey) { + state.frame_builder + .dl_builder + .push_reuse_item(key); +} + +#[no_mangle] +pub extern "C" fn wr_dp_set_cache_size(state: &mut WrState, + cache_size: usize) { + state.frame_builder + .dl_builder + .set_cache_size(cache_size); +} + + +#[no_mangle] pub extern "C" fn wr_dump_display_list(state: &mut WrState, indent: usize, start: *const usize, end: *const usize) -> usize { let start = unsafe { start.as_ref().cloned() }; let end = unsafe { end.as_ref().cloned() }; let range = Range { start, end }; let mut sink = Cursor::new(Vec::new());
--- a/gfx/wr/webrender_api/src/display_list.rs +++ b/gfx/wr/webrender_api/src/display_list.rs @@ -13,16 +13,17 @@ use serde::{Deserialize, Serialize}; use std::io::{stdout, Write}; use std::marker::PhantomData; use std::ops::Range; use std::mem; use std::collections::HashMap; use time::precise_time_ns; // local imports use crate::display_item as di; +use crate::display_item_cache::*; use crate::api::{PipelineId, PropertyBinding}; use crate::gradient_builder::GradientBuilder; use crate::color::ColorF; use crate::font::{FontInstanceKey, GlyphInstance, GlyphOptions}; use crate::image::{ColorDepth, ImageKey}; use crate::units::*; @@ -125,21 +126,28 @@ pub struct BuiltDisplayListDescriptor { /// The second IPC time stamp: after serialization builder_finish_time: u64, /// The third IPC time stamp: just before sending send_start_time: u64, /// The amount of clipping nodes created while building this display list. total_clip_nodes: usize, /// The amount of spatial nodes created while building this display list. total_spatial_nodes: usize, + /// The size of the cache for this display list. + cache_size: usize, + /// The offset for additional display list data. + extra_data_offset: usize, } +impl BuiltDisplayListDescriptor {} + pub struct BuiltDisplayListIter<'a> { list: &'a BuiltDisplayList, data: &'a [u8], + cache: Option<&'a DisplayItemCache>, cur_item: di::DisplayItem, cur_stops: ItemRange<'a, di::GradientStop>, cur_glyphs: ItemRange<'a, GlyphInstance>, cur_filters: ItemRange<'a, di::FilterOp>, cur_filter_data: Vec<TempFilterData<'a>>, cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>, cur_clip_chain_items: ItemRange<'a, di::ClipId>, cur_complex_clip: ItemRange<'a, di::ComplexClipRegion>, @@ -227,35 +235,36 @@ enum Peek { #[derive(Clone)] pub struct AuxIter<'a, T> { item: T, data: &'a [u8], size: usize, // _boo: PhantomData<T>, } -impl BuiltDisplayListDescriptor {} - impl BuiltDisplayList { pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self { BuiltDisplayList { data, descriptor } } pub fn into_data(mut self) -> (Vec<u8>, BuiltDisplayListDescriptor) { self.descriptor.send_start_time = precise_time_ns(); (self.data, self.descriptor) } pub fn data(&self) -> &[u8] { &self.data[..] } - // Currently redundant with data, but may be useful if we add extra data to dl pub fn item_slice(&self) -> &[u8] { - &self.data[..] + &self.data[..self.descriptor.extra_data_offset] + } + + pub fn extra_slice(&self) -> &[u8] { + &self.data[self.descriptor.extra_data_offset..] } pub fn descriptor(&self) -> &BuiltDisplayListDescriptor { &self.descriptor } pub fn times(&self) -> (u64, u64, u64) { ( @@ -269,17 +278,32 @@ impl BuiltDisplayList { self.descriptor.total_clip_nodes } pub fn total_spatial_nodes(&self) -> usize { self.descriptor.total_spatial_nodes } pub fn iter(&self) -> BuiltDisplayListIter { - BuiltDisplayListIter::new(self) + BuiltDisplayListIter::new(self, self.item_slice(), None) + } + + pub fn extra_data_iter(&self) -> BuiltDisplayListIter { + BuiltDisplayListIter::new(self, self.extra_slice(), None) + } + + pub fn iter_with_cache<'a>( + &'a self, + cache: &'a DisplayItemCache + ) -> BuiltDisplayListIter<'a> { + BuiltDisplayListIter::new(self, self.item_slice(), Some(cache)) + } + + pub fn cache_size(&self) -> usize { + self.descriptor.cache_size } } /// Returns the byte-range the slice occupied. fn skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T> { let mut skip_offset = 0usize; *data = peek_from_slice(data, &mut skip_offset); let (skip, rest) = data.split_at(skip_offset); @@ -289,24 +313,25 @@ fn skip_slice<'a, T: peek_poke::Peek>(da ItemRange { bytes: skip, _boo: PhantomData, } } impl<'a> BuiltDisplayListIter<'a> { - pub fn new(list: &'a BuiltDisplayList) -> Self { - Self::new_with_list_and_data(list, list.item_slice()) - } - - pub fn new_with_list_and_data(list: &'a BuiltDisplayList, data: &'a [u8]) -> Self { - BuiltDisplayListIter { + pub fn new( + list: &'a BuiltDisplayList, + data: &'a [u8], + cache: Option<&'a DisplayItemCache>, + ) -> Self { + Self { list, data, + cache, cur_item: di::DisplayItem::PopStackingContext, cur_stops: ItemRange::default(), cur_glyphs: ItemRange::default(), cur_filters: ItemRange::default(), cur_filter_data: Vec::new(), cur_filter_primitives: ItemRange::default(), cur_clip_chain_items: ItemRange::default(), cur_complex_clip: ItemRange::default(), @@ -783,25 +808,32 @@ pub struct SaveState { next_spatial_index: usize, next_clip_chain_id: u64, } #[derive(Clone)] pub struct DisplayListBuilder { pub data: Vec<u8>, pub pipeline_id: PipelineId, + + extra_data: Vec<u8>, + extra_data_chunk_len: usize, + writing_extra_data_chunk: bool, + next_clip_index: usize, next_spatial_index: usize, next_clip_chain_id: u64, builder_start_time: u64, /// The size of the content of this display list. This is used to allow scrolling /// outside the bounds of the display list items themselves. content_size: LayoutSize, save_state: Option<SaveState>, + + cache_size: usize, } impl DisplayListBuilder { pub fn new(pipeline_id: PipelineId, content_size: LayoutSize) -> Self { Self::with_capacity(pipeline_id, content_size, 0) } pub fn with_capacity( @@ -809,22 +841,28 @@ impl DisplayListBuilder { content_size: LayoutSize, capacity: usize, ) -> Self { let start_time = precise_time_ns(); DisplayListBuilder { data: Vec::with_capacity(capacity), pipeline_id, + + extra_data: Vec::new(), + extra_data_chunk_len: 0, + writing_extra_data_chunk: false, + next_clip_index: FIRST_CLIP_NODE_INDEX, next_spatial_index: FIRST_SPATIAL_NODE_INDEX, next_clip_chain_id: 0, builder_start_time: start_time, content_size, save_state: None, + cache_size: 0, } } /// Return the content size for this display list pub fn content_size(&self) -> LayoutSize { self.content_size } @@ -886,37 +924,45 @@ impl DisplayListBuilder { where W: Write { let mut temp = BuiltDisplayList::default(); mem::swap(&mut temp.data, &mut self.data); let mut index: usize = 0; { - let mut iter = BuiltDisplayListIter::new(&temp); + let mut iter = temp.iter(); while let Some(item) = iter.next_raw() { if index >= range.start.unwrap_or(0) && range.end.map_or(true, |e| index < e) { writeln!(sink, "{}{:?}", " ".repeat(indent), item.item()).unwrap(); } index += 1; } } self.data = temp.data; index } + fn active_buffer(&mut self) -> &mut Vec<u8> { + if self.writing_extra_data_chunk { + &mut self.extra_data + } else { + &mut self.data + } + } + /// Add an item to the display list. /// /// NOTE: It is usually preferable to use the specialized methods to push /// display items. Pushing unexpected or invalid items here may /// result in WebRender panicking or behaving in unexpected ways. #[inline] pub fn push_item(&mut self, item: &di::DisplayItem) { - poke_into_vec(item, &mut self.data); + poke_into_vec(item, self.active_buffer()); } fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, I::Item: Poke, { @@ -952,17 +998,17 @@ impl DisplayListBuilder { /// NOTE: Pushing unexpected or invalid items to the display list /// may result in panic and confusion. pub fn push_iter<I>(&mut self, iter: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, I::Item: Poke, { - Self::push_iter_impl(&mut self.data, iter); + Self::push_iter_impl(self.active_buffer(), iter); } pub fn push_rect( &mut self, common: &di::CommonItemProperties, color: ColorF, ) { let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem { @@ -1541,34 +1587,68 @@ impl DisplayListBuilder { }); self.push_item(&item); } pub fn pop_all_shadows(&mut self) { self.push_item(&di::DisplayItem::PopAllShadows); } + pub fn start_extra_data_chunk(&mut self) { + self.writing_extra_data_chunk = true; + self.extra_data_chunk_len = self.extra_data.len(); + } + + // Returns the amount of bytes written to extra data buffer. + pub fn end_extra_data_chunk(&mut self) -> usize { + self.writing_extra_data_chunk = false; + self.extra_data.len() - self.extra_data_chunk_len + } + + pub fn push_reuse_item( + &mut self, + key: di::ItemKey, + ) { + let item = di::DisplayItem::ReuseItem(key); + self.push_item(&item); + } + + pub fn set_cache_size( + &mut self, + cache_size: usize, + ) { + self.cache_size = cache_size; + } + pub fn finalize(mut self) -> (PipelineId, LayoutSize, BuiltDisplayList) { assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save"); // Add `DisplayItem::max_size` zone of zeroes to the end of display list // so there is at least this amount available in the display list during // serialization. ensure_red_zone::<di::DisplayItem>(&mut self.data); + let extra_data_offset = self.data.len(); + + if self.extra_data.len() > 0 { + ensure_red_zone::<di::DisplayItem>(&mut self.extra_data); + self.data.extend(self.extra_data); + } + let end_time = precise_time_ns(); - ( self.pipeline_id, self.content_size, BuiltDisplayList { descriptor: BuiltDisplayListDescriptor { builder_start_time: self.builder_start_time, builder_finish_time: end_time, send_start_time: 0, total_clip_nodes: self.next_clip_index, total_spatial_nodes: self.next_spatial_index, + cache_size: self.cache_size, + extra_data_offset, }, data: self.data, }, ) } }