From 4375178c34ccbcedffb97b1e44f1f8c8d55eee39 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Mon, 16 Sep 2019 21:54:16 +0000 Subject: [PATCH] Bug 1578777 - Move CreateWebRenderCSSFilters() to nsSVGIntegrationUtils. r=jrmuizel Depends on D46058 Differential Revision: https://phabricator.services.mozilla.com/D46059 --HG-- extra : moz-landing-system : lando --- layout/painting/nsDisplayList.cpp | 99 +++------------------------- layout/svg/nsSVGIntegrationUtils.cpp | 87 ++++++++++++++++++++++++ layout/svg/nsSVGIntegrationUtils.h | 11 +++- 3 files changed, 104 insertions(+), 93 deletions(-) diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index afb4f32efa08..4af33b9cdcf2 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -10187,93 +10187,6 @@ void nsDisplayMasksAndClipPaths::PrintEffects(nsACString& aTo) { } #endif -static float ClampStdDeviation(float aStdDeviation) { - // Cap software blur radius for performance reasons. - return std::min(std::max(0.0f, aStdDeviation), 100.0f); -} - -static bool CreateWebRenderCSSFilters(Span aFilters, - nsIFrame* aFrame, - WrFiltersHolder& aWrFilters) { - // All CSS filters are supported by WebRender. SVG filters are not fully - // supported, those use NS_STYLE_FILTER_URL and are handled separately. - - // If there are too many filters to render, then just pretend that we - // succeeded, and don't render any of them. - if (aFilters.Length() > - StaticPrefs::gfx_webrender_max_filter_ops_per_chain()) { - return true; - } - aWrFilters.filters.SetCapacity(aFilters.Length()); - auto& wrFilters = aWrFilters.filters; - for (const StyleFilter& filter : aFilters) { - switch (filter.tag) { - case StyleFilter::Tag::Brightness: - wrFilters.AppendElement( - wr::FilterOp::Brightness(filter.AsBrightness())); - break; - case StyleFilter::Tag::Contrast: - wrFilters.AppendElement(wr::FilterOp::Contrast(filter.AsContrast())); - break; - case StyleFilter::Tag::Grayscale: - wrFilters.AppendElement(wr::FilterOp::Grayscale(filter.AsGrayscale())); - break; - case StyleFilter::Tag::Invert: - wrFilters.AppendElement(wr::FilterOp::Invert(filter.AsInvert())); - break; - case StyleFilter::Tag::Opacity: { - float opacity = filter.AsOpacity(); - wrFilters.AppendElement(wr::FilterOp::Opacity( - wr::PropertyBinding::Value(opacity), opacity)); - break; - } - case StyleFilter::Tag::Saturate: - wrFilters.AppendElement(wr::FilterOp::Saturate(filter.AsSaturate())); - break; - case StyleFilter::Tag::Sepia: - wrFilters.AppendElement(wr::FilterOp::Sepia(filter.AsSepia())); - break; - case StyleFilter::Tag::HueRotate: { - wrFilters.AppendElement( - wr::FilterOp::HueRotate(filter.AsHueRotate().ToDegrees())); - break; - } - case StyleFilter::Tag::Blur: { - // TODO(emilio): we should go directly from css pixels -> device pixels. - float appUnitsPerDevPixel = - aFrame->PresContext()->AppUnitsPerDevPixel(); - wrFilters.AppendElement(mozilla::wr::FilterOp::Blur( - ClampStdDeviation(NSAppUnitsToFloatPixels( - filter.AsBlur().ToAppUnits(), appUnitsPerDevPixel)))); - break; - } - case StyleFilter::Tag::DropShadow: { - float appUnitsPerDevPixel = - aFrame->PresContext()->AppUnitsPerDevPixel(); - const StyleSimpleShadow& shadow = filter.AsDropShadow(); - nscolor color = shadow.color.CalcColor(aFrame); - - wr::Shadow wrShadow; - wrShadow.offset = { - NSAppUnitsToFloatPixels(shadow.horizontal.ToAppUnits(), - appUnitsPerDevPixel), - NSAppUnitsToFloatPixels(shadow.vertical.ToAppUnits(), - appUnitsPerDevPixel)}; - wrShadow.blur_radius = NSAppUnitsToFloatPixels(shadow.blur.ToAppUnits(), - appUnitsPerDevPixel); - wrShadow.color = {NS_GET_R(color) / 255.0f, NS_GET_G(color) / 255.0f, - NS_GET_B(color) / 255.0f, NS_GET_A(color) / 255.0f}; - wrFilters.AppendElement(wr::FilterOp::DropShadow(wrShadow)); - break; - } - default: - return false; - } - } - - return true; -} - already_AddRefed nsDisplayBackdropRootContainer::BuildLayer( nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) { @@ -10317,7 +10230,8 @@ bool nsDisplayBackdropFilters::CanCreateWebRenderCommands( WrFiltersHolder wrFilters; Maybe filterClip; auto filterChain = aFrame->StyleEffects()->mBackdropFilters.AsSpan(); - return CreateWebRenderCSSFilters(filterChain, aFrame, wrFilters) || + return nsSVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, aFrame, + wrFilters) || nsSVGIntegrationUtils::BuildWebRenderFilters(aFrame, filterChain, wrFilters, filterClip); } @@ -10331,7 +10245,8 @@ bool nsDisplayBackdropFilters::CreateWebRenderCommands( WrFiltersHolder wrFilters; Maybe filterClip; auto filterChain = mFrame->StyleEffects()->mBackdropFilters.AsSpan(); - if (!CreateWebRenderCSSFilters(filterChain, mFrame, wrFilters) && + if (!nsSVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, mFrame, + wrFilters) && !nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain, wrFilters, filterClip)) { return false; @@ -10458,7 +10373,8 @@ bool nsDisplayFilters::CanCreateWebRenderCommands() { WrFiltersHolder wrFilters; Maybe filterClip; auto filterChain = mFrame->StyleEffects()->mFilters.AsSpan(); - return CreateWebRenderCSSFilters(filterChain, mFrame, wrFilters) || + return nsSVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, mFrame, + wrFilters) || nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain, wrFilters, filterClip); } @@ -10474,7 +10390,8 @@ bool nsDisplayFilters::CreateWebRenderCommands( WrFiltersHolder wrFilters; Maybe filterClip; auto filterChain = mFrame->StyleEffects()->mFilters.AsSpan(); - if (!CreateWebRenderCSSFilters(filterChain, mFrame, wrFilters) && + if (!nsSVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, mFrame, + wrFilters) && !nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain, wrFilters, filterClip)) { return false; diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index 9c0868235bd7..d90aa63333f7 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -1105,6 +1105,93 @@ void nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams) { aParams.imgParams, opacity); } +static float ClampStdDeviation(float aStdDeviation) { + // Cap software blur radius for performance reasons. + return std::min(std::max(0.0f, aStdDeviation), 100.0f); +} + +bool nsSVGIntegrationUtils::CreateWebRenderCSSFilters( + Span aFilters, nsIFrame* aFrame, + WrFiltersHolder& aWrFilters) { + // All CSS filters are supported by WebRender. SVG filters are not fully + // supported, those use NS_STYLE_FILTER_URL and are handled separately. + + // If there are too many filters to render, then just pretend that we + // succeeded, and don't render any of them. + if (aFilters.Length() > + StaticPrefs::gfx_webrender_max_filter_ops_per_chain()) { + return true; + } + aWrFilters.filters.SetCapacity(aFilters.Length()); + auto& wrFilters = aWrFilters.filters; + for (const StyleFilter& filter : aFilters) { + switch (filter.tag) { + case StyleFilter::Tag::Brightness: + wrFilters.AppendElement( + wr::FilterOp::Brightness(filter.AsBrightness())); + break; + case StyleFilter::Tag::Contrast: + wrFilters.AppendElement(wr::FilterOp::Contrast(filter.AsContrast())); + break; + case StyleFilter::Tag::Grayscale: + wrFilters.AppendElement(wr::FilterOp::Grayscale(filter.AsGrayscale())); + break; + case StyleFilter::Tag::Invert: + wrFilters.AppendElement(wr::FilterOp::Invert(filter.AsInvert())); + break; + case StyleFilter::Tag::Opacity: { + float opacity = filter.AsOpacity(); + wrFilters.AppendElement(wr::FilterOp::Opacity( + wr::PropertyBinding::Value(opacity), opacity)); + break; + } + case StyleFilter::Tag::Saturate: + wrFilters.AppendElement(wr::FilterOp::Saturate(filter.AsSaturate())); + break; + case StyleFilter::Tag::Sepia: + wrFilters.AppendElement(wr::FilterOp::Sepia(filter.AsSepia())); + break; + case StyleFilter::Tag::HueRotate: { + wrFilters.AppendElement( + wr::FilterOp::HueRotate(filter.AsHueRotate().ToDegrees())); + break; + } + case StyleFilter::Tag::Blur: { + // TODO(emilio): we should go directly from css pixels -> device pixels. + float appUnitsPerDevPixel = + aFrame->PresContext()->AppUnitsPerDevPixel(); + wrFilters.AppendElement(mozilla::wr::FilterOp::Blur( + ClampStdDeviation(NSAppUnitsToFloatPixels( + filter.AsBlur().ToAppUnits(), appUnitsPerDevPixel)))); + break; + } + case StyleFilter::Tag::DropShadow: { + float appUnitsPerDevPixel = + aFrame->PresContext()->AppUnitsPerDevPixel(); + const StyleSimpleShadow& shadow = filter.AsDropShadow(); + nscolor color = shadow.color.CalcColor(aFrame); + + wr::Shadow wrShadow; + wrShadow.offset = { + NSAppUnitsToFloatPixels(shadow.horizontal.ToAppUnits(), + appUnitsPerDevPixel), + NSAppUnitsToFloatPixels(shadow.vertical.ToAppUnits(), + appUnitsPerDevPixel)}; + wrShadow.blur_radius = NSAppUnitsToFloatPixels(shadow.blur.ToAppUnits(), + appUnitsPerDevPixel); + wrShadow.color = {NS_GET_R(color) / 255.0f, NS_GET_G(color) / 255.0f, + NS_GET_B(color) / 255.0f, NS_GET_A(color) / 255.0f}; + wrFilters.AppendElement(wr::FilterOp::DropShadow(wrShadow)); + break; + } + default: + return false; + } + } + + return true; +} + bool nsSVGIntegrationUtils::BuildWebRenderFilters( nsIFrame* aFilteredFrame, Span aFilters, WrFiltersHolder& aWrFilters, Maybe& aPostFilterClip) { diff --git a/layout/svg/nsSVGIntegrationUtils.h b/layout/svg/nsSVGIntegrationUtils.h index 614eb00d623f..781eca03e820 100644 --- a/layout/svg/nsSVGIntegrationUtils.h +++ b/layout/svg/nsSVGIntegrationUtils.h @@ -206,8 +206,15 @@ class nsSVGIntegrationUtils final { static void PaintFilter(const PaintFramesParams& aParams); /** - * Try to build WebRender filters for a frame if the filters applied to it are - * supported. + * Build WebRender filters for a frame with CSS filters applied to it. + */ + static bool CreateWebRenderCSSFilters( + mozilla::Span 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,