From bb54c17ce38160b93f8b4bda252c8ba5c996d90b Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Thu, 30 May 2019 03:11:53 +0000 Subject: [PATCH] Bug 1555476 - Implement flood filter in WebRender r=gw Differential Revision: https://phabricator.services.mozilla.com/D33109 --HG-- extra : moz-landing-system : lando --- gfx/wr/webrender/res/brush_blend.glsl | 10 ++++++++ gfx/wr/webrender/src/batch.rs | 5 +++- gfx/wr/webrender/src/internal_types.rs | 10 ++++++-- gfx/wr/webrender/src/picture.rs | 25 +++++++++++++------ gfx/wr/webrender/src/prim_store/picture.rs | 2 ++ gfx/wr/webrender_api/src/display_item.rs | 1 + .../reftests/filters/filter-flood-ref.yaml | 10 ++++++++ .../wrench/reftests/filters/filter-flood.yaml | 10 ++++++++ gfx/wr/wrench/reftests/filters/reftest.list | 1 + gfx/wr/wrench/src/yaml_frame_writer.rs | 3 +++ gfx/wr/wrench/src/yaml_helper.rs | 6 +++++ 11 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 gfx/wr/wrench/reftests/filters/filter-flood-ref.yaml create mode 100644 gfx/wr/wrench/reftests/filters/filter-flood.yaml diff --git a/gfx/wr/webrender/res/brush_blend.glsl b/gfx/wr/webrender/res/brush_blend.glsl index fb5251730743..3d317baf038f 100644 --- a/gfx/wr/webrender/res/brush_blend.glsl +++ b/gfx/wr/webrender/res/brush_blend.glsl @@ -25,6 +25,7 @@ flat varying vec3 vColorOffset; flat varying vec4 vUvClipBounds; flat varying int vTableAddress; flat varying int vFuncs[4]; +flat varying vec4 vFloodColor; #ifdef WR_VERTEX_SHADER @@ -136,6 +137,11 @@ void brush_vs( vTableAddress = prim_user_data.z; break; } + case 14: { + // Flood + vFloodColor = fetch_from_gpu_cache_1(prim_user_data.z); + break; + } default: break; } } @@ -264,6 +270,10 @@ Fragment brush_fs() { color = colora.rgb; alpha = colora.a; break; + case 14: // Flood + color = vFloodColor.rgb; + alpha = vFloodColor.a; + break; default: color = vColorMat * color + vColorOffset; } diff --git a/gfx/wr/webrender/src/batch.rs b/gfx/wr/webrender/src/batch.rs index 58c2c760bcae..9d56344f86a0 100644 --- a/gfx/wr/webrender/src/batch.rs +++ b/gfx/wr/webrender/src/batch.rs @@ -1484,6 +1484,7 @@ impl BatchBuilder { Filter::SrgbToLinear => 11, Filter::LinearToSrgb => 12, Filter::ComponentTransfer => unreachable!(), + Filter::Flood(..) => 14, }; let user_data = match filter { @@ -1510,6 +1511,9 @@ impl BatchBuilder { picture.extra_gpu_data_handles[0].as_int(gpu_cache) } Filter::ComponentTransfer => unreachable!(), + Filter::Flood(_) => { + picture.extra_gpu_data_handles[0].as_int(gpu_cache) + } }; let (uv_rect_address, textures) = render_tasks.resolve_surface( @@ -3181,4 +3185,3 @@ impl<'a, 'rc> RenderTargetContext<'a, 'rc> { ) } } - diff --git a/gfx/wr/webrender/src/internal_types.rs b/gfx/wr/webrender/src/internal_types.rs index 7626923f01d7..02f9c728a642 100644 --- a/gfx/wr/webrender/src/internal_types.rs +++ b/gfx/wr/webrender/src/internal_types.rs @@ -2,7 +2,7 @@ * 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::{DebugCommand, DocumentId, ExternalImageData, ExternalImageId}; +use api::{ColorF, DebugCommand, DocumentId, ExternalImageData, ExternalImageId}; use api::{ImageFormat, ItemTag, NotificationRequest, Shadow, FilterOp, MAX_BLUR_RADIUS}; use api::units::*; use api; @@ -55,6 +55,7 @@ pub enum Filter { SrgbToLinear, LinearToSrgb, ComponentTransfer, + Flood(ColorF), } impl Filter { @@ -92,6 +93,9 @@ impl Filter { Filter::ComponentTransfer => true, Filter::Opacity(_, amount) => { amount > OPACITY_EPSILON + }, + Filter::Flood(color) => { + color.a > OPACITY_EPSILON } } } @@ -128,7 +132,8 @@ impl Filter { } Filter::SrgbToLinear | Filter::LinearToSrgb | - Filter::ComponentTransfer => false, + Filter::ComponentTransfer | + Filter::Flood(..) => false, } } } @@ -151,6 +156,7 @@ impl From for Filter { FilterOp::LinearToSrgb => Filter::LinearToSrgb, FilterOp::ComponentTransfer => Filter::ComponentTransfer, FilterOp::DropShadow(shadow) => Filter::DropShadows(smallvec![shadow]), + FilterOp::Flood(color) => Filter::Flood(color), } } } diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index 599d044069b8..cfa3542bf873 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -3213,15 +3213,26 @@ impl PicturePrimitive { } PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {} PictureCompositeMode::Filter(ref filter) => { - if let Filter::ColorMatrix(ref m) = *filter { - if self.extra_gpu_data_handles.is_empty() { - self.extra_gpu_data_handles.push(GpuCacheHandle::new()); - } - if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handles[0]) { - for i in 0..5 { - request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]); + match *filter { + Filter::ColorMatrix(ref m) => { + if self.extra_gpu_data_handles.is_empty() { + self.extra_gpu_data_handles.push(GpuCacheHandle::new()); + } + if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handles[0]) { + for i in 0..5 { + request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]); + } } } + Filter::Flood(ref color) => { + if self.extra_gpu_data_handles.is_empty() { + self.extra_gpu_data_handles.push(GpuCacheHandle::new()); + } + if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handles[0]) { + request.push(color.to_array()); + } + } + _ => {} } } PictureCompositeMode::ComponentTransferFilter(handle) => { diff --git a/gfx/wr/webrender/src/prim_store/picture.rs b/gfx/wr/webrender/src/prim_store/picture.rs index 54eaa6f81d07..ba05cc2dd83b 100644 --- a/gfx/wr/webrender/src/prim_store/picture.rs +++ b/gfx/wr/webrender/src/prim_store/picture.rs @@ -43,6 +43,7 @@ pub enum PictureCompositeKey { SrgbToLinear, LinearToSrgb, ComponentTransfer(ItemUid), + Flood(ColorU), // MixBlendMode Multiply, @@ -123,6 +124,7 @@ impl From> for PictureCompositeKey { PictureCompositeKey::ColorMatrix(quantized_values) } Filter::ComponentTransfer => unreachable!(), + Filter::Flood(color) => PictureCompositeKey::Flood(color.into()), } } Some(PictureCompositeMode::ComponentTransferFilter(handle)) => { diff --git a/gfx/wr/webrender_api/src/display_item.rs b/gfx/wr/webrender_api/src/display_item.rs index be09c8137dc7..171cb391fbe6 100644 --- a/gfx/wr/webrender_api/src/display_item.rs +++ b/gfx/wr/webrender_api/src/display_item.rs @@ -717,6 +717,7 @@ pub enum FilterOp { SrgbToLinear, LinearToSrgb, ComponentTransfer, + Flood(ColorF), } #[repr(u8)] diff --git a/gfx/wr/wrench/reftests/filters/filter-flood-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-flood-ref.yaml new file mode 100644 index 000000000000..ae4eb6a0d159 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-flood-ref.yaml @@ -0,0 +1,10 @@ +# Test that flood filter is equivalent to drawing a rect with the same size and color +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + items: + - type: rect + bounds: [20, 20, 256, 256] + color: [0, 255.0, 0, 0.4] diff --git a/gfx/wr/wrench/reftests/filters/filter-flood.yaml b/gfx/wr/wrench/reftests/filters/filter-flood.yaml new file mode 100644 index 000000000000..bf896e266f3f --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-flood.yaml @@ -0,0 +1,10 @@ +# Test that flood filter is equivalent to drawing a rect with the same size and color +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + filters: flood([0, 255.0, 0, 0.4]) + items: + - image: "firefox.png" + bounds: 20 20 256 256 diff --git a/gfx/wr/wrench/reftests/filters/reftest.list b/gfx/wr/wrench/reftests/filters/reftest.list index c8a6bd5deecd..c27f13dae840 100644 --- a/gfx/wr/wrench/reftests/filters/reftest.list +++ b/gfx/wr/wrench/reftests/filters/reftest.list @@ -44,3 +44,4 @@ skip_on(android) == filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.yaml # != filter-drop-shadow-huge.yaml blank.yaml == filter-blur-scaled.yaml filter-blur-scaled-ref.yaml skip_on(android) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png # fails on Android +== filter-flood.yaml filter-flood-ref.yaml diff --git a/gfx/wr/wrench/src/yaml_frame_writer.rs b/gfx/wr/wrench/src/yaml_frame_writer.rs index 14f69c36536e..0b41a4681d9f 100644 --- a/gfx/wr/wrench/src/yaml_frame_writer.rs +++ b/gfx/wr/wrench/src/yaml_frame_writer.rs @@ -306,6 +306,9 @@ fn write_stacking_context( FilterOp::ComponentTransfer => { filters.push(Yaml::String("component-transfer".to_string())) } + FilterOp::Flood(color) => { + filters.push(Yaml::String(format!("flood({})", color_to_string(color)))) + } } } diff --git a/gfx/wr/wrench/src/yaml_helper.rs b/gfx/wr/wrench/src/yaml_helper.rs index 96c93fbc4aea..fd5e2d6f8452 100644 --- a/gfx/wr/wrench/src/yaml_helper.rs +++ b/gfx/wr/wrench/src/yaml_helper.rs @@ -613,6 +613,12 @@ impl YamlHelper for Yaml { matrix.clone_from_slice(&m); Some(FilterOp::ColorMatrix(matrix)) } + ("flood", ref args, _) if args.len() == 1 => { + let str = format!("---\ncolor: {}\n", args[0]); + let mut yaml_doc = YamlLoader::load_from_str(&str).expect("Failed to parse flood"); + let yaml = yaml_doc.pop().unwrap(); + Some(FilterOp::Flood(yaml["color"].as_colorf().unwrap())) + } (_, _, _) => None, } } else {