Backed out changeset 1d332a5ff4f9 (bug 1724846) for causing Bug 1727715.

CLOSED TREE
This commit is contained in:
Alexandru Michis
2021-08-26 22:51:05 +03:00
parent 943cb8606e
commit 51a484e3cf
15 changed files with 380 additions and 540 deletions

View File

@@ -465,7 +465,7 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
aSceneBuilderTxn.SetDisplayList(gfx::DeviceColor(0.f, 0.f, 0.f, 0.f), aEpoch,
wr::ToLayoutSize(aPipeline->mScBounds.Size()),
aPipelineId, dl.dl_desc, dl.dl_items,
dl.dl_cache, dl.dl_spatial_tree);
dl.dl_cache);
}
void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
@@ -520,7 +520,7 @@ void AsyncImagePipelineManager::SetEmptyDisplayList(
builder.Finalize(dl);
txn.SetDisplayList(gfx::DeviceColor(0.f, 0.f, 0.f, 0.f), epoch,
wr::ToLayoutSize(pipeline->mScBounds.Size()), aPipelineId,
dl.dl_desc, dl.dl_items, dl.dl_cache, dl.dl_spatial_tree);
dl.dl_desc, dl.dl_items, dl.dl_cache);
}
void AsyncImagePipelineManager::HoldExternalImage(

View File

@@ -18,7 +18,6 @@ void IPDLParamTraits<mozilla::layers::DisplayListData>::Write(
WriteIPDLParam(aMsg, aActor, aParam.mCommands);
WriteIPDLParam(aMsg, aActor, std::move(aParam.mDLItems));
WriteIPDLParam(aMsg, aActor, std::move(aParam.mDLCache));
WriteIPDLParam(aMsg, aActor, std::move(aParam.mDLSpatialTree));
WriteIPDLParam(aMsg, aActor, aParam.mDLDesc);
WriteIPDLParam(aMsg, aActor, aParam.mRemotePipelineIds);
WriteIPDLParam(aMsg, aActor, aParam.mResourceUpdates);
@@ -35,7 +34,6 @@ bool IPDLParamTraits<mozilla::layers::DisplayListData>::Read(
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mCommands) &&
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDLItems) &&
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDLCache) &&
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDLSpatialTree) &&
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDLDesc) &&
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRemotePipelineIds) &&
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResourceUpdates) &&

View File

