зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1656711
. Support hardware accelerated <feGaussianBlur> SVG filters if the x and y radius are not equal with webrender. r=gw
Pretty straight forward, mostly just plumbing stuff through. Differential Revision: https://phabricator.services.mozilla.com/D85666
This commit is contained in:
Родитель
e210ecd37e
Коммит
9db06357a1
|
@ -70,7 +70,7 @@ const OPACITY_EPSILON: f32 = 0.001;
|
|||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum Filter {
|
||||
Identity,
|
||||
Blur(f32),
|
||||
Blur(f32, f32),
|
||||
Brightness(f32),
|
||||
Contrast(f32),
|
||||
Grayscale(f32),
|
||||
|
@ -116,7 +116,7 @@ impl Filter {
|
|||
pub fn is_noop(&self) -> bool {
|
||||
match *self {
|
||||
Filter::Identity => false, // this is intentional
|
||||
Filter::Blur(length) => length == 0.0,
|
||||
Filter::Blur(width, height) => width == 0.0 && height == 0.0,
|
||||
Filter::Brightness(amount) => amount == 1.0,
|
||||
Filter::Contrast(amount) => amount == 1.0,
|
||||
Filter::Grayscale(amount) => amount == 0.0,
|
||||
|
@ -179,7 +179,7 @@ impl From<FilterOp> for Filter {
|
|||
fn from(op: FilterOp) -> Self {
|
||||
match op {
|
||||
FilterOp::Identity => Filter::Identity,
|
||||
FilterOp::Blur(r) => Filter::Blur(r),
|
||||
FilterOp::Blur(w, h) => Filter::Blur(w, h),
|
||||
FilterOp::Brightness(b) => Filter::Brightness(b),
|
||||
FilterOp::Contrast(c) => Filter::Contrast(c),
|
||||
FilterOp::Grayscale(g) => Filter::Grayscale(g),
|
||||
|
|
|
@ -4138,9 +4138,10 @@ impl PictureCompositeMode {
|
|||
let mut result_rect = picture_rect;
|
||||
match self {
|
||||
PictureCompositeMode::Filter(filter) => match filter {
|
||||
Filter::Blur(blur_radius) => {
|
||||
let inflation_factor = clamp_blur_radius(*blur_radius, scale_factors).ceil() * BLUR_SAMPLE_SCALE;
|
||||
result_rect = picture_rect.inflate(inflation_factor, inflation_factor);
|
||||
Filter::Blur(width, height) => {
|
||||
let width_factor = clamp_blur_radius(*width, scale_factors).ceil() * BLUR_SAMPLE_SCALE;
|
||||
let height_factor = clamp_blur_radius(*height, scale_factors).ceil() * BLUR_SAMPLE_SCALE;
|
||||
result_rect = picture_rect.inflate(width_factor, height_factor);
|
||||
},
|
||||
Filter::DropShadows(shadows) => {
|
||||
let mut max_inflation: f32 = 0.0;
|
||||
|
@ -4158,8 +4159,9 @@ impl PictureCompositeMode {
|
|||
let output_rect = match primitive.kind {
|
||||
FilterPrimitiveKind::Blur(ref primitive) => {
|
||||
let input = primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect);
|
||||
let inflation_factor = primitive.radius.round() * BLUR_SAMPLE_SCALE;
|
||||
input.inflate(inflation_factor, inflation_factor)
|
||||
let width_factor = primitive.width.round() * BLUR_SAMPLE_SCALE;
|
||||
let height_factor = primitive.height.round() * BLUR_SAMPLE_SCALE;
|
||||
input.inflate(width_factor, height_factor)
|
||||
}
|
||||
FilterPrimitiveKind::DropShadow(ref primitive) => {
|
||||
let inflation_factor = primitive.shadow.blur_radius.ceil() * BLUR_SAMPLE_SCALE;
|
||||
|
@ -4886,11 +4888,12 @@ impl PicturePrimitive {
|
|||
}
|
||||
|
||||
let dep_info = match raster_config.composite_mode {
|
||||
PictureCompositeMode::Filter(Filter::Blur(blur_radius)) => {
|
||||
let blur_std_deviation = clamp_blur_radius(blur_radius, scale_factors) * device_pixel_scale.0;
|
||||
PictureCompositeMode::Filter(Filter::Blur(width, height)) => {
|
||||
let width_std_deviation = clamp_blur_radius(width, scale_factors) * device_pixel_scale.0;
|
||||
let height_std_deviation = clamp_blur_radius(height, scale_factors) * device_pixel_scale.0;
|
||||
let mut blur_std_deviation = DeviceSize::new(
|
||||
blur_std_deviation * scale_factors.0,
|
||||
blur_std_deviation * scale_factors.1
|
||||
width_std_deviation * scale_factors.0,
|
||||
height_std_deviation * scale_factors.1
|
||||
);
|
||||
let mut device_rect = if self.options.inflate_if_required {
|
||||
let inflation_factor = frame_state.surfaces[raster_config.surface_index.0].inflation_factor;
|
||||
|
@ -5934,8 +5937,8 @@ impl PicturePrimitive {
|
|||
let mut inflation_factor = 0.0;
|
||||
if self.options.inflate_if_required {
|
||||
match composite_mode {
|
||||
PictureCompositeMode::Filter(Filter::Blur(blur_radius)) => {
|
||||
let blur_radius = clamp_blur_radius(blur_radius, scale_factors);
|
||||
PictureCompositeMode::Filter(Filter::Blur(width, height)) => {
|
||||
let blur_radius = f32::max(clamp_blur_radius(width, scale_factors), clamp_blur_radius(height, scale_factors));
|
||||
// The amount of extra space needed for primitives inside
|
||||
// this picture to ensure the visibility check is correct.
|
||||
inflation_factor = blur_radius * BLUR_SAMPLE_SCALE;
|
||||
|
@ -5944,7 +5947,8 @@ impl PicturePrimitive {
|
|||
let mut max = 0.0;
|
||||
for primitive in primitives {
|
||||
if let FilterPrimitiveKind::Blur(ref blur) = primitive.kind {
|
||||
max = f32::max(max, blur.radius);
|
||||
max = f32::max(max, blur.width);
|
||||
max = f32::max(max, blur.height);
|
||||
}
|
||||
}
|
||||
inflation_factor = clamp_blur_radius(max, scale_factors) * BLUR_SAMPLE_SCALE;
|
||||
|
|
|
@ -60,7 +60,7 @@ pub enum FilterPrimitiveKey {
|
|||
Identity(ColorSpace, FilterPrimitiveInput),
|
||||
Flood(ColorSpace, ColorU),
|
||||
Blend(ColorSpace, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveInput),
|
||||
Blur(ColorSpace, Au, FilterPrimitiveInput),
|
||||
Blur(ColorSpace, Au, Au, FilterPrimitiveInput),
|
||||
Opacity(ColorSpace, Au, FilterPrimitiveInput),
|
||||
ColorMatrix(ColorSpace, [Au; 20], FilterPrimitiveInput),
|
||||
DropShadow(ColorSpace, (VectorKey, Au, ColorU), FilterPrimitiveInput),
|
||||
|
@ -79,7 +79,7 @@ pub enum PictureCompositeKey {
|
|||
Identity,
|
||||
|
||||
// FilterOp
|
||||
Blur(Au),
|
||||
Blur(Au, Au),
|
||||
Brightness(Au),
|
||||
Contrast(Au),
|
||||
Grayscale(Au),
|
||||
|
@ -140,7 +140,8 @@ impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
|
|||
}
|
||||
Some(PictureCompositeMode::Filter(op)) => {
|
||||
match op {
|
||||
Filter::Blur(value) => PictureCompositeKey::Blur(Au::from_f32_px(value)),
|
||||
Filter::Blur(width, height) =>
|
||||
PictureCompositeKey::Blur(Au::from_f32_px(width), Au::from_f32_px(height)),
|
||||
Filter::Brightness(value) => PictureCompositeKey::Brightness(Au::from_f32_px(value)),
|
||||
Filter::Contrast(value) => PictureCompositeKey::Contrast(Au::from_f32_px(value)),
|
||||
Filter::Grayscale(value) => PictureCompositeKey::Grayscale(Au::from_f32_px(value)),
|
||||
|
@ -188,7 +189,8 @@ impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
|
|||
FilterPrimitiveKind::Identity(identity) => FilterPrimitiveKey::Identity(primitive.color_space, identity.input),
|
||||
FilterPrimitiveKind::Blend(blend) => FilterPrimitiveKey::Blend(primitive.color_space, blend.mode, blend.input1, blend.input2),
|
||||
FilterPrimitiveKind::Flood(flood) => FilterPrimitiveKey::Flood(primitive.color_space, flood.color.into()),
|
||||
FilterPrimitiveKind::Blur(blur) => FilterPrimitiveKey::Blur(primitive.color_space, Au::from_f32_px(blur.radius), blur.input),
|
||||
FilterPrimitiveKind::Blur(blur) =>
|
||||
FilterPrimitiveKey::Blur(primitive.color_space, Au::from_f32_px(blur.width), Au::from_f32_px(blur.height), blur.input),
|
||||
FilterPrimitiveKind::Opacity(opacity) =>
|
||||
FilterPrimitiveKey::Opacity(primitive.color_space, Au::from_f32_px(opacity.opacity), opacity.input),
|
||||
FilterPrimitiveKind::ColorMatrix(color_matrix) => {
|
||||
|
|
|
@ -946,7 +946,8 @@ impl RenderTask {
|
|||
))
|
||||
}
|
||||
FilterPrimitiveKind::Blur(ref blur) => {
|
||||
let blur_std_deviation = blur.radius * device_pixel_scale.0;
|
||||
let width_std_deviation = blur.width * device_pixel_scale.0;
|
||||
let height_std_deviation = blur.height * device_pixel_scale.0;
|
||||
let input_task_id = get_task_input(
|
||||
&blur.input,
|
||||
filter_primitives,
|
||||
|
@ -958,7 +959,7 @@ impl RenderTask {
|
|||
);
|
||||
|
||||
RenderTask::new_blur(
|
||||
DeviceSize::new(blur_std_deviation, blur_std_deviation),
|
||||
DeviceSize::new(width_std_deviation, height_std_deviation),
|
||||
// TODO: This is a hack to ensure that a blur task's input is always
|
||||
// in the blur's previous pass.
|
||||
render_tasks.add().init(RenderTask::new_svg_filter_primitive(
|
||||
|
|
|
@ -2329,7 +2329,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
// blur radius is 0, the code in Picture::prepare_for_render will
|
||||
// detect this and mark the picture to be drawn directly into the
|
||||
// parent picture, which avoids an intermediate surface and blur.
|
||||
let blur_filter = Filter::Blur(std_deviation);
|
||||
let blur_filter = Filter::Blur(std_deviation, std_deviation);
|
||||
let composite_mode = if blur_filter.is_noop() {
|
||||
None
|
||||
} else {
|
||||
|
|
|
@ -934,7 +934,8 @@ impl FloodPrimitive {
|
|||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
pub struct BlurPrimitive {
|
||||
pub input: FilterPrimitiveInput,
|
||||
pub radius: f32,
|
||||
pub width: f32,
|
||||
pub height: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -1061,7 +1062,7 @@ pub enum FilterOp {
|
|||
/// Filter that does no transformation of the colors, needed for
|
||||
/// debug purposes only.
|
||||
Identity,
|
||||
Blur(f32),
|
||||
Blur(f32, f32),
|
||||
Brightness(f32),
|
||||
Contrast(f32),
|
||||
Grayscale(f32),
|
||||
|
|
|
@ -573,8 +573,8 @@ impl YamlHelper for Yaml {
|
|||
("component-transfer", _, _) => {
|
||||
Some(FilterOp::ComponentTransfer)
|
||||
}
|
||||
("blur", ref args, _) if args.len() == 1 => {
|
||||
Some(FilterOp::Blur(args[0].parse().unwrap()))
|
||||
("blur", ref args, _) if args.len() == 2 => {
|
||||
Some(FilterOp::Blur(args[0].parse().unwrap(), args[1].parse().unwrap()))
|
||||
}
|
||||
("brightness", ref args, _) if args.len() == 1 => {
|
||||
Some(FilterOp::Brightness(args[0].parse().unwrap()))
|
||||
|
@ -729,7 +729,8 @@ impl YamlHelper for Yaml {
|
|||
"blur" => {
|
||||
FilterPrimitiveKind::Blur(BlurPrimitive {
|
||||
input: self["in"].as_filter_input().unwrap(),
|
||||
radius: self["radius"].as_f32().unwrap(),
|
||||
width: self["width"].as_f32().unwrap(),
|
||||
height: self["height"].as_f32().unwrap(),
|
||||
})
|
||||
}
|
||||
"opacity" => {
|
||||
|
|
|
@ -230,13 +230,9 @@ bool FilterInstance::BuildWebRenderFilters(nsIFrame* aFilteredFrame,
|
|||
const GaussianBlurAttributes& blur = attr.as<GaussianBlurAttributes>();
|
||||
|
||||
const Size& stdDev = blur.mStdDeviation;
|
||||
if (stdDev.width != stdDev.height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float radius = stdDev.width;
|
||||
if (radius != 0.0) {
|
||||
aWrFilters.filters.AppendElement(wr::FilterOp::Blur(radius));
|
||||
if (stdDev.width != 0.0 || stdDev.height != 0.0) {
|
||||
aWrFilters.filters.AppendElement(
|
||||
wr::FilterOp::Blur(stdDev.width, stdDev.height));
|
||||
} else {
|
||||
filterIsNoop = true;
|
||||
}
|
||||
|
|
|
@ -1163,8 +1163,9 @@ bool SVGIntegrationUtils::CreateWebRenderCSSFilters(
|
|||
// TODO(emilio): we should go directly from css pixels -> device pixels.
|
||||
float appUnitsPerDevPixel =
|
||||
aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
wrFilters.AppendElement(wr::FilterOp::Blur(NSAppUnitsToFloatPixels(
|
||||
filter.AsBlur().ToAppUnits(), appUnitsPerDevPixel)));
|
||||
float radius = NSAppUnitsToFloatPixels(filter.AsBlur().ToAppUnits(),
|
||||
appUnitsPerDevPixel);
|
||||
wrFilters.AppendElement(wr::FilterOp::Blur(radius, radius));
|
||||
break;
|
||||
}
|
||||
case StyleFilter::Tag::DropShadow: {
|
||||
|
|
Загрузка…
Ссылка в новой задаче