Bug 1555483 - Part 2: Add SVG filter picture composite mode r=gw

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Connor Brewster 2019-07-08 22:32:59 +00:00
Родитель f48188d4e6
Коммит cc5163e0bb
5 изменённых файлов: 114 добавлений и 8 удалений

Просмотреть файл

@ -1640,6 +1640,38 @@ impl BatchBuilder {
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 => {

Просмотреть файл

@ -1981,6 +1981,48 @@ impl<'a> DisplayListFlattener<'a> {
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:

Просмотреть файл

@ -3,7 +3,7 @@
* 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};
@ -1573,6 +1573,8 @@ pub enum PictureCompositeMode {
/// 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.
@ -1938,7 +1940,8 @@ impl PicturePrimitive {
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
}
@ -2442,6 +2445,30 @@ impl PicturePrimitive {
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 {
@ -2990,7 +3017,8 @@ impl PicturePrimitive {
filter_data.update(frame_state);
}
PictureCompositeMode::MixBlend(..) |
PictureCompositeMode::Blit(_) => {}
PictureCompositeMode::Blit(_) |
PictureCompositeMode::SvgFilter(_) => {}
}
true

Просмотреть файл

@ -3,7 +3,7 @@
* 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};
@ -44,6 +44,7 @@ pub enum PictureCompositeKey {
LinearToSrgb,
ComponentTransfer(ItemUid),
Flood(ColorU),
SvgFilter(Vec<FilterPrimitive>),
// MixBlendMode
Multiply,
@ -130,6 +131,9 @@ impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
Some(PictureCompositeMode::ComponentTransferFilter(handle)) => {
PictureCompositeKey::ComponentTransfer(handle.uid())
}
Some(PictureCompositeMode::SvgFilter(filter_primitives)) => {
PictureCompositeKey::SvgFilter(filter_primitives)
}
Some(PictureCompositeMode::Blit(_)) |
Some(PictureCompositeMode::TileCache { .. }) |
None => {

Просмотреть файл

@ -679,7 +679,7 @@ impl RasterSpace {
}
#[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,
@ -701,7 +701,7 @@ pub enum MixBlendMode {
/// 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,
@ -712,7 +712,7 @@ pub enum FilterPrimitiveInput {
}
#[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,
@ -721,7 +721,7 @@ pub struct BlendPrimitive {
/// 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),
}