Bug 1178765 - Part 1: Add backdrop-filter WebRender display items r=gw

Differential Revision: https://phabricator.services.mozilla.com/D39097

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Connor Brewster 2019-08-13 22:02:37 +00:00
parent ec37be04da
commit afa1fcbaed
7 changed files with 167 additions and 52 deletions

View File

@ -344,7 +344,8 @@ struct MOZ_STACK_CLASS StackingContextParams : public WrStackingContextParams {
nullptr,
/* is_backface_visible = */ true,
/* cache_tiles = */ false,
wr::MixBlendMode::Normal} {}
wr::MixBlendMode::Normal,
/* is_backdrop_root = */ false} {}
void SetPreserve3D(bool aPreserve) {
transform_style =

View File

@ -2085,6 +2085,9 @@ pub struct WrStackingContextParams {
/// 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]
@ -2206,7 +2209,8 @@ pub extern "C" fn wr_dp_push_stacking_context(
&r_filter_datas,
&[],
glyph_raster_space,
params.cache_tiles);
params.cache_tiles,
params.is_backdrop_root);
result
}

View File

@ -1311,6 +1311,9 @@ impl<'a> DisplayListFlattener<'a> {
parent_space,
);
}
DisplayItem::BackdropFilter(ref info) => {
unimplemented!();
}
// Do nothing; these are dummy items for the display list parser
DisplayItem::SetGradientStops |

View File

@ -105,6 +105,7 @@ pub enum DisplayItem {
RadialGradient(RadialGradientDisplayItem),
Image(ImageDisplayItem),
YuvImage(YuvImageDisplayItem),
BackdropFilter(BackdropFilterDisplayItem),
// Clips
Clip(ClipDisplayItem),
@ -148,6 +149,7 @@ pub enum DebugDisplayItem {
RadialGradient(RadialGradientDisplayItem),
Image(ImageDisplayItem),
YuvImage(YuvImageDisplayItem),
BackdropFilter(BackdropFilterDisplayItem),
Clip(ClipDisplayItem, Vec<ComplexClipRegion>),
ClipChain(ClipChainItem, Vec<ClipId>),
@ -611,6 +613,13 @@ pub struct RadialGradientDisplayItem {
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,
@ -652,7 +661,10 @@ pub struct StackingContext {
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)]
@ -1364,6 +1376,7 @@ impl DisplayItem {
DisplayItem::StickyFrame(..) => "sticky_frame",
DisplayItem::Text(..) => "text",
DisplayItem::YuvImage(..) => "yuv_image",
DisplayItem::BackdropFilter(..) => "backdrop_filter",
}
}
}

View File

@ -329,6 +329,9 @@ impl<'a> BuiltDisplayListIter<'a> {
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()?;
@ -629,6 +632,7 @@ impl Serialize for BuiltDisplayList {
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,
@ -730,6 +734,7 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
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,
@ -1235,28 +1240,9 @@ impl DisplayListBuilder {
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,
@ -1268,6 +1254,7 @@ impl DisplayListBuilder {
clip_id,
raster_space,
cache_tiles,
is_backdrop_root,
},
});
@ -1281,7 +1268,14 @@ impl DisplayListBuilder {
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.
@ -1306,6 +1300,7 @@ impl DisplayListBuilder {
filter_primitives,
di::RasterSpace::Screen,
/* cache_tiles = */ false,
/* is_backdrop_root = */ false,
);
}
@ -1321,6 +1316,50 @@ impl DisplayListBuilder {
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)

View File

@ -1538,6 +1538,7 @@ impl YamlFrameReader {
"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),
}
@ -1873,6 +1874,7 @@ impl YamlFrameReader {
.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() {
@ -1897,6 +1899,7 @@ impl YamlFrameReader {
&filter_primitives,
raster_space,
cache_tiles,
is_backdrop_root,
);
if !yaml["items"].is_badvalue() {
@ -1910,6 +1913,29 @@ impl YamlFrameReader {
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 {

View File

@ -259,31 +259,12 @@ fn shadow_parameters(shadow: &Shadow) -> String {
)
}
fn write_stacking_context(
fn write_filters(
parent: &mut Table,
sc: &StackingContext,
properties: &SceneProperties,
name: &str,
filter_iter: impl IntoIterator<Item = FilterOp>,
filter_data_iter: &[TempFilterData],
filter_primitive_iter: impl IntoIterator<Item = FilterPrimitive>,
properties: &SceneProperties,
) {
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 {
@ -324,9 +305,14 @@ fn write_stacking_context(
}
}
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| {
@ -361,9 +347,14 @@ fn write_stacking_context(
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();
@ -413,7 +404,37 @@ fn write_stacking_context(
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")]
@ -1340,6 +1361,14 @@ impl YamlFrameWriter {
];
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,