author | Connor Brewster <cbrewster@mozilla.com> |
Wed, 10 Jul 2019 22:36:32 +0000 | |
changeset 482308 | 6c311d8365d2d857f8dcf7115b3613291d84b441 |
parent 482307 | 31009157a5b4152b24b194b6efc10685a3843e6e |
child 482309 | 6db240b7d056ad81030e883eebc9c3ce0a2e108d |
push id | 89692 |
push user | csabou@mozilla.com |
push date | Thu, 11 Jul 2019 01:38:31 +0000 |
treeherder | autoland@b810038f5eb1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gw |
bugs | 1555483 |
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/wr/webrender/src/batch.rs +++ b/gfx/wr/webrender/src/batch.rs @@ -1635,16 +1635,48 @@ impl BatchBuilder { transform_kind, render_tasks, z_id, prim_info.clip_task_index, prim_vis_mask, ctx, ); } + PictureCompositeMode::SvgFilter(..) => { + let kind = BatchKind::Brush( + BrushBatchKind::Image(ImageBufferKind::Texture2DArray) + ); + let (uv_rect_address, textures) = render_tasks.resolve_surface( + surface_task.expect("bug: surface must be allocated by now"), + gpu_cache, + ); + let key = BatchKey::new( + kind, + non_segmented_blend_mode, + textures, + ); + let prim_header_index = prim_headers.push(&prim_header, z_id, [ + ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16), + RasterizationSpace::Screen as i32, + get_shader_opacity(1.0), + 0, + ]); + + self.add_brush_instance_to_batches( + key, + bounding_rect, + z_id, + INVALID_SEGMENT_INDEX, + EdgeAaSegmentMask::empty(), + clip_task_address, + brush_flags, + prim_header_index, + uv_rect_address.as_int(), + ); + } } } None => { // If this picture is being drawn into an existing target (i.e. with // no composition operation), recurse and add to the current batch list. self.add_pic_to_batch( picture, ctx,
--- a/gfx/wr/webrender/src/display_list_flattener.rs +++ b/gfx/wr/webrender/src/display_list_flattener.rs @@ -1976,16 +1976,58 @@ impl<'a> DisplayListFlattener<'a> { println!("\tis a composite picture for a stacking context with {:?}", filter); } // Run the optimize pass on this picture, to see if we can // collapse opacity and avoid drawing to an off-screen surface. self.prim_store.optimize_picture_if_possible(current_pic_index); } + if !stacking_context.composite_ops.filter_primitives.is_empty() { + let composite_mode = PictureCompositeMode::SvgFilter(stacking_context.composite_ops.filter_primitives.clone()); + + let filter_pic_index = PictureIndex(self.prim_store.pictures + .alloc() + .init(PicturePrimitive::new_image( + Some(composite_mode.clone()), + Picture3DContext::Out, + stacking_context.pipeline_id, + None, + true, + stacking_context.is_backface_visible, + stacking_context.requested_raster_space, + PrimitiveList::new( + vec![cur_instance.clone()], + &self.interners, + ), + stacking_context.spatial_node_index, + None, + PictureOptions::default(), + )) + ); + + current_pic_index = filter_pic_index; + cur_instance = create_prim_instance( + current_pic_index, + Some(composite_mode).into(), + stacking_context.is_backface_visible, + ClipChainId::NONE, + stacking_context.spatial_node_index, + &mut self.interners, + ); + + if cur_instance.is_chased() { + println!("\tis a composite picture for a stacking context with an SVG filter"); + } + + // Run the optimize pass on this picture, to see if we can + // collapse opacity and avoid drawing to an off-screen surface. + self.prim_store.optimize_picture_if_possible(current_pic_index); + } + // Same for mix-blend-mode, except we can skip if this primitive is the first in the parent // stacking context. // From https://drafts.fxtf.org/compositing-1/#generalformula, the formula for blending is: // Cs = (1 - ab) x Cs + ab x Blend(Cb, Cs) // where // Cs = Source color // ab = Backdrop alpha // Cb = Backdrop color
--- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -1,14 +1,14 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * 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::{MixBlendMode, PipelineId, PremultipliedColorF}; -use api::{PropertyBinding, PropertyBindingId, FontRenderMode}; +use api::{PropertyBinding, PropertyBindingId, FilterPrimitive, FontRenderMode}; use api::{DebugFlags, RasterSpace, ImageKey, ColorF}; use api::units::*; use crate::box_shadow::{BLUR_SAMPLE_SCALE}; use crate::clip::{ClipStore, ClipDataStore, ClipChainInstance}; use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace, CoordinateSystemId }; use crate::debug_colors; @@ -1568,16 +1568,18 @@ pub enum PictureCompositeMode { /// Apply a component transfer filter. ComponentTransferFilter(FilterDataHandle), /// Draw to intermediate surface, copy straight across. This /// is used for CSS isolation, and plane splitting. Blit(BlitReason), /// Used to cache a picture as a series of tiles. TileCache { }, + /// Apply an SVG filter + SvgFilter(Vec<FilterPrimitive>), } /// Enum value describing the place of a picture in a 3D context. #[derive(Clone, Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] pub enum Picture3DContext<C> { /// The picture is not a part of 3D context sub-hierarchy. Out, @@ -1933,17 +1935,18 @@ impl PicturePrimitive { pub fn can_use_segments(&self) -> bool { match self.raster_config { // TODO(gw): Support brush segment rendering for filter and mix-blend // shaders. It's possible this already works, but I'm just // applying this optimization to Blit mode for now. Some(RasterConfig { composite_mode: PictureCompositeMode::MixBlend(..), .. }) | Some(RasterConfig { composite_mode: PictureCompositeMode::Filter(..), .. }) | Some(RasterConfig { composite_mode: PictureCompositeMode::ComponentTransferFilter(..), .. }) | - Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, ..}) | + Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) | + Some(RasterConfig { composite_mode: PictureCompositeMode::SvgFilter(..), .. }) | None => { false } Some(RasterConfig { composite_mode: PictureCompositeMode::Blit(reason), ..}) => { reason == BlitReason::CLIP } } } @@ -2437,16 +2440,40 @@ impl PicturePrimitive { device_pixel_scale, PrimitiveVisibilityMask::all(), ); let render_task_id = frame_state.render_tasks.add(picture_task); Some((render_task_id, render_task_id)) } + PictureCompositeMode::SvgFilter(..) => { + let uv_rect_kind = calculate_uv_rect_kind( + &pic_rect, + &transform, + &clipped, + device_pixel_scale, + true, + ); + + let picture_task = RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, clipped.size), + unclipped.size, + pic_index, + clipped.origin, + uv_rect_kind, + raster_spatial_node_index, + surface_spatial_node_index, + device_pixel_scale, + ); + + let render_task_id = frame_state.render_tasks.add(picture_task); + + (render_task_id, render_task_id) + } }; if let Some((root, port)) = dep_info { frame_state.surfaces[raster_config.surface_index.0].render_tasks = Some(SurfaceRenderTasks { root, port, }); @@ -2985,17 +3012,18 @@ impl PicturePrimitive { _ => {} } } PictureCompositeMode::ComponentTransferFilter(handle) => { let filter_data = &mut data_stores.filter_data[handle]; filter_data.update(frame_state); } PictureCompositeMode::MixBlend(..) | - PictureCompositeMode::Blit(_) => {} + PictureCompositeMode::Blit(_) | + PictureCompositeMode::SvgFilter(_) => {} } true } } // Calculate a single homogeneous screen-space UV for a picture. fn calculate_screen_uv(
--- a/gfx/wr/webrender/src/prim_store/picture.rs +++ b/gfx/wr/webrender/src/prim_store/picture.rs @@ -1,14 +1,14 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * 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::{ - ColorU, MixBlendMode, + ColorU, MixBlendMode, FilterPrimitive, PropertyBinding, PropertyBindingId, }; use api::units::{Au, LayoutSize, LayoutVector2D}; use crate::intern::ItemUid; use crate::display_list_flattener::IsVisible; use crate::intern::{Internable, InternDebug, Handle as InternHandle}; use crate::internal_types::{LayoutPrimitiveInfo, Filter}; use crate::picture::PictureCompositeMode; @@ -39,16 +39,17 @@ pub enum PictureCompositeKey { Saturate(Au), Sepia(Au), DropShadows(Vec<(VectorKey, Au, ColorU)>), ColorMatrix([Au; 20]), SrgbToLinear, LinearToSrgb, ComponentTransfer(ItemUid), Flood(ColorU), + SvgFilter(Vec<FilterPrimitive>), // MixBlendMode Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, @@ -125,16 +126,19 @@ impl From<Option<PictureCompositeMode>> } Filter::ComponentTransfer => unreachable!(), Filter::Flood(color) => PictureCompositeKey::Flood(color.into()), } } Some(PictureCompositeMode::ComponentTransferFilter(handle)) => { PictureCompositeKey::ComponentTransfer(handle.uid()) } + Some(PictureCompositeMode::SvgFilter(filter_primitives)) => { + PictureCompositeKey::SvgFilter(filter_primitives) + } Some(PictureCompositeMode::Blit(_)) | Some(PictureCompositeMode::TileCache { .. }) | None => { PictureCompositeKey::Identity } } } }
--- a/gfx/wr/webrender_api/src/display_item.rs +++ b/gfx/wr/webrender_api/src/display_item.rs @@ -674,17 +674,17 @@ impl RasterSpace { match *self { RasterSpace::Local(scale) => Some(scale), RasterSpace::Screen => None, } } } #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum MixBlendMode { Normal = 0, Multiply = 1, Screen = 2, Overlay = 3, Darken = 4, Lighten = 5, ColorDodge = 6, @@ -696,37 +696,37 @@ pub enum MixBlendMode { Hue = 12, Saturation = 13, Color = 14, Luminosity = 15, } /// An input to a SVG filter primitive. #[repr(C)] -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, 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)] +#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct BlendPrimitive { pub input1: FilterPrimitiveInput, pub input2: FilterPrimitiveInput, pub mode: MixBlendMode, } /// SVG Filter Primitive. #[repr(C)] -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum FilterPrimitive { Blend(BlendPrimitive), } /// CSS filter. #[repr(C)] #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub enum FilterOp {