Bug 1555476 - Implement flood filter in WebRender r=gw

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Connor Brewster 2019-05-30 03:11:53 +00:00
parent 3f4b49387b
commit bb54c17ce3
11 changed files with 73 additions and 10 deletions

View File

@ -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;
}

View File

@ -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> {
)
}
}

View File

@ -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<FilterOp> for Filter {
FilterOp::LinearToSrgb => Filter::LinearToSrgb,
FilterOp::ComponentTransfer => Filter::ComponentTransfer,
FilterOp::DropShadow(shadow) => Filter::DropShadows(smallvec![shadow]),
FilterOp::Flood(color) => Filter::Flood(color),
}
}
}

View File

@ -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) => {

View File

@ -43,6 +43,7 @@ pub enum PictureCompositeKey {
SrgbToLinear,
LinearToSrgb,
ComponentTransfer(ItemUid),
Flood(ColorU),
// MixBlendMode
Multiply,
@ -123,6 +124,7 @@ impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
PictureCompositeKey::ColorMatrix(quantized_values)
}
Filter::ComponentTransfer => unreachable!(),
Filter::Flood(color) => PictureCompositeKey::Flood(color.into()),
}
}
Some(PictureCompositeMode::ComponentTransferFilter(handle)) => {

View File

@ -717,6 +717,7 @@ pub enum FilterOp {
SrgbToLinear,
LinearToSrgb,
ComponentTransfer,
Flood(ColorF),
}
#[repr(u8)]

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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))))
}
}
}

View File

@ -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 {