Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Bug 1555483 - Part 1: Add SVG filter primitive display item. r=gw
Browse files Browse the repository at this point in the history
  • Loading branch information
cbrewster committed Jul 10, 2019
1 parent 0a51c8c commit f2d2731
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 15 deletions.
1 change: 1 addition & 0 deletions gfx/wr/examples/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ impl App {
true,
&filters,
&[],
&[]
);

let space_and_clip = SpaceAndClipInfo {
Expand Down
12 changes: 8 additions & 4 deletions gfx/wr/webrender/src/display_list_flattener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter};
use api::{ClipId, ColorF, CommonItemProperties, ComplexClipRegion, RasterSpace};
use api::{DisplayItem, DisplayItemRef, ExtendMode, ExternalScrollId};
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GradientStop};
use api::{FilterOp, FilterPrimitive, FontInstanceKey, GlyphInstance, GlyphOptions, GradientStop};
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, ColorDepth};
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
use api::{PropertyBinding, ReferenceFrame, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
Expand Down Expand Up @@ -796,6 +796,7 @@ impl<'a> DisplayListFlattener<'a> {
origin: LayoutPoint,
filters: ItemRange<FilterOp>,
filter_datas: &[TempFilterData],
filter_primitives: ItemRange<FilterPrimitive>,
is_backface_visible: bool,
apply_pipeline_clip: bool,
) {
Expand All @@ -809,6 +810,7 @@ impl<'a> DisplayListFlattener<'a> {
CompositeOps::new(
stacking_context.filter_ops_for_compositing(filters),
stacking_context.filter_datas_for_compositing(filter_datas),
stacking_context.filter_primitives_for_compositing(filter_primitives),
stacking_context.mix_blend_mode_for_compositing(),
)
};
Expand Down Expand Up @@ -1180,6 +1182,7 @@ impl<'a> DisplayListFlattener<'a> {
info.origin,
item.filters(),
item.filter_datas(),
item.filter_primitives(),
info.is_backface_visible,
apply_pipeline_clip,
);
Expand Down Expand Up @@ -1309,9 +1312,10 @@ impl<'a> DisplayListFlattener<'a> {
}

// Do nothing; these are dummy items for the display list parser
DisplayItem::SetGradientStops => {}
DisplayItem::SetFilterOps => {}
DisplayItem::SetFilterData => {}
DisplayItem::SetGradientStops |
DisplayItem::SetFilterOps |
DisplayItem::SetFilterData |
DisplayItem::SetFilterPrimitives => {}

DisplayItem::PopReferenceFrame |
DisplayItem::PopStackingContext => {
Expand Down
17 changes: 16 additions & 1 deletion gfx/wr/webrender/src/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{BuiltDisplayList, ColorF, DynamicProperties, Epoch};
use api::{FilterOp, TempFilterData, FilterData, ComponentTransferFuncType};
use api::{FilterOp, TempFilterData, FilterData, FilterPrimitive, ComponentTransferFuncType};
use api::{PipelineId, PropertyBinding, PropertyBindingId, ItemRange, MixBlendMode, StackingContext};
use api::units::{LayoutSize, LayoutTransform};
use crate::internal_types::{FastHashMap, Filter};
Expand Down Expand Up @@ -206,6 +206,10 @@ pub trait StackingContextHelpers {
&self,
input_filter_datas: &[TempFilterData],
) -> Vec<FilterData>;
fn filter_primitives_for_compositing(
&self,
input_filter_primitives: ItemRange<FilterPrimitive>,
) -> Vec<FilterPrimitive>;
}

impl StackingContextHelpers for StackingContext {
Expand Down Expand Up @@ -254,4 +258,15 @@ impl StackingContextHelpers for StackingContext {
}
filter_datas
}

fn filter_primitives_for_compositing(
&self,
input_filter_primitives: ItemRange<FilterPrimitive>,
) -> Vec<FilterPrimitive> {
// Resolve these in the flattener?
// TODO(gw): Now that we resolve these later on,
// we could probably make it a bit
// more efficient than cloning these here.
input_filter_primitives.iter().map(|primitive| primitive.into()).collect()
}
}
13 changes: 9 additions & 4 deletions gfx/wr/webrender/src/tiling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{ColorF, BorderStyle, MixBlendMode, PipelineId, PremultipliedColorF};
use api::{DocumentLayer, FilterData, ImageFormat, LineOrientation};
use api::{DocumentLayer, FilterData, FilterPrimitive, ImageFormat, LineOrientation};
use api::units::*;
#[cfg(feature = "pathfinder")]
use api::FontRenderMode;
Expand Down Expand Up @@ -1332,18 +1332,23 @@ pub struct CompositeOps {
// Requires only a single texture as input (e.g. most filters)
pub filters: Vec<Filter>,
pub filter_datas: Vec<FilterData>,
pub filter_primitives: Vec<FilterPrimitive>,

// Requires two source textures (e.g. mix-blend-mode)
pub mix_blend_mode: Option<MixBlendMode>,
}

impl CompositeOps {
pub fn new(filters: Vec<Filter>,
filter_datas: Vec<FilterData>,
mix_blend_mode: Option<MixBlendMode>) -> Self {
pub fn new(
filters: Vec<Filter>,
filter_datas: Vec<FilterData>,
filter_primitives: Vec<FilterPrimitive>,
mix_blend_mode: Option<MixBlendMode>
) -> Self {
CompositeOps {
filters,
filter_datas,
filter_primitives,
mix_blend_mode,
}
}
Expand Down
33 changes: 32 additions & 1 deletion gfx/wr/webrender_api/src/display_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub enum DisplayItem {
SetGradientStops,
SetFilterOps,
SetFilterData,
SetFilterPrimitives,

// These marker items terminate a scope introduced by a previous item.
PopReferenceFrame,
Expand Down Expand Up @@ -159,6 +160,7 @@ pub enum DebugDisplayItem {
SetGradientStops(Vec<GradientStop>),
SetFilterOps(Vec<FilterOp>),
SetFilterData(FilterData),
SetFilterPrimitives(Vec<FilterPrimitive>),

PopReferenceFrame,
PopStackingContext,
Expand Down Expand Up @@ -638,7 +640,7 @@ 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>
} // IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive>

#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
Expand Down Expand Up @@ -697,6 +699,34 @@ pub enum MixBlendMode {
Luminosity = 15,
}

/// An input to a SVG filter primitive.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum FilterPrimitiveInput {
/// The input is the original graphic that the filter is being applied to.
Original,
/// The input is the output of the previous filter primitive in the filter primitive chain.
Previous,
/// The input is the output of the filter primitive at the given index in the filter primitive chain.
OutputOfPrimitiveIndex(usize),
}

#[repr(C)]
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct BlendPrimitive {
pub input1: FilterPrimitiveInput,
pub input2: FilterPrimitiveInput,
pub mode: MixBlendMode,
}

/// SVG Filter Primitive.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum FilterPrimitive {
Blend(BlendPrimitive),
}

/// CSS filter.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum FilterOp {
Expand Down Expand Up @@ -1162,6 +1192,7 @@ impl DisplayItem {
DisplayItem::PushStackingContext(..) => "push_stacking_context",
DisplayItem::SetFilterOps => "set_filter_ops",
DisplayItem::SetFilterData => "set_filter_data",
DisplayItem::SetFilterPrimitives => "set_filter_primitives",
DisplayItem::RadialGradient(..) => "radial_gradient",
DisplayItem::Rectangle(..) => "rectangle",
DisplayItem::ScrollFrame(..) => "scroll_frame",
Expand Down
30 changes: 28 additions & 2 deletions gfx/wr/webrender_api/src/display_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ pub struct BuiltDisplayListIter<'a> {
cur_glyphs: ItemRange<'a, GlyphInstance>,
cur_filters: ItemRange<'a, di::FilterOp>,
cur_filter_data: Vec<TempFilterData<'a>>,
cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>,
cur_clip_chain_items: ItemRange<'a, di::ClipId>,
cur_complex_clip: ItemRange<'a, di::ComplexClipRegion>,
peeking: Peek,
Expand Down Expand Up @@ -297,6 +298,7 @@ impl<'a> BuiltDisplayListIter<'a> {
cur_glyphs: ItemRange::default(),
cur_filters: ItemRange::default(),
cur_filter_data: Vec::new(),
cur_filter_primitives: ItemRange::default(),
cur_clip_chain_items: ItemRange::default(),
cur_complex_clip: ItemRange::default(),
peeking: Peek::NotPeeking,
Expand Down Expand Up @@ -335,7 +337,8 @@ impl<'a> BuiltDisplayListIter<'a> {
match self.cur_item {
SetGradientStops |
SetFilterOps |
SetFilterData => {
SetFilterData |
SetFilterPrimitives => {
// These are marker items for populating other display items, don't yield them.
continue;
}
Expand Down Expand Up @@ -391,6 +394,10 @@ impl<'a> BuiltDisplayListIter<'a> {
self.debug_stats.log_slice("set_filter_data.b_values", &data.b_values);
self.debug_stats.log_slice("set_filter_data.a_values", &data.a_values);
}
SetFilterPrimitives => {
self.cur_filter_primitives = skip_slice::<di::FilterPrimitive>(&mut self.data);
self.debug_stats.log_slice("set_filter_primitives.primitives", &self.cur_filter_primitives);
}
ClipChain(_) => {
self.cur_clip_chain_items = skip_slice::<di::ClipId>(&mut self.data);
self.debug_stats.log_slice("clip_chain.clip_ids", &self.cur_clip_chain_items);
Expand Down Expand Up @@ -502,6 +509,10 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> {
&self.iter.cur_filter_data
}

pub fn filter_primitives(&self) -> ItemRange<di::FilterPrimitive> {
self.iter.cur_filter_primitives
}

pub fn clip_chain_items(&self) -> ItemRange<di::ClipId> {
self.iter.cur_clip_chain_items
}
Expand Down Expand Up @@ -602,6 +613,9 @@ impl Serialize for BuiltDisplayList {
a_values: temp_filter_data.a_values.iter().collect(),
})
},
Real::SetFilterPrimitives => Debug::SetFilterPrimitives(
item.iter.cur_filter_primitives.iter().collect()
),
Real::SetGradientStops => Debug::SetGradientStops(
item.iter.cur_stops.iter().collect()
),
Expand Down Expand Up @@ -700,6 +714,10 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
Real::SetFilterData
},
Debug::SetFilterPrimitives(filter_primitives) => {
DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
Real::SetFilterPrimitives
}
Debug::SetGradientStops(stops) => {
DisplayListBuilder::push_iter_impl(&mut temp, stops);
Real::SetGradientStops
Expand Down Expand Up @@ -1425,6 +1443,7 @@ impl DisplayListBuilder {
mix_blend_mode: di::MixBlendMode,
filters: &[di::FilterOp],
filter_datas: &[di::FilterData],
filter_primitives: &[di::FilterPrimitive],
raster_space: di::RasterSpace,
cache_tiles: bool,
) {
Expand All @@ -1445,6 +1464,11 @@ impl DisplayListBuilder {
self.push_iter(&filter_data.a_values);
}

if !filter_primitives.is_empty() {
self.push_item(&di::DisplayItem::SetFilterPrimitives);
self.push_iter(filter_primitives);
}

let item = di::DisplayItem::PushStackingContext(di::PushStackingContextDisplayItem {
origin,
spatial_id,
Expand All @@ -1468,7 +1492,7 @@ 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.
Expand All @@ -1479,6 +1503,7 @@ impl DisplayListBuilder {
is_backface_visible: bool,
filters: &[di::FilterOp],
filter_datas: &[di::FilterData],
filter_primitives: &[di::FilterPrimitive],
) {
self.push_stacking_context(
origin,
Expand All @@ -1489,6 +1514,7 @@ impl DisplayListBuilder {
di::MixBlendMode::Normal,
filters,
filter_datas,
filter_primitives,
di::RasterSpace::Screen,
/* cache_tiles = */ false,
);
Expand Down
2 changes: 2 additions & 0 deletions gfx/wr/wrench/src/yaml_frame_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1881,6 +1881,7 @@ impl YamlFrameReader {

let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]);
let filter_datas = yaml["filter-datas"].as_vec_filter_data().unwrap_or(vec![]);
let filter_primitives = yaml["filter-primitives"].as_vec_filter_primitive().unwrap_or(vec![]);

dl.push_stacking_context(
bounds.origin,
Expand All @@ -1891,6 +1892,7 @@ impl YamlFrameReader {
mix_blend_mode,
&filters,
&filter_datas,
&filter_primitives,
raster_space,
cache_tiles,
);
Expand Down
35 changes: 32 additions & 3 deletions gfx/wr/wrench/src/yaml_frame_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ fn color_to_string(value: ColorF) -> String {
}
}

fn filter_input_to_string(input: FilterPrimitiveInput) -> String {
match input {
FilterPrimitiveInput::Original => "original".into(),
FilterPrimitiveInput::Previous => "previous".into(),
FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => index.to_string(),
}
}

fn color_node(parent: &mut Table, key: &str, value: ColorF) {
yaml_node(parent, key, Yaml::String(color_to_string(value)));
}
Expand Down Expand Up @@ -253,6 +261,7 @@ fn write_stacking_context(
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);

Expand Down Expand Up @@ -349,6 +358,23 @@ fn write_stacking_context(
}

yaml_node(parent, "filter-datas", Yaml::Array(filter_datas));

// filter primitives
let mut filter_primitives = vec![];
for filter_primitive in filter_primitive_iter {
let mut table = new_table();
match filter_primitive {
FilterPrimitive::Blend(blend_primitive) => {
yaml_node(&mut table, "type", Yaml::String("blend".into()));
yaml_node(&mut table, "in1", Yaml::String(filter_input_to_string(blend_primitive.input1)));
yaml_node(&mut table, "in2", Yaml::String(filter_input_to_string(blend_primitive.input2)));
enum_node(&mut table, "mode", blend_primitive.mode);
}
}
filter_primitives.push(Yaml::Hash(table));
}

yaml_node(parent, "filter-primitives", Yaml::Array(filter_primitives));
}

#[cfg(target_os = "macos")]
Expand Down Expand Up @@ -1165,6 +1191,7 @@ impl YamlFrameWriter {
&scene.properties,
base.filters(),
base.filter_datas(),
base.filter_primitives(),
);

let mut sub_iter = base.sub_iter();
Expand Down Expand Up @@ -1277,9 +1304,11 @@ impl YamlFrameWriter {
DisplayItem::PopReferenceFrame |
DisplayItem::PopStackingContext => return,

DisplayItem::SetGradientStops => panic!("dummy item yielded?"),
DisplayItem::SetFilterOps => panic!("dummy item yielded?"),
DisplayItem::SetFilterData => panic!("dummy item yielded?"),
DisplayItem::SetGradientStops |
DisplayItem::SetFilterOps |
DisplayItem::SetFilterData |
DisplayItem::SetFilterPrimitives => panic!("dummy item yielded?"),

DisplayItem::PushShadow(item) => {
str_node(&mut v, "type", "shadow");
vector_node(&mut v, "offset", &item.shadow.offset);
Expand Down
Loading

0 comments on commit f2d2731

Please sign in to comment.