From ebe50f24f73d0f6740c58cab266ee6c8cdb84147 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Wed, 26 Sep 2018 05:57:31 +1000 Subject: [PATCH] Clamp radius in blur filters to a sensible value. Fixes #3118. --- webrender/src/box_shadow.rs | 6 +---- webrender/src/display_list_flattener.rs | 4 +++- webrender_api/src/display_item.rs | 22 +++++++++++++++++++ wrench/reftests/filters/blank.yaml | 2 ++ wrench/reftests/filters/filter-blur-huge.yaml | 10 +++++++++ .../filters/filter-drop-shadow-huge.yaml | 10 +++++++++ wrench/reftests/filters/reftest.list | 2 ++ 7 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 wrench/reftests/filters/blank.yaml create mode 100644 wrench/reftests/filters/filter-blur-huge.yaml create mode 100644 wrench/reftests/filters/filter-drop-shadow-huge.yaml diff --git a/webrender/src/box_shadow.rs b/webrender/src/box_shadow.rs index 1e5d40fc52..5c8dc7e85c 100644 --- a/webrender/src/box_shadow.rs +++ b/webrender/src/box_shadow.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, DeviceIntSize, LayoutPrimitiveInfo}; -use api::{LayoutRect, LayoutSize, LayoutVector2D}; +use api::{LayoutRect, LayoutSize, LayoutVector2D, MAX_BLUR_RADIUS}; use clip::ClipItemKey; use display_list_flattener::DisplayListFlattener; use gpu_cache::GpuCacheHandle; @@ -45,10 +45,6 @@ pub struct BoxShadowClipSource { // The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels. pub const BLUR_SAMPLE_SCALE: f32 = 3.0; -// Maximum blur radius. -// Taken from https://searchfox.org/mozilla-central/rev/c633ffa4c4611f202ca11270dcddb7b29edddff8/layout/painting/nsCSSRendering.cpp#4412 -pub const MAX_BLUR_RADIUS : f32 = 300.; - // A cache key that uniquely identifies a minimally sized // and blurred box-shadow rect that can be stored in the // texture cache and applied to clip-masks. diff --git a/webrender/src/display_list_flattener.rs b/webrender/src/display_list_flattener.rs index ca0bc7a995..f1d74c33d6 100644 --- a/webrender/src/display_list_flattener.rs +++ b/webrender/src/display_list_flattener.rs @@ -1062,9 +1062,11 @@ impl<'a> DisplayListFlattener<'a> { // For each filter, create a new image with that composite mode. for filter in &composite_ops.filters { + let filter = filter.sanitize(); + let mut filter_picture = PicturePrimitive::new_image( self.picture_id_generator.next(), - Some(PictureCompositeMode::Filter(*filter)), + Some(PictureCompositeMode::Filter(filter)), false, pipeline_id, None, diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 40d99e0d37..0d653ae637 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -11,6 +11,10 @@ use {LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, PipelineId, Proper use LayoutSideOffsets; use image::ColorDepth; +// Maximum blur radius. +// Taken from nsCSSRendering.cpp in Gecko. +pub const MAX_BLUR_RADIUS: f32 = 300.; + // NOTE: some of these structs have an "IMPLICIT" comment. // This indicates that the BuiltDisplayList will have serialized // a list of values nearby that this item consumes. The traversal @@ -610,6 +614,24 @@ pub enum FilterOp { ColorMatrix([f32; 20]), } +impl FilterOp { + /// Ensure that the parameters for a filter operation + /// are sensible. + pub fn sanitize(self) -> FilterOp { + match self { + FilterOp::Blur(radius) => { + let radius = radius.min(MAX_BLUR_RADIUS); + FilterOp::Blur(radius) + } + FilterOp::DropShadow(offset, radius, color) => { + let radius = radius.min(MAX_BLUR_RADIUS); + FilterOp::DropShadow(offset, radius, color) + } + filter => filter, + } + } +} + #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct IframeDisplayItem { pub clip_id: ClipId, diff --git a/wrench/reftests/filters/blank.yaml b/wrench/reftests/filters/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/wrench/reftests/filters/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/wrench/reftests/filters/filter-blur-huge.yaml b/wrench/reftests/filters/filter-blur-huge.yaml new file mode 100644 index 0000000000..2f76dd289e --- /dev/null +++ b/wrench/reftests/filters/filter-blur-huge.yaml @@ -0,0 +1,10 @@ +# Don't crash on very large blur radius! +--- +root: + items: + - type: stacking-context + bounds: [10, 10, 260, 260] + filters: blur(1000000) + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] diff --git a/wrench/reftests/filters/filter-drop-shadow-huge.yaml b/wrench/reftests/filters/filter-drop-shadow-huge.yaml new file mode 100644 index 0000000000..dc971a7d3a --- /dev/null +++ b/wrench/reftests/filters/filter-drop-shadow-huge.yaml @@ -0,0 +1,10 @@ +# Don't crash on very large blur radius! +--- +root: + items: + - type: stacking-context + bounds: [10, 10, 260, 260] + filters: drop-shadow([73, 73], 10000000, [255, 0, 0, 1]) + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] diff --git a/wrench/reftests/filters/reftest.list b/wrench/reftests/filters/reftest.list index 04d98f11f9..22816e0366 100644 --- a/wrench/reftests/filters/reftest.list +++ b/wrench/reftests/filters/reftest.list @@ -36,3 +36,5 @@ platform(linux,mac) == blend-clipped.yaml blend-clipped.png == filter-segments.yaml filter-segments-ref.yaml == iframe-dropshadow.yaml iframe-dropshadow-ref.yaml == filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.yaml +!= filter-blur-huge.yaml blank.yaml +!= filter-drop-shadow-huge.yaml blank.yaml