@@ -22,7 +22,6 @@ struct DisplayListData {
nsTArray<WebRenderParentCommand> mCommands;
Maybe<mozilla::ipc::ByteBuf> mDLItems;
Maybe<mozilla::ipc::ByteBuf> mDLCache;
Maybe<mozilla::ipc::ByteBuf> mDLSpatialTree;
wr::BuiltDisplayListDescriptor mDLDesc;
nsTArray<wr::PipelineId> mRemotePipelineIds;
nsTArray<OpUpdateResource> mResourceUpdates;

View File

@@ -1101,8 +1101,7 @@ void WebRenderBridgeParent::SetAPZSampleTime() {
bool WebRenderBridgeParent::SetDisplayList(
const LayoutDeviceRect& aRect, ipc::ByteBuf&& aDLItems,
ipc::ByteBuf&& aDLCache, ipc::ByteBuf&& aSpatialTreeDL,
const wr::BuiltDisplayListDescriptor& aDLDesc,
ipc::ByteBuf&& aDLCache, const wr::BuiltDisplayListDescriptor& aDLDesc,
const nsTArray<OpUpdateResource>& aResourceUpdates,
const nsTArray<RefCountedShmem>& aSmallShmems,
const nsTArray<ipc::Shmem>& aLargeShmems, const TimeStamp& aTxnStartTime,
@@ -1115,7 +1114,6 @@ bool WebRenderBridgeParent::SetDisplayList(
wr::Vec<uint8_t> dlItems(std::move(aDLItems));
wr::Vec<uint8_t> dlCache(std::move(aDLCache));
wr::Vec<uint8_t> dlSpatialTreeData(std::move(aSpatialTreeDL));
if (IsRootWebRenderBridgeParent()) {
#ifdef MOZ_WIDGET_GTK
@@ -1131,7 +1129,7 @@ bool WebRenderBridgeParent::SetDisplayList(
gfx::DeviceColor clearColor(0.f, 0.f, 0.f, 0.f);
aTxn.SetDisplayList(clearColor, aWrEpoch,
wr::ToLayoutSize(RoundedToInt(aRect).Size()), mPipelineId,
aDLDesc, dlItems, dlCache, dlSpatialTreeData);
aDLDesc, dlItems, dlCache);
if (aObserveLayersUpdate) {
aTxn.Notify(
@@ -1177,12 +1175,10 @@ bool WebRenderBridgeParent::ProcessDisplayListData(
return false;
}
if (aDisplayList.mDLItems && aDisplayList.mDLCache &&
aDisplayList.mDLSpatialTree && aValidTransaction &&
if (aDisplayList.mDLItems && aDisplayList.mDLCache && aValidTransaction &&
!SetDisplayList(aDisplayList.mRect,
std::move(aDisplayList.mDLItems.ref()),
std::move(aDisplayList.mDLCache.ref()),
std::move(aDisplayList.mDLSpatialTree.ref()),
aDisplayList.mDLDesc, aDisplayList.mResourceUpdates,
aDisplayList.mSmallShmems, aDisplayList.mLargeShmems,
aTxnStartTime, txn, aWrEpoch, aObserveLayersUpdate)) {

View File

@@ -332,7 +332,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
bool aObserveLayersUpdate);
bool SetDisplayList(const LayoutDeviceRect& aRect, ipc::ByteBuf&& aDLItems,
ipc::ByteBuf&& aDLCache, ipc::ByteBuf&& aSpatialTreeDL,
ipc::ByteBuf&& aDLCache,
const wr::BuiltDisplayListDescriptor& aDLDesc,
const nsTArray<OpUpdateResource>& aResourceUpdates,
const nsTArray<RefCountedShmem>& aSmallShmems,

View File

@@ -461,7 +461,6 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
builder.Finalize(dlData);
mLastDisplayListSize.items_size = dlData.mDLItems->mCapacity;
mLastDisplayListSize.cache_size = dlData.mDLCache->mCapacity;
mLastDisplayListSize.spatial_tree_size = dlData.mDLSpatialTree->mCapacity;
resourceUpdates.Flush(dlData.mResourceUpdates, dlData.mSmallShmems,
dlData.mLargeShmems);
dlData.mRect =

View File

@@ -263,12 +263,10 @@ void TransactionBuilder::SetDisplayList(
const gfx::DeviceColor& aBgColor, Epoch aEpoch,
const wr::LayoutSize& aViewportSize, wr::WrPipelineId pipeline_id,
wr::BuiltDisplayListDescriptor dl_descriptor,
wr::Vec<uint8_t>& dl_items_data, wr::Vec<uint8_t>& dl_cache_data,
wr::Vec<uint8_t>& dl_spatial_tree) {
wr::Vec<uint8_t>& dl_items_data, wr::Vec<uint8_t>& dl_cache_data) {
wr_transaction_set_display_list(mTxn, aEpoch, ToColorF(aBgColor),
aViewportSize, pipeline_id, dl_descriptor,
&dl_items_data.inner, &dl_cache_data.inner,
&dl_spatial_tree.inner);
&dl_items_data.inner, &dl_cache_data.inner);
}
void TransactionBuilder::ClearDisplayList(Epoch aEpoch,
@@ -998,9 +996,9 @@ void DisplayListBuilder::DumpSerializedDisplayList() {
}
void DisplayListBuilder::Finalize(BuiltDisplayList& aOutDisplayList) {
wr_api_finalize_builder(
mWrState, &aOutDisplayList.dl_desc, &aOutDisplayList.dl_items.inner,
&aOutDisplayList.dl_cache.inner, &aOutDisplayList.dl_spatial_tree.inner);
wr_api_finalize_builder(mWrState, &aOutDisplayList.dl_desc,
&aOutDisplayList.dl_items.inner,
&aOutDisplayList.dl_cache.inner);
}
void DisplayListBuilder::Finalize(layers::DisplayListData& aOutTransaction) {
@@ -1008,23 +1006,18 @@ void DisplayListBuilder::Finalize(layers::DisplayListData& aOutTransaction) {
wr_dp_set_cache_size(mWrState, mDisplayItemCache->CurrentSize());
}
wr::VecU8 dlItems, dlCache, dlSpatialTree;
wr::VecU8 dlItems, dlCache;
wr_api_finalize_builder(mWrState, &aOutTransaction.mDLDesc, &dlItems.inner,
&dlCache.inner, &dlSpatialTree.inner);
&dlCache.inner);
aOutTransaction.mDLItems.emplace(dlItems.inner.data, dlItems.inner.length,
dlItems.inner.capacity);
aOutTransaction.mDLCache.emplace(dlCache.inner.data, dlCache.inner.length,
dlCache.inner.capacity);
aOutTransaction.mDLSpatialTree.emplace(dlSpatialTree.inner.data,
dlSpatialTree.inner.length,
dlSpatialTree.inner.capacity);
aOutTransaction.mRemotePipelineIds = std::move(mRemotePipelineIds);
dlItems.inner.capacity = 0;
dlItems.inner.data = nullptr;
dlCache.inner.capacity = 0;
dlCache.inner.data = nullptr;
dlSpatialTree.inner.capacity = 0;
dlSpatialTree.inner.data = nullptr;
}
Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(

View File

@@ -113,8 +113,7 @@ class TransactionBuilder final {
wr::WrPipelineId pipeline_id,
wr::BuiltDisplayListDescriptor dl_descriptor,
wr::Vec<uint8_t>& dl_items_data,
wr::Vec<uint8_t>& dl_cache_data,
wr::Vec<uint8_t>& dl_spatial_tree);
wr::Vec<uint8_t>& dl_cache_data);
void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipeline);

View File

@@ -740,7 +740,6 @@ struct ByteBuffer {
struct BuiltDisplayList {
wr::VecU8 dl_items;
wr::VecU8 dl_cache;
wr::VecU8 dl_spatial_tree;
wr::BuiltDisplayListDescriptor dl_desc;
};

View File

@@ -1842,7 +1842,6 @@ pub extern "C" fn wr_transaction_set_display_list(
dl_descriptor: BuiltDisplayListDescriptor,
dl_items_data: &mut WrVecU8,
dl_cache_data: &mut WrVecU8,
dl_spatial_tree_data: &mut WrVecU8,
) {
let color = if background.a == 0.0 { None } else { Some(background) };
@@ -1854,7 +1853,6 @@ pub extern "C" fn wr_transaction_set_display_list(
let payload = DisplayListPayload {
items_data: dl_items_data.flush_into_vec(),
cache_data: dl_cache_data.flush_into_vec(),
spatial_tree: dl_spatial_tree_data.flush_into_vec(),
};
let dl = BuiltDisplayList::from_data(payload, dl_descriptor);
@@ -3776,14 +3774,12 @@ pub unsafe extern "C" fn wr_api_finalize_builder(
dl_descriptor: &mut BuiltDisplayListDescriptor,
dl_items_data: &mut WrVecU8,
dl_cache_data: &mut WrVecU8,
dl_spatial_tree: &mut WrVecU8,
) {
let frame_builder = mem::replace(&mut state.frame_builder, WebRenderFrameBuilder::new(state.pipeline_id));
let (_, dl) = frame_builder.dl_builder.finalize();
let (payload, descriptor) = dl.into_data();
*dl_items_data = WrVecU8::from_vec(payload.items_data);
*dl_cache_data = WrVecU8::from_vec(payload.cache_data);
*dl_spatial_tree = WrVecU8::from_vec(payload.spatial_tree);
*dl_descriptor = descriptor;
}

View File

@@ -35,16 +35,16 @@
//! - backdrop filters (see add_backdrop_filter)
//!
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, BuiltDisplayList, PrimitiveFlags};
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, PrimitiveFlags};
use api::{ClipId, ColorF, CommonItemProperties, ComplexClipRegion, ComponentTransferFuncType, RasterSpace};
use api::{DisplayItem, DisplayItemRef, ExtendMode, ExternalScrollId, FilterData, SharedFontInstanceMap};
use api::{FilterOp, FilterPrimitive, FontInstanceKey, FontSize, GlyphInstance, GlyphOptions, GradientStop};
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, ColorDepth, QualitySettings};
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId, MixBlendMode, StackingContextFlags};
use api::{PropertyBinding, ReferenceFrameKind, ScrollFrameDescriptor, ScrollSensitivity, ReferenceFrameMapper};
use api::{Shadow, SpaceAndClipInfo, SpatialId, StickyFrameDescriptor, ImageMask, ItemTag};
use api::{PropertyBinding, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
use api::{Shadow, SpaceAndClipInfo, SpatialId, StickyFrameDisplayItem, ImageMask, ItemTag};
use api::{ClipMode, PrimitiveKeyKind, TransformStyle, YuvColorSpace, ColorRange, YuvData, TempFilterData};
use api::{ReferenceTransformBinding, Rotation, FillRule, SpatialTreeItem, ReferenceFrameDescriptor};
use api::{ReferenceTransformBinding, Rotation, FillRule};
use api::units::*;
use crate::image_tiling::simplify_repeated_primitive;
use crate::clip::{ClipChainId, ClipItemKey, ClipStore, ClipItemKeyKind};
@@ -89,6 +89,78 @@ use crate::util::{MaxRect, VecHelper};
use crate::filterdata::{SFilterDataComponent, SFilterData, SFilterDataKey};
use smallvec::SmallVec;
/// The offset stack for a given reference frame.
struct ReferenceFrameState {
/// A stack of current offsets from the current reference frame scope.
offsets: Vec<LayoutVector2D>,
}
/// Maps from stacking context layout coordinates into reference frame
/// relative coordinates.
struct ReferenceFrameMapper {
/// A stack of reference frame scopes.
frames: Vec<ReferenceFrameState>,
}
impl ReferenceFrameMapper {
fn new() -> Self {
ReferenceFrameMapper {
frames: vec![
ReferenceFrameState {
offsets: vec![
LayoutVector2D::zero(),
],
}
],
}
}
/// Push a new scope. This resets the current offset to zero, and is
/// used when a new reference frame or iframe is pushed.
fn push_scope(&mut self) {
self.frames.push(ReferenceFrameState {
offsets: vec![
LayoutVector2D::zero(),
],
});
}
/// Pop a reference frame scope off the stack.
fn pop_scope(&mut self) {
self.frames.pop().unwrap();
}
/// Push a new offset for the current scope. This is used when
/// a new stacking context is pushed.
fn push_offset(&mut self, offset: LayoutVector2D) {
let frame = self.frames.last_mut().unwrap();
let current_offset = *frame.offsets.last().unwrap();
frame.offsets.push(current_offset + offset);
}
/// Pop a local stacking context offset from the current scope.
fn pop_offset(&mut self) {
let frame = self.frames.last_mut().unwrap();
frame.offsets.pop().unwrap();
}
/// Retrieve the current offset to allow converting a stacking context
/// relative coordinate to be relative to the owing reference frame.
/// TODO(gw): We could perhaps have separate coordinate spaces for this,
/// however that's going to either mean a lot of changes to
/// public API code, or a lot of changes to internal code.
/// Before doing that, we should revisit how Gecko would
/// prefer to provide coordinates.
/// TODO(gw): For now, this includes only the reference frame relative
/// offset. Soon, we will expand this to include the initial
/// scroll offsets that are now available on scroll nodes. This
/// will allow normalizing the coordinates even between display
/// lists where APZ has scrolled the content.
fn current_offset(&self) -> LayoutVector2D {
*self.frames.last().unwrap().offsets.last().unwrap()
}
}
/// Offsets primitives (and clips) by the external scroll offset
/// supplied to scroll nodes.
pub struct ScrollOffsetMapper {
@@ -560,43 +632,6 @@ impl<'a> SceneBuilder<'a> {
rf_offset + scroll_offset
}
fn build_spatial_tree_for_display_list(
&mut self,
dl: &BuiltDisplayList,
pipeline_id: PipelineId,
) {
dl.iter_spatial_tree(|item| {
match item {
SpatialTreeItem::ScrollFrame(descriptor) => {
let parent_space = self.get_space(descriptor.parent_space);
self.build_scroll_frame(
descriptor,
parent_space,
pipeline_id,
);
}
SpatialTreeItem::ReferenceFrame(descriptor) => {
let parent_space = self.get_space(descriptor.parent_spatial_id);
self.build_reference_frame(
descriptor,
parent_space,
pipeline_id,
);
}
SpatialTreeItem::StickyFrame(descriptor) => {
let parent_space = self.get_space(descriptor.parent_spatial_id);
self.build_sticky_frame(
descriptor,
parent_space,
);
}
SpatialTreeItem::Invalid => {
unreachable!();
}
}
});
}
fn build_all(&mut self, root_pipeline: &ScenePipeline) {
enum ContextKind<'a> {
Root,
@@ -620,10 +655,6 @@ impl<'a> SceneBuilder<'a> {
root_pipeline.pipeline_id,
&root_pipeline.viewport_size,
);
self.build_spatial_tree_for_display_list(
&root_pipeline.display_list.display_list,
root_pipeline.pipeline_id,
);
let mut stack = vec![BuildContext {
pipeline_id: root_pipeline.pipeline_id,
@@ -682,9 +713,67 @@ impl<'a> SceneBuilder<'a> {
traversal = subtraversal;
continue 'outer;
}
DisplayItem::PushReferenceFrame(..) => {
DisplayItem::PushReferenceFrame(ref info) => {
profile_scope!("build_reference_frame");
let parent_space = self.get_space(info.parent_spatial_id);
let mut subtraversal = item.sub_iter();
let current_offset = self.current_offset(parent_space);
let transform = match info.reference_frame.transform {
ReferenceTransformBinding::Static { binding } => binding,
ReferenceTransformBinding::Computed { scale_from, vertical_flip, rotation } => {
let content_size = &self.iframe_size.last().unwrap();
let mut transform = if let Some(scale_from) = scale_from {
// If we have a 90/270 degree rotation, then scale_from
// and content_size are in different coordinate spaces and
// we need to swap width/height for them to be correct.
match rotation {
Rotation::Degree0 |
Rotation::Degree180 => {
LayoutTransform::scale(
content_size.width / scale_from.width,
content_size.height / scale_from.height,
1.0
)
},
Rotation::Degree90 |
Rotation::Degree270 => {
LayoutTransform::scale(
content_size.height / scale_from.width,
content_size.width / scale_from.height,
1.0
)
}
}
} else {
LayoutTransform::identity()
};
if vertical_flip {
let content_size = &self.iframe_size.last().unwrap();
transform = transform
.then_translate(LayoutVector3D::new(0.0, content_size.height, 0.0))
.pre_scale(1.0, -1.0, 1.0);
}
let rotate = rotation.to_matrix(**content_size);
let transform = transform.then(&rotate);
PropertyBinding::Value(transform)
},
};
self.push_reference_frame(
info.reference_frame.id,
Some(parent_space),
bc.pipeline_id,
info.reference_frame.transform_style,
transform,
info.reference_frame.kind,
current_offset + info.origin.to_vector(),
);
self.rf_mapper.push_scope();
let new_context = BuildContext {
@@ -704,11 +793,30 @@ impl<'a> SceneBuilder<'a> {
profile_scope!("iframe");
let space = self.get_space(info.space_and_clip.spatial_id);
let subtraversal = match self.push_iframe(info, space) {
let (size, subtraversal) = match self.push_iframe(info, space) {
Some(pair) => pair,
None => continue,
};
// Get a clip-chain id for the root clip for this pipeline. We will
// add that as an unconditional clip to any tile cache created within
// this iframe. This ensures these clips are handled by the tile cache
// compositing code, which is more efficient and accurate than applying
// these clips individually to each primitive.
let clip_id = ClipId::root(info.pipeline_id);
let clip_chain_id = self.get_clip_chain(clip_id);
// If this is a root iframe, force a new tile cache both before and after
// adding primitives for this iframe.
if self.iframe_size.is_empty() {
self.add_tile_cache_barrier_if_needed(SliceFlags::empty());
assert!(self.root_iframe_clip.is_none());
self.root_iframe_clip = Some(clip_chain_id);
}
self.rf_mapper.push_scope();
self.iframe_size.push(size);
let new_context = BuildContext {
pipeline_id: info.pipeline_id,
kind: ContextKind::Iframe {
@@ -772,7 +880,7 @@ impl<'a> SceneBuilder<'a> {
fn build_sticky_frame(
&mut self,
info: &StickyFrameDescriptor,
info: &StickyFrameDisplayItem,
parent_node_index: SpatialNodeIndex,
) {
let current_offset = self.current_offset(parent_node_index);
@@ -793,72 +901,9 @@ impl<'a> SceneBuilder<'a> {
self.id_to_index_mapper.add_spatial_node(info.id, index);
}
fn build_reference_frame(
&mut self,
info: &ReferenceFrameDescriptor,
parent_space: SpatialNodeIndex,
pipeline_id: PipelineId,
) {
let transform = match info.reference_frame.transform {
ReferenceTransformBinding::Static { binding } => binding,
ReferenceTransformBinding::Computed { scale_from, vertical_flip, rotation } => {
let content_size = &self.iframe_size.last().unwrap();
let mut transform = if let Some(scale_from) = scale_from {
// If we have a 90/270 degree rotation, then scale_from
// and content_size are in different coordinate spaces and
// we need to swap width/height for them to be correct.
match rotation {
Rotation::Degree0 |
Rotation::Degree180 => {
LayoutTransform::scale(
content_size.width / scale_from.width,
content_size.height / scale_from.height,
1.0
)
},
Rotation::Degree90 |
Rotation::Degree270 => {
LayoutTransform::scale(
content_size.height / scale_from.width,
content_size.width / scale_from.height,
1.0
)
}
}
} else {
LayoutTransform::identity()
};
if vertical_flip {
let content_size = &self.iframe_size.last().unwrap();
transform = transform
.then_translate(LayoutVector3D::new(0.0, content_size.height, 0.0))
.pre_scale(1.0, -1.0, 1.0);
}
let rotate = rotation.to_matrix(**content_size);
let transform = transform.then(&rotate);
PropertyBinding::Value(transform)
},
};
self.push_reference_frame(
info.reference_frame.id,
Some(parent_space),
pipeline_id,
info.reference_frame.transform_style,
transform,
info.reference_frame.kind,
info.origin.to_vector(),
);
}
fn build_scroll_frame(
&mut self,
info: &ScrollFrameDescriptor,
info: &ScrollFrameDisplayItem,
parent_node_index: SpatialNodeIndex,
pipeline_id: PipelineId,
) {
@@ -886,7 +931,7 @@ impl<'a> SceneBuilder<'a> {
&mut self,
info: &IframeDisplayItem,
spatial_node_index: SpatialNodeIndex,
) -> Option<BuiltDisplayListIter<'a>> {
) -> Option<(LayoutSize, BuiltDisplayListIter<'a>)> {
let iframe_pipeline_id = info.pipeline_id;
let pipeline = match self.scene.pipelines.get(&iframe_pipeline_id) {
Some(pipeline) => pipeline,
@@ -945,30 +990,7 @@ impl<'a> SceneBuilder<'a> {
LayoutVector2D::zero(),
);
// Get a clip-chain id for the root clip for this pipeline. We will
// add that as an unconditional clip to any tile cache created within
// this iframe. This ensures these clips are handled by the tile cache
// compositing code, which is more efficient and accurate than applying
// these clips individually to each primitive.
let clip_id = ClipId::root(info.pipeline_id);
let clip_chain_id = self.get_clip_chain(clip_id);
// If this is a root iframe, force a new tile cache both before and after
// adding primitives for this iframe.
if self.iframe_size.is_empty() {
self.add_tile_cache_barrier_if_needed(SliceFlags::empty());
assert!(self.root_iframe_clip.is_none());
self.root_iframe_clip = Some(clip_chain_id);
}
self.iframe_size.push(info.bounds.size());
self.rf_mapper.push_scope();
self.build_spatial_tree_for_display_list(
&pipeline.display_list.display_list,
iframe_pipeline_id,
);
Some(pipeline.display_list.iter())
Some((bounds.size(), pipeline.display_list.iter()))
}
fn get_space(
@@ -1512,6 +1534,25 @@ impl<'a> SceneBuilder<'a> {
&clips,
);
},
DisplayItem::ScrollFrame(ref info) => {
profile_scope!("scrollframe");
let parent_space = self.get_space(info.parent_space);
self.build_scroll_frame(
info,
parent_space,
pipeline_id,
);
}
DisplayItem::StickyFrame(ref info) => {
profile_scope!("stickyframe");
let parent_space = self.get_space(info.parent_spatial_id);
self.build_sticky_frame(
info,
parent_space,
);
}
DisplayItem::BackdropFilter(ref info) => {
profile_scope!("backdrop");

View File

@@ -115,15 +115,6 @@ impl SpaceAndClipInfo {
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum SpatialTreeItem {
ScrollFrame(ScrollFrameDescriptor),
ReferenceFrame(ReferenceFrameDescriptor),
StickyFrame(StickyFrameDescriptor),
Invalid,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum DisplayItem {
@@ -151,6 +142,8 @@ pub enum DisplayItem {
ClipChain(ClipChainItem),
// Spaces and Frames that content can be scoped under.
ScrollFrame(ScrollFrameDisplayItem),
StickyFrame(StickyFrameDisplayItem),
Iframe(IframeDisplayItem),
PushReferenceFrame(ReferenceFrameDisplayListItem),
PushStackingContext(PushStackingContextDisplayItem),
@@ -199,6 +192,8 @@ pub enum DebugDisplayItem {
RectClip(RectClipDisplayItem),
ClipChain(ClipChainItem, Vec<ClipId>),
ScrollFrame(ScrollFrameDisplayItem),
StickyFrame(StickyFrameDisplayItem),
Iframe(IframeDisplayItem),
PushReferenceFrame(ReferenceFrameDisplayListItem),
PushStackingContext(PushStackingContextDisplayItem),
@@ -265,7 +260,7 @@ impl StickyOffsetBounds {
}
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct StickyFrameDescriptor {
pub struct StickyFrameDisplayItem {
pub id: SpatialId,
pub parent_spatial_id: SpatialId,
pub bounds: LayoutRect,
@@ -302,7 +297,7 @@ pub enum ScrollSensitivity {
}
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ScrollFrameDescriptor {
pub struct ScrollFrameDisplayItem {
/// The id of the space this scroll frame creates
pub scroll_frame_id: SpatialId,
/// The size of the contents this contains (so the backend knows how far it can scroll).
@@ -737,10 +732,6 @@ pub struct BackdropFilterDisplayItem {
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ReferenceFrameDisplayListItem {
}
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ReferenceFrameDescriptor {
pub origin: LayoutPoint,
pub parent_spatial_id: SpatialId,
pub reference_frame: ReferenceFrame,
@@ -1719,9 +1710,11 @@ impl DisplayItem {
DisplayItem::SetPoints => "set_points",
DisplayItem::RadialGradient(..) => "radial_gradient",
DisplayItem::Rectangle(..) => "rectangle",
DisplayItem::ScrollFrame(..) => "scroll_frame",
DisplayItem::SetGradientStops => "set_gradient_stops",
DisplayItem::ReuseItems(..) => "reuse_item",
DisplayItem::RetainedItems(..) => "retained_items",
DisplayItem::StickyFrame(..) => "sticky_frame",
DisplayItem::Text(..) => "text",
DisplayItem::YuvImage(..) => "yuv_image",
DisplayItem::BackdropFilter(..) => "backdrop_filter",

View File

@@ -8,7 +8,7 @@ use peek_poke::{poke_inplace_slice, poke_into_vec, Poke};
#[cfg(feature = "deserialize")]
use serde::de::Deserializer;
#[cfg(feature = "serialize")]
use serde::ser::Serializer;
use serde::ser::{Serializer, SerializeSeq};
use serde::{Deserialize, Serialize};
use std::io::Write;
use std::marker::PhantomData;
@@ -114,35 +114,19 @@ pub struct DisplayListPayload {
/// Serde encoded DisplayItemCache structs
pub cache_data: Vec<u8>,
/// Serde encoded SpatialTreeItem structs
pub spatial_tree: Vec<u8>,
}
impl DisplayListPayload {
fn size_in_bytes(&self) -> usize {
self.items_data.len() +
self.cache_data.len() +
self.spatial_tree.len()
}
#[cfg(feature = "serialize")]
fn create_debug_spatial_tree_items(&self) -> Vec<di::SpatialTreeItem> {
let mut items = Vec::new();
iter_spatial_tree(&self.spatial_tree, |item| {
items.push(*item);
});
items
self.cache_data.len()
}
}
impl MallocSizeOf for DisplayListPayload {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.items_data.size_of(ops) +
self.cache_data.size_of(ops) +
self.spatial_tree.size_of(ops)
self.cache_data.size_of(ops)
}
}
@@ -190,7 +174,7 @@ pub struct BuiltDisplayListDescriptor {
#[derive(Clone)]
pub struct DisplayListWithCache {
pub display_list: BuiltDisplayList,
display_list: BuiltDisplayList,
cache: DisplayItemCache,
}
@@ -233,33 +217,13 @@ impl MallocSizeOf for DisplayListWithCache {
}
}
/// A debug (human-readable) representation of a built display list that
/// can be used for capture and replay.
#[cfg(any(feature = "serialize", feature = "deserialize"))]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
struct DisplayListCapture {
display_items: Vec<di::DebugDisplayItem>,
spatial_tree_items: Vec<di::SpatialTreeItem>,
descriptor: BuiltDisplayListDescriptor,
}
#[cfg(feature = "serialize")]
impl Serialize for DisplayListWithCache {
fn serialize<S: Serializer>(
&self,
serializer: S
) -> Result<S::Ok, S::Error> {
let display_items = BuiltDisplayList::create_debug_display_items(self.iter());
let spatial_tree_items = self.display_list.payload.create_debug_spatial_tree_items();
let dl = DisplayListCapture {
display_items,
spatial_tree_items,
descriptor: self.display_list.descriptor,
};
dl.serialize(serializer)
BuiltDisplayList::serialize_with_iterator(serializer, self.iter())
}
}
@@ -269,112 +233,20 @@ impl<'de> Deserialize<'de> for DisplayListWithCache {
where
D: Deserializer<'de>,
{
use crate::display_item::DisplayItem as Real;
use crate::display_item::DebugDisplayItem as Debug;
let capture = DisplayListCapture::deserialize(deserializer)?;
let mut spatial_tree = Vec::new();
for item in capture.spatial_tree_items {
poke_into_vec(&item, &mut spatial_tree);
}
ensure_red_zone::<di::SpatialTreeItem>(&mut spatial_tree);
let mut items_data = Vec::new();
let mut temp = Vec::new();
for complete in capture.display_items {
let item = match complete {
Debug::ClipChain(v, clip_chain_ids) => {
DisplayListBuilder::push_iter_impl(&mut temp, clip_chain_ids);
Real::ClipChain(v)
}
Debug::Text(v, glyphs) => {
DisplayListBuilder::push_iter_impl(&mut temp, glyphs);
Real::Text(v)
},
Debug::Iframe(v) => {
Real::Iframe(v)
}
Debug::PushReferenceFrame(v) => {
Real::PushReferenceFrame(v)
}
Debug::SetFilterOps(filters) => {
DisplayListBuilder::push_iter_impl(&mut temp, filters);
Real::SetFilterOps
},
Debug::SetFilterData(filter_data) => {
let func_types: Vec<di::ComponentTransferFuncType> =
[filter_data.func_r_type,
filter_data.func_g_type,
filter_data.func_b_type,
filter_data.func_a_type].to_vec();
DisplayListBuilder::push_iter_impl(&mut temp, func_types);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.r_values);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.g_values);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.b_values);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
Real::SetFilterData
},
Debug::SetFilterPrimitives(filter_primitives) => {
DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
Real::SetFilterPrimitives
}
Debug::SetGradientStops(stops) => {
DisplayListBuilder::push_iter_impl(&mut temp, stops);
Real::SetGradientStops
},
Debug::SetPoints(points) => {
DisplayListBuilder::push_iter_impl(&mut temp, points);
Real::SetPoints
},
Debug::RectClip(v) => Real::RectClip(v),
Debug::RoundedRectClip(v) => Real::RoundedRectClip(v),
Debug::ImageMaskClip(v) => Real::ImageMaskClip(v),
Debug::Rectangle(v) => Real::Rectangle(v),
Debug::ClearRectangle(v) => Real::ClearRectangle(v),
Debug::HitTest(v) => Real::HitTest(v),
Debug::Line(v) => Real::Line(v),
Debug::Image(v) => Real::Image(v),
Debug::RepeatingImage(v) => Real::RepeatingImage(v),
Debug::YuvImage(v) => Real::YuvImage(v),
Debug::Border(v) => Real::Border(v),
Debug::BoxShadow(v) => Real::BoxShadow(v),
Debug::Gradient(v) => Real::Gradient(v),
Debug::RadialGradient(v) => Real::RadialGradient(v),
Debug::ConicGradient(v) => Real::ConicGradient(v),
Debug::PushStackingContext(v) => Real::PushStackingContext(v),
Debug::PushShadow(v) => Real::PushShadow(v),
Debug::BackdropFilter(v) => Real::BackdropFilter(v),
Debug::PopStackingContext => Real::PopStackingContext,
Debug::PopReferenceFrame => Real::PopReferenceFrame,
Debug::PopAllShadows => Real::PopAllShadows,
};
poke_into_vec(&item, &mut items_data);
// the aux data is serialized after the item, hence the temporary
items_data.extend(temp.drain(..));
}
// 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 items_data);
let display_list = BuiltDisplayList::deserialize(deserializer)?;
let cache = DisplayItemCache::new();
Ok(DisplayListWithCache {
display_list: BuiltDisplayList {
descriptor: capture.descriptor,
payload: DisplayListPayload {
cache_data: Vec::new(),
items_data,
spatial_tree,
},
},
cache: DisplayItemCache::new(),
display_list,
cache,
})
}
}
impl BuiltDisplayListDescriptor {}
pub struct BuiltDisplayListIter<'a> {
list: &'a BuiltDisplayList,
data: &'a [u8],
cache: Option<&'a DisplayItemCache>,
pending_items: std::slice::Iter<'a, CachedDisplayItem>,
@@ -463,6 +335,10 @@ pub struct DisplayItemRef<'a: 'b, 'b> {
// Some of these might just become ItemRanges
impl<'a, 'b> DisplayItemRef<'a, 'b> {
pub fn display_list(&self) -> &BuiltDisplayList {
self.iter.display_list()
}
// Creates a new iterator where this element's iterator is, to hack around borrowck.
pub fn sub_iter(&self) -> BuiltDisplayListIter<'a> {
self.iter.sub_iter()
@@ -572,18 +448,18 @@ impl BuiltDisplayList {
}
pub fn iter(&self) -> BuiltDisplayListIter {
BuiltDisplayListIter::new(self.items_data(), None)
BuiltDisplayListIter::new(self, self.items_data(), None)
}
pub fn cache_data_iter(&self) -> BuiltDisplayListIter {
BuiltDisplayListIter::new(self.cache_data(), None)
BuiltDisplayListIter::new(self, self.cache_data(), None)
}
pub fn iter_with_cache<'a>(
&'a self,
cache: &'a DisplayItemCache
) -> BuiltDisplayListIter<'a> {
BuiltDisplayListIter::new(self.items_data(), Some(cache))
BuiltDisplayListIter::new(self, self.items_data(), Some(cache))
}
pub fn cache_size(&self) -> usize {
@@ -594,17 +470,15 @@ impl BuiltDisplayList {
self.payload.size_in_bytes()
}
pub fn iter_spatial_tree<F>(&self, f: F) where F: FnMut(&di::SpatialTreeItem) {
iter_spatial_tree(&self.payload.spatial_tree, f)
}
#[cfg(feature = "serialize")]
pub fn create_debug_display_items(
pub fn serialize_with_iterator<S: Serializer>(
serializer: S,
mut iterator: BuiltDisplayListIter,
) -> Vec<di::DebugDisplayItem> {
use di::DisplayItem as Real;
use di::DebugDisplayItem as Debug;
let mut debug_items = Vec::new();
) -> Result<S::Ok, S::Error> {
use crate::display_item::DisplayItem as Real;
use crate::display_item::DebugDisplayItem as Debug;
let mut seq = serializer.serialize_seq(None)?;
while let Some(item) = iterator.next_raw() {
let serial_di = match *item.item() {
@@ -612,6 +486,7 @@ impl BuiltDisplayList {
v,
item.iter.cur_clip_chain_items.iter().collect()
),
Real::ScrollFrame(v) => Debug::ScrollFrame(v),
Real::Text(v) => Debug::Text(
v,
item.iter.cur_glyphs.iter().collect()
@@ -651,6 +526,7 @@ impl BuiltDisplayList {
Real::RectClip(v) => Debug::RectClip(v),
Real::RoundedRectClip(v) => Debug::RoundedRectClip(v),
Real::ImageMaskClip(v) => Debug::ImageMaskClip(v),
Real::StickyFrame(v) => Debug::StickyFrame(v),
Real::Rectangle(v) => Debug::Rectangle(v),
Real::ClearRectangle(v) => Debug::ClearRectangle(v),
Real::HitTest(v) => Debug::HitTest(v),
@@ -675,10 +551,9 @@ impl BuiltDisplayList {
Real::ReuseItems(_) |
Real::RetainedItems(_) => unreachable!("Unexpected item"),
};
debug_items.push(serial_di);
seq.serialize_element(&serial_di)?
}
debug_items
seq.end()
}
}
@@ -699,10 +574,12 @@ fn skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T> {
impl<'a> BuiltDisplayListIter<'a> {
pub fn new(
list: &'a BuiltDisplayList,
data: &'a [u8],
cache: Option<&'a DisplayItemCache>,
) -> Self {
Self {
list,
data,
cache,
pending_items: [].iter(),
@@ -725,12 +602,16 @@ impl<'a> BuiltDisplayListIter<'a> {
pub fn sub_iter(&self) -> Self {
let mut iter = BuiltDisplayListIter::new(
self.data, self.cache
self.list, self.data, self.cache
);
iter.pending_items = self.pending_items.clone();
iter
}
pub fn display_list(&self) -> &'a BuiltDisplayList {
self.list
}
pub fn current_item(&self) -> &di::DisplayItem {
match self.cur_cached_item {
Some(cached_item) => cached_item.display_item(),
@@ -980,6 +861,141 @@ impl<'a, T: Copy + peek_poke::Peek> Iterator for AuxIter<'a, T> {
impl<'a, T: Copy + peek_poke::Peek> ::std::iter::ExactSizeIterator for AuxIter<'a, T> {}
#[cfg(feature = "serialize")]
impl Serialize for BuiltDisplayList {
fn serialize<S: Serializer>(
&self,
serializer: S
) -> Result<S::Ok, S::Error> {
Self::serialize_with_iterator(serializer, self.iter())
}
}
// The purpose of this implementation is to deserialize
// a display list from one format just to immediately
// serialize then into a "built" `Vec<u8>`.
#[cfg(feature = "deserialize")]
impl<'de> Deserialize<'de> for BuiltDisplayList {
fn deserialize<D: Deserializer<'de>>(
deserializer: D
) -> Result<Self, D::Error> {
use crate::display_item::DisplayItem as Real;
use crate::display_item::DebugDisplayItem as Debug;
let list = Vec::<Debug>::deserialize(deserializer)?;
let mut items_data = Vec::new();
let mut temp = Vec::new();
let mut total_clip_nodes = FIRST_CLIP_NODE_INDEX;
let mut total_spatial_nodes = FIRST_SPATIAL_NODE_INDEX;
for complete in list {
let item = match complete {
Debug::ClipChain(v, clip_chain_ids) => {
DisplayListBuilder::push_iter_impl(&mut temp, clip_chain_ids);
Real::ClipChain(v)
}
Debug::ScrollFrame(v) => {
total_spatial_nodes += 1;
total_clip_nodes += 1;
Real::ScrollFrame(v)
}
Debug::StickyFrame(v) => {
total_spatial_nodes += 1;
Real::StickyFrame(v)
}
Debug::Text(v, glyphs) => {
DisplayListBuilder::push_iter_impl(&mut temp, glyphs);
Real::Text(v)
},
Debug::Iframe(v) => {
total_clip_nodes += 1;
Real::Iframe(v)
}
Debug::PushReferenceFrame(v) => {
total_spatial_nodes += 1;
Real::PushReferenceFrame(v)
}
Debug::SetFilterOps(filters) => {
DisplayListBuilder::push_iter_impl(&mut temp, filters);
Real::SetFilterOps
},
Debug::SetFilterData(filter_data) => {
let func_types: Vec<di::ComponentTransferFuncType> =
[filter_data.func_r_type,
filter_data.func_g_type,
filter_data.func_b_type,
filter_data.func_a_type].to_vec();
DisplayListBuilder::push_iter_impl(&mut temp, func_types);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.r_values);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.g_values);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.b_values);
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
Real::SetFilterData
},
Debug::SetFilterPrimitives(filter_primitives) => {
DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
Real::SetFilterPrimitives
}
Debug::SetGradientStops(stops) => {
DisplayListBuilder::push_iter_impl(&mut temp, stops);
Real::SetGradientStops
},
Debug::SetPoints(points) => {
DisplayListBuilder::push_iter_impl(&mut temp, points);
Real::SetPoints
},
Debug::RectClip(v) => Real::RectClip(v),
Debug::RoundedRectClip(v) => Real::RoundedRectClip(v),
Debug::ImageMaskClip(v) => Real::ImageMaskClip(v),
Debug::Rectangle(v) => Real::Rectangle(v),
Debug::ClearRectangle(v) => Real::ClearRectangle(v),
Debug::HitTest(v) => Real::HitTest(v),
Debug::Line(v) => Real::Line(v),
Debug::Image(v) => Real::Image(v),
Debug::RepeatingImage(v) => Real::RepeatingImage(v),
Debug::YuvImage(v) => Real::YuvImage(v),
Debug::Border(v) => Real::Border(v),
Debug::BoxShadow(v) => Real::BoxShadow(v),
Debug::Gradient(v) => Real::Gradient(v),
Debug::RadialGradient(v) => Real::RadialGradient(v),
Debug::ConicGradient(v) => Real::ConicGradient(v),
Debug::PushStackingContext(v) => Real::PushStackingContext(v),
Debug::PushShadow(v) => Real::PushShadow(v),
Debug::BackdropFilter(v) => Real::BackdropFilter(v),
Debug::PopStackingContext => Real::PopStackingContext,
Debug::PopReferenceFrame => Real::PopReferenceFrame,
Debug::PopAllShadows => Real::PopAllShadows,
};
poke_into_vec(&item, &mut items_data);
// the aux data is serialized after the item, hence the temporary
items_data.extend(temp.drain(..));
}
// 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 items_data);
Ok(BuiltDisplayList {
payload: DisplayListPayload {
items_data,
cache_data: Vec::new(),
},
descriptor: BuiltDisplayListDescriptor {
gecko_display_list_type: GeckoDisplayListType::None,
builder_start_time: 0,
builder_finish_time: 1,
send_start_time: 1,
total_clip_nodes,
total_spatial_nodes,
cache_size: 0,
},
})
}
}
#[derive(Clone, Debug)]
pub struct SaveState {
dl_items_len: usize,
@@ -1000,23 +1016,6 @@ pub enum DisplayListSection {
Chunk,
}
/// A small portion of a normal spatial node that we store during DL construction to
/// enable snapping and reference frame <-> stacking context coord mapping. In future
/// we'll aim to remove this and have the full spatial tree available during DL build.
#[derive(Clone)]
pub struct SpatialNodeInfo {
/// The total external scroll offset applicable at this node
accumulated_external_scroll_offset: LayoutVector2D,
}
impl SpatialNodeInfo {
fn identity() -> Self {
SpatialNodeInfo {
accumulated_external_scroll_offset: LayoutVector2D::zero(),
}
}
}
#[derive(Clone)]
pub struct DisplayListBuilder {
payload: DisplayListPayload,
@@ -1034,19 +1033,12 @@ pub struct DisplayListBuilder {
cache_size: usize,
serialized_content_buffer: Option<String>,
/// Helper struct to map stacking context coords <-> reference frame coords.
rf_mapper: ReferenceFrameMapper,
/// Minimal info about encountered spatial nodes to allow snapping during DL building
spatial_nodes: Vec<SpatialNodeInfo>,
}
#[repr(C)]
pub struct DisplayListCapacity {
items_size: usize,
cache_size: usize,
spatial_tree_size: usize,
}
impl DisplayListCapacity {
@@ -1054,7 +1046,6 @@ impl DisplayListCapacity {
DisplayListCapacity {
items_size: 0,
cache_size: 0,
spatial_tree_size: 0,
}
}
}
@@ -1074,7 +1065,6 @@ impl DisplayListBuilder {
payload: DisplayListPayload {
items_data: Vec::with_capacity(capacity.items_size),
cache_data: Vec::with_capacity(capacity.cache_size),
spatial_tree: Vec::with_capacity(capacity.spatial_tree_size),
},
pipeline_id,
@@ -1088,9 +1078,6 @@ impl DisplayListBuilder {
save_state: None,
cache_size: 0,
serialized_content_buffer: None,
rf_mapper: ReferenceFrameMapper::new(),
spatial_nodes: vec![SpatialNodeInfo::identity(); FIRST_SPATIAL_NODE_INDEX + 1],
}
}
@@ -1226,11 +1213,6 @@ impl DisplayListBuilder {
self.push_item_to_section(item, self.default_section());
}
#[inline]
pub fn push_spatial_tree_item(&mut self, item: &di::SpatialTreeItem) {
poke_into_vec(item, &mut self.payload.spatial_tree);
}
fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
where
I: IntoIterator,
@@ -1617,15 +1599,7 @@ impl DisplayListBuilder {
) -> di::SpatialId {
let id = self.generate_spatial_index();
let current_offset = self.current_offset(parent_spatial_id);
let origin = origin + current_offset;
self.add_spatial_node_info(
id,
LayoutVector2D::zero(),
);
let descriptor = di::SpatialTreeItem::ReferenceFrame(di::ReferenceFrameDescriptor {
let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
parent_spatial_id,
origin,
reference_frame: di::ReferenceFrame {
@@ -1637,14 +1611,8 @@ impl DisplayListBuilder {
id,
},
});
self.push_spatial_tree_item(&descriptor);
self.rf_mapper.push_scope();
let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
});
self.push_item(&item);
id
}
@@ -1658,10 +1626,7 @@ impl DisplayListBuilder {
) -> di::SpatialId {
let id = self.generate_spatial_index();
let current_offset = self.current_offset(parent_spatial_id);
let origin = origin + current_offset;
let descriptor = di::SpatialTreeItem::ReferenceFrame(di::ReferenceFrameDescriptor {
let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
parent_spatial_id,
origin,
reference_frame: di::ReferenceFrame {
@@ -1678,19 +1643,12 @@ impl DisplayListBuilder {
id,
},
});
self.push_spatial_tree_item(&descriptor);
self.rf_mapper.push_scope();
let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
});
self.push_item(&item);
id
}
pub fn pop_reference_frame(&mut self) {
self.rf_mapper.pop_scope();
self.push_item(&di::DisplayItem::PopReferenceFrame);
}
@@ -1723,7 +1681,6 @@ impl DisplayListBuilder {
},
});
self.rf_mapper.push_offset(origin.to_vector());
self.push_item(&item);
}
@@ -1770,7 +1727,6 @@ impl DisplayListBuilder {
}
pub fn pop_stacking_context(&mut self) {
self.rf_mapper.pop_offset();
self.push_item(&di::DisplayItem::PopStackingContext);
}
@@ -1851,15 +1807,7 @@ impl DisplayListBuilder {
external_scroll_offset: LayoutVector2D,
) -> di::SpatialId {
let scroll_frame_id = self.generate_spatial_index();
let parent = self.spatial_nodes[parent_space.0].clone();
self.add_spatial_node_info(
scroll_frame_id,
parent.accumulated_external_scroll_offset + external_scroll_offset,
);
let descriptor = di::SpatialTreeItem::ScrollFrame(di::ScrollFrameDescriptor {
let item = di::DisplayItem::ScrollFrame(di::ScrollFrameDisplayItem {
content_rect,
frame_rect,
parent_space,
@@ -1869,7 +1817,7 @@ impl DisplayListBuilder {
external_scroll_offset,
});
self.push_spatial_tree_item(&descriptor);
self.push_item(&item);
scroll_frame_id
}
@@ -1958,14 +1906,7 @@ impl DisplayListBuilder {
previously_applied_offset: LayoutVector2D,
) -> di::SpatialId {
let id = self.generate_spatial_index();
let parent = self.spatial_nodes[parent_spatial_id.0].clone();
self.add_spatial_node_info(
id,
parent.accumulated_external_scroll_offset,
);
let descriptor = di::SpatialTreeItem::StickyFrame(di::StickyFrameDescriptor {
let item = di::DisplayItem::StickyFrame(di::StickyFrameDisplayItem {
parent_spatial_id,
id,
bounds: frame_rect,
@@ -1975,7 +1916,7 @@ impl DisplayListBuilder {
previously_applied_offset,
});
self.push_spatial_tree_item(&descriptor);
self.push_item(&item);
id
}
@@ -2088,7 +2029,6 @@ impl DisplayListBuilder {
// serialization.
ensure_red_zone::<di::DisplayItem>(&mut self.payload.items_data);
ensure_red_zone::<di::DisplayItem>(&mut self.payload.cache_data);
ensure_red_zone::<di::SpatialTreeItem>(&mut self.payload.spatial_tree);
let end_time = precise_time_ns();
(
@@ -2107,117 +2047,4 @@ impl DisplayListBuilder {
},
)
}
/// Retrieve the current offset to allow converting a stacking context
/// relative coordinate to be relative to the owing reference frame,
/// also considering any external scroll offset on the provided
/// spatial node.
fn current_offset(
&mut self,
spatial_id: di::SpatialId,
) -> LayoutVector2D {
// Get the current offset from stacking context <-> reference frame space.
let rf_offset = self.rf_mapper.current_offset();
// Get the external scroll offset, if applicable.
let scroll_offset = self.spatial_nodes[spatial_id.0].accumulated_external_scroll_offset;
rf_offset + scroll_offset
}
/// Add info about a spatial node that is needed during DL building.
fn add_spatial_node_info(
&mut self,
id: di::SpatialId,
accumulated_external_scroll_offset: LayoutVector2D,
) {
self.spatial_nodes.resize(id.0 + 1, SpatialNodeInfo::identity());
let info = &mut self.spatial_nodes[id.0];
info.accumulated_external_scroll_offset = accumulated_external_scroll_offset;
}
}
fn iter_spatial_tree<F>(spatial_tree: &[u8], mut f: F) where F: FnMut(&di::SpatialTreeItem) {
let mut src = spatial_tree;
let mut item = di::SpatialTreeItem::Invalid;
while src.len() > di::SpatialTreeItem::max_size() {
src = peek_from_slice(src, &mut item);
f(&item);
}
}
/// The offset stack for a given reference frame.
#[derive(Clone)]
struct ReferenceFrameState {
/// A stack of current offsets from the current reference frame scope.
offsets: Vec<LayoutVector2D>,
}
/// Maps from stacking context layout coordinates into reference frame
/// relative coordinates.
#[derive(Clone)]
pub struct ReferenceFrameMapper {
/// A stack of reference frame scopes.
frames: Vec<ReferenceFrameState>,
}
impl ReferenceFrameMapper {
pub fn new() -> Self {
ReferenceFrameMapper {
frames: vec![
ReferenceFrameState {
offsets: vec![
LayoutVector2D::zero(),
],
}
],
}
}
/// Push a new scope. This resets the current offset to zero, and is
/// used when a new reference frame or iframe is pushed.
pub fn push_scope(&mut self) {
self.frames.push(ReferenceFrameState {
offsets: vec![
LayoutVector2D::zero(),
],
});
}
/// Pop a reference frame scope off the stack.
pub fn pop_scope(&mut self) {
self.frames.pop().unwrap();
}
/// Push a new offset for the current scope. This is used when
/// a new stacking context is pushed.
pub fn push_offset(&mut self, offset: LayoutVector2D) {
let frame = self.frames.last_mut().unwrap();
let current_offset = *frame.offsets.last().unwrap();
frame.offsets.push(current_offset + offset);
}
/// Pop a local stacking context offset from the current scope.
pub fn pop_offset(&mut self) {
let frame = self.frames.last_mut().unwrap();
frame.offsets.pop().unwrap();
}
/// Retrieve the current offset to allow converting a stacking context
/// relative coordinate to be relative to the owing reference frame.
/// TODO(gw): We could perhaps have separate coordinate spaces for this,
/// however that's going to either mean a lot of changes to
/// public API code, or a lot of changes to internal code.
/// Before doing that, we should revisit how Gecko would
/// prefer to provide coordinates.
/// TODO(gw): For now, this includes only the reference frame relative
/// offset. Soon, we will expand this to include the initial
/// scroll offsets that are now available on scroll nodes. This
/// will allow normalizing the coordinates even between display
/// lists where APZ has scrolled the content.
pub fn current_offset(&self) -> LayoutVector2D {
*self.frames.last().unwrap().offsets.last().unwrap()
}
}

View File

@@ -89,7 +89,7 @@ fuzzy(0-20,0-999) fails-if(OSX>=1008&&!skiaContent) != downscale-2e.html?205,53,
# Skip on Android because it runs reftests via http, and moz-icon isn't
# accessible from http/https origins anymore.
fuzzy(0-25,0-3940) fuzzy-if(gtkWidget&&!webrender,4-4,2616-2616) fuzzy-if(gtkWidget&&!webrender&&!layersGPUAccelerated,0-0,0-0) fuzzy-if(gtkWidget&&webrender,0-0,0-0) skip-if(Android) fuzzy-if(appleSilicon,0-20,0-10123) == downscale-moz-icon-1.html downscale-moz-icon-1-ref.html # gtkWidget Bug 1592059: regular is 2616, no-accel is 0, qr passes with 0
fuzzy(0-17,0-3940) fuzzy-if(gtkWidget&&!webrender,4-4,2616-2616) fuzzy-if(gtkWidget&&!webrender&&!layersGPUAccelerated,0-0,0-0) fuzzy-if(gtkWidget&&webrender,0-0,0-0) skip-if(Android) fuzzy-if(appleSilicon,0-20,0-10123) == downscale-moz-icon-1.html downscale-moz-icon-1-ref.html # gtkWidget Bug 1592059: regular is 2616, no-accel is 0, qr passes with 0
== downscale-png.html?16,16,interlaced downscale-png.html?16,16,normal
== downscale-png.html?24,24,interlaced downscale-png.html?24,24,normal

View File

@@ -1,3 +1,3 @@
[devicepixel.html]
fuzzy: maxDifference=0-52;totalPixels=0-1100
fuzzy: maxDifference=0-2;totalPixels=0-1391
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1723618