| author | Connor Brewster <cbrewster@mozilla.com> |
| Tue, 13 Aug 2019 22:02:37 +0000 | |
| changeset 487806 | b5d6ed62cda18c51ae303d6b904771850a3d1e03 |
| parent 487805 | 828e2e9b86e85bbd7e6483c3437d50980433859c |
| child 487807 | abdb4f5f3323cc1474d02a3722741c5d2cea5df7 |
| push id | 36430 |
| push user | dvarga@mozilla.com |
| push date | Wed, 14 Aug 2019 04:09:17 +0000 |
| treeherder | mozilla-central@d3deef805f92 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | gw |
| bugs | 1178765 |
| milestone | 70.0a1 |
| first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
| last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -339,17 +339,18 @@ struct MOZ_STACK_CLASS StackingContextPa : WrStackingContextParams{WrStackingContextClip::None(), nullptr, nullptr, wr::TransformStyle::Flat, wr::WrReferenceFrameKind::Transform, nullptr, /* is_backface_visible = */ true, /* cache_tiles = */ false, - wr::MixBlendMode::Normal} {} + wr::MixBlendMode::Normal, + /* is_backdrop_root = */ false} {} void SetPreserve3D(bool aPreserve) { transform_style = aPreserve ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat; } nsTArray<wr::FilterOp> mFilters; nsTArray<wr::WrFilterData> mFilterDatas;
--- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -2080,16 +2080,19 @@ pub struct WrStackingContextParams { pub opacity: *const f32, pub transform_style: TransformStyle, pub reference_frame_kind: WrReferenceFrameKind, pub scrolling_relative_to: *const u64, pub is_backface_visible: bool, /// True if picture caching should be enabled for this stacking context. pub cache_tiles: bool, pub mix_blend_mode: MixBlendMode, + /// True if this stacking context is a backdrop root. + /// https://drafts.fxtf.org/filter-effects-2/#BackdropRoot + pub is_backdrop_root: bool, } #[no_mangle] pub extern "C" fn wr_dp_push_stacking_context( state: &mut WrState, mut bounds: LayoutRect, spatial_id: WrSpatialId, params: &WrStackingContextParams, @@ -2201,17 +2204,18 @@ pub extern "C" fn wr_dp_push_stacking_co params.is_backface_visible, wr_clip_id, params.transform_style, params.mix_blend_mode, &filters, &r_filter_datas, &[], glyph_raster_space, - params.cache_tiles); + params.cache_tiles, + params.is_backdrop_root); result } #[no_mangle] pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState, is_reference_frame: bool) { debug_assert!(unsafe { !is_in_render_thread() });
--- a/gfx/wr/webrender/src/display_list_flattener.rs +++ b/gfx/wr/webrender/src/display_list_flattener.rs @@ -1306,16 +1306,19 @@ impl<'a> DisplayListFlattener<'a> { } DisplayItem::StickyFrame(ref info) => { let parent_space = self.get_space(&info.parent_spatial_id); self.flatten_sticky_frame( info, parent_space, ); } + DisplayItem::BackdropFilter(ref info) => { + unimplemented!(); + } // Do nothing; these are dummy items for the display list parser DisplayItem::SetGradientStops | DisplayItem::SetFilterOps | DisplayItem::SetFilterData | DisplayItem::SetFilterPrimitives => {} DisplayItem::PopReferenceFrame |
--- a/gfx/wr/webrender_api/src/display_item.rs +++ b/gfx/wr/webrender_api/src/display_item.rs @@ -100,16 +100,17 @@ pub enum DisplayItem { Line(LineDisplayItem), Border(BorderDisplayItem), BoxShadow(BoxShadowDisplayItem), PushShadow(PushShadowDisplayItem), Gradient(GradientDisplayItem), RadialGradient(RadialGradientDisplayItem), Image(ImageDisplayItem), YuvImage(YuvImageDisplayItem), + BackdropFilter(BackdropFilterDisplayItem), // Clips Clip(ClipDisplayItem), ClipChain(ClipChainItem), // Spaces and Frames that content can be scoped under. ScrollFrame(ScrollFrameDisplayItem), StickyFrame(StickyFrameDisplayItem), @@ -143,16 +144,17 @@ pub enum DebugDisplayItem { Line(LineDisplayItem), Border(BorderDisplayItem), BoxShadow(BoxShadowDisplayItem), PushShadow(PushShadowDisplayItem), Gradient(GradientDisplayItem), RadialGradient(RadialGradientDisplayItem), Image(ImageDisplayItem), YuvImage(YuvImageDisplayItem), + BackdropFilter(BackdropFilterDisplayItem), Clip(ClipDisplayItem, Vec<ComplexClipRegion>), ClipChain(ClipChainItem, Vec<ClipId>), ScrollFrame(ScrollFrameDisplayItem, Vec<ComplexClipRegion>), StickyFrame(StickyFrameDisplayItem), Iframe(IframeDisplayItem), PushReferenceFrame(ReferenceFrameDisplayListItem), @@ -606,16 +608,23 @@ pub struct RadialGradientDisplayItem { // FIXME: this should ideally just be `tile_origin` here, with the clip_rect // defining the bounds of the item. Needs non-trivial backend changes. pub bounds: LayoutRect, pub gradient: RadialGradient, pub tile_size: LayoutSize, pub tile_spacing: LayoutSize, } +/// Renders a filtered region of its backdrop +#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)] +pub struct BackdropFilterDisplayItem { + pub common: CommonItemProperties, +} +// IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive> + #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)] pub struct ReferenceFrameDisplayListItem { pub origin: LayoutPoint, pub parent_spatial_id: SpatialId, pub reference_frame: ReferenceFrame, } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)] @@ -647,17 +656,20 @@ pub struct PushStackingContextDisplayIte #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)] pub struct StackingContext { pub transform_style: TransformStyle, pub mix_blend_mode: MixBlendMode, pub clip_id: Option<ClipId>, pub raster_space: RasterSpace, /// True if picture caching should be used on this stacking context. pub cache_tiles: bool, -} // IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive> + /// True if this stacking context is a backdrop root. + pub is_backdrop_root: bool, +} +// IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive> #[repr(u8)] #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)] pub enum TransformStyle { Flat = 0, Preserve3D = 1, } @@ -1359,16 +1371,17 @@ impl DisplayItem { DisplayItem::SetFilterPrimitives => "set_filter_primitives", DisplayItem::RadialGradient(..) => "radial_gradient", DisplayItem::Rectangle(..) => "rectangle", DisplayItem::ScrollFrame(..) => "scroll_frame", DisplayItem::SetGradientStops => "set_gradient_stops", DisplayItem::StickyFrame(..) => "sticky_frame", DisplayItem::Text(..) => "text", DisplayItem::YuvImage(..) => "yuv_image", + DisplayItem::BackdropFilter(..) => "backdrop_filter", } } } macro_rules! impl_default_for_enums { ($($enum:ident => $init:expr ),+) => { $(impl Default for $enum { #[allow(unused_imports)]
--- a/gfx/wr/webrender_api/src/display_list.rs +++ b/gfx/wr/webrender_api/src/display_list.rs @@ -324,16 +324,19 @@ impl<'a> BuiltDisplayListIter<'a> { } Peek::NotPeeking => { /* do nothing */ } } // Don't let these bleed into another item self.cur_stops = ItemRange::default(); self.cur_complex_clip = ItemRange::default(); self.cur_clip_chain_items = ItemRange::default(); + self.cur_filters = ItemRange::default(); + self.cur_filter_primitives = ItemRange::default(); + self.cur_filter_data.clear(); loop { self.next_raw()?; match self.cur_item { SetGradientStops | SetFilterOps | SetFilterData | SetFilterPrimitives => { @@ -624,16 +627,17 @@ impl Serialize for BuiltDisplayList { Real::Border(v) => Debug::Border(v), Real::BoxShadow(v) => Debug::BoxShadow(v), Real::Gradient(v) => Debug::Gradient(v), Real::RadialGradient(v) => Debug::RadialGradient(v), Real::Iframe(v) => Debug::Iframe(v), Real::PushReferenceFrame(v) => Debug::PushReferenceFrame(v), Real::PushStackingContext(v) => Debug::PushStackingContext(v), Real::PushShadow(v) => Debug::PushShadow(v), + Real::BackdropFilter(v) => Debug::BackdropFilter(v), Real::PopReferenceFrame => Debug::PopReferenceFrame, Real::PopStackingContext => Debug::PopStackingContext, Real::PopAllShadows => Debug::PopAllShadows, }; seq.serialize_element(&serial_di)? } seq.end() @@ -725,16 +729,17 @@ impl<'de> Deserialize<'de> for BuiltDisp Debug::Image(v) => Real::Image(v), Debug::YuvImage(v) => Real::YuvImage(v), Debug::Border(v) => Real::Border(v), Debug::BoxShadow(v) => Real::BoxShadow(v), Debug::Gradient(v) => Real::Gradient(v), Debug::RadialGradient(v) => Real::RadialGradient(v), Debug::PushStackingContext(v) => Real::PushStackingContext(v), Debug::PushShadow(v) => Real::PushShadow(v), + Debug::BackdropFilter(v) => Real::BackdropFilter(v), Debug::PopStackingContext => Real::PopStackingContext, Debug::PopReferenceFrame => Real::PopReferenceFrame, Debug::PopAllShadows => Real::PopAllShadows, }; poke_into_vec(&item, &mut data); // the aux data is serialized after the item, hence the temporary data.extend(temp.drain(..)); @@ -1230,63 +1235,52 @@ impl DisplayListBuilder { clip_id: Option<di::ClipId>, transform_style: di::TransformStyle, mix_blend_mode: di::MixBlendMode, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], raster_space: di::RasterSpace, cache_tiles: bool, + is_backdrop_root: bool, ) { - if filters.len() > 0 { - self.push_item(&di::DisplayItem::SetFilterOps); - self.push_iter(filters); - } - - for filter_data in filter_datas { - let func_types = [ - filter_data.func_r_type, filter_data.func_g_type, - filter_data.func_b_type, filter_data.func_a_type]; - self.push_item(&di::DisplayItem::SetFilterData); - self.push_iter(&func_types); - self.push_iter(&filter_data.r_values); - self.push_iter(&filter_data.g_values); - self.push_iter(&filter_data.b_values); - self.push_iter(&filter_data.a_values); - } - - if !filter_primitives.is_empty() { - self.push_item(&di::DisplayItem::SetFilterPrimitives); - self.push_iter(filter_primitives); - } + self.push_filters(filters, filter_datas, filter_primitives); let item = di::DisplayItem::PushStackingContext(di::PushStackingContextDisplayItem { origin, spatial_id, is_backface_visible, stacking_context: di::StackingContext { transform_style, mix_blend_mode, clip_id, raster_space, cache_tiles, + is_backdrop_root, }, }); self.push_item(&item); } /// Helper for examples/ code. pub fn push_simple_stacking_context( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, is_backface_visible: bool, ) { - self.push_simple_stacking_context_with_filters(origin, spatial_id, is_backface_visible, &[], &[], &[]); + self.push_simple_stacking_context_with_filters( + origin, + spatial_id, + is_backface_visible, + &[], + &[], + &[], + ); } /// Helper for examples/ code. pub fn push_simple_stacking_context_with_filters( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, is_backface_visible: bool, @@ -1301,31 +1295,76 @@ impl DisplayListBuilder { None, di::TransformStyle::Flat, di::MixBlendMode::Normal, filters, filter_datas, filter_primitives, di::RasterSpace::Screen, /* cache_tiles = */ false, + /* is_backdrop_root = */ false, ); } pub fn pop_stacking_context(&mut self) { self.push_item(&di::DisplayItem::PopStackingContext); } pub fn push_stops(&mut self, stops: &[di::GradientStop]) { if stops.is_empty() { return; } self.push_item(&di::DisplayItem::SetGradientStops); self.push_iter(stops); } + pub fn push_backdrop_filter( + &mut self, + common: &di::CommonItemProperties, + filters: &[di::FilterOp], + filter_datas: &[di::FilterData], + filter_primitives: &[di::FilterPrimitive], + ) { + self.push_filters(filters, filter_datas, filter_primitives); + + let item = di::DisplayItem::BackdropFilter(di::BackdropFilterDisplayItem { + common: *common, + }); + self.push_item(&item); + } + + pub fn push_filters( + &mut self, + filters: &[di::FilterOp], + filter_datas: &[di::FilterData], + filter_primitives: &[di::FilterPrimitive], + ) { + if filters.len() > 0 { + self.push_item(&di::DisplayItem::SetFilterOps); + self.push_iter(filters); + } + + for filter_data in filter_datas { + let func_types = [ + filter_data.func_r_type, filter_data.func_g_type, + filter_data.func_b_type, filter_data.func_a_type]; + self.push_item(&di::DisplayItem::SetFilterData); + self.push_iter(&func_types); + self.push_iter(&filter_data.r_values); + self.push_iter(&filter_data.g_values); + self.push_iter(&filter_data.b_values); + self.push_iter(&filter_data.a_values); + } + + if !filter_primitives.is_empty() { + self.push_item(&di::DisplayItem::SetFilterPrimitives); + self.push_iter(filter_primitives); + } + } + fn generate_clip_index(&mut self) -> di::ClipId { self.next_clip_index += 1; di::ClipId::Clip(self.next_clip_index - 1, self.pipeline_id) } fn generate_spatial_index(&mut self) -> di::SpatialId { self.next_spatial_index += 1; di::SpatialId::new(self.next_spatial_index - 1, self.pipeline_id)
--- a/gfx/wr/wrench/src/yaml_frame_reader.rs +++ b/gfx/wr/wrench/src/yaml_frame_reader.rs @@ -1533,16 +1533,17 @@ impl YamlFrameReader { "box-shadow" => self.handle_box_shadow(dl, item, &mut info), "iframe" => self.handle_iframe(dl, item, &mut info), "stacking-context" => { self.add_stacking_context_from_yaml(dl, wrench, item, false, &mut info) } "reference-frame" => self.handle_reference_frame(dl, wrench, item), "shadow" => self.handle_push_shadow(dl, item, &mut info), "pop-all-shadows" => self.handle_pop_all_shadows(dl), + "backdrop-filter" => self.handle_backdrop_filter(dl, item, &mut info), _ => println!("Skipping unknown item type: {:?}", item), } if pushed_clip { self.clip_id_stack.pop().unwrap(); } if set_clip_id.is_some() { self.clip_id_stack.pop().unwrap(); @@ -1868,16 +1869,17 @@ impl YamlFrameReader { .unwrap_or(TransformStyle::Flat); let mix_blend_mode = yaml["mix-blend-mode"] .as_mix_blend_mode() .unwrap_or(MixBlendMode::Normal); let raster_space = yaml["raster-space"] .as_raster_space() .unwrap_or(RasterSpace::Screen); let cache_tiles = yaml["cache"].as_bool().unwrap_or(false); + let is_backdrop_root = yaml["backdrop-root"].as_bool().unwrap_or(false); if is_root { if let Some(size) = yaml["scroll-offset"].as_point() { let external_id = ExternalScrollId(0, dl.pipeline_id); self.scroll_offsets.insert(external_id, LayoutPoint::new(size.x, size.y)); } } @@ -1892,29 +1894,53 @@ impl YamlFrameReader { clip_node_id, transform_style, mix_blend_mode, &filters, &filter_datas, &filter_primitives, raster_space, cache_tiles, + is_backdrop_root, ); if !yaml["items"].is_badvalue() { self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]); } dl.pop_stacking_context(); if reference_frame_id.is_some() { self.spatial_id_stack.pop().unwrap(); dl.pop_reference_frame(); } } + + fn handle_backdrop_filter( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + info.clip_rect = try_intersect!( + self.resolve_rect(&item["bounds"]), + &info.clip_rect + ); + + let filters = item["filters"].as_vec_filter_op().unwrap_or(vec![]); + let filter_datas = item["filter-datas"].as_vec_filter_data().unwrap_or(vec![]); + let filter_primitives = item["filter-primitives"].as_vec_filter_primitive().unwrap_or(vec![]); + + dl.push_backdrop_filter( + &info, + &filters, + &filter_datas, + &filter_primitives, + ); + } } impl WrenchThing for YamlFrameReader { fn do_frame(&mut self, wrench: &mut Wrench) -> u32 { let mut should_build_yaml = false; // If YAML isn't read yet, or watching source file, reload from disk. if self.yaml_string.is_empty() || self.watch_source {
--- a/gfx/wr/wrench/src/yaml_frame_writer.rs +++ b/gfx/wr/wrench/src/yaml_frame_writer.rs @@ -254,41 +254,22 @@ fn shadow_parameters(shadow: &Shadow) -> format!( "[{},{}],{},[{}]", shadow.offset.x, shadow.offset.y, shadow.blur_radius, color_to_string(shadow.color) ) } -fn write_stacking_context( +fn write_filters( parent: &mut Table, - sc: &StackingContext, + name: &str, + filter_iter: impl IntoIterator<Item = FilterOp>, properties: &SceneProperties, - filter_iter: impl IntoIterator<Item = FilterOp>, - filter_data_iter: &[TempFilterData], - filter_primitive_iter: impl IntoIterator<Item = FilterPrimitive>, ) { - enum_node(parent, "transform-style", sc.transform_style); - - let raster_space = match sc.raster_space { - RasterSpace::Local(scale) => { - format!("local({})", scale) - } - RasterSpace::Screen => { - "screen".to_owned() - } - }; - str_node(parent, "raster-space", &raster_space); - - // mix_blend_mode - if sc.mix_blend_mode != MixBlendMode::Normal { - enum_node(parent, "mix-blend-mode", sc.mix_blend_mode) - } - // filters let mut filters = vec![]; for filter in filter_iter { match filter { FilterOp::Identity => { filters.push(Yaml::String("identity".into())) } FilterOp::Blur(x) => { filters.push(Yaml::String(format!("blur({})", x))) } FilterOp::Brightness(x) => { filters.push(Yaml::String(format!("brightness({})", x))) } FilterOp::Contrast(x) => { filters.push(Yaml::String(format!("contrast({})", x))) } FilterOp::Grayscale(x) => { filters.push(Yaml::String(format!("grayscale({})", x))) } @@ -319,19 +300,24 @@ fn write_stacking_context( filters.push(Yaml::String("component-transfer".to_string())) } FilterOp::Flood(color) => { filters.push(Yaml::String(format!("flood({})", color_to_string(color)))) } } } - yaml_node(parent, "filters", Yaml::Array(filters)); + yaml_node(parent, name, Yaml::Array(filters)); +} - // filter datas +fn write_filter_datas( + parent: &mut Table, + name: &str, + filter_data_iter: &[TempFilterData], +) { let mut filter_datas = vec![]; for filter_data in filter_data_iter { let func_types = filter_data.func_types.iter().map(|func_type| { match func_type { ComponentTransferFuncType::Identity => { Yaml::String("Identity".to_string()) } ComponentTransferFuncType::Table => { Yaml::String("Table".to_string()) } ComponentTransferFuncType::Discrete => { Yaml::String("Discrete".to_string()) } ComponentTransferFuncType::Linear => { Yaml::String("Linear".to_string()) } @@ -356,19 +342,24 @@ fn write_stacking_context( Yaml::Array(r_values), Yaml::Array(g_values), Yaml::Array(b_values), Yaml::Array(a_values), ].to_vec(); filter_datas.push(Yaml::Array(avec)); } - yaml_node(parent, "filter-datas", Yaml::Array(filter_datas)); + yaml_node(parent, name, Yaml::Array(filter_datas)); +} - // filter primitives +fn write_filter_primitives( + parent: &mut Table, + name: &str, + filter_primitive_iter: impl IntoIterator<Item = FilterPrimitive>, +) { let mut filter_primitives = vec![]; for filter_primitive in filter_primitive_iter { let mut table = new_table(); match filter_primitive.kind { FilterPrimitiveKind::Identity(identity_primitive) => { yaml_node(&mut table, "type", Yaml::String("identity".into())); filter_input_node(&mut table, "in", identity_primitive.input); } @@ -408,17 +399,47 @@ fn write_stacking_context( yaml_node(&mut table, "type", Yaml::String("component-transfer".into())); filter_input_node(&mut table, "in", component_transfer_primitive.input); } } enum_node(&mut table, "color-space", filter_primitive.color_space); filter_primitives.push(Yaml::Hash(table)); } - yaml_node(parent, "filter-primitives", Yaml::Array(filter_primitives)); + yaml_node(parent, name, Yaml::Array(filter_primitives)); +} + +fn write_stacking_context( + parent: &mut Table, + sc: &StackingContext, + properties: &SceneProperties, + filter_iter: impl IntoIterator<Item = FilterOp>, + filter_data_iter: &[TempFilterData], + filter_primitive_iter: impl IntoIterator<Item = FilterPrimitive>, +) { + enum_node(parent, "transform-style", sc.transform_style); + + let raster_space = match sc.raster_space { + RasterSpace::Local(scale) => { + format!("local({})", scale) + } + RasterSpace::Screen => { + "screen".to_owned() + } + }; + str_node(parent, "raster-space", &raster_space); + + // mix_blend_mode + if sc.mix_blend_mode != MixBlendMode::Normal { + enum_node(parent, "mix-blend-mode", sc.mix_blend_mode) + } + + write_filters(parent, "filters", filter_iter, properties); + write_filter_datas(parent, "filter-datas", filter_data_iter); + write_filter_primitives(parent, "filter-primitives", filter_primitive_iter); } #[cfg(target_os = "macos")] fn native_font_handle_to_yaml( rsrc: &mut ResourceGenerator, handle: &NativeFontHandle, parent: &mut yaml_rust::yaml::Hash, path_opt: &mut Option<PathBuf>, @@ -1335,16 +1356,24 @@ impl YamlFrameWriter { yaml_node(&mut v, "vertical-offset-bounds", Yaml::Array(vertical)); let applied = vec![ Yaml::Real(item.previously_applied_offset.x.to_string()), Yaml::Real(item.previously_applied_offset.y.to_string()), ]; yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied)); } + DisplayItem::BackdropFilter(item) => { + str_node(&mut v, "type", "backdrop-filter"); + common_node(&mut v, clip_id_mapper, &item.common); + + write_filters(&mut v, "filters", base.filters(), &scene.properties); + write_filter_datas(&mut v, "filter-datas", base.filter_datas()); + write_filter_primitives(&mut v, "filter-primitives", base.filter_primitives()); + } DisplayItem::PopReferenceFrame | DisplayItem::PopStackingContext => return, DisplayItem::SetGradientStops | DisplayItem::SetFilterOps | DisplayItem::SetFilterData | DisplayItem::SetFilterPrimitives => panic!("dummy item yielded?"),