зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1896503 - Implement FilterInstance code to send SVG filter graph to WebRender r=mstange,gw
Differential Revision: https://phabricator.services.mozilla.com/D174208
This commit is contained in:
Родитель
69918535dc
Коммит
cac93eda00
|
@ -795,9 +795,6 @@ pub struct FilterGraphNodeKey {
|
|||
/// sRGB texture pixel colors on load and convert back on store, for correct
|
||||
/// interpolation
|
||||
pub linear: bool,
|
||||
/// padding for output rect if we need a border to get correct clamping, or
|
||||
/// to account for larger final subregion than source rect (see bug 1869672)
|
||||
pub inflate: i16,
|
||||
/// virtualized picture input binding 1 (i.e. texture source), typically
|
||||
/// this is used, but certain filters do not use it
|
||||
pub inputs: Vec<FilterGraphPictureReferenceKey>,
|
||||
|
@ -811,7 +808,6 @@ impl From<FilterGraphNode> for FilterGraphNodeKey {
|
|||
FilterGraphNodeKey{
|
||||
kept_by_optimizer: node.kept_by_optimizer,
|
||||
linear: node.linear,
|
||||
inflate: node.inflate,
|
||||
inputs: node.inputs.into_iter().map(|node| {node.into()}).collect(),
|
||||
subregion: [
|
||||
Au::from_f32_px(node.subregion.min.x),
|
||||
|
|
|
@ -1640,7 +1640,7 @@ impl RenderTask {
|
|||
data_stores: &mut DataStores,
|
||||
uv_rect_kind: UvRectKind,
|
||||
original_task_id: RenderTaskId,
|
||||
_surface_rects_task_size: DeviceIntSize,
|
||||
surface_rects_task_size: DeviceIntSize,
|
||||
surface_rects_clipped: DeviceRect,
|
||||
surface_rects_clipped_local: PictureRect,
|
||||
) -> RenderTaskId {
|
||||
|
@ -2256,39 +2256,29 @@ impl RenderTask {
|
|||
},
|
||||
}
|
||||
|
||||
// If this is the output node, we have to match the provided filter
|
||||
// subregion as the primitive it is applied to is already placed (it
|
||||
// was calculated in get_surface_rects using get_coverage_svgfe).
|
||||
let node_subregion = match is_output {
|
||||
true => output_subregion,
|
||||
false => used_subregion,
|
||||
};
|
||||
// If this is the output node, apply the output clip.
|
||||
let node_inflate = node.inflate;
|
||||
let mut create_output_task = false;
|
||||
if is_output {
|
||||
// If we're drawing a subregion that encloses output_subregion
|
||||
// we can just crop the node to output_subregion.
|
||||
if used_subregion.to_i32().contains_box(&output_rect) {
|
||||
used_subregion = output_subregion;
|
||||
} else {
|
||||
// We'll have to create an extra blit task after this task
|
||||
// so that there is transparent black padding around it.
|
||||
create_output_task = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert subregion from layout pixels to integer device pixels and
|
||||
// then calculate size afterwards so it reflects the used pixel area
|
||||
//
|
||||
// In case of the output node we preserve the exact filter_subregion
|
||||
// task size.
|
||||
//
|
||||
// This can be an empty rect if the source_subregion invalidation
|
||||
// rect didn't request any pixels of this node, but we can't skip
|
||||
// creating tasks that have no size because they would leak in the
|
||||
// render task graph with no consumers
|
||||
let node_task_rect =
|
||||
match is_output {
|
||||
true => output_rect,
|
||||
false => node_subregion.to_i32(),
|
||||
};
|
||||
|
||||
// SVG spec requires that a later node sampling pixels outside
|
||||
// this node's subregion will receive a transparent black color
|
||||
// for those samples, we achieve this by adding a 1 pixel border
|
||||
// around the target rect, which works fine with the clamping of the
|
||||
// texture fetch in the shader, and to account for the offset we
|
||||
// have to make a UvRectKind::Quad mapping for later nodes to use
|
||||
// when sampling this output, if they use feOffset or have a
|
||||
// larger target rect those samples will be clamped to the
|
||||
// transparent black border and thus meet spec.
|
||||
let node_task_rect: DeviceIntRect = used_subregion.to_i32().cast_unit();
|
||||
let mut node_task_size = node_task_rect.size().cast_unit();
|
||||
|
||||
// We have to limit the render target sizes we're asking for on the
|
||||
|
@ -2300,22 +2290,31 @@ impl RenderTask {
|
|||
// space. Blurs will do this same logic if their intermediate is
|
||||
// too large. We use a simple halving calculation here so that
|
||||
// pixel alignment is still vaguely sensible.
|
||||
while node_task_size.width as usize + node.inflate as usize * 2 > MAX_SURFACE_SIZE ||
|
||||
node_task_size.height as usize + node.inflate as usize * 2 > MAX_SURFACE_SIZE {
|
||||
while node_task_size.width as usize + node_inflate as usize * 2 > MAX_SURFACE_SIZE ||
|
||||
node_task_size.height as usize + node_inflate as usize * 2 > MAX_SURFACE_SIZE {
|
||||
node_task_size.width >>= 1;
|
||||
node_task_size.height >>= 1;
|
||||
}
|
||||
// Add the inflate border
|
||||
node_task_size.width += node.inflate as i32 * 2;
|
||||
node_task_size.height += node.inflate as i32 * 2;
|
||||
|
||||
// SVG spec requires that a later node sampling pixels outside
|
||||
// this node's subregion will receive a transparent black color
|
||||
// for those samples, we achieve this by adding a 1 pixel border
|
||||
// around the target rect, which works fine with the clamping of the
|
||||
// texture fetch in the shader, and to account for the offset we
|
||||
// have to make a UvRectKind::Quad mapping for later nodes to use
|
||||
// when sampling this output, if they use feOffset or have a
|
||||
// larger target rect those samples will be clamped to the
|
||||
// transparent black border and thus meet spec.
|
||||
node_task_size.width += node_inflate as i32 * 2;
|
||||
node_task_size.height += node_inflate as i32 * 2;
|
||||
|
||||
// Make the uv_rect_kind for this node's task to use, this matters
|
||||
// only on the final node because we don't use it internally
|
||||
let node_uv_rect_kind =
|
||||
uv_rect_kind_for_task_size(node_task_size, node.inflate);
|
||||
uv_rect_kind_for_task_size(node_task_size, node_inflate);
|
||||
|
||||
// Create task for this node
|
||||
let task_id;
|
||||
let mut task_id;
|
||||
match op {
|
||||
FilterGraphOp::SVGFEGaussianBlur { std_deviation_x, std_deviation_y } => {
|
||||
// Note: wrap_prim_with_filters copies the SourceGraphic to
|
||||
|
@ -2430,7 +2429,7 @@ impl RenderTask {
|
|||
node: FilterGraphNode{
|
||||
kept_by_optimizer: true,
|
||||
linear: node.linear,
|
||||
inflate: node.inflate,
|
||||
inflate: node_inflate,
|
||||
inputs: [
|
||||
FilterGraphPictureReference{
|
||||
buffer_id: blur_input.buffer_id,
|
||||
|
@ -2440,7 +2439,7 @@ impl RenderTask {
|
|||
source_padding: LayoutRect::zero(),
|
||||
target_padding: LayoutRect::zero(),
|
||||
}].to_vec(),
|
||||
subregion: node_subregion,
|
||||
subregion: used_subregion,
|
||||
},
|
||||
op: FilterGraphOp::SVGFEIdentity,
|
||||
content_origin: DevicePoint::zero(),
|
||||
|
@ -2575,7 +2574,7 @@ impl RenderTask {
|
|||
node: FilterGraphNode{
|
||||
kept_by_optimizer: true,
|
||||
linear: node.linear,
|
||||
inflate: node.inflate,
|
||||
inflate: node_inflate,
|
||||
inputs: [
|
||||
// Original picture
|
||||
*blur_input,
|
||||
|
@ -2588,7 +2587,7 @@ impl RenderTask {
|
|||
source_padding: LayoutRect::zero(),
|
||||
target_padding: LayoutRect::zero(),
|
||||
}].to_vec(),
|
||||
subregion: node_subregion,
|
||||
subregion: used_subregion,
|
||||
},
|
||||
op: FilterGraphOp::SVGFEDropShadow{
|
||||
color,
|
||||
|
@ -2618,7 +2617,7 @@ impl RenderTask {
|
|||
node: FilterGraphNode{
|
||||
kept_by_optimizer: true,
|
||||
linear: node.linear,
|
||||
inflate: node.inflate,
|
||||
inflate: node_inflate,
|
||||
inputs: [
|
||||
FilterGraphPictureReference{
|
||||
buffer_id: FilterOpGraphPictureBufferId::None,
|
||||
|
@ -2635,7 +2634,7 @@ impl RenderTask {
|
|||
target_padding: LayoutRect::zero(),
|
||||
}
|
||||
].to_vec(),
|
||||
subregion: node_subregion,
|
||||
subregion: used_subregion,
|
||||
},
|
||||
op: op.clone(),
|
||||
content_origin: DevicePoint::zero(),
|
||||
|
@ -2661,8 +2660,8 @@ impl RenderTask {
|
|||
kept_by_optimizer: true,
|
||||
linear: node.linear,
|
||||
inputs: node_inputs.iter().map(|input| {input.0}).collect(),
|
||||
subregion: node_subregion,
|
||||
inflate: node.inflate,
|
||||
subregion: used_subregion,
|
||||
inflate: node_inflate,
|
||||
},
|
||||
op: op.clone(),
|
||||
content_origin: DevicePoint::zero(),
|
||||
|
@ -2693,8 +2692,8 @@ impl RenderTask {
|
|||
kept_by_optimizer: true,
|
||||
linear: node.linear,
|
||||
inputs: node_inputs.iter().map(|input| {input.0}).collect(),
|
||||
subregion: node_subregion,
|
||||
inflate: node.inflate,
|
||||
subregion: used_subregion,
|
||||
inflate: node_inflate,
|
||||
},
|
||||
op: op.clone(),
|
||||
content_origin: DevicePoint::zero(),
|
||||
|
@ -2720,9 +2719,44 @@ impl RenderTask {
|
|||
// to look them up quickly, since nodes can only depend on previous
|
||||
// nodes in the same list
|
||||
task_by_buffer_id[filter_index] = task_id;
|
||||
subregion_by_buffer_id[filter_index] = node_subregion;
|
||||
subregion_by_buffer_id[filter_index] = used_subregion;
|
||||
|
||||
if is_output {
|
||||
// The final task we create is the output picture.
|
||||
output_task_id = task_id;
|
||||
if create_output_task {
|
||||
// If the final node subregion is smaller than the output rect,
|
||||
// we need to pad it with transparent black to match SVG spec,
|
||||
// as the output task rect is larger than the invalidated area,
|
||||
// ideally the origin and size of the picture we return should
|
||||
// be used instead of the get_rect result for sizing geometry,
|
||||
// as it would allow us to produce a much smaller rect.
|
||||
let output_uv_rect_kind =
|
||||
uv_rect_kind_for_task_size(surface_rects_task_size, 0);
|
||||
task_id = frame_state.rg_builder.add().init(RenderTask::new_dynamic(
|
||||
surface_rects_task_size,
|
||||
RenderTaskKind::SVGFENode(
|
||||
SVGFEFilterTask{
|
||||
node: FilterGraphNode{
|
||||
kept_by_optimizer: true,
|
||||
linear: false,
|
||||
inputs: [FilterGraphPictureReference{
|
||||
buffer_id: FilterOpGraphPictureBufferId::None,
|
||||
subregion: used_subregion,
|
||||
offset: LayoutVector2D::zero(),
|
||||
inflate: node_inflate,
|
||||
source_padding: LayoutRect::zero(),
|
||||
target_padding: LayoutRect::zero(),
|
||||
}].to_vec(),
|
||||
subregion: output_subregion,
|
||||
inflate: 0,
|
||||
},
|
||||
op: FilterGraphOp::SVGFEIdentity,
|
||||
content_origin: surface_rects_clipped.min,
|
||||
extra_gpu_cache_handle: None,
|
||||
}
|
||||
),
|
||||
).with_uv_rect_kind(output_uv_rect_kind));
|
||||
frame_state.rg_builder.add_dependency(task_id, output_task_id);
|
||||
output_task_id = task_id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3795,6 +3795,9 @@ impl<'a> SceneBuilder<'a> {
|
|||
// For each filter, create a new image with that composite mode.
|
||||
let mut current_filter_data_index = 0;
|
||||
// Check if the filter chain is actually an SVGFE filter graph DAG
|
||||
//
|
||||
// TODO: We technically could translate all CSS filters to SVGFE here if
|
||||
// we want to reduce redundant code.
|
||||
if let Some(Filter::SVGGraphNode(..)) = filter_ops.first() {
|
||||
// The interesting parts of the handling of SVG filters are:
|
||||
// * scene_building.rs : wrap_prim_with_filters (you are here)
|
||||
|
@ -3808,9 +3811,6 @@ impl<'a> SceneBuilder<'a> {
|
|||
// Easily tunable for debugging proper handling of inflated rects,
|
||||
// this should normally be 1
|
||||
const SVGFE_INFLATE: i16 = 1;
|
||||
// Easily tunable for debugging proper handling of inflated rects,
|
||||
// this should normally be 0
|
||||
const SVGFE_INFLATE_OUTPUT: i16 = 0;
|
||||
|
||||
// Validate inputs to all filters.
|
||||
//
|
||||
|
@ -3846,14 +3846,14 @@ impl<'a> SceneBuilder<'a> {
|
|||
let mut filters: Vec<(FilterGraphNode, FilterGraphOp)> = Vec::new();
|
||||
filters.reserve(BUFFER_LIMIT);
|
||||
for (original_id, parsefilter) in filter_ops.iter().enumerate() {
|
||||
match parsefilter {
|
||||
Filter::SVGGraphNode(parsenode, op) => {
|
||||
if filters.len() >= BUFFER_LIMIT {
|
||||
// If the DAG is too large we drop it entirely, the spec
|
||||
// allows this.
|
||||
return source;
|
||||
}
|
||||
if filters.len() >= BUFFER_LIMIT {
|
||||
// If the DAG is too large to process, the spec requires
|
||||
// that we drop all filters and display source image as-is.
|
||||
return source;
|
||||
}
|
||||
|
||||
let newfilter = match parsefilter {
|
||||
Filter::SVGGraphNode(parsenode, op) => {
|
||||
// We need to offset the subregion by the stacking context
|
||||
// offset or we'd be in the wrong coordinate system, prims
|
||||
// are already offset by this same amount.
|
||||
|
@ -3923,7 +3923,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{..} |
|
||||
FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching{..} => {
|
||||
assert!(remapped_inputs.len() == 0);
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
}
|
||||
FilterGraphOp::SVGFEColorMatrix{..} |
|
||||
FilterGraphOp::SVGFEIdentity |
|
||||
|
@ -3932,7 +3932,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
FilterGraphOp::SVGFEToAlpha => {
|
||||
assert!(remapped_inputs.len() == 1);
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
}
|
||||
FilterGraphOp::SVGFEComponentTransfer => {
|
||||
assert!(remapped_inputs.len() == 1);
|
||||
|
@ -3977,7 +3977,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
.intern(&filter_data_key, || ());
|
||||
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), FilterGraphOp::SVGFEComponentTransferInterned{handle, creates_pixels}));
|
||||
(newnode.clone(), FilterGraphOp::SVGFEComponentTransferInterned{handle, creates_pixels})
|
||||
}
|
||||
FilterGraphOp::SVGFEComponentTransferInterned{..} => unreachable!(),
|
||||
FilterGraphOp::SVGFETile => {
|
||||
|
@ -3988,7 +3988,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
remapped_inputs[0].target_padding =
|
||||
LayoutRect::max_rect();
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
}
|
||||
FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate{kernel_unit_length_x, kernel_unit_length_y, ..} |
|
||||
FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone{kernel_unit_length_x, kernel_unit_length_y, ..} |
|
||||
|
@ -4010,7 +4010,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
remapped_inputs[0].target_padding
|
||||
.inflate(padding.width, padding.height);
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
},
|
||||
FilterGraphOp::SVGFEDiffuseLightingDistant{kernel_unit_length_x, kernel_unit_length_y, ..} |
|
||||
FilterGraphOp::SVGFEDiffuseLightingPoint{kernel_unit_length_x, kernel_unit_length_y, ..} |
|
||||
|
@ -4035,7 +4035,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
remapped_inputs[0].target_padding
|
||||
.inflate(padding.width, padding.height);
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
},
|
||||
FilterGraphOp::SVGFEDisplacementMap { scale, .. } => {
|
||||
assert!(remapped_inputs.len() == 2);
|
||||
|
@ -4060,7 +4060,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
remapped_inputs[1].target_padding
|
||||
.inflate(padding.width, padding.height);
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
},
|
||||
FilterGraphOp::SVGFEDropShadow{ dx, dy, std_deviation_x, std_deviation_y, .. } => {
|
||||
assert!(remapped_inputs.len() == 1);
|
||||
|
@ -4090,7 +4090,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
)
|
||||
);
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
},
|
||||
FilterGraphOp::SVGFEGaussianBlur{std_deviation_x, std_deviation_y} => {
|
||||
assert!(remapped_inputs.len() == 1);
|
||||
|
@ -4107,7 +4107,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
remapped_inputs[0].target_padding
|
||||
.inflate(padding.width, padding.height);
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode.clone(), op.clone())
|
||||
}
|
||||
FilterGraphOp::SVGFEBlendColor |
|
||||
FilterGraphOp::SVGFEBlendColorBurn |
|
||||
|
@ -4134,62 +4134,59 @@ impl<'a> SceneBuilder<'a> {
|
|||
FilterGraphOp::SVGFECompositeXOR => {
|
||||
assert!(remapped_inputs.len() == 2);
|
||||
newnode.inputs = remapped_inputs;
|
||||
filters.push((newnode.clone(), op.clone()));
|
||||
(newnode, op.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// Set the reference remapping for the last (or only) node
|
||||
// that we just pushed
|
||||
let id = (filters.len() - 1) as i16;
|
||||
if let Some(pic) = reference_for_buffer_id.get_mut(original_id as usize) {
|
||||
*pic = FilterGraphPictureReference {
|
||||
buffer_id: FilterOpGraphPictureBufferId::BufferId(id),
|
||||
subregion: newnode.subregion,
|
||||
offset: LayoutVector2D::zero(),
|
||||
inflate: newnode.inflate,
|
||||
source_padding: LayoutRect::zero(),
|
||||
target_padding: LayoutRect::zero(),
|
||||
};
|
||||
}
|
||||
}
|
||||
Filter::Opacity(valuebinding, value) => {
|
||||
// Opacity filter is sometimes appended by
|
||||
// wr_dp_push_stacking_context before we get here,
|
||||
// convert to SVGFEOpacity in the graph. Note that
|
||||
// linear is set to false because it has no meaning for
|
||||
// opacity (which scales all of the RGBA uniformly).
|
||||
let pic = reference_for_buffer_id[original_id as usize - 1];
|
||||
(
|
||||
FilterGraphNode {
|
||||
kept_by_optimizer: false,
|
||||
linear: false,
|
||||
inflate: SVGFE_INFLATE,
|
||||
inputs: [pic].to_vec(),
|
||||
subregion: pic.subregion,
|
||||
},
|
||||
FilterGraphOp::SVGFEOpacity{
|
||||
valuebinding: *valuebinding,
|
||||
value: *value,
|
||||
},
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
panic!("wrap_prim_with_filters: Mixed SVG and CSS filters?")
|
||||
log!(Level::Warn, "wrap_prim_with_filters: unexpected filter after SVG filters filter[{:?}]={:?}", original_id, parsefilter);
|
||||
// If we can't figure out how to process the graph, spec
|
||||
// requires that we drop all filters and display source
|
||||
// image as-is.
|
||||
return source;
|
||||
}
|
||||
}
|
||||
};
|
||||
let id = filters.len();
|
||||
filters.push(newfilter);
|
||||
|
||||
// Set the reference remapping for the last (or only) node
|
||||
// that we just pushed
|
||||
reference_for_buffer_id[original_id] = FilterGraphPictureReference {
|
||||
buffer_id: FilterOpGraphPictureBufferId::BufferId(id as i16),
|
||||
subregion: filters[id].0.subregion,
|
||||
offset: LayoutVector2D::zero(),
|
||||
inflate: filters[id].0.inflate,
|
||||
source_padding: LayoutRect::zero(),
|
||||
target_padding: LayoutRect::zero(),
|
||||
};
|
||||
}
|
||||
|
||||
// Push a special output node at the end, this will correctly handle
|
||||
// the final subregion, which may not have the same bounds as the
|
||||
// surface it is being blitted into, so it needs to properly handle
|
||||
// the cropping and UvRectKind, it also has no inflate.
|
||||
if filters.len() >= BUFFER_LIMIT {
|
||||
// If the DAG is too large we drop it entirely
|
||||
// If the DAG is too large to process, the spec requires
|
||||
// that we drop all filters and display source image as-is.
|
||||
return source;
|
||||
}
|
||||
let mut outputnode = FilterGraphNode {
|
||||
kept_by_optimizer: true,
|
||||
linear: false,
|
||||
inflate: SVGFE_INFLATE_OUTPUT,
|
||||
inputs: Vec::new(),
|
||||
subregion: LayoutRect::max_rect(),
|
||||
};
|
||||
outputnode.inputs.push(reference_for_buffer_id[filter_ops.len() - 1]);
|
||||
filters.push((
|
||||
outputnode,
|
||||
FilterGraphOp::SVGFEIdentity,
|
||||
));
|
||||
|
||||
// We want to optimize the filter DAG and then wrap it in a single
|
||||
// picture, we will use a custom RenderTask method to process the
|
||||
// DAG later, there's not really an easy way to keep it as a series
|
||||
// of pictures like CSS filters use.
|
||||
//
|
||||
// The main optimization we can do here is looking for feOffset
|
||||
// filters we can merge away - because all of the node inputs
|
||||
// support offset capability implicitly. We can also remove no-op
|
||||
// filters (identity) if Gecko produced any.
|
||||
//
|
||||
// TODO: optimize the graph here
|
||||
|
||||
// Mark used graph nodes, starting at the last graph node, since
|
||||
// this is a DAG in sorted order we can just iterate backwards and
|
||||
|
@ -4223,8 +4220,8 @@ impl<'a> SceneBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// Validate the DAG nature of the graph again - if we find anything
|
||||
// wrong here it means the above code is bugged.
|
||||
// Validate the DAG nature of the graph - if we find anything wrong
|
||||
// here it means the above code is bugged.
|
||||
let mut invalid_dag = false;
|
||||
for (id, (node, _op)) in filters.iter().enumerate() {
|
||||
for input in &node.inputs {
|
||||
|
|
|
@ -2299,8 +2299,32 @@ void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
|
|||
gfx::Matrix5x4* colorMatrix =
|
||||
nsDocShell::Cast(docShell)->GetColorMatrix();
|
||||
if (colorMatrix) {
|
||||
wrFilters.filters.AppendElement(
|
||||
wr::FilterOp::ColorMatrix(colorMatrix->components));
|
||||
// Note: This color matrix was added here in for accessibility in
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1431466 , it could be
|
||||
// done with regular SVG in the document as long as it is accelerated,
|
||||
// and it's probably best to do this in linearRGB, now that it is
|
||||
// feasible to do so
|
||||
// TODO(ahale): Make sure to test this works correctly before enabling
|
||||
if (StaticPrefs::gfx_webrender_svg_filter_effects() &&
|
||||
StaticPrefs::
|
||||
gfx_webrender_svg_filter_effects_also_use_for_docshell_fecolormatrix()) {
|
||||
// WebRender SVGFE code needs a valid filter region, so use 1<<30 as
|
||||
// rendering will already be heavily degraded at that range.
|
||||
static constexpr float kExtent = 1024.0f * 1024.0f * 1024.0f;
|
||||
wr::LayoutRect subregion = {{-kExtent, -kExtent}, {kExtent, kExtent}};
|
||||
auto node = wr::FilterOpGraphNode{};
|
||||
node.input.buffer_id = wr::FilterOpGraphPictureBufferId::None();
|
||||
node.input2.buffer_id = wr::FilterOpGraphPictureBufferId::None();
|
||||
node.subregion = subregion;
|
||||
wrFilters.filters.AppendElement(
|
||||
wr::FilterOp::SVGFESourceGraphic(node));
|
||||
node.input.buffer_id = wr::FilterOpGraphPictureBufferId::BufferId(0);
|
||||
wrFilters.filters.AppendElement(
|
||||
wr::FilterOp::SVGFEColorMatrix(node, colorMatrix->components));
|
||||
} else {
|
||||
wrFilters.filters.AppendElement(
|
||||
wr::FilterOp::ColorMatrix(colorMatrix->components));
|
||||
}
|
||||
}
|
||||
|
||||
wrManager->EndTransactionWithoutLayer(this, aBuilder,
|
||||
|
@ -8284,18 +8308,25 @@ bool nsDisplayBackdropFilters::CreateWebRenderCommands(
|
|||
WrFiltersHolder wrFilters;
|
||||
const ComputedStyle& style = mStyle ? *mStyle : *mFrame->Style();
|
||||
auto filterChain = style.StyleEffects()->mBackdropFilters.AsSpan();
|
||||
bool initialized = true;
|
||||
if (!SVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, mFrame,
|
||||
wrFilters) &&
|
||||
!SVGIntegrationUtils::BuildWebRenderFilters(
|
||||
mFrame, filterChain, StyleFilterType::BackdropFilter, wrFilters,
|
||||
initialized)) {
|
||||
// Try building a CSS filter chain
|
||||
WrFiltersStatus status = SVGIntegrationUtils::CreateWebRenderCSSFilters(
|
||||
filterChain, mFrame, wrFilters);
|
||||
if (status == WrFiltersStatus::BLOB_FALLBACK) {
|
||||
// If the filters are too complex for CSS filters, try SVG filters
|
||||
auto offsetForSVGFilters =
|
||||
nsLayoutUtils::ComputeOffsetToUserSpace(aDisplayListBuilder, mFrame);
|
||||
status = SVGIntegrationUtils::BuildWebRenderFilters(
|
||||
mFrame, filterChain, StyleFilterType::BackdropFilter, wrFilters,
|
||||
offsetForSVGFilters);
|
||||
}
|
||||
|
||||
if (status == WrFiltersStatus::BLOB_FALLBACK) {
|
||||
// TODO: If painting backdrop-filters on the content side is implemented,
|
||||
// consider returning false to fall back to that.
|
||||
wrFilters = {};
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
if (status == WrFiltersStatus::UNSUPPORTED) {
|
||||
wrFilters = {};
|
||||
}
|
||||
|
||||
|
@ -8399,32 +8430,47 @@ bool nsDisplayFilters::CreateWebRenderCommands(
|
|||
WrFiltersHolder wrFilters;
|
||||
const ComputedStyle& style = mStyle ? *mStyle : *mFrame->Style();
|
||||
auto filterChain = style.StyleEffects()->mFilters.AsSpan();
|
||||
bool initialized = true;
|
||||
if (!SVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, mFrame,
|
||||
wrFilters) &&
|
||||
!SVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain,
|
||||
StyleFilterType::Filter,
|
||||
wrFilters, initialized)) {
|
||||
if (mStyle) {
|
||||
// Try building a CSS filter chain
|
||||
WrFiltersStatus status = SVGIntegrationUtils::CreateWebRenderCSSFilters(
|
||||
filterChain, mFrame, wrFilters);
|
||||
if (status == WrFiltersStatus::BLOB_FALLBACK) {
|
||||
// Try building an SVG filter graph
|
||||
auto offsetForSVGFilters =
|
||||
nsLayoutUtils::ComputeOffsetToUserSpace(aDisplayListBuilder, mFrame);
|
||||
status = SVGIntegrationUtils::BuildWebRenderFilters(
|
||||
mFrame, filterChain, StyleFilterType::Filter, wrFilters,
|
||||
offsetForSVGFilters);
|
||||
if (status == WrFiltersStatus::BLOB_FALLBACK && mStyle) {
|
||||
// TODO(bug 1769223): Support fallback filters in the root code-path,
|
||||
// perhaps. For now treat it the same way as invalid filters.
|
||||
wrFilters = {};
|
||||
} else {
|
||||
// Draw using fallback.
|
||||
return false;
|
||||
status = WrFiltersStatus::UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
// https://drafts.fxtf.org/filter-effects/#typedef-filter-url:
|
||||
//
|
||||
// If the filter references a non-existent object or the referenced object
|
||||
// is not a filter element, then the whole filter chain is ignored. No
|
||||
// filter is applied to the object.
|
||||
//
|
||||
// Note that other engines have a weird discrepancy between SVG and HTML
|
||||
// content here, but the spec is clear.
|
||||
wrFilters = {};
|
||||
switch (status) {
|
||||
case WrFiltersStatus::BLOB_FALLBACK:
|
||||
// Draw using fallback.
|
||||
return false;
|
||||
case WrFiltersStatus::UNSUPPORTED:
|
||||
// https://drafts.fxtf.org/filter-effects/#typedef-filter-url:
|
||||
//
|
||||
// If the filter references a non-existent object or the referenced
|
||||
// object is not a filter element, then the whole filter chain is
|
||||
// ignored. No filter is applied to the object.
|
||||
//
|
||||
// Note that other engines have a weird discrepancy between SVG and HTML
|
||||
// content here, but the spec is clear.
|
||||
wrFilters = {};
|
||||
break;
|
||||
case WrFiltersStatus::DISABLED_FOR_PERFORMANCE:
|
||||
// SVG spec allows us to drop the entire filter graph if it contains too
|
||||
// many filters to render or other performance considerations.
|
||||
wrFilters = {};
|
||||
break;
|
||||
case WrFiltersStatus::CHAIN:
|
||||
case WrFiltersStatus::SVGFE:
|
||||
// Filter the image using the wrFilters produced above.
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t clipChainId;
|
||||
|
|
|
@ -1581,12 +1581,12 @@ fuzzy(0-64,0-45) == 614272-1.svg 614272-1-ref.svg
|
|||
!= 618071.html 618071-notref.html
|
||||
== 619117-1.html 619117-1-ref.html
|
||||
== 619511-1.html 619511-1-ref.html
|
||||
fails-if(useDrawSnapshot) == 621253-1-externalFilter.html 621253-1-ref.html
|
||||
fails-if(useDrawSnapshot) == 621253-1-internalFilter.html 621253-1-ref.html
|
||||
fails-if(useDrawSnapshot) == 621253-2-externalFilter.html 621253-2-ref.html
|
||||
fails-if(useDrawSnapshot) == 621253-2-internalFilter.html 621253-2-ref.html
|
||||
fails-if(useDrawSnapshot) fuzzy-if(geckoview&&!emulator&&gfxSVGFEColorMatrix,0-4,0-32) == 621253-1-externalFilter.html 621253-1-ref.html
|
||||
fails-if(useDrawSnapshot) fuzzy-if(geckoview&&!emulator&&gfxSVGFEColorMatrix,0-4,0-32) == 621253-1-internalFilter.html 621253-1-ref.html
|
||||
fails-if(useDrawSnapshot) fuzzy-if(geckoview&&!emulator&&gfxSVGFEColorMatrix,0-4,0-32) == 621253-2-externalFilter.html 621253-2-ref.html
|
||||
fails-if(useDrawSnapshot) fuzzy-if(geckoview&&!emulator&&gfxSVGFEColorMatrix,0-4,0-32) == 621253-2-internalFilter.html 621253-2-ref.html
|
||||
random-if(winWidget) == 621918-1.svg 621918-1-ref.svg # 1-pixel diacritic positioning discrepancy in rotated text (may depend on platform fonts)
|
||||
random-if(winWidget) fuzzy-if(geckoview&&!emulator,0-255,0-22) == 621918-2.svg 621918-2-ref.svg # same 1px issue as above
|
||||
random-if(winWidget) fuzzy-if(geckoview&&!emulator,0-255,0-23) == 621918-2.svg 621918-2-ref.svg # same 1px issue as above
|
||||
fuzzy-if(winWidget,0-5,0-1) == 622585-1.html 622585-1-ref.html # bug 789402
|
||||
fuzzy(0-1,0-40000) == 625409-1.html 625409-1-ref.html
|
||||
== 627393-1.html about:blank
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
== blend-constant-background-color.html blend-constant-background-color-ref.html
|
||||
== blend-gradient-background-color.html blend-gradient-background-color-ref.html
|
||||
== blend-image.html blend-image-ref.html
|
||||
fuzzy-if(geckoview&&device,3-3,5-5) == blend-difference-stacking.html blend-difference-stacking-ref.html
|
||||
# for some reason this test ends up with a subpixel misalignment for the '.'
|
||||
# character when using gfx.webrender.svg-filters.enable=true, but other text
|
||||
# works, however the text is not the purpose of this test, so just use fuzzy.
|
||||
fuzzy(0-73,0-8) == blend-difference-stacking.html blend-difference-stacking-ref.html
|
||||
|
||||
fuzzy(0-1,0-30000) == background-blending-alpha.html background-blending-alpha-ref.html
|
||||
== background-blending-gradient-color.html background-blending-gradient-color-ref.html
|
||||
|
|
|
@ -12,11 +12,11 @@ fuzzy-if(winWidget,47-129,47-54) == element-paint-simple.html element-paint-simp
|
|||
== element-paint-recursion.html element-paint-recursion-ref.html
|
||||
== element-paint-continuation.html element-paint-continuation-ref.html
|
||||
== element-paint-transform-01.html element-paint-transform-01-ref.html
|
||||
random-if(winWidget) fuzzy-if(!useDrawSnapshot,255-255,39-42) == element-paint-transform-02.html element-paint-transform-02-ref.html # bug 587133
|
||||
fuzzy(0-201,0-1486) == element-paint-transform-02.html element-paint-transform-02-ref.html # bug 587133
|
||||
== element-paint-background-size-01.html element-paint-background-size-01-ref.html
|
||||
== element-paint-background-size-02.html element-paint-background-size-02-ref.html
|
||||
fuzzy(0-255,0-4) == element-paint-transform-repeated.html element-paint-transform-repeated-ref.html # Bug 1475907
|
||||
fuzzy-if(winWidget,0-255,0-24) fuzzy-if(!useDrawSnapshot,255-255,50-115) == element-paint-transform-03.html element-paint-transform-03-ref.html
|
||||
fuzzy(0-255,0-144) == element-paint-transform-03.html element-paint-transform-03-ref.html
|
||||
|
||||
# For element() uses fallback / skia in WebRender, which antialiases differently from WR.
|
||||
# For Windows: bug 1496542, the scrollframe snaps differently.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="786" viewBox="0,0,512,512">
|
||||
<defs>
|
||||
<clipPath id="clip-vXP8Ybe5">
|
||||
<path d="M0,512v-512h512v512z"/>
|
||||
</clipPath>
|
||||
<path d="M0,600v-600h512v600z"/>
|
||||
</clipPath>
|
||||
<filter id="filter-wVmTgUOU" filterUnits="objectBoundingBox" x="-30%" y="-30%" width="160%" height="170%" color-interpolation-filters="sRGB">
|
||||
<feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" in="SourceGraphic"/>
|
||||
<feOffset dy="28"/>
|
||||
|
|
До Ширина: | Высота: | Размер: 762 B После Ширина: | Высота: | Размер: 760 B |
|
@ -1,17 +1,17 @@
|
|||
# These tests verify that CSS filters behave properly.
|
||||
# e.g. filter: blur(3px)
|
||||
|
||||
== blur.html blur-ref.html
|
||||
== blur.svg blur-ref.svg
|
||||
fuzzy(0-1,0-1000000) == blur.html blur-ref.html
|
||||
fuzzy(0-1,0-1000000) == blur.svg blur-ref.svg
|
||||
== blur-calc.html blur-calc-ref.html
|
||||
== blur-calc-negative.html blur-calc-negative-ref.html
|
||||
fuzzy-if(cocoaWidget,0-1,0-2) skip-if(winWidget) == blur-cap-large-radius-on-software.html blur-cap-large-radius-on-software-ref.html
|
||||
fuzzy-if(!useDrawSnapshot,2-5,4764-8168) fuzzy-if(Android&&device&&!swgl,5-5,8574-8574) == blur-clip-rect.html ../feGaussianBlur-4-ref.svg
|
||||
== blur-em-radius.html blur-em-radius-ref.html
|
||||
== blur-clip-rect.html ../feGaussianBlur-4-ref.svg
|
||||
fuzzy(0-1,0-1000000) == blur-em-radius.html blur-em-radius-ref.html
|
||||
== blur-invalid-radius.html blur-invalid-radius-ref.html
|
||||
== blur-rem-radius.html blur-rem-radius-ref.html
|
||||
fuzzy(0-1,0-1000000) == blur-rem-radius.html blur-rem-radius-ref.html
|
||||
== blur-zero-radius.html blur-zero-radius-ref.html
|
||||
fails-if(useDrawSnapshot) == blur-zoomed-page.html blur-zoomed-page-ref.html
|
||||
fails-if(useDrawSnapshot) fuzzy-if(gfxSVGFEGaussianBlur,0-2,0-1000000) == blur-zoomed-page.html blur-zoomed-page-ref.html
|
||||
== brightness.html brightness-ref.html
|
||||
== brightness-darken.html brightness-darken-ref.html
|
||||
== brightness-extreme.html brightness-extreme-ref.html
|
||||
|
@ -25,9 +25,9 @@ fails-if(useDrawSnapshot) == blur-zoomed-page.html blur-zoomed-page-ref.html
|
|||
== contrast-percent.html contrast-percent-ref.html
|
||||
== contrast-reduce.html contrast-reduce-ref.html
|
||||
== contrast-zero.html contrast-zero-ref.html
|
||||
== drop-shadow.html drop-shadow-ref.html
|
||||
== drop-shadow-default-color.html drop-shadow-default-color-ref.html
|
||||
== drop-shadow-negative-offset.html drop-shadow-negative-offset-ref.html
|
||||
fuzzy(0-4,0-1000000) == drop-shadow.html drop-shadow-ref.html
|
||||
fuzzy(0-4,0-1000000) == drop-shadow-default-color.html drop-shadow-default-color-ref.html
|
||||
fuzzy(0-4,0-1000000) == drop-shadow-negative-offset.html drop-shadow-negative-offset-ref.html
|
||||
== filter-on-huge-bbox.html pass.svg
|
||||
fuzzy(0-1,0-44) fuzzy-if(winWidget,0-1,0-198) == filter-on-outer-svg.html pass.svg
|
||||
fuzzy(0-1,0-10000) == grayscale.html grayscale-ref.html
|
||||
|
|
|
@ -20,17 +20,17 @@ include svg-filter-chains/reftest.list
|
|||
== dynamic-filter-invalidation-03.svg pass.svg
|
||||
== dynamic-filter-invalidation-04.svg pass.svg
|
||||
|
||||
fuzzy(0-1,0-42500) == feBlend-1.svg feBlend-1-ref.svg
|
||||
== feBlend-2.svg feBlend-2-ref.svg
|
||||
fuzzy(0-2,0-1000000) == feBlend-1.svg feBlend-1-ref.svg
|
||||
fuzzy-if(geckoview&&!emulator&&gfxSVGFEBlend,0-14,0-136) == feBlend-2.svg feBlend-2-ref.svg
|
||||
|
||||
fuzzy(0-1,0-6400) == feColorMatrix-1.svg feColorMatrix-1-ref.svg
|
||||
fuzzy(0-1,0-10000) == feColorMatrix-2.svg feColorMatrix-2-ref.svg
|
||||
fuzzy(0-2,0-1000000) == feColorMatrix-1.svg feColorMatrix-1-ref.svg
|
||||
fuzzy(0-2,0-1000000) == feColorMatrix-2.svg feColorMatrix-2-ref.svg
|
||||
|
||||
== feComponentTransfer-1.svg feComponentTransfer-1-ref.svg
|
||||
== feComponentTransfer-2.svg feComponentTransfer-2-ref.svg
|
||||
|
||||
fuzzy(0-1,0-9600) == feComposite-1.svg feComposite-1-ref.svg
|
||||
fuzzy(0-1,0-10000) == feComposite-2.svg feComposite-2-ref.svg
|
||||
fuzzy(0-2,0-1000000) == feComposite-1.svg feComposite-1-ref.svg
|
||||
fuzzy(0-2,0-1000000) == feComposite-2.svg feComposite-2-ref.svg
|
||||
|
||||
== feConvolveMatrix-1.svg feConvolveMatrix-1-ref.svg
|
||||
== feConvolveMatrix-2.svg feConvolveMatrix-2-ref.svg
|
||||
|
@ -38,16 +38,24 @@ fuzzy(0-1,0-10000) == feComposite-2.svg feComposite-2-ref.svg
|
|||
== feDisplacementMap-1.svg feDisplacementMap-1-ref.svg
|
||||
== feDisplacementMap-2.svg feDisplacementMap-2-ref.svg
|
||||
|
||||
fuzzy(0-1,0-1600) == feFlood-1.svg feFlood-1-ref.svg
|
||||
skip-if(winWidget) fuzzy(0-1,0-6400) == feFlood-2.svg feFlood-2-ref.svg
|
||||
fuzzy(0-2,0-1000000) == feFlood-1.svg feFlood-1-ref.svg
|
||||
fuzzy(0-2,0-1000000) == feFlood-2.svg feFlood-2-ref.svg
|
||||
|
||||
fuzzy(0-2,0-6404) fuzzy-if(Android&&device&&!swgl,6-6,6400-6400) == feGaussianBlur-1.svg feGaussianBlur-1-ref.svg
|
||||
fuzzy(0-2,0-304) == feGaussianBlur-2.svg feGaussianBlur-2-ref.svg
|
||||
# NOTE: some of these use multiple fuzzy conditions, each fuzzy condition
|
||||
# is simply setting the fuzzy parameters that will be used by the == at the end,
|
||||
# so the last fuzzy wins in terms of override order.
|
||||
fuzzy(0-8,0-1000000) == feGaussianBlur-1.svg feGaussianBlur-1-ref.svg
|
||||
pref(gfx.webrender.svg-filter-effects,false) fuzzy(0-6,0-1000000) == feGaussianBlur-2.svg feGaussianBlur-2-ref.svg
|
||||
pref(gfx.webrender.svg-filter-effects,true) fuzzy(0-8,0-1000000) == feGaussianBlur-2.svg feGaussianBlur-2-ref.svg
|
||||
# != feGaussianBlur-3.svg feGaussianBlur-3-ref.svg
|
||||
fuzzy-if(!useDrawSnapshot,2-5,4764-8168) fuzzy-if(Android&&device&&!swgl,5-5,8574-8574) == feGaussianBlur-4.svg feGaussianBlur-4-ref.svg
|
||||
fuzzy-if(geckoview,0-4,0-200) == feGaussianBlur-5.svg feGaussianBlur-5-ref.svg
|
||||
== feGaussianBlur-6.svg feGaussianBlur-6-ref.svg
|
||||
skip-if(winWidget) == feGaussianBlur-cap-large-directional-radius-on-software.html feGaussianBlur-cap-large-directional-radius-on-software-ref.html
|
||||
pref(gfx.webrender.svg-filter-effects,false) == feGaussianBlur-4.svg feGaussianBlur-4-ref.svg
|
||||
pref(gfx.webrender.svg-filter-effects,true) == feGaussianBlur-4.svg feGaussianBlur-4-ref.svg
|
||||
fuzzy-if(geckoview,0-4,0-200) fuzzy-if(gfxSVGFEGaussianBlur,0-0,0-0) == feGaussianBlur-5.svg feGaussianBlur-5-ref.svg
|
||||
fuzzy(0-2,0-10000) == feGaussianBlur-6.svg feGaussianBlur-6-ref.svg
|
||||
# SVGFE implementation deliberately does not cap blur radius (but resolution
|
||||
# degrades), the regular WebRender CSS filter also does not need to cap radius
|
||||
# for the same reason, so this test is now only relevant to blob fallback
|
||||
skip-if(!useDrawSnapshot) == feGaussianBlur-cap-large-directional-radius-on-software.html feGaussianBlur-cap-large-directional-radius-on-software-ref.html
|
||||
|
||||
!= feImage-1.svg about:blank # (Make sure our image renders at all)
|
||||
== feImage-1.svg feImage-1-ref.svg
|
||||
|
@ -67,10 +75,10 @@ skip-if(winWidget) == feGaussianBlur-cap-large-directional-radius-on-software.ht
|
|||
|
||||
# no tests for feTurbulence
|
||||
|
||||
fuzzy-if(geckoview,0-36,0-220) == filter-clipped-rect-01.svg pass.svg
|
||||
== filter-clipped-rect-01.svg pass.svg
|
||||
== filter-in-pattern-01.svg pass.svg
|
||||
fuzzy(0-5,0-67) != filter-in-pattern-02.svg filter-in-pattern-02-ref.svg
|
||||
random-if(winWidget) == filter-in-mask-01.svg pass.svg # bug 1356139
|
||||
== filter-in-mask-01.svg pass.svg
|
||||
== filter-in-mask-02.svg pass.svg
|
||||
== filter-inner-svg-01.svg pass.svg
|
||||
== filter-inner-svg-02.svg pass.svg
|
||||
|
@ -99,7 +107,7 @@ fuzzy(0-10,0-1200) == filter-nested-filtering-02.svg pass.svg
|
|||
== feComponentTransfer-04.svg pass.svg
|
||||
== feComposite-arguments-01.svg pass.svg
|
||||
fuzzy-if(winWidget,0-1,0-39600) == feComposite-operator-lighter.svg feComposite-operator-lighter-ref.html
|
||||
fuzzy(0-85,0-28600) == feComposite-paint-01.svg feComposite-paint-01-ref.svg
|
||||
fuzzy(0-85,0-28600) fuzzy-if(gfxSVGFEComposite,0-2,0-1000000) == feComposite-paint-01.svg feComposite-paint-01-ref.svg
|
||||
fuzzy(0-1,0-10000) == feConvolveMatrix-bias-01.svg feConvolveMatrix-bias-01-ref.svg
|
||||
== feConvolveMatrix-order-01.svg feConvolveMatrix-order-01-ref.svg
|
||||
|
||||
|
@ -107,11 +115,11 @@ fuzzy(0-1,0-400) == feDisplacementMap-alpha-01.svg pass.svg
|
|||
fuzzy(0-2,0-500) == feDisplacementMap-colour-01.svg feDisplacementMap-colour-01-ref.svg
|
||||
== feDisplacementMap-scale-01.svg pass.svg
|
||||
|
||||
fuzzy-if(winWidget,0-2,0-25) fuzzy-if(!useDrawSnapshot,55-98,14033-16467) == feDropShadow-01.svg feDropShadow-01-ref.svg
|
||||
fuzzy-if(winWidget,0-2,0-25) fuzzy-if(!useDrawSnapshot,55-98,14033-16467) fuzzy-if(gfxSVGFEDropShadow&&!gfxSVGFEOffset,97-98,21575-22951) fuzzy-if(gfxSVGFEOffset,0-2,0-1000000) == feDropShadow-01.svg feDropShadow-01-ref.svg
|
||||
|
||||
== feFlood-color-01.svg pass.svg
|
||||
|
||||
fuzzy-if(!useDrawSnapshot||(winWidget&&isCoverageBuild),20-21,5523-5647) == feGaussianBlur-alpha-01.svg feGaussianBlur-alpha-01-ref.svg
|
||||
fuzzy(0-21,0-1000000) == feGaussianBlur-alpha-01.svg feGaussianBlur-alpha-01-ref.svg
|
||||
|
||||
== feMorphology-radius-negative-01.svg pass.svg
|
||||
== feMorphology-radius-negative-02.svg pass.svg
|
||||
|
@ -135,8 +143,7 @@ fuzzy(0-1,0-10000) == feTurbulence-zero-baseFreq-01.svg feTurbulence-zero-baseFr
|
|||
!= feTurbulence-zero-baseFreq-02.svg about:blank
|
||||
|
||||
== outside-sourcegraphic-1.svg outside-sourcegraphic-ref.svg
|
||||
# These failures are caused by bug 1586055
|
||||
fails-if(!useDrawSnapshot) == outside-sourcegraphic-2.svg outside-sourcegraphic-ref.svg
|
||||
fails-if(!useDrawSnapshot) == outside-sourcegraphic-3.svg outside-sourcegraphic-ref.svg
|
||||
== nested-filter.html nested-filter-ref.html
|
||||
== outside-sourcegraphic-2.svg outside-sourcegraphic-ref.svg
|
||||
== outside-sourcegraphic-3.svg outside-sourcegraphic-ref.svg
|
||||
fuzzy-if(geckoview&&!emulator,0-4,0-124) == nested-filter.html nested-filter-ref.html
|
||||
== filter-giant.svg pass.svg
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
== clip-input.svg clip-input-ref.svg
|
||||
== clip-original-SourceGraphic.svg clip-original-SourceGraphic-ref.svg
|
||||
== clip-output.svg clip-output-ref.svg
|
||||
fuzzy(0-5,0-20300) fuzzy-if(Android&&device&&!swgl,5-5,21751-21751) == default-subregion.svg default-subregion-ref.svg
|
||||
fuzzy(0-1,0-1000000) == default-subregion.svg default-subregion-ref.svg
|
||||
== different-FillPaint-filter-regions.svg different-FillPaint-filter-regions-ref.svg
|
||||
== different-StrokePaint-filter-regions.svg different-StrokePaint-filter-regions-ref.svg
|
||||
== dont-clip-previous-primitives.svg dont-clip-previous-primitives-ref.svg
|
||||
== intersecting-filter-regions.svg intersecting-filter-regions-ref.svg
|
||||
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13184) fuzzy-if(Android&&device&&!swgl,8-8,12391-12391) == long-chain.svg simple-chain-ref.svg
|
||||
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13184) fuzzy-if(Android&&device&&!swgl,8-8,12391-12391) == multiple-primitives-per-filter.svg simple-chain-ref.svg
|
||||
fuzzy-if(winWidget,0-1,0-173) fuzzy-if(!useDrawSnapshot||(winWidget&&isCoverageBuild),9-9,5128-5496) fuzzy-if(!useDrawSnapshot&&swgl,7-7,12820-12830) fuzzy-if(Android&&device&&!swgl,8-8,12355-12355) == second-filter-uses-SourceAlpha.svg second-filter-uses-SourceAlpha-ref.svg
|
||||
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13180) fuzzy-if(Android&&device&&!swgl,8-8,12391-12391) == second-filter-uses-SourceGraphic.svg simple-chain-ref.svg
|
||||
== long-chain.svg simple-chain-ref.svg
|
||||
== multiple-primitives-per-filter.svg simple-chain-ref.svg
|
||||
fuzzy(0-1,0-1000000) == second-filter-uses-SourceAlpha.svg second-filter-uses-SourceAlpha-ref.svg
|
||||
== second-filter-uses-SourceGraphic.svg simple-chain-ref.svg
|
||||
== simple-chain.svg simple-chain-ref.svg
|
||||
|
|
|
@ -61,7 +61,10 @@ skip == blend-difference-stacking.html blend-difference-stacking-ref.html # bug
|
|||
== active-transform-blend-mode.html active-transform-blend-mode-ref.html
|
||||
== active-clip-and-mask.html active-clip-and-mask-ref.html
|
||||
|
||||
fuzzy(0-11,0-7155) == blur-inside-clipPath.svg blur-inside-clipPath-ref.svg
|
||||
# this test exists to detect if clip paths are erroneously cropped by the
|
||||
# unfiltered size of the primitive, which was bug 1459890, so the blur fuzz
|
||||
# doesn't matter, as if the error occurs it causes a much more drastic change
|
||||
fuzzy(0-20,0-9840) == blur-inside-clipPath.svg blur-inside-clipPath-ref.svg
|
||||
|
||||
== border-radius-01.html pass.svg
|
||||
== mask-image-filter-transform.html mask-image-filter-transform-ref.html
|
||||
|
@ -177,7 +180,7 @@ fuzzy-if(winWidget,0-3,0-1200) == dynamic-rect-02.svg dynamic-rect-02-ref.svg #
|
|||
== dynamic-stroke-width-01.svg pass.svg
|
||||
== dynamic-switch-01.svg pass.svg
|
||||
== dynamic-text-01.svg dynamic-text-01-ref.svg
|
||||
fuzzy-if(winWidget,0-3,0-12739) == dynamic-text-02.svg dynamic-text-02-ref.svg # bug 776038 for Win7, Win8
|
||||
fuzzy-if(winWidget,0-4,0-12739) fuzzy-if(gfxSVGFEGaussianBlur,0-7,0-1000000) == dynamic-text-02.svg dynamic-text-02-ref.svg # bug 776038 for Win7, Win8
|
||||
fuzzy-if(winWidget,0-2,0-10539) == dynamic-text-03.svg dynamic-text-03-ref.svg # bug 776038 for Win7
|
||||
== dynamic-text-04.svg dynamic-text-04-ref.svg
|
||||
== dynamic-text-05.svg pass.svg
|
||||
|
@ -471,7 +474,7 @@ fuzzy(0-1,0-2600) == svg-in-foreignObject-02.xhtml svg-in-foreignObject-01-ref.x
|
|||
== suspend-08.svg pass.svg
|
||||
|
||||
== svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed-ref.xhtml
|
||||
== svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in-ref.xhtml
|
||||
fuzzy-if(geckoview&&!emulator&&gfxSVGFEComponentTransfer,0-4,0-305) == svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in-ref.xhtml
|
||||
== svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out-ref.xhtml
|
||||
== svg-transform-01.svg pass.svg
|
||||
== svg-transform-02.svg pass.svg
|
||||
|
|
|
@ -18,7 +18,7 @@ fuzzy-if(Android,0-255,0-30) == clipPath-html-06-extref.xhtml clipPath-html-06-r
|
|||
fails-if(useDrawSnapshot) == clipPath-html-zoomed-01.xhtml clipPath-html-01-ref.svg
|
||||
== clipPath-transformed-html-01.xhtml ../pass.svg
|
||||
== clipPath-transformed-html-02.xhtml ../pass.svg
|
||||
== css-and-svg-filter-01.html css-and-svg-filter-01-ref.html
|
||||
fuzzy-if(geckoview&&!emulator,0-3,0-20) == css-and-svg-filter-01.html css-and-svg-filter-01-ref.html
|
||||
== conditions-outer-svg-01.xhtml ../pass.svg
|
||||
== conditions-outer-svg-02.xhtml ../pass.svg
|
||||
== dynamic-conditions-outer-svg-01.xhtml ../pass.svg
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -131,15 +131,28 @@ class FilterInstance {
|
|||
|
||||
/**
|
||||
* Try to build WebRender filters for a frame if the filters applied to it are
|
||||
* supported. aInitialized is set to true if the filter has been initialized
|
||||
* and false otherwise (e.g. a bad url). If aInitialized is false the filter
|
||||
* the filter contents should not be drawn.
|
||||
* supported, returns a status that indicates which code path will handle the
|
||||
* filters on this frame, or if we must fall back to blob image.
|
||||
*/
|
||||
static bool BuildWebRenderFilters(
|
||||
static WrFiltersStatus BuildWebRenderFilters(
|
||||
nsIFrame* aFilteredFrame,
|
||||
mozilla::Span<const mozilla::StyleFilter> aFilters,
|
||||
StyleFilterType aStyleFilterType, WrFiltersHolder& aWrFilters,
|
||||
bool& aInitialized);
|
||||
const nsPoint& aOffsetForSVGFilters);
|
||||
|
||||
/**
|
||||
* Try to build WebRender SVG filter graph for a frame based on SVG and CSS
|
||||
* filters. If given an unreasonably costly set of filters this can reject
|
||||
* the entire filter graph (a behavior permitted by SVG spec).
|
||||
*
|
||||
* See WrFiltersStatus for possible outcomes.
|
||||
* Prefs such as gfx.webrender.svg-filter-effects affect this.
|
||||
*/
|
||||
static WrFiltersStatus BuildWebRenderSVGFiltersImpl(
|
||||
nsIFrame* aFilteredFrame,
|
||||
mozilla::Span<const mozilla::StyleFilter> aFilters,
|
||||
StyleFilterType aStyleFilterType, WrFiltersHolder& aWrFilters,
|
||||
const nsPoint& aOffsetForSVGFilters);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -166,6 +179,8 @@ class FilterInstance {
|
|||
* ink overflow rect for the target element.
|
||||
* @param aOverrideBBox [optional] Use a different SVG bbox for the target
|
||||
* element. Must be non-null if aTargetFrame is null.
|
||||
* @param aFilterSpaceBoundsNotSnapped [optional] The calculated bbox in
|
||||
* userspace can be returend in the provided outparam.
|
||||
*/
|
||||
FilterInstance(
|
||||
nsIFrame* aTargetFrame, nsIContent* aTargetContent,
|
||||
|
@ -177,13 +192,13 @@ class FilterInstance {
|
|||
const nsRegion* aPostFilterDirtyRegion = nullptr,
|
||||
const nsRegion* aPreFilterDirtyRegion = nullptr,
|
||||
const nsRect* aPreFilterInkOverflowRectOverride = nullptr,
|
||||
const gfxRect* aOverrideBBox = nullptr);
|
||||
const gfxRect* aOverrideBBox = nullptr,
|
||||
gfxRect* aFilterSpaceBoundsNotSnapped = nullptr);
|
||||
|
||||
static bool BuildWebRenderFiltersImpl(
|
||||
static WrFiltersStatus BuildWebRenderFiltersImpl(
|
||||
nsIFrame* aFilteredFrame,
|
||||
mozilla::Span<const mozilla::StyleFilter> aFilters,
|
||||
StyleFilterType aStyleFilterType, WrFiltersHolder& aWrFilters,
|
||||
bool& aInitialized);
|
||||
StyleFilterType aStyleFilterType, WrFiltersHolder& aWrFilters);
|
||||
|
||||
/**
|
||||
* Returns true if the filter instance was created successfully.
|
||||
|
@ -366,6 +381,11 @@ class FilterInstance {
|
|||
*/
|
||||
nsIntRect mTargetBBoxInFilterSpace;
|
||||
|
||||
/**
|
||||
* The SVG filter element rect, in filter space, may be non-integer.
|
||||
*/
|
||||
gfxRect mFilterSpaceBoundsNotSnapped;
|
||||
|
||||
/**
|
||||
* Transform rects between filter space and frame space in CSS pixels.
|
||||
*/
|
||||
|
|
|
@ -32,7 +32,8 @@ SVGFilterInstance::SVGFilterInstance(
|
|||
const StyleFilter& aFilter, SVGFilterFrame* aFilterFrame,
|
||||
nsIContent* aTargetContent, const UserSpaceMetrics& aMetrics,
|
||||
const gfxRect& aTargetBBox,
|
||||
const MatrixScalesDouble& aUserSpaceToFilterSpaceScale)
|
||||
const MatrixScalesDouble& aUserSpaceToFilterSpaceScale,
|
||||
gfxRect& aFilterSpaceBoundsNotSnapped)
|
||||
: mFilter(aFilter),
|
||||
mTargetContent(aTargetContent),
|
||||
mMetrics(aMetrics),
|
||||
|
@ -54,6 +55,7 @@ SVGFilterInstance::SVGFilterInstance(
|
|||
if (!ComputeBounds()) {
|
||||
return;
|
||||
}
|
||||
aFilterSpaceBoundsNotSnapped = mFilterSpaceBoundsNotSnapped;
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
|
@ -88,6 +90,7 @@ bool SVGFilterInstance::ComputeBounds() {
|
|||
// can align them with the pixel boundaries of the offscreen surface.
|
||||
// The offscreen surface has the same scale as filter space.
|
||||
gfxRect filterSpaceBounds = UserSpaceToFilterSpace(userSpaceBounds);
|
||||
mFilterSpaceBoundsNotSnapped = filterSpaceBounds;
|
||||
filterSpaceBounds.RoundOut();
|
||||
if (filterSpaceBounds.width <= 0 || filterSpaceBounds.height <= 0) {
|
||||
// 0 disables rendering, < 0 is error. dispatch error console warning
|
||||
|
|
|
@ -79,11 +79,12 @@ class SVGFilterInstance {
|
|||
* @param aTargetBBox The SVG bbox to use for the target frame, computed by
|
||||
* the caller. The caller may decide to override the actual SVG bbox.
|
||||
*/
|
||||
SVGFilterInstance(
|
||||
const StyleFilter& aFilter, SVGFilterFrame* aFilterFrame,
|
||||
nsIContent* aTargetContent, const UserSpaceMetrics& aMetrics,
|
||||
const gfxRect& aTargetBBox,
|
||||
const gfx::MatrixScalesDouble& aUserSpaceToFilterSpaceScale);
|
||||
SVGFilterInstance(const StyleFilter& aFilter, SVGFilterFrame* aFilterFrame,
|
||||
nsIContent* aTargetContent,
|
||||
const UserSpaceMetrics& aMetrics,
|
||||
const gfxRect& aTargetBBox,
|
||||
const gfx::MatrixScalesDouble& aUserSpaceToFilterSpaceScale,
|
||||
gfxRect& aFilterSpaceBoundsNotSnapped);
|
||||
|
||||
/**
|
||||
* Returns true if the filter instance was created successfully.
|
||||
|
@ -225,6 +226,11 @@ class SVGFilterInstance {
|
|||
*/
|
||||
nsIntRect mFilterSpaceBounds;
|
||||
|
||||
/**
|
||||
* The bounds of the filter element itself, which may be non-integer.
|
||||
*/
|
||||
gfxRect mFilterSpaceBoundsNotSnapped;
|
||||
|
||||
/**
|
||||
* The scale factors between user space and filter space.
|
||||
*/
|
||||
|
|
|
@ -949,9 +949,17 @@ void SVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams,
|
|||
opacity);
|
||||
}
|
||||
|
||||
bool SVGIntegrationUtils::CreateWebRenderCSSFilters(
|
||||
WrFiltersStatus SVGIntegrationUtils::CreateWebRenderCSSFilters(
|
||||
Span<const StyleFilter> aFilters, nsIFrame* aFrame,
|
||||
WrFiltersHolder& aWrFilters) {
|
||||
// Check if prefs are set to convert the CSS filters to SVG filters and use
|
||||
// the new WebRender SVG filter rendering, rather than the existing CSS filter
|
||||
// support
|
||||
if (StaticPrefs::gfx_webrender_svg_filter_effects() &&
|
||||
StaticPrefs::
|
||||
gfx_webrender_svg_filter_effects_also_convert_css_filters()) {
|
||||
return WrFiltersStatus::BLOB_FALLBACK;
|
||||
}
|
||||
// All CSS filters are supported by WebRender. SVG filters are not fully
|
||||
// supported, those use NS_STYLE_FILTER_URL and are handled separately.
|
||||
|
||||
|
@ -959,8 +967,10 @@ bool SVGIntegrationUtils::CreateWebRenderCSSFilters(
|
|||
// succeeded, and don't render any of them.
|
||||
if (aFilters.Length() >
|
||||
StaticPrefs::gfx_webrender_max_filter_ops_per_chain()) {
|
||||
return true;
|
||||
return WrFiltersStatus::DISABLED_FOR_PERFORMANCE;
|
||||
}
|
||||
// Track status so we can do cleanup if unsupported filters are found.
|
||||
WrFiltersStatus status = WrFiltersStatus::CHAIN;
|
||||
aWrFilters.filters.SetCapacity(aFilters.Length());
|
||||
auto& wrFilters = aWrFilters.filters;
|
||||
for (const StyleFilter& filter : aFilters) {
|
||||
|
@ -1024,28 +1034,39 @@ bool SVGIntegrationUtils::CreateWebRenderCSSFilters(
|
|||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
status = WrFiltersStatus::BLOB_FALLBACK;
|
||||
break;
|
||||
}
|
||||
if (status != WrFiltersStatus::CHAIN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (status != WrFiltersStatus::CHAIN) {
|
||||
// Clean up the filters holder if we can't render filters this way.
|
||||
aWrFilters = {};
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool SVGIntegrationUtils::BuildWebRenderFilters(
|
||||
WrFiltersStatus SVGIntegrationUtils::BuildWebRenderFilters(
|
||||
nsIFrame* aFilteredFrame, Span<const StyleFilter> aFilters,
|
||||
StyleFilterType aStyleFilterType, WrFiltersHolder& aWrFilters,
|
||||
bool& aInitialized) {
|
||||
return FilterInstance::BuildWebRenderFilters(
|
||||
aFilteredFrame, aFilters, aStyleFilterType, aWrFilters, aInitialized);
|
||||
const nsPoint& aOffsetForSVGFilters) {
|
||||
return FilterInstance::BuildWebRenderFilters(aFilteredFrame, aFilters,
|
||||
aStyleFilterType, aWrFilters,
|
||||
aOffsetForSVGFilters);
|
||||
}
|
||||
|
||||
bool SVGIntegrationUtils::CanCreateWebRenderFiltersForFrame(nsIFrame* aFrame) {
|
||||
WrFiltersHolder wrFilters;
|
||||
auto filterChain = aFrame->StyleEffects()->mFilters.AsSpan();
|
||||
bool initialized = true;
|
||||
return CreateWebRenderCSSFilters(filterChain, aFrame, wrFilters) ||
|
||||
BuildWebRenderFilters(aFrame, filterChain, StyleFilterType::Filter,
|
||||
wrFilters, initialized);
|
||||
WrFiltersStatus status =
|
||||
CreateWebRenderCSSFilters(filterChain, aFrame, wrFilters);
|
||||
if (status == WrFiltersStatus::BLOB_FALLBACK) {
|
||||
status = BuildWebRenderFilters(aFrame, filterChain, StyleFilterType::Filter,
|
||||
wrFilters, nsPoint());
|
||||
}
|
||||
return status == WrFiltersStatus::CHAIN || status == WrFiltersStatus::SVGFE;
|
||||
}
|
||||
|
||||
bool SVGIntegrationUtils::UsesSVGEffectsNotSupportedInCompositor(
|
||||
|
|
|
@ -22,7 +22,27 @@ struct nsPoint;
|
|||
struct nsRect;
|
||||
struct nsSize;
|
||||
|
||||
enum class WrFiltersStatus {
|
||||
// Image will be rendered unftilered - the filter graph contains invalid refs
|
||||
// (which SVG spec states will be rendered as if there is no filter graph).
|
||||
UNSUPPORTED = 0,
|
||||
// Image will be rendered unfiltered - the filter graph provided is
|
||||
// excessively costly to render and has been dropped (per SVG spec we can do
|
||||
// this to preserve user experience).
|
||||
DISABLED_FOR_PERFORMANCE = 1,
|
||||
// Image will be rendered using blob fallback (software rendering) due to
|
||||
// unsupported operations (in either the CSS or SVGFE path).
|
||||
BLOB_FALLBACK = 2,
|
||||
// Image will be rendered using a simple CSS filter chain in WebRender.
|
||||
CHAIN = 3,
|
||||
// Filter graph will be rendered using WebRender SVGFE code path, this can
|
||||
// handle any kind of filter graph consisting of supported operations (most
|
||||
// operations are supported).
|
||||
SVGFE = 4,
|
||||
};
|
||||
|
||||
struct WrFiltersHolder {
|
||||
// TODO(Bug 1899691): Better to use AutoTArray here...
|
||||
nsTArray<mozilla::wr::FilterOp> filters;
|
||||
nsTArray<mozilla::wr::WrFilterData> filter_datas;
|
||||
mozilla::Maybe<nsRect> post_filters_clip;
|
||||
|
@ -192,19 +212,18 @@ class SVGIntegrationUtils final {
|
|||
/**
|
||||
* Build WebRender filters for a frame with CSS filters applied to it.
|
||||
*/
|
||||
static bool CreateWebRenderCSSFilters(Span<const StyleFilter> aFilters,
|
||||
nsIFrame* aFrame,
|
||||
WrFiltersHolder& aWrFilters);
|
||||
static WrFiltersStatus CreateWebRenderCSSFilters(
|
||||
Span<const StyleFilter> aFilters, nsIFrame* aFrame,
|
||||
WrFiltersHolder& aWrFilters);
|
||||
|
||||
/**
|
||||
* Try to build WebRender filters for a frame with SVG filters applied to it
|
||||
* if the filters are supported.
|
||||
*/
|
||||
static bool BuildWebRenderFilters(nsIFrame* aFilteredFrame,
|
||||
Span<const StyleFilter> aFilters,
|
||||
StyleFilterType aStyleFilterType,
|
||||
WrFiltersHolder& aWrFilters,
|
||||
bool& aInitialized);
|
||||
static WrFiltersStatus BuildWebRenderFilters(
|
||||
nsIFrame* aFilteredFrame, Span<const StyleFilter> aFilters,
|
||||
StyleFilterType aStyleFilterType, WrFiltersHolder& aWrFilters,
|
||||
const nsPoint& aOffsetForSVGFilters);
|
||||
|
||||
/**
|
||||
* Check if the filters present on |aFrame| are supported by WebRender.
|
||||
|
|
|
@ -648,6 +648,36 @@ function BuildConditionSandbox(aURL) {
|
|||
sandbox.swgl = g.windowUtils.layerManagerType.startsWith(
|
||||
"WebRender (Software"
|
||||
);
|
||||
// These detect if each SVG filter primitive is enabled in WebRender
|
||||
sandbox.gfxSVGFE =
|
||||
Services.prefs.getBoolPref("gfx.webrender.svg-filter-effects") &&
|
||||
!g.useDrawSnapshot;
|
||||
sandbox.gfxSVGFEColorMatrix =
|
||||
Services.prefs.getBoolPref(
|
||||
"gfx.webrender.svg-filter-effects.fecolormatrix"
|
||||
) && sandbox.gfxSVGFE;
|
||||
sandbox.gfxSVGFEComponentTransfer =
|
||||
Services.prefs.getBoolPref(
|
||||
"gfx.webrender.svg-filter-effects.fecomponenttransfer"
|
||||
) && sandbox.gfxSVGFE;
|
||||
sandbox.gfxSVGFEComposite =
|
||||
Services.prefs.getBoolPref(
|
||||
"gfx.webrender.svg-filter-effects.fecomposite"
|
||||
) && sandbox.gfxSVGFE;
|
||||
sandbox.gfxSVGFEDropShadow =
|
||||
Services.prefs.getBoolPref(
|
||||
"gfx.webrender.svg-filter-effects.fedropshadow"
|
||||
) && sandbox.gfxSVGFE;
|
||||
sandbox.gfxSVGFEFlood =
|
||||
Services.prefs.getBoolPref("gfx.webrender.svg-filter-effects.feflood") &&
|
||||
sandbox.gfxSVGFE;
|
||||
sandbox.gfxSVGFEGaussianBlur =
|
||||
Services.prefs.getBoolPref(
|
||||
"gfx.webrender.svg-filter-effects.fegaussianblur"
|
||||
) && sandbox.gfxSVGFE;
|
||||
sandbox.gfxSVGFEOffset =
|
||||
Services.prefs.getBoolPref("gfx.webrender.svg-filter-effects.feoffset") &&
|
||||
sandbox.gfxSVGFE;
|
||||
|
||||
// Use this to annotate reftests that fail in drawSnapshot, but
|
||||
// the reason hasn't been investigated (or fixed) yet.
|
||||
|
|
|
@ -6525,6 +6525,117 @@
|
|||
mirror: once
|
||||
#endif
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects
|
||||
type: RelaxedAtomicBool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.also-convert-css-filters
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.also-use-for-docshell-fecolormatrix
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.opacity
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.toalpha
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.feblend
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fecolormatrix
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fecomponenttransfer
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fecomposite
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.feconvolvematrix
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fediffuselighting
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fedisplacementmap
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fedropshadow
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.feflood
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fegaussianblur
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.feimage
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.femerge
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.femorphology
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Disabled for now due to https://bugzilla.mozilla.org/show_bug.cgi?id=1902136
|
||||
- name: gfx.webrender.svg-filter-effects.feoffset
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fespecularlighting
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.fetile
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-filter-effects.feturbulence
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: gfx.webrender.svg-images
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[blur-text.html]
|
||||
fuzzy:
|
||||
maxDifference=0-8;totalPixels=0-55000
|
|
@ -1,3 +0,0 @@
|
|||
[effect-reference-on-transparent-element.html]
|
||||
expected:
|
||||
FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[filter-region-transformed-child-001.html]
|
||||
expected:
|
||||
FAIL
|
|
@ -1,2 +1,4 @@
|
|||
[svg-multiple-filter-functions.html]
|
||||
expected: FAIL
|
||||
fuzzy:
|
||||
maxDifference=0-1;totalPixels=0-10000
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче