mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-01 22:07:41 +00:00
Bug 1518605 - Update webrender to commit e16ab884672151fbdebc149479f9bfdecd1da216 (WR PR #3251). r=kats
https://github.com/servo/webrender/pull/3251 Differential Revision: https://phabricator.services.mozilla.com/D16005 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
271033048d
commit
44eff8f1b7
@ -1 +1 @@
|
||||
9019124fdccab50096ef5af76d1acbd251c1ad07
|
||||
e16ab884672151fbdebc149479f9bfdecd1da216
|
||||
|
@ -142,12 +142,21 @@ impl Rectangle {
|
||||
api::BorderRadius::uniform(20.),
|
||||
api::ClipMode::Clip
|
||||
);
|
||||
let clip_id = builder.define_clip(rect, vec![region], None);
|
||||
builder.push_clip_id(clip_id);
|
||||
let clip_id = builder.define_clip(
|
||||
&api::SpaceAndClipInfo::root_scroll(pipeline_id),
|
||||
rect,
|
||||
vec![region],
|
||||
None,
|
||||
);
|
||||
|
||||
builder.push_rect(&api::PrimitiveInfo::new(rect), self.color);
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.push_rect(
|
||||
&api::PrimitiveInfo::new(rect),
|
||||
&api::SpaceAndClipInfo {
|
||||
spatial_id: api::SpatialId::root_scroll_node(pipeline_id),
|
||||
clip_id,
|
||||
},
|
||||
self.color,
|
||||
);
|
||||
|
||||
let mut transaction = api::Transaction::new();
|
||||
transaction.set_display_list(
|
||||
|
@ -26,14 +26,16 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = (0, 0).to(1920, 1080);
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -42,7 +44,7 @@ impl Example for App {
|
||||
);
|
||||
|
||||
for _ in 0 .. self.rect_count {
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 0.05));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 0.05));
|
||||
}
|
||||
|
||||
builder.pop_stacking_context();
|
||||
|
@ -40,6 +40,7 @@ impl App {
|
||||
bounds: LayoutRect,
|
||||
color: ColorF,
|
||||
builder: &mut DisplayListBuilder,
|
||||
pipeline_id: PipelineId,
|
||||
property_key: PropertyBindingKey<LayoutTransform>,
|
||||
opacity_key: Option<PropertyBindingKey<f32>>,
|
||||
) {
|
||||
@ -54,17 +55,17 @@ impl App {
|
||||
}
|
||||
};
|
||||
|
||||
let reference_frame_id = builder.push_reference_frame(
|
||||
let spatial_id = builder.push_reference_frame(
|
||||
&LayoutRect::new(bounds.origin, LayoutSize::zero()),
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
TransformStyle::Flat,
|
||||
Some(PropertyBinding::Binding(property_key, LayoutTransform::identity())),
|
||||
None,
|
||||
);
|
||||
|
||||
builder.push_clip_id(reference_frame_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new(LayoutRect::zero()),
|
||||
spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -72,26 +73,29 @@ impl App {
|
||||
RasterSpace::Screen,
|
||||
);
|
||||
|
||||
let space_and_clip = SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id: ClipId::root(pipeline_id),
|
||||
};
|
||||
let clip_bounds = LayoutRect::new(LayoutPoint::zero(), bounds.size);
|
||||
let complex_clip = ComplexClipRegion {
|
||||
rect: clip_bounds,
|
||||
radii: BorderRadius::uniform(30.0),
|
||||
mode: ClipMode::Clip,
|
||||
};
|
||||
let clip_id = builder.define_clip(clip_bounds, vec![complex_clip], None);
|
||||
builder.push_clip_id(clip_id);
|
||||
let clip_id = builder.define_clip(&space_and_clip, clip_bounds, vec![complex_clip], None);
|
||||
|
||||
// Fill it with a white rect
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new(LayoutRect::new(LayoutPoint::zero(), bounds.size)),
|
||||
&SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id,
|
||||
},
|
||||
color,
|
||||
);
|
||||
|
||||
builder.pop_clip_id();
|
||||
|
||||
builder.pop_stacking_context();
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
@ -106,22 +110,22 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let opacity_key = self.opacity_key;
|
||||
|
||||
let bounds = (150, 150).to(250, 250);
|
||||
let key0 = self.property_key0;
|
||||
self.add_rounded_rect(bounds, ColorF::new(1.0, 0.0, 0.0, 0.5), builder, key0, Some(opacity_key));
|
||||
self.add_rounded_rect(bounds, ColorF::new(1.0, 0.0, 0.0, 0.5), builder, pipeline_id, key0, Some(opacity_key));
|
||||
|
||||
let bounds = (400, 400).to(600, 600);
|
||||
let key1 = self.property_key1;
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 1.0, 0.0, 0.5), builder, key1, None);
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 1.0, 0.0, 0.5), builder, pipeline_id, key1, None);
|
||||
|
||||
let bounds = (200, 500).to(350, 580);
|
||||
let key2 = self.property_key2;
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 0.0, 1.0, 0.5), builder, key2, None);
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 0.0, 1.0, 0.5), builder, pipeline_id, key2, None);
|
||||
}
|
||||
|
||||
fn on_event(&mut self, win_event: winit::WindowEvent, api: &RenderApi, document_id: DocumentId) -> bool {
|
||||
|
@ -186,13 +186,17 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
let spatial_id = root_space_and_clip.spatial_id;
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -217,14 +221,19 @@ impl Example for App {
|
||||
BorderRadius::uniform(20.0),
|
||||
ClipMode::Clip
|
||||
);
|
||||
let id = builder.define_clip(bounds, vec![complex], Some(mask));
|
||||
builder.push_clip_id(id);
|
||||
let clip_id = builder.define_clip(&root_space_and_clip, bounds, vec![complex], Some(mask));
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new((100, 100).to(200, 200)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((250, 100).to(350, 200));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new((250, 100).to(350, 200)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
let border_side = BorderSide {
|
||||
color: ColorF::new(0.0, 0.0, 1.0, 1.0),
|
||||
style: BorderStyle::Groove,
|
||||
@ -239,9 +248,12 @@ impl Example for App {
|
||||
do_aa: true,
|
||||
});
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
|
||||
builder.push_border(&info, border_widths, border_details);
|
||||
builder.pop_clip_id();
|
||||
builder.push_border(
|
||||
&LayoutPrimitiveInfo::new((100, 100).to(200, 200)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
border_widths,
|
||||
border_details,
|
||||
);
|
||||
|
||||
if false {
|
||||
// draw box shadow?
|
||||
@ -253,10 +265,10 @@ impl Example for App {
|
||||
let spread_radius = 0.0;
|
||||
let simple_border_radius = 8.0;
|
||||
let box_shadow_type = BoxShadowClipMode::Inset;
|
||||
let info = LayoutPrimitiveInfo::with_clip_rect(rect, bounds);
|
||||
|
||||
builder.push_box_shadow(
|
||||
&info,
|
||||
&LayoutPrimitiveInfo::with_clip_rect(rect, bounds),
|
||||
&root_space_and_clip,
|
||||
simple_box_bounds,
|
||||
offset,
|
||||
color,
|
||||
|
@ -17,7 +17,7 @@ use rayon::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use webrender::api::{self, DisplayListBuilder, DocumentId, PipelineId, RenderApi, Transaction};
|
||||
use webrender::api::ColorF;
|
||||
use webrender::api::{ColorF, SpaceAndClipInfo};
|
||||
use webrender::euclid::size2;
|
||||
|
||||
// This example shows how to implement a very basic BlobImageHandler that can only render
|
||||
@ -200,7 +200,7 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: api::DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let blob_img1 = api.generate_blob_image_key();
|
||||
@ -220,9 +220,11 @@ impl Example for App {
|
||||
);
|
||||
|
||||
let bounds = api::LayoutRect::new(api::LayoutPoint::zero(), builder.content_size());
|
||||
let info = api::LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
&api::LayoutPrimitiveInfo::new(bounds),
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
api::TransformStyle::Flat,
|
||||
api::MixBlendMode::Normal,
|
||||
@ -230,9 +232,9 @@ impl Example for App {
|
||||
api::RasterSpace::Screen,
|
||||
);
|
||||
|
||||
let info = api::LayoutPrimitiveInfo::new((30, 30).by(500, 500));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&api::LayoutPrimitiveInfo::new((30, 30).by(500, 500)),
|
||||
&space_and_clip,
|
||||
api::LayoutSize::new(500.0, 500.0),
|
||||
api::LayoutSize::new(0.0, 0.0),
|
||||
api::ImageRendering::Auto,
|
||||
@ -241,9 +243,9 @@ impl Example for App {
|
||||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
let info = api::LayoutPrimitiveInfo::new((600, 600).by(200, 200));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&api::LayoutPrimitiveInfo::new((600, 600).by(200, 200)),
|
||||
&space_and_clip,
|
||||
api::LayoutSize::new(200.0, 200.0),
|
||||
api::LayoutSize::new(0.0, 0.0),
|
||||
api::ImageRendering::Auto,
|
||||
|
@ -90,7 +90,7 @@ impl Example for App {
|
||||
base_builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
framebuffer_size: DeviceIntSize,
|
||||
_: PipelineId,
|
||||
_pipeline_id: PipelineId,
|
||||
_: DocumentId,
|
||||
) {
|
||||
if self.documents.is_empty() {
|
||||
@ -102,6 +102,7 @@ impl Example for App {
|
||||
}
|
||||
|
||||
for doc in &self.documents {
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(doc.pipeline_id);
|
||||
let mut builder = DisplayListBuilder::new(
|
||||
doc.pipeline_id,
|
||||
doc.content_rect.size,
|
||||
@ -113,6 +114,7 @@ impl Example for App {
|
||||
|
||||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new(doc.content_rect),
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -121,6 +123,7 @@ impl Example for App {
|
||||
);
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new(local_rect),
|
||||
&space_and_clip,
|
||||
doc.color,
|
||||
);
|
||||
builder.pop_stacking_context();
|
||||
|
@ -107,6 +107,7 @@ impl App {
|
||||
);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(document.content_rect);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
let mut builder = DisplayListBuilder::new(
|
||||
document.pipeline_id,
|
||||
document.content_rect.size,
|
||||
@ -114,6 +115,7 @@ impl App {
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -121,7 +123,7 @@ impl App {
|
||||
RasterSpace::Screen,
|
||||
);
|
||||
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 0.0, 1.0));
|
||||
builder.pop_stacking_context();
|
||||
|
||||
txn.set_root_pipeline(pipeline_id);
|
||||
@ -145,7 +147,7 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
if self.output_document.is_none() {
|
||||
@ -155,8 +157,11 @@ impl Example for App {
|
||||
}
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -166,6 +171,7 @@ impl Example for App {
|
||||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
info.rect.size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
|
@ -35,10 +35,12 @@ impl Example for App {
|
||||
|
||||
let sub_pipeline_id = PipelineId(pipeline_id.0, 42);
|
||||
let mut sub_builder = DisplayListBuilder::new(sub_pipeline_id, sub_bounds.size);
|
||||
let mut space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(sub_bounds);
|
||||
sub_builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -47,7 +49,7 @@ impl Example for App {
|
||||
);
|
||||
|
||||
// green rect visible == success
|
||||
sub_builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
sub_builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
sub_builder.pop_stacking_context();
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
@ -60,19 +62,19 @@ impl Example for App {
|
||||
);
|
||||
api.send_transaction(document_id, txn);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(sub_bounds);
|
||||
let reference_frame_id = builder.push_reference_frame(
|
||||
space_and_clip.spatial_id = builder.push_reference_frame(
|
||||
&sub_bounds,
|
||||
space_and_clip.spatial_id,
|
||||
TransformStyle::Flat,
|
||||
Some(PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity())),
|
||||
None,
|
||||
);
|
||||
builder.push_clip_id(reference_frame_id);
|
||||
|
||||
|
||||
// And this is for the root pipeline
|
||||
let info = LayoutPrimitiveInfo::new(sub_bounds);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -80,11 +82,9 @@ impl Example for App {
|
||||
RasterSpace::Screen,
|
||||
);
|
||||
// red rect under the iframe: if this is visible, things have gone wrong
|
||||
builder.push_rect(&info, ColorF::new(1.0, 0.0, 0.0, 1.0));
|
||||
builder.push_iframe(&info, sub_pipeline_id, false);
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 0.0, 0.0, 1.0));
|
||||
builder.push_iframe(&info, &space_and_clip, sub_pipeline_id, false);
|
||||
builder.pop_stacking_context();
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let (image_descriptor, image_data) = image_helper::make_checkerboard(32, 32);
|
||||
@ -39,8 +39,11 @@ impl Example for App {
|
||||
|
||||
let bounds = (0, 0).to(512, 512);
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -56,6 +59,7 @@ impl Example for App {
|
||||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
@ -70,6 +74,7 @@ impl Example for App {
|
||||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Pixelated,
|
||||
|
@ -187,11 +187,13 @@ impl Window {
|
||||
let layout_size = framebuffer_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
|
||||
let mut txn = Transaction::new();
|
||||
let mut builder = DisplayListBuilder::new(self.pipeline_id, layout_size);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
|
||||
|
||||
let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -203,7 +205,7 @@ impl Window {
|
||||
LayoutPoint::new(100.0, 100.0),
|
||||
LayoutSize::new(100.0, 200.0)
|
||||
));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
|
||||
let text_bounds = LayoutRect::new(
|
||||
LayoutPoint::new(100.0, 50.0),
|
||||
@ -263,6 +265,7 @@ impl Window {
|
||||
let info = LayoutPrimitiveInfo::new(text_bounds);
|
||||
builder.push_text(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
&glyphs,
|
||||
self.font_instance_key,
|
||||
ColorF::new(1.0, 1.0, 0.0, 1.0),
|
||||
|
@ -27,14 +27,16 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let info = LayoutPrimitiveInfo::new(
|
||||
LayoutRect::new(LayoutPoint::zero(), builder.content_size())
|
||||
);
|
||||
let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
root_space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -48,6 +50,7 @@ impl Example for App {
|
||||
let scrollbox = (0, 0).to(300, 400);
|
||||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new((10, 10).by(0, 0)),
|
||||
root_space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -55,7 +58,8 @@ impl Example for App {
|
||||
RasterSpace::Screen,
|
||||
);
|
||||
// set the scrolling clip
|
||||
let clip_id = builder.define_scroll_frame(
|
||||
let space_and_clip1 = builder.define_scroll_frame(
|
||||
&root_space_and_clip,
|
||||
None,
|
||||
(0, 0).by(1000, 1000),
|
||||
scrollbox,
|
||||
@ -63,30 +67,30 @@ impl Example for App {
|
||||
None,
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
);
|
||||
builder.push_clip_id(clip_id);
|
||||
|
||||
// now put some content into it.
|
||||
// start with a white background
|
||||
let mut info = LayoutPrimitiveInfo::new((0, 0).to(1000, 1000));
|
||||
info.tag = Some((0, 1));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip1, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
// let's make a 50x50 blue square as a visual reference
|
||||
let mut info = LayoutPrimitiveInfo::new((0, 0).to(50, 50));
|
||||
info.tag = Some((0, 2));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip1, ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
|
||||
// and a 50x50 green square next to it with an offset clip
|
||||
// to see what that looks like
|
||||
let mut info =
|
||||
LayoutPrimitiveInfo::with_clip_rect((50, 0).to(100, 50), (60, 10).to(110, 60));
|
||||
info.tag = Some((0, 3));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip1, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
|
||||
// Below the above rectangles, set up a nested scrollbox. It's still in
|
||||
// the same stacking context, so note that the rects passed in need to
|
||||
// be relative to the stacking context.
|
||||
let nested_clip_id = builder.define_scroll_frame(
|
||||
let space_and_clip2 = builder.define_scroll_frame(
|
||||
&space_and_clip1,
|
||||
None,
|
||||
(0, 100).to(300, 1000),
|
||||
(0, 100).to(200, 300),
|
||||
@ -94,25 +98,25 @@ impl Example for App {
|
||||
None,
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
);
|
||||
builder.push_clip_id(nested_clip_id);
|
||||
|
||||
// give it a giant gray background just to distinguish it and to easily
|
||||
// visually identify the nested scrollbox
|
||||
let mut info = LayoutPrimitiveInfo::new((-1000, -1000).to(5000, 5000));
|
||||
info.tag = Some((0, 4));
|
||||
builder.push_rect(&info, ColorF::new(0.5, 0.5, 0.5, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip2, ColorF::new(0.5, 0.5, 0.5, 1.0));
|
||||
|
||||
// add a teal square to visualize the scrolling/clipping behaviour
|
||||
// as you scroll the nested scrollbox
|
||||
let mut info = LayoutPrimitiveInfo::new((0, 200).to(50, 250));
|
||||
info.tag = Some((0, 5));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip2, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
|
||||
// Add a sticky frame. It will "stick" twice while scrolling, once
|
||||
// at a margin of 10px from the bottom, for 40 pixels of scrolling,
|
||||
// and once at a margin of 10px from the top, for 60 pixels of
|
||||
// scrolling.
|
||||
let sticky_id = builder.define_sticky_frame(
|
||||
space_and_clip2.spatial_id,
|
||||
(50, 350).by(50, 50),
|
||||
SideOffsets2D::new(Some(10.0), None, Some(10.0), None),
|
||||
StickyOffsetBounds::new(-40.0, 60.0),
|
||||
@ -120,21 +124,23 @@ impl Example for App {
|
||||
LayoutVector2D::new(0.0, 0.0)
|
||||
);
|
||||
|
||||
builder.push_clip_id(sticky_id);
|
||||
let mut info = LayoutPrimitiveInfo::new((50, 350).by(50, 50));
|
||||
info.tag = Some((0, 6));
|
||||
builder.push_rect(&info, ColorF::new(0.5, 0.5, 1.0, 1.0));
|
||||
builder.pop_clip_id(); // sticky_id
|
||||
builder.push_rect(
|
||||
&info,
|
||||
&SpaceAndClipInfo {
|
||||
spatial_id: sticky_id,
|
||||
clip_id: space_and_clip2.clip_id,
|
||||
},
|
||||
ColorF::new(0.5, 0.5, 1.0, 1.0),
|
||||
);
|
||||
|
||||
// just for good measure add another teal square further down and to
|
||||
// the right, which can be scrolled into view by the user
|
||||
let mut info = LayoutPrimitiveInfo::new((250, 350).to(300, 400));
|
||||
info.tag = Some((0, 7));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip2, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
|
||||
builder.pop_clip_id(); // nested_clip_id
|
||||
|
||||
builder.pop_clip_id(); // clip_id
|
||||
builder.pop_stacking_context();
|
||||
}
|
||||
|
||||
|
@ -91,13 +91,16 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = (0, 0).to(512, 512);
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -146,6 +149,7 @@ impl Example for App {
|
||||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
@ -163,6 +167,7 @@ impl Example for App {
|
||||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
@ -180,6 +185,7 @@ impl Example for App {
|
||||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
|
@ -88,13 +88,16 @@ impl Example for App {
|
||||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
@ -161,6 +164,7 @@ impl Example for App {
|
||||
);
|
||||
builder.push_yuv_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
YuvData::NV12(yuv_chanel1, yuv_chanel2),
|
||||
ColorDepth::Color8,
|
||||
YuvColorSpace::Rec601,
|
||||
@ -173,6 +177,7 @@ impl Example for App {
|
||||
);
|
||||
builder.push_yuv_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
YuvData::PlanarYCbCr(yuv_chanel1, yuv_chanel2_1, yuv_chanel3),
|
||||
ColorDepth::Color8,
|
||||
YuvColorSpace::Rec601,
|
||||
|
@ -108,7 +108,7 @@ performance impacts on WebRender.
|
||||
# Clipping and Positioning in the Display List
|
||||
|
||||
Each non-structural WebRender display list item has
|
||||
* A `ClipId` of a `SpatialNode` or `ClipNode` for positioning
|
||||
* A `SpatialId` of a `SpatialNode` for positioning
|
||||
* A `ClipId` of a `ClipNode` or a `ClipChain` for clipping
|
||||
* An item-specific rectangular clip rectangle
|
||||
|
||||
@ -120,28 +120,13 @@ independent of how the node is positioned and items can be clipped by any
|
||||
the item-specific clipping rectangle is applied directly to the item and should
|
||||
never result in the creation of a clip mask itself.
|
||||
|
||||
Perhaps the most inconvenient holdover from the previous single-tree
|
||||
hierarchical design is that `SpatialNodes`, `ClipNodes`, and `ClipChains` all
|
||||
share a single `ClipId` id type. This means that the client must be a bit
|
||||
careful when using the API. For instance, when specifying the parent of
|
||||
`ClipNode` one can use the `ClipId` or another `ClipNode` or a `SpatialNode`,
|
||||
but not one for a `ClipChain`.
|
||||
|
||||
WebRender's internal representation of clipping and positioning is not a perfect
|
||||
match to the display list representation of these concepts. This is due, again,
|
||||
to the evolutionary nature of the design. The general trend is that the display
|
||||
list gradually moves toward the internal representation. The most important of
|
||||
these incongruities is that while `ClipNodes`, sticky frames, and scroll frames
|
||||
are defined and simply return a `ClipId`, reference frames return a `ClipId` and
|
||||
also are pushed and popped like stacking contexts.
|
||||
|
||||
## Converting `ClipId` to global `ClipScrollTree` indices
|
||||
## Converting user-exposed `ClipId`/`SpatialId` to internal indices
|
||||
|
||||
WebRender must access `ClipNodes` and `SpatialNodes` quite a bit when building
|
||||
scenes and frames, so it tries to convert `ClipIds`, which are already
|
||||
scenes and frames, so it tries to convert `ClipId`/`SpatialId`, which are already
|
||||
per-pipeline indices, to global scene-wide indices. Internally this is a
|
||||
conversion from `ClipId` into `SpatialNodeIndex` or
|
||||
`ClipChainIndex`. In order to make this conversion cheaper, the
|
||||
conversion from `ClipId` into `ClipNodeIndex` or `ClipChainIndex`, and from
|
||||
`SpatialId` into `SpatialNodeIndex`. In order to make this conversion cheaper, the
|
||||
`DisplayListFlattner` assigns offsets for each pipeline and node type in the
|
||||
scene-wide `ClipScrollTree`.
|
||||
|
||||
@ -160,8 +145,7 @@ structure copies information necessary for hit testing from the
|
||||
new `ClipScrollTree` is under construction.
|
||||
|
||||
# Ideas for the Future
|
||||
1. Expose the difference between ids for `SpatialNodes`, `ClipNodes`, and
|
||||
`ClipChains` in the API.
|
||||
1. Expose the difference between `ClipId` and `ClipChainId` in the API.
|
||||
2. Prevent having to duplicate the `ClipScrollTree` for hit testing.
|
||||
3. Avoid having to create placeholder nodes in the `ClipScrollTree` while
|
||||
processing iframes.
|
||||
|
@ -204,6 +204,7 @@ pub struct ClipChainId(pub u32);
|
||||
// node, a bounds error will occur.
|
||||
impl ClipChainId {
|
||||
pub const NONE: Self = ClipChainId(u32::MAX);
|
||||
pub const INVALID: Self = ClipChainId(0xDEADBEEF);
|
||||
}
|
||||
|
||||
// A clip chain node is an id for a range of clip sources,
|
||||
|
@ -3,8 +3,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ExternalScrollId, LayoutPoint, LayoutRect, LayoutVector2D};
|
||||
use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation};
|
||||
use api::{TransformStyle, LayoutSize, LayoutTransform, PropertyBinding, ScrollSensitivity, WorldPoint};
|
||||
use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation, ScrollSensitivity};
|
||||
use api::{LayoutSize, LayoutTransform, PropertyBinding, TransformStyle, WorldPoint};
|
||||
use gpu_types::TransformPalette;
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use print_tree::{PrintTree, PrintTreePrinter};
|
||||
@ -46,6 +46,7 @@ impl CoordinateSystem {
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct SpatialNodeIndex(pub u32);
|
||||
|
||||
//Note: these have to match ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
pub const ROOT_SPATIAL_NODE_INDEX: SpatialNodeIndex = SpatialNodeIndex(0);
|
||||
const TOPMOST_SCROLL_NODE_INDEX: SpatialNodeIndex = SpatialNodeIndex(1);
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, ClipAndScrollInfo};
|
||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter};
|
||||
use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{DisplayItemRef, ExtendMode, ExternalScrollId, AuHelpers};
|
||||
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, GradientStop};
|
||||
@ -10,7 +10,7 @@ use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, C
|
||||
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
|
||||
use api::{PropertyBinding, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use api::{Shadow, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{ClipMode, TransformStyle, YuvColorSpace, YuvData};
|
||||
use app_units::Au;
|
||||
use clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore};
|
||||
@ -49,7 +49,7 @@ struct ClipNode {
|
||||
}
|
||||
|
||||
impl ClipNode {
|
||||
fn new(id: ClipChainId, count: usize) -> ClipNode {
|
||||
fn new(id: ClipChainId, count: usize) -> Self {
|
||||
ClipNode {
|
||||
id,
|
||||
count,
|
||||
@ -57,16 +57,16 @@ impl ClipNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// A data structure that keeps track of mapping between API ClipIds and the indices used
|
||||
/// internally in the ClipScrollTree to avoid having to do HashMap lookups. ClipIdToIndexMapper is
|
||||
/// responsible for mapping both ClipId to ClipChainIndex and ClipId to SpatialNodeIndex.
|
||||
/// A data structure that keeps track of mapping between API Ids for clips/spatials and the indices
|
||||
/// used internally in the ClipScrollTree to avoid having to do HashMap lookups. NodeIdToIndexMapper
|
||||
/// is responsible for mapping both ClipId to ClipChainIndex and SpatialId to SpatialNodeIndex.
|
||||
#[derive(Default)]
|
||||
pub struct ClipIdToIndexMapper {
|
||||
pub struct NodeIdToIndexMapper {
|
||||
clip_node_map: FastHashMap<ClipId, ClipNode>,
|
||||
spatial_node_map: FastHashMap<ClipId, SpatialNodeIndex>,
|
||||
spatial_node_map: FastHashMap<SpatialId, SpatialNodeIndex>,
|
||||
}
|
||||
|
||||
impl ClipIdToIndexMapper {
|
||||
impl NodeIdToIndexMapper {
|
||||
pub fn add_clip_chain(
|
||||
&mut self,
|
||||
id: ClipId,
|
||||
@ -77,16 +77,7 @@ impl ClipIdToIndexMapper {
|
||||
debug_assert!(_old_value.is_none());
|
||||
}
|
||||
|
||||
pub fn map_to_parent_clip_chain(
|
||||
&mut self,
|
||||
id: ClipId,
|
||||
parent_id: &ClipId,
|
||||
) {
|
||||
let parent_node = self.clip_node_map[parent_id];
|
||||
self.add_clip_chain(id, parent_node.id, parent_node.count);
|
||||
}
|
||||
|
||||
pub fn map_spatial_node(&mut self, id: ClipId, index: SpatialNodeIndex) {
|
||||
pub fn map_spatial_node(&mut self, id: SpatialId, index: SpatialNodeIndex) {
|
||||
let _old_value = self.spatial_node_map.insert(id, index);
|
||||
debug_assert!(_old_value.is_none());
|
||||
}
|
||||
@ -95,18 +86,12 @@ impl ClipIdToIndexMapper {
|
||||
self.clip_node_map[id]
|
||||
}
|
||||
|
||||
pub fn get_clip_chain_id(&self, id: &ClipId) -> ClipChainId {
|
||||
self.clip_node_map[id].id
|
||||
pub fn get_clip_chain_id(&self, id: ClipId) -> ClipChainId {
|
||||
self.clip_node_map[&id].id
|
||||
}
|
||||
|
||||
pub fn get_spatial_node_index(&self, id: ClipId) -> SpatialNodeIndex {
|
||||
match id {
|
||||
ClipId::Clip(..) |
|
||||
ClipId::Spatial(..) => {
|
||||
self.spatial_node_map[&id]
|
||||
}
|
||||
ClipId::ClipChain(_) => panic!("Tried to use ClipChain as scroll node."),
|
||||
}
|
||||
pub fn get_spatial_node_index(&self, id: SpatialId) -> SpatialNodeIndex {
|
||||
self.spatial_node_map[&id]
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,9 +112,9 @@ pub struct DisplayListFlattener<'a> {
|
||||
/// output textures.
|
||||
output_pipelines: &'a FastHashSet<PipelineId>,
|
||||
|
||||
/// The data structure that converting between ClipId and the various index
|
||||
/// types that the ClipScrollTree uses.
|
||||
id_to_index_mapper: ClipIdToIndexMapper,
|
||||
/// The data structure that converting between ClipId/SpatialId and the various
|
||||
/// index types that the ClipScrollTree uses.
|
||||
id_to_index_mapper: NodeIdToIndexMapper,
|
||||
|
||||
/// A stack of stacking context properties.
|
||||
sc_stack: Vec<FlattenedStackingContext>,
|
||||
@ -188,7 +173,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
font_instances,
|
||||
config: *frame_builder_config,
|
||||
output_pipelines,
|
||||
id_to_index_mapper: ClipIdToIndexMapper::default(),
|
||||
id_to_index_mapper: NodeIdToIndexMapper::default(),
|
||||
hit_testing_runs: Vec::new(),
|
||||
pending_shadow_items: VecDeque::new(),
|
||||
sc_stack: Vec::new(),
|
||||
@ -453,11 +438,6 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
frame_size: &LayoutSize,
|
||||
) {
|
||||
let pipeline_id = pipeline.pipeline_id;
|
||||
let reference_frame_info = self.simple_scroll_and_clip_chain(
|
||||
&ClipId::root_reference_frame(pipeline_id),
|
||||
);
|
||||
|
||||
let root_scroll_node = ClipId::root_scroll_node(pipeline_id);
|
||||
|
||||
self.push_stacking_context(
|
||||
pipeline_id,
|
||||
@ -465,8 +445,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
TransformStyle::Flat,
|
||||
true,
|
||||
true,
|
||||
root_scroll_node,
|
||||
None,
|
||||
ROOT_SPATIAL_NODE_INDEX,
|
||||
ClipChainId::NONE,
|
||||
RasterSpace::Screen,
|
||||
);
|
||||
|
||||
@ -477,6 +457,10 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
if self.scene.root_pipeline_id != Some(pipeline_id) {
|
||||
if let Some(pipeline) = self.scene.pipelines.get(&pipeline_id) {
|
||||
if let Some(bg_color) = pipeline.background_color {
|
||||
let reference_frame_info = ScrollNodeAndClipChain::new(
|
||||
self.id_to_index_mapper.get_spatial_node_index(SpatialId::root_reference_frame(pipeline_id)),
|
||||
ClipChainId::NONE,
|
||||
);
|
||||
let root_bounds = LayoutRect::new(LayoutPoint::zero(), *frame_size);
|
||||
let info = LayoutPrimitiveInfo::new(root_bounds);
|
||||
self.add_solid_rectangle(
|
||||
@ -488,7 +472,11 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
self.flatten_items(&mut pipeline.display_list.iter(), pipeline_id, LayoutVector2D::zero());
|
||||
self.flatten_items(
|
||||
&mut pipeline.display_list.iter(),
|
||||
pipeline_id,
|
||||
LayoutVector2D::zero(),
|
||||
);
|
||||
|
||||
self.pop_stacking_context();
|
||||
}
|
||||
@ -506,12 +494,10 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
None => break,
|
||||
};
|
||||
|
||||
if SpecificDisplayItem::PopReferenceFrame == *item.item() {
|
||||
return;
|
||||
}
|
||||
|
||||
if SpecificDisplayItem::PopStackingContext == *item.item() {
|
||||
return;
|
||||
match item.item() {
|
||||
SpecificDisplayItem::PopReferenceFrame |
|
||||
SpecificDisplayItem::PopStackingContext => return,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.flatten_item(
|
||||
@ -533,8 +519,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
&mut self,
|
||||
item: &DisplayItemRef,
|
||||
info: &StickyFrameDisplayItem,
|
||||
clip_and_scroll: &ScrollNodeAndClipChain,
|
||||
parent_id: &ClipId,
|
||||
parent_node_index: SpatialNodeIndex,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) {
|
||||
let frame_rect = item.rect().translate(reference_frame_relative_offset);
|
||||
@ -547,20 +532,19 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
);
|
||||
|
||||
let index = self.clip_scroll_tree.add_sticky_frame(
|
||||
clip_and_scroll.spatial_node_index, /* parent id */
|
||||
parent_node_index,
|
||||
sticky_frame_info,
|
||||
info.id.pipeline_id(),
|
||||
);
|
||||
self.id_to_index_mapper.map_spatial_node(info.id, index);
|
||||
self.id_to_index_mapper.map_to_parent_clip_chain(info.id, parent_id);
|
||||
}
|
||||
|
||||
fn flatten_scroll_frame(
|
||||
&mut self,
|
||||
item: &DisplayItemRef,
|
||||
info: &ScrollFrameDisplayItem,
|
||||
parent_node_index: SpatialNodeIndex,
|
||||
pipeline_id: PipelineId,
|
||||
clip_and_scroll_ids: &ClipAndScrollInfo,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) {
|
||||
let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0);
|
||||
@ -574,20 +558,18 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
// This is useful when calculating scroll extents for the
|
||||
// SpatialNode::scroll(..) API as well as for properly setting sticky
|
||||
// positioning offsets.
|
||||
let frame_rect = item.clip_rect().translate(reference_frame_relative_offset);
|
||||
let content_rect = item.rect().translate(reference_frame_relative_offset);
|
||||
let frame_rect = clip_region.main.translate(reference_frame_relative_offset);
|
||||
let content_size = item.rect().size;
|
||||
|
||||
debug_assert!(info.clip_id != info.scroll_frame_id);
|
||||
|
||||
self.add_clip_node(info.clip_id, clip_and_scroll_ids, clip_region);
|
||||
self.add_clip_node(info.clip_id, item.space_and_clip_info(), clip_region);
|
||||
|
||||
self.add_scroll_frame(
|
||||
info.scroll_frame_id,
|
||||
info.clip_id,
|
||||
parent_node_index,
|
||||
info.external_id,
|
||||
pipeline_id,
|
||||
&frame_rect,
|
||||
&content_rect.size,
|
||||
&content_size,
|
||||
info.scroll_sensitivity,
|
||||
ScrollFrameKind::Explicit,
|
||||
);
|
||||
@ -597,33 +579,34 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
&mut self,
|
||||
traversal: &mut BuiltDisplayListIter<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
item: &DisplayItemRef,
|
||||
parent_spatial_node: SpatialNodeIndex,
|
||||
origin: LayoutPoint,
|
||||
reference_frame: &ReferenceFrame,
|
||||
clip_and_scroll_ids: &ClipAndScrollInfo,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
) {
|
||||
self.push_reference_frame(
|
||||
reference_frame.id,
|
||||
Some(clip_and_scroll_ids.scroll_node_id),
|
||||
clip_and_scroll_ids.clip_node_id,
|
||||
Some(parent_spatial_node),
|
||||
pipeline_id,
|
||||
reference_frame.transform_style,
|
||||
reference_frame.transform,
|
||||
reference_frame.perspective,
|
||||
reference_frame_relative_offset + item.rect().origin.to_vector(),
|
||||
reference_frame_relative_offset + origin.to_vector(),
|
||||
);
|
||||
|
||||
self.flatten_items(traversal, pipeline_id, LayoutVector2D::zero());
|
||||
}
|
||||
|
||||
|
||||
fn flatten_stacking_context(
|
||||
&mut self,
|
||||
traversal: &mut BuiltDisplayListIter<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
item: &DisplayItemRef,
|
||||
stacking_context: &StackingContext,
|
||||
scroll_node_id: ClipId,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
origin: LayoutPoint,
|
||||
filters: ItemRange<FilterOp>,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
is_backface_visible: bool,
|
||||
) {
|
||||
// Avoid doing unnecessary work for empty stacking contexts.
|
||||
@ -636,26 +619,31 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
// TODO(optimization?): self.traversal.display_list()
|
||||
let display_list = self.scene.get_display_list_for_pipeline(pipeline_id);
|
||||
CompositeOps::new(
|
||||
stacking_context.filter_ops_for_compositing(display_list, item.filters()),
|
||||
stacking_context.filter_ops_for_compositing(display_list, filters),
|
||||
stacking_context.mix_blend_mode_for_compositing(),
|
||||
)
|
||||
};
|
||||
|
||||
let clip_chain_id = match stacking_context.clip_id {
|
||||
Some(clip_id) => self.id_to_index_mapper.get_clip_chain_id(clip_id),
|
||||
None => ClipChainId::NONE,
|
||||
};
|
||||
|
||||
self.push_stacking_context(
|
||||
pipeline_id,
|
||||
composition_operations,
|
||||
stacking_context.transform_style,
|
||||
is_backface_visible,
|
||||
false,
|
||||
scroll_node_id,
|
||||
stacking_context.clip_node_id,
|
||||
spatial_node_index,
|
||||
clip_chain_id,
|
||||
stacking_context.raster_space,
|
||||
);
|
||||
|
||||
self.flatten_items(
|
||||
traversal,
|
||||
pipeline_id,
|
||||
reference_frame_relative_offset + item.rect().origin.to_vector(),
|
||||
*reference_frame_relative_offset + origin.to_vector(),
|
||||
);
|
||||
|
||||
self.pop_stacking_context();
|
||||
@ -665,7 +653,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
&mut self,
|
||||
item: &DisplayItemRef,
|
||||
info: &IframeDisplayItem,
|
||||
clip_and_scroll_ids: &ClipAndScrollInfo,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) {
|
||||
let iframe_pipeline_id = info.pipeline_id;
|
||||
@ -678,21 +666,20 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
};
|
||||
|
||||
let clip_chain_index = self.add_clip_node(
|
||||
info.clip_id,
|
||||
clip_and_scroll_ids,
|
||||
ClipId::root(iframe_pipeline_id),
|
||||
item.space_and_clip_info(),
|
||||
ClipRegion::create_for_clip_node_with_local_clip(
|
||||
item.clip_rect(),
|
||||
reference_frame_relative_offset
|
||||
reference_frame_relative_offset,
|
||||
),
|
||||
);
|
||||
self.pipeline_clip_chain_stack.push(clip_chain_index);
|
||||
|
||||
let bounds = item.rect();
|
||||
let origin = *reference_frame_relative_offset + bounds.origin.to_vector();
|
||||
self.push_reference_frame(
|
||||
ClipId::root_reference_frame(iframe_pipeline_id),
|
||||
Some(info.clip_id),
|
||||
None,
|
||||
let spatial_node_index = self.push_reference_frame(
|
||||
SpatialId::root_reference_frame(iframe_pipeline_id),
|
||||
Some(spatial_node_index),
|
||||
iframe_pipeline_id,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
@ -702,8 +689,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
|
||||
let iframe_rect = LayoutRect::new(LayoutPoint::zero(), bounds.size);
|
||||
self.add_scroll_frame(
|
||||
ClipId::root_scroll_node(iframe_pipeline_id),
|
||||
ClipId::root_reference_frame(iframe_pipeline_id),
|
||||
SpatialId::root_scroll_node(iframe_pipeline_id),
|
||||
spatial_node_index,
|
||||
Some(ExternalScrollId(0, iframe_pipeline_id)),
|
||||
iframe_pipeline_id,
|
||||
&iframe_rect,
|
||||
@ -726,10 +713,17 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
pipeline_id: PipelineId,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
) -> Option<BuiltDisplayListIter<'a>> {
|
||||
let clip_and_scroll_ids = item.clip_and_scroll();
|
||||
let clip_and_scroll = self.map_clip_and_scroll(&clip_and_scroll_ids);
|
||||
|
||||
let space_and_clip = item.space_and_clip_info();
|
||||
let clip_and_scroll = ScrollNodeAndClipChain::new(
|
||||
self.id_to_index_mapper.get_spatial_node_index(space_and_clip.spatial_id),
|
||||
if space_and_clip.clip_id.is_valid() {
|
||||
self.id_to_index_mapper.get_clip_chain_id(space_and_clip.clip_id)
|
||||
} else {
|
||||
ClipChainId::INVALID
|
||||
},
|
||||
);
|
||||
let prim_info = item.get_layout_primitive_info(&reference_frame_relative_offset);
|
||||
|
||||
match *item.item() {
|
||||
SpecificDisplayItem::Image(ref info) => {
|
||||
self.add_image(
|
||||
@ -861,10 +855,11 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
self.flatten_stacking_context(
|
||||
&mut subtraversal,
|
||||
pipeline_id,
|
||||
&item,
|
||||
&info.stacking_context,
|
||||
clip_and_scroll_ids.scroll_node_id,
|
||||
reference_frame_relative_offset,
|
||||
clip_and_scroll.spatial_node_index,
|
||||
item.rect().origin,
|
||||
item.filters(),
|
||||
&reference_frame_relative_offset,
|
||||
prim_info.is_backface_visible,
|
||||
);
|
||||
return Some(subtraversal);
|
||||
@ -874,20 +869,19 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
self.flatten_reference_frame(
|
||||
&mut subtraversal,
|
||||
pipeline_id,
|
||||
&item,
|
||||
clip_and_scroll.spatial_node_index,
|
||||
item.rect().origin,
|
||||
&info.reference_frame,
|
||||
&clip_and_scroll_ids,
|
||||
reference_frame_relative_offset,
|
||||
);
|
||||
return Some(subtraversal);
|
||||
|
||||
}
|
||||
SpecificDisplayItem::Iframe(ref info) => {
|
||||
self.flatten_iframe(
|
||||
&item,
|
||||
info,
|
||||
&clip_and_scroll_ids,
|
||||
&reference_frame_relative_offset
|
||||
clip_and_scroll.spatial_node_index,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
}
|
||||
SpecificDisplayItem::Clip(ref info) => {
|
||||
@ -898,7 +892,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
info.image_mask,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
self.add_clip_node(info.id, &clip_and_scroll_ids, clip_region);
|
||||
self.add_clip_node(info.id, space_and_clip, clip_region);
|
||||
}
|
||||
SpecificDisplayItem::ClipChain(ref info) => {
|
||||
// For a user defined clip-chain the parent (if specified) must
|
||||
@ -907,7 +901,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
// is used to provide a root clip chain for iframes.
|
||||
let mut parent_clip_chain_id = match info.parent {
|
||||
Some(id) => {
|
||||
self.id_to_index_mapper.get_clip_chain_id(&ClipId::ClipChain(id))
|
||||
self.id_to_index_mapper.get_clip_chain_id(ClipId::ClipChain(id))
|
||||
}
|
||||
None => {
|
||||
self.pipeline_clip_chain_stack.last().cloned().unwrap()
|
||||
@ -923,11 +917,11 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
let mut clip_chain_id = parent_clip_chain_id;
|
||||
|
||||
// For each specified clip id
|
||||
for item in self.get_clip_chain_items(pipeline_id, item.clip_chain_items()) {
|
||||
for clip_item in self.get_clip_chain_items(pipeline_id, item.clip_chain_items()) {
|
||||
// Map the ClipId to an existing clip chain node.
|
||||
let item_clip_node = self
|
||||
.id_to_index_mapper
|
||||
.get_clip_node(&item);
|
||||
.get_clip_node(&clip_item);
|
||||
|
||||
let mut clip_node_clip_chain_id = item_clip_node.id;
|
||||
|
||||
@ -973,25 +967,25 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
self.flatten_scroll_frame(
|
||||
&item,
|
||||
info,
|
||||
clip_and_scroll.spatial_node_index,
|
||||
pipeline_id,
|
||||
&clip_and_scroll_ids,
|
||||
&reference_frame_relative_offset
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
}
|
||||
SpecificDisplayItem::StickyFrame(ref info) => {
|
||||
self.flatten_sticky_frame(
|
||||
&item,
|
||||
info,
|
||||
&clip_and_scroll,
|
||||
&clip_and_scroll_ids.scroll_node_id,
|
||||
&reference_frame_relative_offset
|
||||
clip_and_scroll.spatial_node_index,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
}
|
||||
|
||||
// Do nothing; these are dummy items for the display list parser
|
||||
SpecificDisplayItem::SetGradientStops => {}
|
||||
|
||||
SpecificDisplayItem::PopStackingContext | SpecificDisplayItem::PopReferenceFrame => {
|
||||
SpecificDisplayItem::PopReferenceFrame |
|
||||
SpecificDisplayItem::PopStackingContext => {
|
||||
unreachable!("Should have returned in parent method.")
|
||||
}
|
||||
SpecificDisplayItem::PushShadow(shadow) => {
|
||||
@ -1030,13 +1024,12 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
.clip_interner
|
||||
.intern(&item, || ());
|
||||
|
||||
clip_chain_id = self.clip_store
|
||||
.add_clip_chain_node(
|
||||
handle,
|
||||
local_pos,
|
||||
spatial_node_index,
|
||||
clip_chain_id,
|
||||
);
|
||||
clip_chain_id = self.clip_store.add_clip_chain_node(
|
||||
handle,
|
||||
local_pos,
|
||||
spatial_node_index,
|
||||
clip_chain_id,
|
||||
);
|
||||
}
|
||||
|
||||
clip_chain_id
|
||||
@ -1218,16 +1211,10 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
transform_style: TransformStyle,
|
||||
is_backface_visible: bool,
|
||||
is_pipeline_root: bool,
|
||||
spatial_node: ClipId,
|
||||
clipping_node: Option<ClipId>,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
clip_chain_id: ClipChainId,
|
||||
requested_raster_space: RasterSpace,
|
||||
) {
|
||||
let spatial_node_index = self.id_to_index_mapper.get_spatial_node_index(spatial_node);
|
||||
let clip_chain_id = match clipping_node {
|
||||
Some(ref clipping_node) => self.id_to_index_mapper.get_clip_chain_id(clipping_node),
|
||||
None => ClipChainId::NONE,
|
||||
};
|
||||
|
||||
// Check if this stacking context is the root of a pipeline, and the caller
|
||||
// has requested it as an output frame.
|
||||
let frame_output_pipeline_id = if is_pipeline_root && self.output_pipelines.contains(&pipeline_id) {
|
||||
@ -1294,7 +1281,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
// has a clip node. In the future, we may decide during
|
||||
// prepare step to skip the intermediate surface if the
|
||||
// clip node doesn't affect the stacking context rect.
|
||||
let should_isolate = clipping_node.is_some();
|
||||
let should_isolate = clip_chain_id != ClipChainId::NONE;
|
||||
|
||||
// Push the SC onto the stack, so we know how to handle things in
|
||||
// pop_stacking_context.
|
||||
@ -1586,16 +1573,14 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
|
||||
pub fn push_reference_frame(
|
||||
&mut self,
|
||||
reference_frame_id: ClipId,
|
||||
parent_scroll_id: Option<ClipId>,
|
||||
parent_clip_id: Option<ClipId>,
|
||||
reference_frame_id: SpatialId,
|
||||
parent_index: Option<SpatialNodeIndex>,
|
||||
pipeline_id: PipelineId,
|
||||
transform_style: TransformStyle,
|
||||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
) -> SpatialNodeIndex {
|
||||
let parent_index = parent_scroll_id.map(|id| self.id_to_index_mapper.get_spatial_node_index(id));
|
||||
let index = self.clip_scroll_tree.add_reference_frame(
|
||||
parent_index,
|
||||
transform_style,
|
||||
@ -1606,11 +1591,6 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
);
|
||||
self.id_to_index_mapper.map_spatial_node(reference_frame_id, index);
|
||||
|
||||
match parent_clip_id.or(parent_scroll_id) {
|
||||
Some(ref parent_id) =>
|
||||
self.id_to_index_mapper.map_to_parent_clip_chain(reference_frame_id, parent_id),
|
||||
_ => self.id_to_index_mapper.add_clip_chain(reference_frame_id, ClipChainId::NONE, 0),
|
||||
}
|
||||
index
|
||||
}
|
||||
|
||||
@ -1625,9 +1605,10 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
register_prim_chase_id(id);
|
||||
}
|
||||
|
||||
self.push_reference_frame(
|
||||
ClipId::root_reference_frame(pipeline_id),
|
||||
None,
|
||||
self.id_to_index_mapper.add_clip_chain(ClipId::root(pipeline_id), ClipChainId::NONE, 0);
|
||||
|
||||
let spatial_node_index = self.push_reference_frame(
|
||||
SpatialId::root_reference_frame(pipeline_id),
|
||||
None,
|
||||
pipeline_id,
|
||||
TransformStyle::Flat,
|
||||
@ -1637,8 +1618,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
);
|
||||
|
||||
self.add_scroll_frame(
|
||||
ClipId::root_scroll_node(pipeline_id),
|
||||
ClipId::root_reference_frame(pipeline_id),
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
spatial_node_index,
|
||||
Some(ExternalScrollId(0, pipeline_id)),
|
||||
pipeline_id,
|
||||
&LayoutRect::new(LayoutPoint::zero(), *viewport_size),
|
||||
@ -1651,7 +1632,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
pub fn add_clip_node<I>(
|
||||
&mut self,
|
||||
new_node_id: ClipId,
|
||||
parent: &ClipAndScrollInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
clip_region: ClipRegion<I>,
|
||||
) -> ClipChainId
|
||||
where
|
||||
@ -1661,15 +1642,9 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
// and the positioning node associated with those clip sources.
|
||||
|
||||
// Map from parent ClipId to existing clip-chain.
|
||||
let mut parent_clip_chain_index = self
|
||||
.id_to_index_mapper
|
||||
.get_clip_chain_id(&parent.clip_node_id());
|
||||
let mut parent_clip_chain_index = self.id_to_index_mapper.get_clip_chain_id(space_and_clip.clip_id);
|
||||
// Map the ClipId for the positioning node to a spatial node index.
|
||||
let spatial_node = self.id_to_index_mapper.get_spatial_node_index(parent.scroll_node_id);
|
||||
|
||||
// Add a mapping for this ClipId in case it's referenced as a positioning node.
|
||||
self.id_to_index_mapper
|
||||
.map_spatial_node(new_node_id, spatial_node);
|
||||
let spatial_node = self.id_to_index_mapper.get_spatial_node_index(space_and_clip.spatial_id);
|
||||
|
||||
let mut clip_count = 0;
|
||||
|
||||
@ -1740,8 +1715,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
|
||||
pub fn add_scroll_frame(
|
||||
&mut self,
|
||||
new_node_id: ClipId,
|
||||
parent_id: ClipId,
|
||||
new_node_id: SpatialId,
|
||||
parent_node_index: SpatialNodeIndex,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
pipeline_id: PipelineId,
|
||||
frame_rect: &LayoutRect,
|
||||
@ -1749,7 +1724,6 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
frame_kind: ScrollFrameKind,
|
||||
) -> SpatialNodeIndex {
|
||||
let parent_node_index = self.id_to_index_mapper.get_spatial_node_index(parent_id);
|
||||
let node_index = self.clip_scroll_tree.add_scroll_frame(
|
||||
parent_node_index,
|
||||
external_id,
|
||||
@ -1760,7 +1734,6 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
frame_kind,
|
||||
);
|
||||
self.id_to_index_mapper.map_spatial_node(new_node_id, node_index);
|
||||
self.id_to_index_mapper.map_to_parent_clip_chain(new_node_id, &parent_id);
|
||||
node_index
|
||||
}
|
||||
|
||||
@ -2477,17 +2450,6 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn map_clip_and_scroll(&mut self, info: &ClipAndScrollInfo) -> ScrollNodeAndClipChain {
|
||||
ScrollNodeAndClipChain::new(
|
||||
self.id_to_index_mapper.get_spatial_node_index(info.scroll_node_id),
|
||||
self.id_to_index_mapper.get_clip_chain_id(&info.clip_node_id())
|
||||
)
|
||||
}
|
||||
|
||||
pub fn simple_scroll_and_clip_chain(&mut self, id: &ClipId) -> ScrollNodeAndClipChain {
|
||||
self.map_clip_and_scroll(&ClipAndScrollInfo::simple(*id))
|
||||
}
|
||||
|
||||
pub fn add_primitive_instance_to_3d_root(&mut self, instance: PrimitiveInstance) {
|
||||
// find the 3D root and append to the children list
|
||||
for sc in self.sc_stack.iter_mut().rev() {
|
||||
|
@ -1589,8 +1589,8 @@ impl ToDebugString for SpecificDisplayItem {
|
||||
SpecificDisplayItem::PopAllShadows => String::from("pop_all_shadows"),
|
||||
SpecificDisplayItem::PopReferenceFrame => String::from("pop_reference_frame"),
|
||||
SpecificDisplayItem::PopStackingContext => String::from("pop_stacking_context"),
|
||||
SpecificDisplayItem::PushReferenceFrame(..) => String::from("push_reference_frame"),
|
||||
SpecificDisplayItem::PushShadow(..) => String::from("push_shadow"),
|
||||
SpecificDisplayItem::PushReferenceFrame(..) => String::from("push_reference_frame"),
|
||||
SpecificDisplayItem::PushStackingContext(..) => String::from("push_stacking_context"),
|
||||
SpecificDisplayItem::RadialGradient(..) => String::from("radial_gradient"),
|
||||
SpecificDisplayItem::Rectangle(..) => String::from("rectangle"),
|
||||
|
@ -20,32 +20,6 @@ pub const MAX_BLUR_RADIUS: f32 = 300.;
|
||||
// a list of values nearby that this item consumes. The traversal
|
||||
// iterator should handle finding these.
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ClipAndScrollInfo {
|
||||
pub scroll_node_id: ClipId,
|
||||
pub clip_node_id: Option<ClipId>,
|
||||
}
|
||||
|
||||
impl ClipAndScrollInfo {
|
||||
pub fn simple(node_id: ClipId) -> ClipAndScrollInfo {
|
||||
ClipAndScrollInfo {
|
||||
scroll_node_id: node_id,
|
||||
clip_node_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(scroll_node_id: ClipId, clip_node_id: ClipId) -> ClipAndScrollInfo {
|
||||
ClipAndScrollInfo {
|
||||
scroll_node_id,
|
||||
clip_node_id: Some(clip_node_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clip_node_id(&self) -> ClipId {
|
||||
self.clip_node_id.unwrap_or(self.scroll_node_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// A tag that can be used to identify items during hit testing. If the tag
|
||||
/// is missing then the item doesn't take part in hit testing at all. This
|
||||
/// is composed of two numbers. In Servo, the first is an identifier while the
|
||||
@ -60,8 +34,8 @@ pub type ItemTag = (u64, u16);
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct GenericDisplayItem<T> {
|
||||
pub item: T,
|
||||
pub clip_and_scroll: ClipAndScrollInfo,
|
||||
pub layout: LayoutPrimitiveInfo,
|
||||
pub space_and_clip: SpaceAndClipInfo,
|
||||
}
|
||||
|
||||
pub type DisplayItem = GenericDisplayItem<SpecificDisplayItem>;
|
||||
@ -71,8 +45,8 @@ pub type DisplayItem = GenericDisplayItem<SpecificDisplayItem>;
|
||||
#[derive(Serialize)]
|
||||
pub struct SerializedDisplayItem<'a> {
|
||||
pub item: &'a SpecificDisplayItem,
|
||||
pub clip_and_scroll: &'a ClipAndScrollInfo,
|
||||
pub layout: &'a LayoutPrimitiveInfo,
|
||||
pub space_and_clip: &'a SpaceAndClipInfo,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
@ -103,6 +77,29 @@ impl LayoutPrimitiveInfo {
|
||||
|
||||
pub type LayoutPrimitiveInfo = PrimitiveInfo<LayoutPixel>;
|
||||
|
||||
/// Per-primitive information about the nodes in the clip tree and
|
||||
/// the spatial tree that the primitive belongs to.
|
||||
///
|
||||
/// Note: this is a separate struct from `PrimitiveInfo` because
|
||||
/// it needs indirectional mapping during the DL flattening phase,
|
||||
/// turning into `ScrollNodeAndClipChain`.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct SpaceAndClipInfo {
|
||||
pub spatial_id: SpatialId,
|
||||
pub clip_id: ClipId,
|
||||
}
|
||||
|
||||
impl SpaceAndClipInfo {
|
||||
/// Create a new space/clip info associated with the root
|
||||
/// scroll frame.
|
||||
pub fn root_scroll(pipeline_id: PipelineId) -> Self {
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: SpatialId::root_scroll_node(pipeline_id),
|
||||
clip_id: ClipId::root(pipeline_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum SpecificDisplayItem {
|
||||
@ -121,10 +118,10 @@ pub enum SpecificDisplayItem {
|
||||
RadialGradient(RadialGradientDisplayItem),
|
||||
ClipChain(ClipChainItem),
|
||||
Iframe(IframeDisplayItem),
|
||||
PushReferenceFrame(ReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
PushStackingContext(PushStackingContextDisplayItem),
|
||||
PopStackingContext,
|
||||
PushReferenceFrame(PushReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
SetGradientStops,
|
||||
PushShadow(Shadow),
|
||||
PopAllShadows,
|
||||
@ -154,10 +151,10 @@ pub enum CompletelySpecificDisplayItem {
|
||||
Gradient(GradientDisplayItem),
|
||||
RadialGradient(RadialGradientDisplayItem),
|
||||
Iframe(IframeDisplayItem),
|
||||
PushReferenceFrame(ReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
PushStackingContext(PushStackingContextDisplayItem, Vec<FilterOp>),
|
||||
PopStackingContext,
|
||||
PushReferenceFrame(PushReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
SetGradientStops(Vec<GradientStop>),
|
||||
PushShadow(Shadow),
|
||||
PopAllShadows,
|
||||
@ -194,7 +191,7 @@ impl StickyOffsetBounds {
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct StickyFrameDisplayItem {
|
||||
pub id: ClipId,
|
||||
pub id: SpatialId,
|
||||
|
||||
/// The margins that should be maintained between the edge of the parent viewport and this
|
||||
/// sticky frame. A margin of None indicates that the sticky frame should not stick at all
|
||||
@ -230,7 +227,7 @@ pub enum ScrollSensitivity {
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ScrollFrameDisplayItem {
|
||||
pub clip_id: ClipId,
|
||||
pub scroll_frame_id: ClipId,
|
||||
pub scroll_frame_id: SpatialId,
|
||||
pub external_id: Option<ExternalScrollId>,
|
||||
pub image_mask: Option<ImageMask>,
|
||||
pub scroll_sensitivity: ScrollSensitivity,
|
||||
@ -517,7 +514,7 @@ pub struct RadialGradientDisplayItem {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PushReferenceFrameDisplayListItem {
|
||||
pub struct ReferenceFrameDisplayListItem {
|
||||
pub reference_frame: ReferenceFrame,
|
||||
}
|
||||
|
||||
@ -532,7 +529,7 @@ pub struct ReferenceFrame {
|
||||
pub transform_style: TransformStyle,
|
||||
pub transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
pub perspective: Option<LayoutTransform>,
|
||||
pub id: ClipId,
|
||||
pub id: SpatialId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
@ -544,7 +541,7 @@ pub struct PushStackingContextDisplayItem {
|
||||
pub struct StackingContext {
|
||||
pub transform_style: TransformStyle,
|
||||
pub mix_blend_mode: MixBlendMode,
|
||||
pub clip_node_id: Option<ClipId>,
|
||||
pub clip_id: Option<ClipId>,
|
||||
pub raster_space: RasterSpace,
|
||||
} // IMPLICIT: filters: Vec<FilterOp>
|
||||
|
||||
@ -647,7 +644,6 @@ impl FilterOp {
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IframeDisplayItem {
|
||||
pub clip_id: ClipId,
|
||||
pub pipeline_id: PipelineId,
|
||||
pub ignore_missing_pipeline: bool,
|
||||
}
|
||||
@ -857,48 +853,82 @@ impl ComplexClipRegion {
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ClipChainId(pub u64, pub PipelineId);
|
||||
|
||||
/// A reference to a clipping node defining how an item is clipped.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum ClipId {
|
||||
Spatial(usize, PipelineId),
|
||||
Clip(usize, PipelineId),
|
||||
ClipChain(ClipChainId),
|
||||
}
|
||||
|
||||
const ROOT_REFERENCE_FRAME_CLIP_ID: usize = 0;
|
||||
const ROOT_SCROLL_NODE_CLIP_ID: usize = 1;
|
||||
const ROOT_CLIP_ID: usize = 0;
|
||||
|
||||
impl ClipId {
|
||||
pub fn root_scroll_node(pipeline_id: PipelineId) -> ClipId {
|
||||
ClipId::Spatial(ROOT_SCROLL_NODE_CLIP_ID, pipeline_id)
|
||||
/// Return the root clip ID - effectively doing no clipping.
|
||||
pub fn root(pipeline_id: PipelineId) -> Self {
|
||||
ClipId::Clip(ROOT_CLIP_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn root_reference_frame(pipeline_id: PipelineId) -> ClipId {
|
||||
ClipId::Spatial(ROOT_REFERENCE_FRAME_CLIP_ID, pipeline_id)
|
||||
/// Return an invalid clip ID - needed in places where we carry
|
||||
/// one but need to not attempt to use it.
|
||||
pub fn invalid() -> Self {
|
||||
ClipId::Clip(!0, PipelineId::dummy())
|
||||
}
|
||||
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
match *self {
|
||||
ClipId::Spatial(_, pipeline_id) |
|
||||
ClipId::Clip(_, pipeline_id) |
|
||||
ClipId::ClipChain(ClipChainId(_, pipeline_id)) => pipeline_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_root_scroll_node(&self) -> bool {
|
||||
pub fn is_root(&self) -> bool {
|
||||
match *self {
|
||||
ClipId::Spatial(ROOT_SCROLL_NODE_CLIP_ID, _) => true,
|
||||
_ => false,
|
||||
ClipId::Clip(id, _) => id == ROOT_CLIP_ID,
|
||||
ClipId::ClipChain(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_root_reference_frame(&self) -> bool {
|
||||
pub fn is_valid(&self) -> bool {
|
||||
match *self {
|
||||
ClipId::Spatial(ROOT_REFERENCE_FRAME_CLIP_ID, _) => true,
|
||||
_ => false,
|
||||
ClipId::Clip(id, _) => id != !0,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a spatial node defining item positioning.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct SpatialId(pub usize, PipelineId);
|
||||
|
||||
const ROOT_REFERENCE_FRAME_SPATIAL_ID: usize = 0;
|
||||
const ROOT_SCROLL_NODE_SPATIAL_ID: usize = 1;
|
||||
|
||||
impl SpatialId {
|
||||
pub fn new(spatial_node_index: usize, pipeline_id: PipelineId) -> Self {
|
||||
SpatialId(spatial_node_index, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn root_reference_frame(pipeline_id: PipelineId) -> Self {
|
||||
SpatialId(ROOT_REFERENCE_FRAME_SPATIAL_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn root_scroll_node(pipeline_id: PipelineId) -> Self {
|
||||
SpatialId(ROOT_SCROLL_NODE_SPATIAL_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
self.1
|
||||
}
|
||||
|
||||
pub fn is_root_reference_frame(&self) -> bool {
|
||||
self.0 == ROOT_REFERENCE_FRAME_SPATIAL_ID
|
||||
}
|
||||
|
||||
pub fn is_root_scroll_node(&self) -> bool {
|
||||
self.0 == ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
}
|
||||
}
|
||||
|
||||
/// An external identifier that uniquely identifies a scroll frame independent of its ClipId, which
|
||||
/// may change from frame to frame. This should be unique within a pipeline. WebRender makes no
|
||||
/// attempt to ensure uniqueness. The zero value is reserved for use by the root scroll node of
|
||||
|
@ -15,16 +15,16 @@ use std::ops::Range;
|
||||
use std::{io, mem, ptr, slice};
|
||||
use time::precise_time_ns;
|
||||
use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, CacheMarkerDisplayItem};
|
||||
use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
|
||||
use {BoxShadowDisplayItem, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
|
||||
use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
|
||||
use {FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, Gradient, GradientBuilder};
|
||||
use {GradientDisplayItem, GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask};
|
||||
use {ImageRendering, LayoutPoint, LayoutPrimitiveInfo, LayoutRect, LayoutSideOffsets, LayoutSize};
|
||||
use {LayoutTransform, LayoutVector2D, LineDisplayItem, LineOrientation, LineStyle, MixBlendMode};
|
||||
use {PipelineId, PropertyBinding, PushReferenceFrameDisplayListItem};
|
||||
use {PipelineId, PropertyBinding, ReferenceFrameDisplayListItem};
|
||||
use {PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
|
||||
use {RectangleDisplayItem, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use {SerializedDisplayItem, Shadow, SpecificDisplayItem};
|
||||
use {SerializedDisplayItem, Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem};
|
||||
use {StackingContext, StickyFrameDisplayItem, StickyOffsetBounds};
|
||||
use {TextDisplayItem, TransformStyle, YuvColorSpace, YuvData, YuvImageDisplayItem, ColorDepth};
|
||||
|
||||
@ -32,13 +32,13 @@ use {TextDisplayItem, TransformStyle, YuvColorSpace, YuvData, YuvImageDisplayIte
|
||||
// This needs to be set to (renderer::MAX_VERTEX_TEXTURE_WIDTH - VECS_PER_TEXT_RUN) * 2
|
||||
pub const MAX_TEXT_RUN_LENGTH: usize = 2040;
|
||||
|
||||
// We start at 2, because the root reference is always 0 and the root scroll node is always 1.
|
||||
// See ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
// TODO(mrobinson): It would be a good idea to eliminate the root scroll frame which is only
|
||||
// used by Servo.
|
||||
const FIRST_SPATIAL_NODE_INDEX: usize = 2;
|
||||
|
||||
// There are no default clips, so we start at the 0 index for clips.
|
||||
const FIRST_CLIP_NODE_INDEX: usize = 0;
|
||||
// See ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
const FIRST_CLIP_NODE_INDEX: usize = 1;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
@ -213,9 +213,8 @@ impl<'a> BuiltDisplayListIter<'a> {
|
||||
cur_item: DisplayItem {
|
||||
// Dummy data, will be overwritten by `next`
|
||||
item: SpecificDisplayItem::PopStackingContext,
|
||||
clip_and_scroll:
|
||||
ClipAndScrollInfo::simple(ClipId::root_scroll_node(PipelineId::dummy())),
|
||||
layout: LayoutPrimitiveInfo::new(LayoutRect::zero()),
|
||||
space_and_clip: SpaceAndClipInfo::root_scroll(PipelineId::dummy())
|
||||
},
|
||||
cur_stops: ItemRange::default(),
|
||||
cur_glyphs: ItemRange::default(),
|
||||
@ -370,8 +369,8 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> {
|
||||
&self.iter.cur_item.layout.clip_rect
|
||||
}
|
||||
|
||||
pub fn clip_and_scroll(&self) -> ClipAndScrollInfo {
|
||||
self.iter.cur_item.clip_and_scroll
|
||||
pub fn space_and_clip_info(&self) -> &SpaceAndClipInfo {
|
||||
&self.iter.cur_item.space_and_clip
|
||||
}
|
||||
|
||||
pub fn item(&self) -> &SpecificDisplayItem {
|
||||
@ -490,13 +489,13 @@ impl Serialize for BuiltDisplayList {
|
||||
SpecificDisplayItem::Gradient(v) => Gradient(v),
|
||||
SpecificDisplayItem::RadialGradient(v) => RadialGradient(v),
|
||||
SpecificDisplayItem::Iframe(v) => Iframe(v),
|
||||
SpecificDisplayItem::PushReferenceFrame(v) => PushReferenceFrame(v),
|
||||
SpecificDisplayItem::PopReferenceFrame => PopReferenceFrame,
|
||||
SpecificDisplayItem::PushStackingContext(v) => PushStackingContext(
|
||||
v,
|
||||
item.iter.list.get(item.iter.cur_filters).collect()
|
||||
),
|
||||
SpecificDisplayItem::PopStackingContext => PopStackingContext,
|
||||
SpecificDisplayItem::PushReferenceFrame(v) => PushReferenceFrame(v),
|
||||
SpecificDisplayItem::PopReferenceFrame => PopReferenceFrame,
|
||||
SpecificDisplayItem::SetGradientStops => SetGradientStops(
|
||||
item.iter.list.get(item.iter.cur_stops).collect()
|
||||
),
|
||||
@ -505,8 +504,8 @@ impl Serialize for BuiltDisplayList {
|
||||
SpecificDisplayItem::PushCacheMarker(m) => PushCacheMarker(m),
|
||||
SpecificDisplayItem::PopCacheMarker => PopCacheMarker,
|
||||
},
|
||||
clip_and_scroll: display_item.clip_and_scroll,
|
||||
layout: display_item.layout,
|
||||
space_and_clip: display_item.space_and_clip,
|
||||
};
|
||||
seq.serialize_element(&serial_di)?
|
||||
}
|
||||
@ -551,7 +550,7 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
||||
total_clip_nodes += 1;
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, complex_clips);
|
||||
SpecificDisplayItem::ScrollFrame(specific_item)
|
||||
},
|
||||
}
|
||||
StickyFrame(specific_item) => {
|
||||
total_spatial_nodes += 1;
|
||||
SpecificDisplayItem::StickyFrame(specific_item)
|
||||
@ -574,16 +573,16 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
||||
total_clip_nodes += 1;
|
||||
SpecificDisplayItem::Iframe(specific_item)
|
||||
}
|
||||
PushReferenceFrame(v) => {
|
||||
total_spatial_nodes += 1;
|
||||
SpecificDisplayItem::PushReferenceFrame(v)
|
||||
}
|
||||
PopReferenceFrame => SpecificDisplayItem::PopReferenceFrame,
|
||||
PushStackingContext(specific_item, filters) => {
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, filters);
|
||||
SpecificDisplayItem::PushStackingContext(specific_item)
|
||||
},
|
||||
PopStackingContext => SpecificDisplayItem::PopStackingContext,
|
||||
PushReferenceFrame(specific_item) => {
|
||||
total_spatial_nodes += 1;
|
||||
SpecificDisplayItem::PushReferenceFrame(specific_item)
|
||||
}
|
||||
PopReferenceFrame => SpecificDisplayItem::PopReferenceFrame,
|
||||
SetGradientStops(stops) => {
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, stops);
|
||||
SpecificDisplayItem::SetGradientStops
|
||||
@ -593,8 +592,8 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
||||
PushCacheMarker(marker) => SpecificDisplayItem::PushCacheMarker(marker),
|
||||
PopCacheMarker => SpecificDisplayItem::PopCacheMarker,
|
||||
},
|
||||
clip_and_scroll: complete.clip_and_scroll,
|
||||
layout: complete.layout,
|
||||
space_and_clip: complete.space_and_clip,
|
||||
};
|
||||
serialize_fast(&mut data, &item);
|
||||
// the aux data is serialized after the item, hence the temporary
|
||||
@ -832,7 +831,6 @@ impl<'a, 'b> Read for UnsafeReader<'a, 'b> {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SaveState {
|
||||
dl_len: usize,
|
||||
clip_stack_len: usize,
|
||||
next_clip_index: usize,
|
||||
next_spatial_index: usize,
|
||||
next_clip_chain_id: u64,
|
||||
@ -842,7 +840,6 @@ pub struct SaveState {
|
||||
pub struct DisplayListBuilder {
|
||||
pub data: Vec<u8>,
|
||||
pub pipeline_id: PipelineId,
|
||||
clip_stack: Vec<ClipAndScrollInfo>,
|
||||
next_clip_index: usize,
|
||||
next_spatial_index: usize,
|
||||
next_clip_chain_id: u64,
|
||||
@ -869,9 +866,6 @@ impl DisplayListBuilder {
|
||||
DisplayListBuilder {
|
||||
data: Vec::with_capacity(capacity),
|
||||
pipeline_id,
|
||||
clip_stack: vec![
|
||||
ClipAndScrollInfo::simple(ClipId::root_scroll_node(pipeline_id)),
|
||||
],
|
||||
next_clip_index: FIRST_CLIP_NODE_INDEX,
|
||||
next_spatial_index: FIRST_SPATIAL_NODE_INDEX,
|
||||
next_clip_chain_id: 0,
|
||||
@ -897,7 +891,6 @@ impl DisplayListBuilder {
|
||||
assert!(self.save_state.is_none(), "DisplayListBuilder doesn't support nested saves");
|
||||
|
||||
self.save_state = Some(SaveState {
|
||||
clip_stack_len: self.clip_stack.len(),
|
||||
dl_len: self.data.len(),
|
||||
next_clip_index: self.next_clip_index,
|
||||
next_spatial_index: self.next_spatial_index,
|
||||
@ -909,7 +902,6 @@ impl DisplayListBuilder {
|
||||
pub fn restore(&mut self) {
|
||||
let state = self.save_state.take().expect("No save to restore DisplayListBuilder from");
|
||||
|
||||
self.clip_stack.truncate(state.clip_stack_len);
|
||||
self.data.truncate(state.dl_len);
|
||||
self.next_clip_index = state.next_clip_index;
|
||||
self.next_spatial_index = state.next_spatial_index;
|
||||
@ -969,36 +961,31 @@ impl DisplayListBuilder {
|
||||
/// 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.
|
||||
pub fn push_item(&mut self, item: &SpecificDisplayItem, layout: &LayoutPrimitiveInfo) {
|
||||
serialize_fast(
|
||||
&mut self.data,
|
||||
SerializedDisplayItem {
|
||||
item,
|
||||
clip_and_scroll: self.clip_stack.last().unwrap(),
|
||||
layout,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn push_item_with_clip_scroll_info(
|
||||
#[inline]
|
||||
pub fn push_item(
|
||||
&mut self,
|
||||
item: &SpecificDisplayItem,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
clip_and_scroll: &ClipAndScrollInfo
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
) {
|
||||
serialize_fast(
|
||||
&mut self.data,
|
||||
SerializedDisplayItem {
|
||||
item,
|
||||
clip_and_scroll,
|
||||
layout,
|
||||
space_and_clip,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_new_empty_item(&mut self, item: &SpecificDisplayItem) {
|
||||
let layout = &LayoutPrimitiveInfo::new(LayoutRect::zero());
|
||||
self.push_item(item, layout)
|
||||
let pipeline_id = self.pipeline_id;
|
||||
self.push_item(
|
||||
item,
|
||||
&LayoutPrimitiveInfo::new(LayoutRect::zero()),
|
||||
&SpaceAndClipInfo::root_scroll(pipeline_id),
|
||||
)
|
||||
}
|
||||
|
||||
fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
|
||||
@ -1046,18 +1033,28 @@ impl DisplayListBuilder {
|
||||
Self::push_iter_impl(&mut self.data, iter);
|
||||
}
|
||||
|
||||
pub fn push_rect(&mut self, layout: &LayoutPrimitiveInfo, color: ColorF) {
|
||||
pub fn push_rect(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
color: ColorF,
|
||||
) {
|
||||
let item = SpecificDisplayItem::Rectangle(RectangleDisplayItem { color });
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_clear_rect(&mut self, layout: &LayoutPrimitiveInfo) {
|
||||
self.push_item(&SpecificDisplayItem::ClearRectangle, layout);
|
||||
pub fn push_clear_rect(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
) {
|
||||
self.push_item(&SpecificDisplayItem::ClearRectangle, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_line(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
wavy_line_thickness: f32,
|
||||
orientation: LineOrientation,
|
||||
color: &ColorF,
|
||||
@ -1070,12 +1067,13 @@ impl DisplayListBuilder {
|
||||
style,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_image(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
stretch_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
image_rendering: ImageRendering,
|
||||
@ -1092,13 +1090,14 @@ impl DisplayListBuilder {
|
||||
color,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
/// Push a yuv image. All planar data in yuv image should use the same buffer type.
|
||||
pub fn push_yuv_image(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
yuv_data: YuvData,
|
||||
color_depth: ColorDepth,
|
||||
color_space: YuvColorSpace,
|
||||
@ -1110,12 +1109,13 @@ impl DisplayListBuilder {
|
||||
color_space,
|
||||
image_rendering,
|
||||
});
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_text(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
glyphs: &[GlyphInstance],
|
||||
font_key: FontInstanceKey,
|
||||
color: ColorF,
|
||||
@ -1128,7 +1128,7 @@ impl DisplayListBuilder {
|
||||
});
|
||||
|
||||
for split_glyphs in glyphs.chunks(MAX_TEXT_RUN_LENGTH) {
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
self.push_iter(split_glyphs);
|
||||
}
|
||||
}
|
||||
@ -1166,17 +1166,19 @@ impl DisplayListBuilder {
|
||||
pub fn push_border(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
widths: LayoutSideOffsets,
|
||||
details: BorderDetails,
|
||||
) {
|
||||
let item = SpecificDisplayItem::Border(BorderDisplayItem { details, widths });
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_box_shadow(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
box_bounds: LayoutRect,
|
||||
offset: LayoutVector2D,
|
||||
color: ColorF,
|
||||
@ -1195,7 +1197,7 @@ impl DisplayListBuilder {
|
||||
clip_mode,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
/// Pushes a linear gradient to be displayed.
|
||||
@ -1215,6 +1217,7 @@ impl DisplayListBuilder {
|
||||
pub fn push_gradient(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
gradient: Gradient,
|
||||
tile_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
@ -1225,7 +1228,7 @@ impl DisplayListBuilder {
|
||||
tile_spacing,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
/// Pushes a radial gradient to be displayed.
|
||||
@ -1234,6 +1237,7 @@ impl DisplayListBuilder {
|
||||
pub fn push_radial_gradient(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
gradient: RadialGradient,
|
||||
tile_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
@ -1244,18 +1248,20 @@ impl DisplayListBuilder {
|
||||
tile_spacing,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_reference_frame(
|
||||
&mut self,
|
||||
rect: &LayoutRect,
|
||||
parent: SpatialId,
|
||||
transform_style: TransformStyle,
|
||||
transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
perspective: Option<LayoutTransform>,
|
||||
) -> ClipId {
|
||||
) -> SpatialId {
|
||||
let id = self.generate_spatial_index();
|
||||
let item = SpecificDisplayItem::PushReferenceFrame(PushReferenceFrameDisplayListItem {
|
||||
|
||||
let item = SpecificDisplayItem::PushReferenceFrame(ReferenceFrameDisplayListItem {
|
||||
reference_frame: ReferenceFrame {
|
||||
transform_style,
|
||||
transform,
|
||||
@ -1263,7 +1269,12 @@ impl DisplayListBuilder {
|
||||
id,
|
||||
},
|
||||
});
|
||||
self.push_item(&item, &LayoutPrimitiveInfo::new(*rect));
|
||||
|
||||
let layout = LayoutPrimitiveInfo::new(*rect);
|
||||
self.push_item(&item, &layout, &SpaceAndClipInfo {
|
||||
spatial_id: parent,
|
||||
clip_id: ClipId::invalid(),
|
||||
});
|
||||
id
|
||||
}
|
||||
|
||||
@ -1287,7 +1298,8 @@ impl DisplayListBuilder {
|
||||
pub fn push_stacking_context(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
clip_node_id: Option<ClipId>,
|
||||
spatial_id: SpatialId,
|
||||
clip_id: Option<ClipId>,
|
||||
transform_style: TransformStyle,
|
||||
mix_blend_mode: MixBlendMode,
|
||||
filters: &[FilterOp],
|
||||
@ -1297,12 +1309,15 @@ impl DisplayListBuilder {
|
||||
stacking_context: StackingContext {
|
||||
transform_style,
|
||||
mix_blend_mode,
|
||||
clip_node_id,
|
||||
clip_id,
|
||||
raster_space,
|
||||
},
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, &SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id: ClipId::invalid(),
|
||||
});
|
||||
self.push_iter(filters);
|
||||
}
|
||||
|
||||
@ -1323,9 +1338,9 @@ impl DisplayListBuilder {
|
||||
ClipId::Clip(self.next_clip_index - 1, self.pipeline_id)
|
||||
}
|
||||
|
||||
fn generate_spatial_index(&mut self) -> ClipId {
|
||||
fn generate_spatial_index(&mut self) -> SpatialId {
|
||||
self.next_spatial_index += 1;
|
||||
ClipId::Spatial(self.next_spatial_index - 1, self.pipeline_id)
|
||||
SpatialId::new(self.next_spatial_index - 1, self.pipeline_id)
|
||||
}
|
||||
|
||||
fn generate_clip_chain_id(&mut self) -> ClipChainId {
|
||||
@ -1335,38 +1350,14 @@ impl DisplayListBuilder {
|
||||
|
||||
pub fn define_scroll_frame<I>(
|
||||
&mut self,
|
||||
parent_space_and_clip: &SpaceAndClipInfo,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
content_rect: LayoutRect,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
) -> ClipId
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
let parent = self.clip_stack.last().unwrap().scroll_node_id;
|
||||
self.define_scroll_frame_with_parent(
|
||||
parent,
|
||||
external_id,
|
||||
content_rect,
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
scroll_sensitivity)
|
||||
}
|
||||
|
||||
pub fn define_scroll_frame_with_parent<I>(
|
||||
&mut self,
|
||||
parent: ClipId,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
content_rect: LayoutRect,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
) -> ClipId
|
||||
) -> SpaceAndClipInfo
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
@ -1381,14 +1372,17 @@ impl DisplayListBuilder {
|
||||
scroll_sensitivity,
|
||||
});
|
||||
|
||||
self.push_item_with_clip_scroll_info(
|
||||
self.push_item(
|
||||
&item,
|
||||
&LayoutPrimitiveInfo::with_clip_rect(content_rect, clip_rect),
|
||||
&ClipAndScrollInfo::simple(parent),
|
||||
parent_space_and_clip,
|
||||
);
|
||||
self.push_iter(complex_clips);
|
||||
|
||||
scroll_frame_id
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: scroll_frame_id,
|
||||
clip_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define_clip_chain<I>(
|
||||
@ -1408,45 +1402,7 @@ impl DisplayListBuilder {
|
||||
|
||||
pub fn define_clip<I>(
|
||||
&mut self,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
) -> ClipId
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
let clip_and_scroll = self.clip_stack.last().unwrap().clone();
|
||||
self.define_clip_impl(
|
||||
clip_and_scroll,
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn define_clip_with_parent<I>(
|
||||
&mut self,
|
||||
parent: ClipId,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
) -> ClipId
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
self.define_clip_impl(
|
||||
ClipAndScrollInfo::simple(parent),
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
)
|
||||
}
|
||||
|
||||
fn define_clip_impl<I>(
|
||||
&mut self,
|
||||
scrollinfo: ClipAndScrollInfo,
|
||||
parent_space_and_clip: &SpaceAndClipInfo,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
@ -1461,21 +1417,24 @@ impl DisplayListBuilder {
|
||||
image_mask,
|
||||
});
|
||||
|
||||
let layout = LayoutPrimitiveInfo::new(clip_rect);
|
||||
|
||||
self.push_item_with_clip_scroll_info(&item, &layout, &scrollinfo);
|
||||
self.push_item(
|
||||
&item,
|
||||
&LayoutPrimitiveInfo::new(clip_rect),
|
||||
parent_space_and_clip,
|
||||
);
|
||||
self.push_iter(complex_clips);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn define_sticky_frame(
|
||||
&mut self,
|
||||
parent_spatial_id: SpatialId,
|
||||
frame_rect: LayoutRect,
|
||||
margins: SideOffsets2D<Option<f32>>,
|
||||
vertical_offset_bounds: StickyOffsetBounds,
|
||||
horizontal_offset_bounds: StickyOffsetBounds,
|
||||
previously_applied_offset: LayoutVector2D,
|
||||
) -> ClipId {
|
||||
) -> SpatialId {
|
||||
let id = self.generate_spatial_index();
|
||||
let item = SpecificDisplayItem::StickyFrame(StickyFrameDisplayItem {
|
||||
id,
|
||||
@ -1485,44 +1444,38 @@ impl DisplayListBuilder {
|
||||
previously_applied_offset,
|
||||
});
|
||||
|
||||
let layout = LayoutPrimitiveInfo::new(frame_rect);
|
||||
self.push_item(&item, &layout);
|
||||
self.push_item(
|
||||
&item,
|
||||
&LayoutPrimitiveInfo::new(frame_rect),
|
||||
&SpaceAndClipInfo {
|
||||
spatial_id: parent_spatial_id,
|
||||
clip_id: ClipId::invalid(),
|
||||
},
|
||||
);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn push_clip_id(&mut self, id: ClipId) {
|
||||
self.clip_stack.push(ClipAndScrollInfo::simple(id));
|
||||
}
|
||||
|
||||
pub fn push_clip_and_scroll_info(&mut self, layout: ClipAndScrollInfo) {
|
||||
self.clip_stack.push(layout);
|
||||
}
|
||||
|
||||
pub fn pop_clip_id(&mut self) {
|
||||
self.clip_stack.pop();
|
||||
if let Some(save_state) = self.save_state.as_ref() {
|
||||
assert!(self.clip_stack.len() >= save_state.clip_stack_len,
|
||||
"Cannot pop clips that were pushed before the DisplayListBuilder save.");
|
||||
}
|
||||
assert!(!self.clip_stack.is_empty());
|
||||
}
|
||||
|
||||
pub fn push_iframe(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
pipeline_id: PipelineId,
|
||||
ignore_missing_pipeline: bool
|
||||
) {
|
||||
let item = SpecificDisplayItem::Iframe(IframeDisplayItem {
|
||||
clip_id: self.generate_clip_index(),
|
||||
pipeline_id,
|
||||
ignore_missing_pipeline,
|
||||
});
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_shadow(&mut self, layout: &LayoutPrimitiveInfo, shadow: Shadow) {
|
||||
self.push_item(&SpecificDisplayItem::PushShadow(shadow), layout);
|
||||
pub fn push_shadow(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
shadow: Shadow,
|
||||
) {
|
||||
self.push_item(&SpecificDisplayItem::PushShadow(shadow), layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn pop_all_shadows(&mut self) {
|
||||
@ -1533,6 +1486,7 @@ impl DisplayListBuilder {
|
||||
assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
|
||||
|
||||
let end_time = precise_time_ns();
|
||||
|
||||
(
|
||||
self.pipeline_id,
|
||||
self.content_size,
|
||||
|
@ -7,22 +7,22 @@ root:
|
||||
scroll-offset: [0, 50]
|
||||
items:
|
||||
# The rectangles below should stay in place even when the parent scroll area scrolls,
|
||||
# because they are use the root reference frame as their scroll node (fixed position).
|
||||
# because they use the root reference frame as their scroll node (fixed position).
|
||||
# On the other hand, the clip item here will scroll with its parent scroll area. Normally
|
||||
# fixed position items would only be clipped by their reference frame (in this case the
|
||||
# root), but ince these items specify an auxiliary clip, they will be clipped by their
|
||||
# root), but since these items specify an auxiliary clip, they will be clipped by their
|
||||
# sibling clip (42).
|
||||
- type: clip
|
||||
bounds: [10, 60, 50, 50]
|
||||
id: 42
|
||||
- type: stacking-context
|
||||
bounds: [10, 10, 100, 100]
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 50]
|
||||
color: green
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
- type: rect
|
||||
bounds: [0, 50, 100, 50]
|
||||
color: red
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
- type: clip
|
||||
bounds: [10, 60, 50, 50]
|
||||
id: 42
|
||||
- type: stacking-context
|
||||
bounds: [10, 10, 100, 100]
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 50]
|
||||
color: green
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
- type: rect
|
||||
bounds: [0, 50, 100, 50]
|
||||
color: red
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
|
@ -2,18 +2,14 @@ root:
|
||||
bounds: [0, 0, 1024, 10000]
|
||||
scroll-offset: [0, 100]
|
||||
items:
|
||||
# This stacking context should not scroll out of view because it is fixed position.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 50]
|
||||
items:
|
||||
# This item should not scroll out of view because it is fixed position.
|
||||
- type: rect
|
||||
bounds: [0, 0, 50, 50]
|
||||
color: green
|
||||
clip-and-scroll: root-reference-frame
|
||||
# Even though there is a fixed position stacking context, it should scroll,
|
||||
# because it is fixed relative to its reference frame. The reference frame
|
||||
# of this stacking context is the stacking context parent because it has
|
||||
# a transformation.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 50]
|
||||
transform: translate(60, 100)
|
||||
@ -22,17 +18,21 @@ root:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 50]
|
||||
items:
|
||||
# Even though there is a custom clip-scroll ID, it should scroll,
|
||||
# because it is fixed relative to its reference frame. The reference frame
|
||||
# of this stacking context is the stacking context parent because it has
|
||||
# a transformation.
|
||||
- type: rect
|
||||
bounds: [0, 0, 50, 50]
|
||||
color: green
|
||||
clip-and-scroll: 100
|
||||
# This is similar to the previous case, but ensures that this still works
|
||||
# even with an identity transform.
|
||||
- type: stacking-context
|
||||
bounds: [120, 0, 50, 200]
|
||||
transform: translate(0, 0)
|
||||
id: 101
|
||||
items:
|
||||
# This is similar to the previous case, but ensures that this still works
|
||||
# even with an identity transform.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 200]
|
||||
items:
|
||||
@ -40,12 +40,12 @@ root:
|
||||
bounds: [0, 100, 50, 50]
|
||||
color: green
|
||||
clip-and-scroll: 101
|
||||
# This is similar to the previous case, but for perspective.
|
||||
- type: stacking-context
|
||||
bounds: [180, 0, 50, 200]
|
||||
perspective: 1
|
||||
id: 102
|
||||
items:
|
||||
# This is similar to the previous case, but for perspective.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 200]
|
||||
items:
|
||||
|
@ -6,7 +6,6 @@ root:
|
||||
# ensure that offsets within reference frames are handled
|
||||
# properly when drawing the mask.
|
||||
bounds: [10, 10, 100, 100]
|
||||
scroll-policy: scrollable
|
||||
items:
|
||||
- type: scroll-frame
|
||||
bounds: [0, 0, 100, 100]
|
||||
@ -15,15 +14,14 @@ root:
|
||||
rect: [0, 0, 100, 100]
|
||||
repeat: false
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: green
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: green
|
||||
|
||||
# The same test, but this time ensure that scroll offsets don't affect the masking.
|
||||
-
|
||||
type: stacking-context
|
||||
bounds: [100, 0, 100, 100]
|
||||
scroll-policy: scrollable
|
||||
items:
|
||||
- type: scroll-frame
|
||||
bounds: [10, 10, 100, 300]
|
||||
|
@ -1,28 +1,28 @@
|
||||
---
|
||||
root:
|
||||
items:
|
||||
-
|
||||
root:
|
||||
items:
|
||||
-
|
||||
bounds: [8, 8, 500, 500]
|
||||
type: "stacking-context"
|
||||
items:
|
||||
-
|
||||
items:
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: clip
|
||||
id: 2
|
||||
items:
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: rect
|
||||
color: red
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: "stacking-context"
|
||||
transform: translate(100, 0)
|
||||
items:
|
||||
-
|
||||
bounds: [-100, 0, 200, 200]
|
||||
clip-rect: [-300, -300, 900, 900]
|
||||
type: rect
|
||||
color: green
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: rect
|
||||
color: red
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: "stacking-context"
|
||||
transform: translate(100, 0)
|
||||
items:
|
||||
-
|
||||
bounds: [-100, 0, 200, 200]
|
||||
clip-rect: [-300, -300, 900, 900]
|
||||
type: rect
|
||||
color: green
|
||||
id: [0, 0]
|
||||
pipelines: []
|
||||
|
@ -49,27 +49,6 @@ def is_linux():
|
||||
return sys.platform.startswith('linux')
|
||||
|
||||
|
||||
def debugger():
|
||||
if "DEBUGGER" in os.environ:
|
||||
return os.environ["DEBUGGER"]
|
||||
return None
|
||||
|
||||
|
||||
def use_gdb():
|
||||
return debugger() in ['gdb', 'cgdb', 'rust-gdb']
|
||||
|
||||
|
||||
def use_rr():
|
||||
return debugger() == 'rr'
|
||||
|
||||
|
||||
def optimized_build():
|
||||
if "OPTIMIZED" in os.environ:
|
||||
opt = os.environ["OPTIMIZED"]
|
||||
return opt not in ["0", "false"]
|
||||
return True
|
||||
|
||||
|
||||
def set_osmesa_env(bin_path):
|
||||
"""Set proper LD_LIBRARY_PATH and DRIVE for software rendering on Linux and OSX"""
|
||||
if is_linux():
|
||||
@ -88,34 +67,11 @@ def set_osmesa_env(bin_path):
|
||||
|
||||
extra_flags = os.getenv('CARGOFLAGS', None)
|
||||
extra_flags = extra_flags.split(' ') if extra_flags else []
|
||||
build_cmd = ['cargo', 'build'] + extra_flags + ['--verbose', '--features', 'headless']
|
||||
if optimized_build():
|
||||
build_cmd += ['--release']
|
||||
|
||||
objdir = ''
|
||||
if optimized_build():
|
||||
objdir = '../target/release/'
|
||||
else:
|
||||
objdir = '../target/debug/'
|
||||
|
||||
subprocess.check_call(build_cmd)
|
||||
|
||||
set_osmesa_env(objdir)
|
||||
|
||||
dbg_cmd = []
|
||||
if use_rr():
|
||||
dbg_cmd = ['rr', 'record']
|
||||
elif use_gdb():
|
||||
dbg_cmd = [debugger(), '--args']
|
||||
elif debugger():
|
||||
print("Unknown debugger: " + debugger())
|
||||
sys.exit(1)
|
||||
|
||||
subprocess.check_call(['cargo', 'build'] + extra_flags + ['--release', '--verbose', '--features', 'headless'])
|
||||
set_osmesa_env('../target/release/')
|
||||
# TODO(gw): We have an occasional accuracy issue or bug (could be WR or OSMesa)
|
||||
# where the output of a previous test that uses intermediate targets can
|
||||
# cause 1.0 / 255.0 pixel differences in a subsequent test. For now, we
|
||||
# run tests with no-scissor mode, which ensures a complete target clear
|
||||
# between test runs. But we should investigate this further...
|
||||
cmd = dbg_cmd + [objdir + '/wrench', '--no-scissor', '-h'] + sys.argv[1:]
|
||||
print('Running: `' + ' '.join(cmd) + '`')
|
||||
subprocess.check_call(cmd)
|
||||
subprocess.check_call(['../target/release/wrench', '--no-scissor', '-h'] + sys.argv[1:])
|
||||
|
@ -109,6 +109,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
size(151., 56.0),
|
||||
size(151.0, 56.0),
|
||||
ImageRendering::Auto,
|
||||
@ -170,12 +171,18 @@ impl<'a> RawtestHarness<'a> {
|
||||
|
||||
let image_size = size(1510., 111256.);
|
||||
|
||||
let clip_id = builder.define_clip(rect(40., 41., 200., 201.), vec![], None);
|
||||
let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
let clip_id = builder.define_clip(
|
||||
&root_space_and_clip,
|
||||
rect(40., 41., 200., 201.),
|
||||
vec![],
|
||||
None,
|
||||
);
|
||||
|
||||
builder.push_clip_id(clip_id);
|
||||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&SpaceAndClipInfo { clip_id, spatial_id: root_space_and_clip.spatial_id },
|
||||
image_size * 2.,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
@ -191,8 +198,6 @@ impl<'a> RawtestHarness<'a> {
|
||||
}
|
||||
);
|
||||
|
||||
builder.pop_clip_id();
|
||||
|
||||
let mut epoch = Epoch(0);
|
||||
|
||||
self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates);
|
||||
@ -242,7 +247,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
}
|
||||
|
||||
fn test_insufficient_blob_visible_area(&mut self) {
|
||||
println!("\tinsufficient blob visible area.");
|
||||
println!("\tinsufficient blob visible area...");
|
||||
|
||||
// This test compares two almost identical display lists containing the a blob
|
||||
// image. The only difference is that one of the display lists specifies a visible
|
||||
@ -261,6 +266,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
let layout_size = LayoutSize::new(800.0, 800.0);
|
||||
let image_size = size(800.0, 800.0);
|
||||
let info = LayoutPrimitiveInfo::new(rect(0.0, 0.0, 800.0, 800.0));
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
let mut txn = Transaction::new();
|
||||
@ -281,6 +287,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
@ -317,6 +324,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
@ -349,6 +357,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
DeviceIntPoint::new(0, window_size.height - test_size.height),
|
||||
test_size,
|
||||
);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
// This exposes a crash in tile decomposition
|
||||
let mut txn = Transaction::new();
|
||||
@ -371,6 +380,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
@ -396,6 +406,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
@ -426,6 +437,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
@ -461,6 +473,8 @@ impl<'a> RawtestHarness<'a> {
|
||||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
{
|
||||
let api = &self.wrench.api;
|
||||
@ -487,6 +501,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -510,6 +525,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
let info = LayoutPrimitiveInfo::new(rect(1.0, 60.0, 200.0, 200.0));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -534,10 +550,6 @@ impl<'a> RawtestHarness<'a> {
|
||||
assert!(pixels_first != pixels_second);
|
||||
|
||||
// cleanup
|
||||
txn = Transaction::new();
|
||||
txn.delete_blob_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
}
|
||||
|
||||
@ -553,6 +565,8 @@ impl<'a> RawtestHarness<'a> {
|
||||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
let (blob_img, blob_img2) = {
|
||||
let api = &self.wrench.api;
|
||||
@ -599,6 +613,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
let push_images = |builder: &mut DisplayListBuilder| {
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -608,6 +623,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
);
|
||||
builder.push_image(
|
||||
&info2,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -666,11 +682,6 @@ impl<'a> RawtestHarness<'a> {
|
||||
assert_eq!(img2_requested.load(Ordering::SeqCst), 2);
|
||||
|
||||
// cleanup
|
||||
txn = Transaction::new();
|
||||
txn.delete_blob_image(blob_img);
|
||||
txn.delete_blob_image(blob_img2);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
}
|
||||
|
||||
@ -685,6 +696,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
let blob_img = {
|
||||
@ -704,6 +716,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -731,6 +744,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
let info = LayoutPrimitiveInfo::new(rect(0.0, 60.0, 200.0, 200.0));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -756,6 +770,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
let info = LayoutPrimitiveInfo::new(rect(0.0, 60.0, 200.0, 200.0));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -769,11 +784,6 @@ impl<'a> RawtestHarness<'a> {
|
||||
|
||||
assert!(pixels_first == pixels_second);
|
||||
assert!(pixels_first != pixels_third);
|
||||
|
||||
// cleanup
|
||||
txn = Transaction::new();
|
||||
txn.delete_blob_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
}
|
||||
|
||||
// Ensures that content doing a save-restore produces the same results as not
|
||||
@ -792,54 +802,71 @@ impl<'a> RawtestHarness<'a> {
|
||||
let mut do_test = |should_try_and_fail| {
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
||||
let clip = builder.define_clip(
|
||||
let spatial_id = SpatialId::root_scroll_node(self.wrench.root_pipeline_id);
|
||||
let clip_id = builder.define_clip(
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
rect(110., 120., 200., 200.),
|
||||
None::<ComplexClipRegion>,
|
||||
None
|
||||
);
|
||||
builder.push_clip_id(clip);
|
||||
builder.push_rect(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
builder.push_rect(
|
||||
&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0),
|
||||
);
|
||||
|
||||
if should_try_and_fail {
|
||||
builder.save();
|
||||
let clip = builder.define_clip(
|
||||
let clip_id = builder.define_clip(
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
rect(80., 80., 90., 90.),
|
||||
None::<ComplexClipRegion>,
|
||||
None
|
||||
);
|
||||
builder.push_clip_id(clip);
|
||||
builder.push_rect(&PrimitiveInfo::new(rect(110., 110., 50., 50.)),
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_shadow(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
Shadow {
|
||||
offset: LayoutVector2D::new(1.0, 1.0),
|
||||
blur_radius: 1.0,
|
||||
color: ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
});
|
||||
builder.push_line(&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0), LineStyle::Solid);
|
||||
let space_and_clip = SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id
|
||||
};
|
||||
builder.push_rect(
|
||||
&PrimitiveInfo::new(rect(110., 110., 50., 50.)),
|
||||
&space_and_clip,
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
builder.push_shadow(
|
||||
&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
&space_and_clip,
|
||||
Shadow {
|
||||
offset: LayoutVector2D::new(1.0, 1.0),
|
||||
blur_radius: 1.0,
|
||||
color: ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
},
|
||||
);
|
||||
builder.push_line(
|
||||
&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
&space_and_clip,
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
LineStyle::Solid,
|
||||
);
|
||||
builder.restore();
|
||||
}
|
||||
|
||||
{
|
||||
builder.save();
|
||||
let clip = builder.define_clip(
|
||||
let clip_id = builder.define_clip(
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
rect(80., 80., 100., 100.),
|
||||
None::<ComplexClipRegion>,
|
||||
None
|
||||
);
|
||||
builder.push_clip_id(clip);
|
||||
builder.push_rect(&PrimitiveInfo::new(rect(150., 150., 100., 100.)),
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.push_rect(
|
||||
&PrimitiveInfo::new(rect(150., 150., 100., 100.)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0),
|
||||
);
|
||||
builder.clear_save();
|
||||
}
|
||||
|
||||
builder.pop_clip_id();
|
||||
|
||||
let txn = Transaction::new();
|
||||
|
||||
self.submit_dl(&mut Epoch(0), layout_size, builder, &txn.resource_updates);
|
||||
@ -866,6 +893,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut do_test = |shadow_is_red| {
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
@ -875,15 +903,22 @@ impl<'a> RawtestHarness<'a> {
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0)
|
||||
};
|
||||
|
||||
builder.push_shadow(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
builder.push_shadow(
|
||||
&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
&space_and_clip,
|
||||
Shadow {
|
||||
offset: LayoutVector2D::new(1.0, 1.0),
|
||||
blur_radius: 1.0,
|
||||
color: shadow_color,
|
||||
});
|
||||
builder.push_line(&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0), LineStyle::Solid);
|
||||
},
|
||||
);
|
||||
builder.push_line(
|
||||
&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
&space_and_clip,
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
LineStyle::Solid,
|
||||
);
|
||||
builder.pop_all_shadows();
|
||||
|
||||
let txn = Transaction::new();
|
||||
@ -923,6 +958,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
|
||||
builder.push_image(
|
||||
&LayoutPrimitiveInfo::new(rect(300.0, 70.0, 150.0, 50.0)),
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
size(150.0, 50.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
@ -991,7 +1027,11 @@ impl<'a> RawtestHarness<'a> {
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
let info = LayoutPrimitiveInfo::new(LayoutRect::new(LayoutPoint::zero(),
|
||||
LayoutSize::new(100.0, 100.0)));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(
|
||||
&info,
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_root_pipeline(self.wrench.root_pipeline_id);
|
||||
@ -1017,11 +1057,12 @@ impl<'a> RawtestHarness<'a> {
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
// Add a rectangle that covers the entire scene.
|
||||
let mut info = LayoutPrimitiveInfo::new(LayoutRect::new(LayoutPoint::zero(), layout_size));
|
||||
info.tag = Some((0, 1));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
// Add a simple 100x100 rectangle at 100,0.
|
||||
let mut info = LayoutPrimitiveInfo::new(LayoutRect::new(
|
||||
@ -1029,7 +1070,7 @@ impl<'a> RawtestHarness<'a> {
|
||||
LayoutSize::new(100., 100.)
|
||||
));
|
||||
info.tag = Some((0, 2));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
let make_rounded_complex_clip = |rect: &LayoutRect, radius: f32| -> ComplexClipRegion {
|
||||
ComplexClipRegion::new(
|
||||
@ -1039,30 +1080,46 @@ impl<'a> RawtestHarness<'a> {
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
// Add a rectangle that is clipped by a rounded rect clip item.
|
||||
let rect = LayoutRect::new(LayoutPoint::new(100., 100.), LayoutSize::new(100., 100.));
|
||||
let clip_id = builder.define_clip(rect, vec![make_rounded_complex_clip(&rect, 20.)], None);
|
||||
builder.push_clip_id(clip_id);
|
||||
let mut info = LayoutPrimitiveInfo::new(rect);
|
||||
info.tag = Some((0, 4));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.pop_clip_id();
|
||||
|
||||
let temp_clip_id = builder.define_clip(
|
||||
&space_and_clip,
|
||||
rect,
|
||||
vec![make_rounded_complex_clip(&rect, 20.)],
|
||||
None,
|
||||
);
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo {
|
||||
tag: Some((0, 4)),
|
||||
.. LayoutPrimitiveInfo::new(rect)
|
||||
},
|
||||
&SpaceAndClipInfo {
|
||||
clip_id: temp_clip_id,
|
||||
spatial_id: space_and_clip.spatial_id,
|
||||
},
|
||||
ColorF::new(1.0, 1.0, 1.0, 1.0),
|
||||
);
|
||||
|
||||
// Add a rectangle that is clipped by a ClipChain containing a rounded rect.
|
||||
let rect = LayoutRect::new(LayoutPoint::new(200., 100.), LayoutSize::new(100., 100.));
|
||||
let clip_id = builder.define_clip(rect, vec![make_rounded_complex_clip(&rect, 20.)], None);
|
||||
let clip_id = builder.define_clip(
|
||||
&space_and_clip,
|
||||
rect,
|
||||
vec![make_rounded_complex_clip(&rect, 20.)],
|
||||
None,
|
||||
);
|
||||
let clip_chain_id = builder.define_clip_chain(None, vec![clip_id]);
|
||||
builder.push_clip_and_scroll_info(ClipAndScrollInfo::new(
|
||||
ClipId::root_scroll_node(self.wrench.root_pipeline_id),
|
||||
ClipId::ClipChain(clip_chain_id),
|
||||
));
|
||||
let mut info = LayoutPrimitiveInfo::new(rect);
|
||||
info.tag = Some((0, 5));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.pop_clip_id();
|
||||
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo {
|
||||
tag: Some((0, 5)),
|
||||
.. LayoutPrimitiveInfo::new(rect)
|
||||
},
|
||||
&SpaceAndClipInfo {
|
||||
clip_id: ClipId::ClipChain(clip_chain_id),
|
||||
spatial_id: space_and_clip.spatial_id,
|
||||
},
|
||||
ColorF::new(1.0, 1.0, 1.0, 1.0),
|
||||
);
|
||||
|
||||
let mut epoch = Epoch(0);
|
||||
let txn = Transaction::new();
|
||||
|
@ -224,7 +224,11 @@ pub struct YamlFrameReader {
|
||||
|
||||
/// A HashMap that allows specifying a numeric id for clip and clip chains in YAML
|
||||
/// and having each of those ids correspond to a unique ClipId.
|
||||
clip_id_map: HashMap<u64, ClipId>,
|
||||
user_clip_id_map: HashMap<u64, ClipId>,
|
||||
user_spatial_id_map: HashMap<u64, SpatialId>,
|
||||
|
||||
clip_id_stack: Vec<ClipId>,
|
||||
spatial_id_stack: Vec<SpatialId>,
|
||||
}
|
||||
|
||||
impl YamlFrameReader {
|
||||
@ -243,9 +247,12 @@ impl YamlFrameReader {
|
||||
fonts: HashMap::new(),
|
||||
font_instances: HashMap::new(),
|
||||
font_render_mode: None,
|
||||
image_map: HashMap::new(),
|
||||
clip_id_map: HashMap::new(),
|
||||
allow_mipmaps: false,
|
||||
image_map: HashMap::new(),
|
||||
user_clip_id_map: HashMap::new(),
|
||||
user_spatial_id_map: HashMap::new(),
|
||||
clip_id_stack: Vec::new(),
|
||||
spatial_id_stack: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,6 +270,13 @@ impl YamlFrameReader {
|
||||
wrench.api.update_resources(txn.resource_updates);
|
||||
}
|
||||
|
||||
fn top_space_and_clip(&self) -> SpaceAndClipInfo {
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: *self.spatial_id_stack.last().unwrap(),
|
||||
clip_id: *self.clip_id_stack.last().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn yaml_path(&self) -> &PathBuf {
|
||||
&self.yaml_path
|
||||
}
|
||||
@ -316,13 +330,21 @@ impl YamlFrameReader {
|
||||
yaml: &Yaml
|
||||
) {
|
||||
// Don't allow referencing clips between pipelines for now.
|
||||
self.clip_id_map.clear();
|
||||
self.user_clip_id_map.clear();
|
||||
self.user_spatial_id_map.clear();
|
||||
self.clip_id_stack.clear();
|
||||
self.clip_id_stack.push(ClipId::root(pipeline_id));
|
||||
self.spatial_id_stack.clear();
|
||||
self.spatial_id_stack.push(SpatialId::root_scroll_node(pipeline_id));
|
||||
|
||||
let content_size = self.get_root_size_from_yaml(wrench, yaml);
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id, content_size);
|
||||
let mut info = LayoutPrimitiveInfo::new(LayoutRect::zero());
|
||||
self.add_stacking_context_from_yaml(&mut builder, wrench, yaml, true, &mut info);
|
||||
self.display_lists.push(builder.finalize());
|
||||
|
||||
assert_eq!(self.clip_id_stack.len(), 1);
|
||||
assert_eq!(self.spatial_id_stack.len(), 1);
|
||||
}
|
||||
|
||||
fn to_complex_clip_region(&mut self, item: &Yaml) -> ComplexClipRegion {
|
||||
@ -362,50 +384,84 @@ impl YamlFrameReader {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_to_clip_id(&self, number: u64, pipeline_id: PipelineId) -> ClipId {
|
||||
match number {
|
||||
0 => ClipId::root_reference_frame(pipeline_id),
|
||||
1 => ClipId::root_scroll_node(pipeline_id),
|
||||
_ => self.clip_id_map[&number],
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn to_clip_id(&self, item: &Yaml, pipeline_id: PipelineId) -> Option<ClipId> {
|
||||
match *item {
|
||||
Yaml::Integer(value) => Some(self.u64_to_clip_id(value as u64, pipeline_id)),
|
||||
Yaml::String(ref id_string) if id_string == "root-reference-frame" =>
|
||||
Some(ClipId::root_reference_frame(pipeline_id)),
|
||||
Yaml::String(ref id_string) if id_string == "root-scroll-node" =>
|
||||
Some(ClipId::root_scroll_node(pipeline_id)),
|
||||
Yaml::Integer(value) => Some(self.user_clip_id_map[&(value as u64)]),
|
||||
Yaml::String(ref id_string) if id_string == "root_clip" =>
|
||||
Some(ClipId::root(pipeline_id)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_spatial_id(&self, item: &Yaml, pipeline_id: PipelineId) -> SpatialId {
|
||||
match *item {
|
||||
Yaml::Integer(value) => self.user_spatial_id_map[&(value as u64)],
|
||||
Yaml::String(ref id_string) if id_string == "root-reference-frame" =>
|
||||
SpatialId::root_reference_frame(pipeline_id),
|
||||
Yaml::String(ref id_string) if id_string == "root-scroll-node" =>
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
_ => {
|
||||
println!("Unable to parse SpatialId {:?}", item);
|
||||
SpatialId::root_reference_frame(pipeline_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_clip_id_mapping(&mut self, numeric_id: u64, real_id: ClipId) {
|
||||
assert!(numeric_id != 0, "id=0 is reserved for the root reference frame");
|
||||
assert!(numeric_id != 1, "id=1 is reserved for the root scroll node");
|
||||
self.clip_id_map.insert(numeric_id, real_id);
|
||||
assert_ne!(numeric_id, 0, "id=0 is reserved for the root clip");
|
||||
self.user_clip_id_map.insert(numeric_id, real_id);
|
||||
}
|
||||
|
||||
pub fn add_spatial_id_mapping(&mut self, numeric_id: u64, real_id: SpatialId) {
|
||||
assert_ne!(numeric_id, 0, "id=0 is reserved for the root reference frame");
|
||||
assert_ne!(numeric_id, 1, "id=1 is reserved for the root scroll node");
|
||||
self.user_spatial_id_map.insert(numeric_id, real_id);
|
||||
}
|
||||
|
||||
fn to_clip_and_scroll_info(
|
||||
&self,
|
||||
item: &Yaml,
|
||||
pipeline_id: PipelineId
|
||||
) -> Option<ClipAndScrollInfo> {
|
||||
) -> (Option<ClipId>, Option<SpatialId>) {
|
||||
// Note: this is tricky. In the old code the single ID could be used either way
|
||||
// for clip/scroll. In the new code we are trying to reflect that and not break
|
||||
// all the reftests. Ultimately we'd want the clip and scroll nodes to be
|
||||
// provided separately in YAML.
|
||||
match *item {
|
||||
Yaml::BadValue => (None, None),
|
||||
Yaml::Array(ref array) if array.len() == 2 => {
|
||||
let scroll_id = match self.to_clip_id(&array[0], pipeline_id) {
|
||||
Some(id) => id,
|
||||
None => return None,
|
||||
};
|
||||
let clip_id = match self.to_clip_id(&array[1], pipeline_id) {
|
||||
Some(id) => id,
|
||||
None => return None,
|
||||
};
|
||||
Some(ClipAndScrollInfo::new(scroll_id, clip_id))
|
||||
let scroll_id = self.to_spatial_id(&array[0], pipeline_id);
|
||||
let clip_id = self.to_clip_id(&array[1], pipeline_id);
|
||||
(clip_id, Some(scroll_id))
|
||||
}
|
||||
Yaml::String(ref id_string) if id_string == "root-reference-frame" => {
|
||||
let scroll_id = SpatialId::root_reference_frame(pipeline_id);
|
||||
let clip_id = ClipId::root(pipeline_id);
|
||||
(Some(clip_id), Some(scroll_id))
|
||||
}
|
||||
Yaml::String(ref id_string) if id_string == "root-scroll-node" => {
|
||||
let scroll_id = SpatialId::root_scroll_node(pipeline_id);
|
||||
(None, Some(scroll_id))
|
||||
}
|
||||
Yaml::String(ref id_string) if id_string == "root_clip" => {
|
||||
let clip_id = ClipId::root(pipeline_id);
|
||||
(Some(clip_id), None)
|
||||
}
|
||||
Yaml::Integer(value) => {
|
||||
let scroll_id = self.user_spatial_id_map
|
||||
.get(&(value as u64))
|
||||
.cloned();
|
||||
let clip_id = self.user_clip_id_map
|
||||
.get(&(value as u64))
|
||||
.cloned();
|
||||
assert!(scroll_id.is_some() || clip_id.is_some(),
|
||||
"clip-and-scroll index not found: {}", value);
|
||||
(clip_id, scroll_id)
|
||||
}
|
||||
_ => {
|
||||
println!("Unable to parse clip/scroll {:?}", item);
|
||||
(None, None)
|
||||
}
|
||||
_ => self.to_clip_id(item, pipeline_id).map(|id| ClipAndScrollInfo::simple(id)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -709,7 +765,7 @@ impl YamlFrameReader {
|
||||
.as_rect()
|
||||
.expect("rect type must have bounds");
|
||||
let color = item["color"].as_colorf().unwrap_or(ColorF::WHITE);
|
||||
dl.push_rect(&info, color);
|
||||
dl.push_rect(&info, &self.top_space_and_clip(), color);
|
||||
}
|
||||
|
||||
fn handle_clear_rect(
|
||||
@ -721,7 +777,7 @@ impl YamlFrameReader {
|
||||
info.rect = item["bounds"]
|
||||
.as_rect()
|
||||
.expect("clear-rect type must have bounds");
|
||||
dl.push_clear_rect(&info);
|
||||
dl.push_clear_rect(&info, &self.top_space_and_clip());
|
||||
}
|
||||
|
||||
fn handle_line(
|
||||
@ -777,6 +833,7 @@ impl YamlFrameReader {
|
||||
|
||||
dl.push_line(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
wavy_line_thickness,
|
||||
orientation,
|
||||
&color,
|
||||
@ -803,7 +860,7 @@ impl YamlFrameReader {
|
||||
let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size);
|
||||
let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero());
|
||||
|
||||
dl.push_gradient(&info, gradient, tile_size, tile_spacing);
|
||||
dl.push_gradient(&info, &self.top_space_and_clip(), gradient, tile_size, tile_spacing);
|
||||
}
|
||||
|
||||
fn handle_radial_gradient(
|
||||
@ -825,7 +882,13 @@ impl YamlFrameReader {
|
||||
let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size);
|
||||
let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero());
|
||||
|
||||
dl.push_radial_gradient(&info, gradient, tile_size, tile_spacing);
|
||||
dl.push_radial_gradient(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
gradient,
|
||||
tile_size,
|
||||
tile_spacing,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_border(
|
||||
@ -987,7 +1050,7 @@ impl YamlFrameReader {
|
||||
None
|
||||
};
|
||||
if let Some(details) = border_details {
|
||||
dl.push_border(&info, widths, details);
|
||||
dl.push_border(&info, &self.top_space_and_clip(), widths, details);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1028,6 +1091,7 @@ impl YamlFrameReader {
|
||||
|
||||
dl.push_box_shadow(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
box_bounds,
|
||||
offset,
|
||||
color,
|
||||
@ -1090,6 +1154,7 @@ impl YamlFrameReader {
|
||||
|
||||
dl.push_yuv_image(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
yuv_data,
|
||||
color_depth,
|
||||
color_space,
|
||||
@ -1150,7 +1215,16 @@ impl YamlFrameReader {
|
||||
item
|
||||
),
|
||||
};
|
||||
dl.push_image(&info, stretch_size, tile_spacing, rendering, alpha_type, image_key, ColorF::WHITE);
|
||||
dl.push_image(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
rendering,
|
||||
alpha_type,
|
||||
image_key,
|
||||
ColorF::WHITE,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_text(
|
||||
@ -1265,7 +1339,14 @@ impl YamlFrameReader {
|
||||
};
|
||||
info.rect = rect;
|
||||
|
||||
dl.push_text(&info, &glyphs, font_instance_key, color, None);
|
||||
dl.push_text(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
&glyphs,
|
||||
font_instance_key,
|
||||
color,
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_iframe(
|
||||
@ -1277,7 +1358,7 @@ impl YamlFrameReader {
|
||||
info.rect = item["bounds"].as_rect().expect("iframe must have bounds");
|
||||
let pipeline_id = item["id"].as_pipeline_id().unwrap();
|
||||
let ignore = item["ignore_missing_pipeline"].as_bool().unwrap_or(true);
|
||||
dl.push_iframe(&info, pipeline_id, ignore);
|
||||
dl.push_iframe(&info, &self.top_space_and_clip(), pipeline_id, ignore);
|
||||
}
|
||||
|
||||
pub fn get_complex_clip_for_item(&mut self, yaml: &Yaml) -> Option<ComplexClipRegion> {
|
||||
@ -1332,12 +1413,15 @@ impl YamlFrameReader {
|
||||
continue;
|
||||
}
|
||||
|
||||
let clip_scroll_info = self.to_clip_and_scroll_info(
|
||||
let (set_clip_id, set_scroll_id) = self.to_clip_and_scroll_info(
|
||||
&item["clip-and-scroll"],
|
||||
dl.pipeline_id
|
||||
);
|
||||
if let Some(clip_scroll_info) = clip_scroll_info {
|
||||
dl.push_clip_and_scroll_info(clip_scroll_info);
|
||||
if let Some(clip_id) = set_clip_id {
|
||||
self.clip_id_stack.push(clip_id);
|
||||
}
|
||||
if let Some(scroll_id) = set_scroll_id {
|
||||
self.spatial_id_stack.push(scroll_id);
|
||||
}
|
||||
|
||||
let complex_clip = self.get_complex_clip_for_item(item);
|
||||
@ -1348,8 +1432,13 @@ impl YamlFrameReader {
|
||||
match item_type {
|
||||
"clip" | "clip-chain" | "scroll-frame" => {},
|
||||
_ => {
|
||||
let id = dl.define_clip(clip_rect, vec![complex_clip], None);
|
||||
dl.push_clip_id(id);
|
||||
let id = dl.define_clip(
|
||||
&self.top_space_and_clip(),
|
||||
clip_rect,
|
||||
vec![complex_clip],
|
||||
None,
|
||||
);
|
||||
self.clip_id_stack.push(id);
|
||||
pushed_clip = true;
|
||||
}
|
||||
}
|
||||
@ -1385,14 +1474,14 @@ impl YamlFrameReader {
|
||||
}
|
||||
|
||||
if pushed_clip {
|
||||
dl.pop_clip_id();
|
||||
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
}
|
||||
|
||||
if clip_scroll_info.is_some() {
|
||||
dl.pop_clip_id();
|
||||
if set_clip_id.is_some() {
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
}
|
||||
if set_scroll_id.is_some() {
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1419,7 +1508,8 @@ impl YamlFrameReader {
|
||||
id
|
||||
});
|
||||
|
||||
let real_id = dl.define_scroll_frame(
|
||||
let space_and_clip = dl.define_scroll_frame(
|
||||
&self.top_space_and_clip(),
|
||||
external_id,
|
||||
content_rect,
|
||||
clip_rect,
|
||||
@ -1428,13 +1518,16 @@ impl YamlFrameReader {
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
);
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id, real_id);
|
||||
self.add_spatial_id_mapping(numeric_id, space_and_clip.spatial_id);
|
||||
self.add_clip_id_mapping(numeric_id, space_and_clip.clip_id);
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(real_id);
|
||||
self.spatial_id_stack.push(space_and_clip.spatial_id);
|
||||
self.clip_id_stack.push(space_and_clip.clip_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1448,6 +1541,7 @@ impl YamlFrameReader {
|
||||
let numeric_id = yaml["id"].as_i64().map(|id| id as u64);
|
||||
|
||||
let real_id = dl.define_sticky_frame(
|
||||
*self.spatial_id_stack.last().unwrap(),
|
||||
bounds,
|
||||
SideOffsets2D::new(
|
||||
yaml["margin-top"].as_f32(),
|
||||
@ -1461,13 +1555,13 @@ impl YamlFrameReader {
|
||||
);
|
||||
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id, real_id);
|
||||
self.add_spatial_id_mapping(numeric_id, real_id);
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(real_id);
|
||||
self.spatial_id_stack.push(real_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1483,6 +1577,7 @@ impl YamlFrameReader {
|
||||
|
||||
dl.push_shadow(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
Shadow {
|
||||
blur_radius,
|
||||
offset,
|
||||
@ -1499,8 +1594,9 @@ impl YamlFrameReader {
|
||||
let numeric_id = yaml["id"].as_i64().expect("clip chains must have an id");
|
||||
let clip_ids: Vec<ClipId> = yaml["clips"]
|
||||
.as_vec_u64()
|
||||
.unwrap_or_else(Vec::new)
|
||||
.iter().map(|id| self.u64_to_clip_id(*id, builder.pipeline_id))
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.map(|id| self.user_clip_id_map[id])
|
||||
.collect();
|
||||
|
||||
let parent = self.to_clip_id(&yaml["parent"], builder.pipeline_id);
|
||||
@ -1520,15 +1616,22 @@ impl YamlFrameReader {
|
||||
let complex_clips = self.to_complex_clip_regions(&yaml["complex"]);
|
||||
let image_mask = self.to_image_mask(&yaml["image-mask"], wrench);
|
||||
|
||||
let real_id = dl.define_clip(clip_rect, complex_clips, image_mask);
|
||||
let space_and_clip = self.top_space_and_clip();
|
||||
let real_id = dl.define_clip(
|
||||
&space_and_clip,
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
);
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id as u64, real_id);
|
||||
self.add_spatial_id_mapping(numeric_id as u64, space_and_clip.spatial_id);
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(real_id);
|
||||
self.clip_id_stack.push(real_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1544,7 +1647,7 @@ impl YamlFrameReader {
|
||||
dl: &mut DisplayListBuilder,
|
||||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
) -> ClipId {
|
||||
) -> SpatialId {
|
||||
let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32());
|
||||
let bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
let default_transform_origin = LayoutPoint::new(
|
||||
@ -1578,6 +1681,7 @@ impl YamlFrameReader {
|
||||
|
||||
let reference_frame_id = dl.push_reference_frame(
|
||||
&bounds,
|
||||
*self.spatial_id_stack.last().unwrap(),
|
||||
transform_style,
|
||||
transform.into(),
|
||||
perspective,
|
||||
@ -1585,7 +1689,7 @@ impl YamlFrameReader {
|
||||
|
||||
let numeric_id = yaml["id"].as_i64();
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id as u64, reference_frame_id);
|
||||
self.add_spatial_id_mapping(numeric_id as u64, reference_frame_id);
|
||||
}
|
||||
|
||||
reference_frame_id
|
||||
@ -1597,14 +1701,14 @@ impl YamlFrameReader {
|
||||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
) {
|
||||
let reference_frame_id = self.push_reference_frame(dl, wrench, yaml);
|
||||
let real_id = self.push_reference_frame(dl, wrench, yaml);
|
||||
self.spatial_id_stack.push(real_id);
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(reference_frame_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
}
|
||||
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
dl.pop_reference_frame();
|
||||
}
|
||||
|
||||
@ -1617,21 +1721,21 @@ impl YamlFrameReader {
|
||||
info: &mut LayoutPrimitiveInfo,
|
||||
) {
|
||||
let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32());
|
||||
let bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
info.rect = bounds;
|
||||
info.clip_rect = bounds;
|
||||
let mut bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
|
||||
let reference_frame_id = if !yaml["transform"].is_badvalue() ||
|
||||
!yaml["perspective"].is_badvalue() {
|
||||
let reference_frame_id = self.push_reference_frame(dl, wrench, yaml);
|
||||
info.rect.origin = LayoutPoint::zero();
|
||||
info.clip_rect.origin = LayoutPoint::zero();
|
||||
self.spatial_id_stack.push(reference_frame_id);
|
||||
bounds.origin = LayoutPoint::zero();
|
||||
Some(reference_frame_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// note: this API is deprecated, use the standard clip-and-scroll field instead
|
||||
let clip_node_id = self.to_clip_id(&yaml["clip-node"], dl.pipeline_id);
|
||||
|
||||
let transform_style = yaml["transform-style"]
|
||||
.as_transform_style()
|
||||
.unwrap_or(TransformStyle::Flat);
|
||||
@ -1651,12 +1755,12 @@ impl YamlFrameReader {
|
||||
|
||||
let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]);
|
||||
|
||||
if let Some(reference_frame_id) = reference_frame_id {
|
||||
dl.push_clip_id(reference_frame_id);
|
||||
}
|
||||
info.rect = bounds;
|
||||
info.clip_rect = bounds;
|
||||
|
||||
dl.push_stacking_context(
|
||||
&info,
|
||||
*self.spatial_id_stack.last().unwrap(),
|
||||
clip_node_id,
|
||||
transform_style,
|
||||
mix_blend_mode,
|
||||
@ -1671,10 +1775,7 @@ impl YamlFrameReader {
|
||||
dl.pop_stacking_context();
|
||||
|
||||
if reference_frame_id.is_some() {
|
||||
dl.pop_clip_id();
|
||||
}
|
||||
|
||||
if reference_frame_id.is_some() {
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
dl.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use super::CURRENT_FRAME_NUMBER;
|
||||
use time;
|
||||
use webrender;
|
||||
use webrender::api::*;
|
||||
use webrender::api::SpecificDisplayItem::*;
|
||||
use webrender::api::SpecificDisplayItem as Sdi;
|
||||
use webrender::api::channel::Payload;
|
||||
use yaml_helper::StringEnum;
|
||||
use yaml_rust::{Yaml, YamlEmitter};
|
||||
@ -206,7 +206,7 @@ fn write_reference_frame(
|
||||
matrix4d_node(parent, "perspective", &perspective);
|
||||
}
|
||||
|
||||
usize_node(parent, "id", clip_id_mapper.add_id(reference_frame.id));
|
||||
usize_node(parent, "id", clip_id_mapper.add_spatial_id(reference_frame.id));
|
||||
}
|
||||
|
||||
fn write_stacking_context(
|
||||
@ -214,7 +214,6 @@ fn write_stacking_context(
|
||||
sc: &StackingContext,
|
||||
properties: &SceneProperties,
|
||||
filter_iter: AuxIter<FilterOp>,
|
||||
clip_id_mapper: &ClipIdMapper,
|
||||
) {
|
||||
enum_node(parent, "transform-style", sc.transform_style);
|
||||
|
||||
@ -228,10 +227,6 @@ fn write_stacking_context(
|
||||
};
|
||||
str_node(parent, "raster-space", &raster_space);
|
||||
|
||||
if let Some(clip_node_id) = sc.clip_node_id {
|
||||
yaml_node(parent, "clip-node", clip_id_mapper.map_id(&clip_node_id));
|
||||
}
|
||||
|
||||
// mix_blend_mode
|
||||
if sc.mix_blend_mode != MixBlendMode::Normal {
|
||||
enum_node(parent, "mix-blend-mode", sc.mix_blend_mode)
|
||||
@ -767,18 +762,22 @@ impl YamlFrameWriter {
|
||||
);
|
||||
}
|
||||
|
||||
yaml_node(&mut v, "clip-and-scroll", clip_id_mapper.map_info(&base.clip_and_scroll()));
|
||||
let space_and_clip = base.space_and_clip_info();
|
||||
let clip_id = if space_and_clip.clip_id.is_root() { None } else { Some(space_and_clip.clip_id) };
|
||||
yaml_node(&mut v, "clip-and-scroll",
|
||||
clip_id_mapper.map_clip_and_scroll_ids(clip_id, space_and_clip.spatial_id)
|
||||
);
|
||||
bool_node(&mut v, "backface-visible", base.is_backface_visible());
|
||||
|
||||
match *base.item() {
|
||||
Rectangle(item) => {
|
||||
Sdi::Rectangle(item) => {
|
||||
str_node(&mut v, "type", "rect");
|
||||
color_node(&mut v, "color", item.color);
|
||||
}
|
||||
ClearRectangle => {
|
||||
Sdi::ClearRectangle => {
|
||||
str_node(&mut v, "type", "clear-rect");;
|
||||
}
|
||||
Line(item) => {
|
||||
Sdi::Line(item) => {
|
||||
str_node(&mut v, "type", "line");
|
||||
if let LineStyle::Wavy = item.style {
|
||||
f32_node(&mut v, "thickness", item.wavy_line_thickness);
|
||||
@ -787,7 +786,7 @@ impl YamlFrameWriter {
|
||||
color_node(&mut v, "color", item.color);
|
||||
str_node(&mut v, "style", item.style.as_str());
|
||||
}
|
||||
Text(item) => {
|
||||
Sdi::Text(item) => {
|
||||
let gi = display_list.get(base.glyphs());
|
||||
let mut indices: Vec<u32> = vec![];
|
||||
let mut offsets: Vec<f32> = vec![];
|
||||
@ -841,7 +840,7 @@ impl YamlFrameWriter {
|
||||
}
|
||||
}
|
||||
}
|
||||
Image(item) => {
|
||||
Sdi::Image(item) => {
|
||||
if let Some(path) = self.path_for_image(item.image_key) {
|
||||
path_node(&mut v, "image", &path);
|
||||
}
|
||||
@ -864,12 +863,12 @@ impl YamlFrameWriter {
|
||||
AlphaType::Alpha => str_node(&mut v, "alpha-type", "alpha"),
|
||||
};
|
||||
}
|
||||
YuvImage(_) => {
|
||||
Sdi::YuvImage(_) => {
|
||||
str_node(&mut v, "type", "yuv-image");
|
||||
// TODO
|
||||
println!("TODO YAML YuvImage");
|
||||
}
|
||||
Border(item) => {
|
||||
Sdi::Border(item) => {
|
||||
str_node(&mut v, "type", "border");
|
||||
match item.details {
|
||||
BorderDetails::Normal(ref details) => {
|
||||
@ -984,7 +983,7 @@ impl YamlFrameWriter {
|
||||
}
|
||||
}
|
||||
}
|
||||
BoxShadow(item) => {
|
||||
Sdi::BoxShadow(item) => {
|
||||
str_node(&mut v, "type", "box-shadow");
|
||||
rect_node(&mut v, "box-bounds", &item.box_bounds);
|
||||
vector_node(&mut v, "offset", &item.offset);
|
||||
@ -1000,7 +999,7 @@ impl YamlFrameWriter {
|
||||
};
|
||||
str_node(&mut v, "clip-mode", clip_mode);
|
||||
}
|
||||
Gradient(item) => {
|
||||
Sdi::Gradient(item) => {
|
||||
str_node(&mut v, "type", "gradient");
|
||||
point_node(&mut v, "start", &item.gradient.start_point);
|
||||
point_node(&mut v, "end", &item.gradient.end_point);
|
||||
@ -1018,7 +1017,7 @@ impl YamlFrameWriter {
|
||||
item.gradient.extend_mode == ExtendMode::Repeat,
|
||||
);
|
||||
}
|
||||
RadialGradient(item) => {
|
||||
Sdi::RadialGradient(item) => {
|
||||
str_node(&mut v, "type", "radial-gradient");
|
||||
size_node(&mut v, "tile-size", &item.tile_size);
|
||||
size_node(&mut v, "tile-spacing", &item.tile_spacing);
|
||||
@ -1029,12 +1028,12 @@ impl YamlFrameWriter {
|
||||
display_list
|
||||
);
|
||||
}
|
||||
Iframe(item) => {
|
||||
Sdi::Iframe(item) => {
|
||||
str_node(&mut v, "type", "iframe");
|
||||
u32_vec_node(&mut v, "id", &[item.pipeline_id.0, item.pipeline_id.1]);
|
||||
bool_node(&mut v, "ignore_missing_pipeline", item.ignore_missing_pipeline);
|
||||
}
|
||||
PushStackingContext(item) => {
|
||||
Sdi::PushStackingContext(item) => {
|
||||
str_node(&mut v, "type", "stacking-context");
|
||||
let filters = display_list.get(base.filters());
|
||||
write_stacking_context(
|
||||
@ -1042,6 +1041,18 @@ impl YamlFrameWriter {
|
||||
&item.stacking_context,
|
||||
&scene.properties,
|
||||
filters,
|
||||
);
|
||||
|
||||
let mut sub_iter = base.sub_iter();
|
||||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
Sdi::PushReferenceFrame(item) => {
|
||||
str_node(&mut v, "type", "reference-frame");
|
||||
write_reference_frame(
|
||||
&mut v,
|
||||
&item.reference_frame,
|
||||
&scene.properties,
|
||||
clip_id_mapper,
|
||||
);
|
||||
|
||||
@ -1049,22 +1060,9 @@ impl YamlFrameWriter {
|
||||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
PushReferenceFrame(item) => {
|
||||
str_node(&mut v, "type", "reference-frame");
|
||||
write_reference_frame(
|
||||
&mut v,
|
||||
&item.reference_frame,
|
||||
&scene.properties,
|
||||
clip_id_mapper
|
||||
);
|
||||
|
||||
let mut sub_iter = base.sub_iter();
|
||||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
Clip(item) => {
|
||||
Sdi::Clip(item) => {
|
||||
str_node(&mut v, "type", "clip");
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_id(item.id));
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_clip_id(item.id));
|
||||
|
||||
let (complex_clips, complex_clip_count) = base.complex_clip();
|
||||
if let Some(complex) = self.make_complex_clips_node(
|
||||
@ -1079,25 +1077,25 @@ impl YamlFrameWriter {
|
||||
yaml_node(&mut v, "image-mask", mask_yaml);
|
||||
}
|
||||
}
|
||||
ClipChain(item) => {
|
||||
Sdi::ClipChain(item) => {
|
||||
str_node(&mut v, "type", "clip-chain");
|
||||
|
||||
let id = ClipId::ClipChain(item.id);
|
||||
u32_node(&mut v, "id", clip_id_mapper.add_id(id) as u32);
|
||||
u32_node(&mut v, "id", clip_id_mapper.add_clip_id(id) as u32);
|
||||
|
||||
let clip_ids = display_list.get(base.clip_chain_items()).map(|clip_id| {
|
||||
clip_id_mapper.map_id(&clip_id)
|
||||
clip_id_mapper.map_clip_id(&clip_id)
|
||||
}).collect();
|
||||
yaml_node(&mut v, "clips", Yaml::Array(clip_ids));
|
||||
|
||||
if let Some(parent) = item.parent {
|
||||
let parent = ClipId::ClipChain(parent);
|
||||
yaml_node(&mut v, "parent", clip_id_mapper.map_id(&parent));
|
||||
yaml_node(&mut v, "parent", clip_id_mapper.map_clip_id(&parent));
|
||||
}
|
||||
}
|
||||
ScrollFrame(item) => {
|
||||
Sdi::ScrollFrame(item) => {
|
||||
str_node(&mut v, "type", "scroll-frame");
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_id(item.scroll_frame_id));
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_spatial_id(item.scroll_frame_id));
|
||||
size_node(&mut v, "content-size", &base.rect().size);
|
||||
rect_node(&mut v, "bounds", &base.clip_rect());
|
||||
|
||||
@ -1114,9 +1112,9 @@ impl YamlFrameWriter {
|
||||
yaml_node(&mut v, "image-mask", mask_yaml);
|
||||
}
|
||||
}
|
||||
StickyFrame(item) => {
|
||||
Sdi::StickyFrame(item) => {
|
||||
str_node(&mut v, "type", "sticky-frame");
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_id(item.id));
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_spatial_id(item.id));
|
||||
rect_node(&mut v, "bounds", &base.clip_rect());
|
||||
|
||||
if let Some(margin) = item.margins.top {
|
||||
@ -1151,21 +1149,22 @@ impl YamlFrameWriter {
|
||||
yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied));
|
||||
}
|
||||
|
||||
PopCacheMarker => return,
|
||||
PushCacheMarker(_) => {
|
||||
Sdi::PopReferenceFrame |
|
||||
Sdi::PopStackingContext => return,
|
||||
|
||||
Sdi::PopCacheMarker => return,
|
||||
Sdi::PushCacheMarker(_) => {
|
||||
str_node(&mut v, "type", "cache-marker");
|
||||
}
|
||||
|
||||
PopStackingContext => return,
|
||||
PopReferenceFrame => return,
|
||||
SetGradientStops => panic!("dummy item yielded?"),
|
||||
PushShadow(shadow) => {
|
||||
Sdi::SetGradientStops => panic!("dummy item yielded?"),
|
||||
Sdi::PushShadow(shadow) => {
|
||||
str_node(&mut v, "type", "shadow");
|
||||
vector_node(&mut v, "offset", &shadow.offset);
|
||||
color_node(&mut v, "color", shadow.color);
|
||||
f32_node(&mut v, "blur-radius", shadow.blur_radius);
|
||||
}
|
||||
PopAllShadows => {
|
||||
Sdi::PopAllShadows => {
|
||||
str_node(&mut v, "type", "pop-all-shadows");
|
||||
}
|
||||
}
|
||||
@ -1247,43 +1246,62 @@ impl webrender::ApiRecordingReceiver for YamlFrameWriterReceiver {
|
||||
}
|
||||
|
||||
/// This structure allows mapping both `Clip` and `ClipExternalId`
|
||||
/// `ClipIds` onto one set of numeric ids. This prevents ids
|
||||
/// from clashing in the yaml output.
|
||||
/// `ClipIds` onto one set of numeric ids. It also handles `SpatialId`
|
||||
/// in a separate map. This prevents ids from clashing in the yaml output.
|
||||
struct ClipIdMapper {
|
||||
hash_map: HashMap<ClipId, usize>,
|
||||
clip_map: HashMap<ClipId, usize>,
|
||||
spatial_map: HashMap<SpatialId, usize>,
|
||||
current_clip_id: usize,
|
||||
current_spatial_id: usize,
|
||||
}
|
||||
|
||||
impl ClipIdMapper {
|
||||
fn new() -> ClipIdMapper {
|
||||
fn new() -> Self {
|
||||
ClipIdMapper {
|
||||
hash_map: HashMap::new(),
|
||||
current_clip_id: 2,
|
||||
clip_map: HashMap::new(),
|
||||
spatial_map: HashMap::new(),
|
||||
current_clip_id: 1, // see FIRST_CLIP_NODE_INDEX
|
||||
current_spatial_id: 2, // see FIRST_SPATIAL_NODE_INDEX
|
||||
}
|
||||
}
|
||||
|
||||
fn add_id(&mut self, id: ClipId) -> usize {
|
||||
self.hash_map.insert(id, self.current_clip_id);
|
||||
fn add_clip_id(&mut self, id: ClipId) -> usize {
|
||||
self.clip_map.insert(id, self.current_clip_id);
|
||||
self.current_clip_id += 1;
|
||||
self.current_clip_id - 1
|
||||
}
|
||||
|
||||
fn map_id(&self, id: &ClipId) -> Yaml {
|
||||
fn add_spatial_id(&mut self, id: SpatialId) -> usize {
|
||||
self.spatial_map.insert(id, self.current_spatial_id);
|
||||
self.current_spatial_id += 1;
|
||||
self.current_spatial_id - 1
|
||||
}
|
||||
|
||||
fn map_spatial_id(&self, id: &SpatialId) -> Yaml {
|
||||
if id.is_root_reference_frame() {
|
||||
Yaml::String("root-reference-frame".to_owned())
|
||||
} else if id.is_root_scroll_node() {
|
||||
Yaml::String("root-scroll-node".to_owned())
|
||||
} else {
|
||||
Yaml::Integer(*self.hash_map.get(id).unwrap() as i64)
|
||||
Yaml::Integer(self.spatial_map[id] as i64)
|
||||
}
|
||||
}
|
||||
|
||||
fn map_info(&self, info: &ClipAndScrollInfo) -> Yaml {
|
||||
let scroll_node_yaml = self.map_id(&info.scroll_node_id);
|
||||
match info.clip_node_id {
|
||||
fn map_clip_id(&self, id: &ClipId) -> Yaml {
|
||||
assert!(id.is_valid());
|
||||
if id.is_root() {
|
||||
Yaml::String("root_clip".to_owned())
|
||||
} else {
|
||||
Yaml::Integer(self.clip_map[id] as i64)
|
||||
}
|
||||
}
|
||||
|
||||
fn map_clip_and_scroll_ids(&self, clip_id: Option<ClipId>, spatial_id: SpatialId) -> Yaml {
|
||||
let scroll_node_yaml = self.map_spatial_id(&spatial_id);
|
||||
match clip_id {
|
||||
Some(ref clip_node_id) => Yaml::Array(vec![
|
||||
scroll_node_yaml,
|
||||
self.map_id(&clip_node_id)
|
||||
self.map_clip_id(&clip_node_id)
|
||||
]),
|
||||
None => scroll_node_yaml,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user