зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1365972 - Add initial WebRender support for nsDisplayFilter. r=rhunt, r=mattwoodrow
This commit is contained in:
Родитель
1d80223f3d
Коммит
7d937678f4
|
@ -2250,6 +2250,12 @@ public:
|
|||
return mEventRegionsOverride;
|
||||
}
|
||||
|
||||
void SetFilterChain(nsTArray<CSSFilter>&& aFilterChain) {
|
||||
mFilterChain = aFilterChain;
|
||||
}
|
||||
|
||||
nsTArray<CSSFilter>& GetFilterChain() { return mFilterChain; }
|
||||
|
||||
protected:
|
||||
friend class ReadbackProcessor;
|
||||
|
||||
|
@ -2336,6 +2342,7 @@ protected:
|
|||
// the intermediate surface.
|
||||
bool mChildrenChanged;
|
||||
EventRegionsOverride mEventRegionsOverride;
|
||||
nsTArray<CSSFilter> mFilterChain;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "LayersTypes.h"
|
||||
|
||||
#include "nsStyleStruct.h" // for nsStyleFilter
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
CSSFilter ToCSSFilter(const nsStyleFilter& filter)
|
||||
{
|
||||
switch (filter.GetType()) {
|
||||
case NS_STYLE_FILTER_BRIGHTNESS: {
|
||||
return {
|
||||
CSSFilterType::BRIGHTNESS,
|
||||
filter.GetFilterParameter().GetFactorOrPercentValue(),
|
||||
};
|
||||
}
|
||||
case NS_STYLE_FILTER_CONTRAST: {
|
||||
return {
|
||||
CSSFilterType::CONTRAST,
|
||||
filter.GetFilterParameter().GetFactorOrPercentValue(),
|
||||
};
|
||||
}
|
||||
// All other filter types should be prevented by the code which converts
|
||||
// display items into layers.
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Tried to convert an unsupported filter");
|
||||
return { CSSFilterType::CONTRAST, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
@ -35,6 +35,8 @@ namespace android {
|
|||
class MOZ_EXPORT GraphicBuffer;
|
||||
} // namespace android
|
||||
|
||||
struct nsStyleFilter;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -309,6 +311,25 @@ enum class ScrollDirection : uint32_t {
|
|||
SENTINEL /* for IPC serialization */
|
||||
};
|
||||
|
||||
enum class CSSFilterType : int8_t {
|
||||
BLUR,
|
||||
BRIGHTNESS,
|
||||
CONTRAST,
|
||||
GRAYSCALE,
|
||||
HUE_ROTATE,
|
||||
INVERT,
|
||||
OPACITY,
|
||||
SATURATE,
|
||||
SEPIA,
|
||||
};
|
||||
|
||||
struct CSSFilter {
|
||||
CSSFilterType type;
|
||||
float argument;
|
||||
};
|
||||
|
||||
CSSFilter ToCSSFilter(const nsStyleFilter& filter);
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -383,6 +383,7 @@ UNIFIED_SOURCES += [
|
|||
'LayerScope.cpp',
|
||||
'LayersLogging.cpp',
|
||||
'LayerSorter.cpp',
|
||||
'LayersTypes.cpp',
|
||||
'opengl/CompositingRenderTargetOGL.cpp',
|
||||
'opengl/CompositorOGL.cpp',
|
||||
'opengl/GLBlitTextureImageHelper.cpp',
|
||||
|
|
|
@ -20,16 +20,19 @@ StackingContextHelper::StackingContextHelper()
|
|||
StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
WebRenderLayer* aLayer,
|
||||
const Maybe<gfx::Matrix4x4>& aTransform)
|
||||
const Maybe<gfx::Matrix4x4>& aTransform,
|
||||
const nsTArray<WrFilterOp>& aFilters)
|
||||
: mBuilder(&aBuilder)
|
||||
{
|
||||
WrRect scBounds = aParentSC.ToRelativeWrRect(aLayer->BoundsForStackingContext());
|
||||
Layer* layer = aLayer->GetLayer();
|
||||
mTransform = aTransform.valueOr(layer->GetTransform());
|
||||
|
||||
float opacity = 1.0f;
|
||||
mBuilder->PushStackingContext(scBounds, 0, &opacity,
|
||||
mTransform.IsIdentity() ? nullptr : &mTransform,
|
||||
wr::ToWrMixBlendMode(layer->GetMixBlendMode()));
|
||||
wr::ToWrMixBlendMode(layer->GetMixBlendMode()),
|
||||
aFilters);
|
||||
mOrigin = aLayer->Bounds().TopLeft();
|
||||
}
|
||||
|
||||
|
@ -38,18 +41,21 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
|
|||
WebRenderLayer* aLayer,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr)
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
const nsTArray<WrFilterOp>& aFilters)
|
||||
: mBuilder(&aBuilder)
|
||||
{
|
||||
WrRect scBounds = aParentSC.ToRelativeWrRect(aLayer->BoundsForStackingContext());
|
||||
if (aTransformPtr) {
|
||||
mTransform = *aTransformPtr;
|
||||
}
|
||||
|
||||
mBuilder->PushStackingContext(scBounds,
|
||||
aAnimationsId,
|
||||
aOpacityPtr,
|
||||
aTransformPtr,
|
||||
wr::ToWrMixBlendMode(aLayer->GetLayer()->GetMixBlendMode()));
|
||||
wr::ToWrMixBlendMode(aLayer->GetLayer()->GetMixBlendMode()),
|
||||
aFilters);
|
||||
mOrigin = aLayer->Bounds().TopLeft();
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ public:
|
|||
StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
WebRenderLayer* aLayer,
|
||||
const Maybe<gfx::Matrix4x4>& aTransform = Nothing());
|
||||
const Maybe<gfx::Matrix4x4>& aTransform = Nothing(),
|
||||
const nsTArray<WrFilterOp>& aFilters = nsTArray<WrFilterOp>());
|
||||
// Alternate constructor which invokes the version of PushStackingContext
|
||||
// for animations.
|
||||
StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
|
@ -39,7 +40,8 @@ public:
|
|||
WebRenderLayer* aLayer,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr);
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
const nsTArray<WrFilterOp>& aFilters = nsTArray<WrFilterOp>());
|
||||
// This version of the constructor should only be used at the root level
|
||||
// of the tree, so that we have a StackingContextHelper to pass down into
|
||||
// the RenderLayer traversal, but don't actually want it to push a stacking
|
||||
|
|
|
@ -275,7 +275,8 @@ WebRenderCompositableHolder::ApplyAsyncImages(wr::WebRenderAPI* aApi)
|
|||
0,
|
||||
&opacity,
|
||||
holder->mScTransform.IsIdentity() ? nullptr : &holder->mScTransform,
|
||||
holder->mMixBlendMode);
|
||||
holder->mMixBlendMode,
|
||||
nsTArray<WrFilterOp>());
|
||||
|
||||
LayerRect rect(0, 0, holder->mCurrentTexture->GetSize().width, holder->mCurrentTexture->GetSize().height);
|
||||
if (holder->mScaleToSize.isSome()) {
|
||||
|
|
|
@ -114,8 +114,13 @@ WebRenderContainerLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
|
|||
transformForSC = nullptr;
|
||||
}
|
||||
|
||||
nsTArray<WrFilterOp> filters;
|
||||
for (const CSSFilter& filter : this->GetFilterChain()) {
|
||||
filters.AppendElement(wr::ToWrFilterOp(filter));
|
||||
}
|
||||
|
||||
ScrollingLayersHelper scroller(this, aBuilder, aSc);
|
||||
StackingContextHelper sc(aSc, aBuilder, this, animationsId, opacityForSC, transformForSC);
|
||||
StackingContextHelper sc(aSc, aBuilder, this, animationsId, opacityForSC, transformForSC, filters);
|
||||
|
||||
LayerRect rect = Bounds();
|
||||
DumpLayerInfo("ContainerLayer", rect);
|
||||
|
|
|
@ -504,6 +504,7 @@ private:
|
|||
DECL_OVERRIDE_PREF(Live, "layers.advanced.caret-layers", LayersAllowCaretLayers, gfxPrefs::OverrideBase_WebRender());
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.columnRule-layers", LayersAllowColumnRuleLayers, gfxPrefs::OverrideBase_WebRender());
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.displaybuttonborder-layers", LayersAllowDisplayButtonBorder, gfxPrefs::OverrideBase_WebRender());
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.filter-layers", LayersAllowFilterLayers, gfxPrefs::OverrideBase_WebRender());
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.image-layers", LayersAllowImageLayers, gfxPrefs::OverrideBase_WebRendest());
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.outline-layers", LayersAllowOutlineLayers, gfxPrefs::OverrideBase_WebRender());
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.solid-color", LayersAllowSolidColorLayers, gfxPrefs::OverrideBase_WebRender());
|
||||
|
|
|
@ -556,7 +556,8 @@ DisplayListBuilder::PushStackingContext(const WrRect& aBounds,
|
|||
const uint64_t& aAnimationId,
|
||||
const float* aOpacity,
|
||||
const gfx::Matrix4x4* aTransform,
|
||||
const WrMixBlendMode& aMixBlendMode)
|
||||
const WrMixBlendMode& aMixBlendMode,
|
||||
const nsTArray<WrFilterOp>& aFilters)
|
||||
{
|
||||
WrMatrix matrix;
|
||||
if (aTransform) {
|
||||
|
@ -566,7 +567,8 @@ DisplayListBuilder::PushStackingContext(const WrRect& aBounds,
|
|||
WRDL_LOG("PushStackingContext b=%s t=%s\n", Stringify(aBounds).c_str(),
|
||||
aTransform ? Stringify(*aTransform).c_str() : "none");
|
||||
wr_dp_push_stacking_context(mWrState, aBounds, aAnimationId, aOpacity,
|
||||
maybeTransform, aMixBlendMode);
|
||||
maybeTransform, aMixBlendMode,
|
||||
aFilters.Elements(), aFilters.Length());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -150,7 +150,8 @@ public:
|
|||
const uint64_t& aAnimationId,
|
||||
const float* aOpacity,
|
||||
const gfx::Matrix4x4* aTransform,
|
||||
const WrMixBlendMode& aMixBlendMode);
|
||||
const WrMixBlendMode& aMixBlendMode,
|
||||
const nsTArray<WrFilterOp>& aFilters);
|
||||
void PopStackingContext();
|
||||
|
||||
void PushClip(const WrRect& aClipRect,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "Units.h"
|
||||
#include "nsStyleConsts.h"
|
||||
|
@ -551,6 +552,38 @@ struct BuiltDisplayList {
|
|||
WrBuiltDisplayListDescriptor dl_desc;
|
||||
};
|
||||
|
||||
static inline WrFilterOpType ToWrFilterOpType(const layers::CSSFilterType type) {
|
||||
switch (type) {
|
||||
case layers::CSSFilterType::BLUR:
|
||||
return WrFilterOpType::Blur;
|
||||
case layers::CSSFilterType::BRIGHTNESS:
|
||||
return WrFilterOpType::Brightness;
|
||||
case layers::CSSFilterType::CONTRAST:
|
||||
return WrFilterOpType::Contrast;
|
||||
case layers::CSSFilterType::GRAYSCALE:
|
||||
return WrFilterOpType::Grayscale;
|
||||
case layers::CSSFilterType::HUE_ROTATE:
|
||||
return WrFilterOpType::HueRotate;
|
||||
case layers::CSSFilterType::INVERT:
|
||||
return WrFilterOpType::Invert;
|
||||
case layers::CSSFilterType::OPACITY:
|
||||
return WrFilterOpType::Opacity;
|
||||
case layers::CSSFilterType::SATURATE:
|
||||
return WrFilterOpType::Saturate;
|
||||
case layers::CSSFilterType::SEPIA:
|
||||
return WrFilterOpType::Sepia;
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("Tried to convert unknown filter type.");
|
||||
return WrFilterOpType::Grayscale;
|
||||
}
|
||||
|
||||
static inline WrFilterOp ToWrFilterOp(const layers::CSSFilter& filter) {
|
||||
return {
|
||||
ToWrFilterOpType(filter.type),
|
||||
filter.argument,
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::HashSet;
|
|||
use std::ffi::CString;
|
||||
use std::{mem, slice};
|
||||
use std::path::PathBuf;
|
||||
use std::os::raw::{c_void, c_char};
|
||||
use std::os::raw::{c_void, c_char, c_float};
|
||||
use std::collections::HashMap;
|
||||
use gleam::gl;
|
||||
|
||||
|
@ -59,6 +59,27 @@ type WrYuvColorSpace = YuvColorSpace;
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct WrExternalImageId(pub u64);
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum WrFilterOpType {
|
||||
Blur = 0,
|
||||
Brightness = 1,
|
||||
Contrast = 2,
|
||||
Grayscale = 3,
|
||||
HueRotate = 4,
|
||||
Invert = 5,
|
||||
Opacity = 6,
|
||||
Saturate = 7,
|
||||
Sepia = 8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct WrFilterOp {
|
||||
filter_type: WrFilterOpType,
|
||||
argument: c_float,
|
||||
}
|
||||
|
||||
impl Into<ExternalImageId> for WrExternalImageId {
|
||||
fn into(self) -> ExternalImageId {
|
||||
ExternalImageId(self.0)
|
||||
|
@ -1245,12 +1266,28 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
animation_id: u64,
|
||||
opacity: *const f32,
|
||||
transform: *const WrMatrix,
|
||||
mix_blend_mode: WrMixBlendMode) {
|
||||
mix_blend_mode: WrMixBlendMode,
|
||||
filters: *const WrFilterOp,
|
||||
filter_count: usize) {
|
||||
assert!(unsafe { !is_in_render_thread() });
|
||||
|
||||
let bounds = bounds.into();
|
||||
|
||||
let mut filters: Vec<FilterOp> = Vec::new();
|
||||
let c_filters = make_slice(filters, filter_count);
|
||||
let mut filters : Vec<FilterOp> = c_filters.iter().map(|c_filter| {
|
||||
match c_filter.filter_type {
|
||||
WrFilterOpType::Blur => FilterOp::Blur(Au::from_f32_px(c_filter.argument)),
|
||||
WrFilterOpType::Brightness => FilterOp::Brightness(c_filter.argument),
|
||||
WrFilterOpType::Contrast => FilterOp::Contrast(c_filter.argument),
|
||||
WrFilterOpType::Grayscale => FilterOp::Grayscale(c_filter.argument),
|
||||
WrFilterOpType::HueRotate => FilterOp::HueRotate(c_filter.argument),
|
||||
WrFilterOpType::Invert => FilterOp::Invert(c_filter.argument),
|
||||
WrFilterOpType::Opacity => FilterOp::Opacity(PropertyBinding::Value(c_filter.argument)),
|
||||
WrFilterOpType::Saturate => FilterOp::Saturate(c_filter.argument),
|
||||
WrFilterOpType::Sepia => FilterOp::Sepia(c_filter.argument),
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let opacity = unsafe { opacity.as_ref() };
|
||||
if let Some(opacity) = opacity {
|
||||
if *opacity < 1.0 {
|
||||
|
|
|
@ -51,6 +51,20 @@ enum class WrExternalImageType : uint32_t {
|
|||
Sentinel /* this must be last for serialization purposes. */
|
||||
};
|
||||
|
||||
enum class WrFilterOpType : uint32_t {
|
||||
Blur = 0,
|
||||
Brightness = 1,
|
||||
Contrast = 2,
|
||||
Grayscale = 3,
|
||||
HueRotate = 4,
|
||||
Invert = 5,
|
||||
Opacity = 6,
|
||||
Saturate = 7,
|
||||
Sepia = 8,
|
||||
|
||||
Sentinel /* this must be last for serialization purposes. */
|
||||
};
|
||||
|
||||
enum class WrGradientExtendMode : uint32_t {
|
||||
Clamp = 0,
|
||||
Repeat = 1,
|
||||
|
@ -423,6 +437,16 @@ struct WrComplexClipRegion {
|
|||
}
|
||||
};
|
||||
|
||||
struct WrFilterOp {
|
||||
WrFilterOpType filter_type;
|
||||
float argument;
|
||||
|
||||
bool operator==(const WrFilterOp& aOther) const {
|
||||
return filter_type == aOther.filter_type &&
|
||||
argument == aOther.argument;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrGlyphInstance {
|
||||
uint32_t index;
|
||||
WrPoint point;
|
||||
|
@ -784,7 +808,9 @@ void wr_dp_push_stacking_context(WrState *aState,
|
|||
uint64_t aAnimationId,
|
||||
const float *aOpacity,
|
||||
const WrMatrix *aTransform,
|
||||
WrMixBlendMode aMixBlendMode)
|
||||
WrMixBlendMode aMixBlendMode,
|
||||
const WrFilterOp *aFilters,
|
||||
size_t aFilterCount)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
|
|
|
@ -8635,6 +8635,17 @@ nsDisplayFilter::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
newContainerParameters, nullptr);
|
||||
|
||||
LayerState state = this->GetLayerState(aBuilder, aManager, newContainerParameters);
|
||||
if (container && state != LAYER_SVG_EFFECTS) {
|
||||
const nsTArray<nsStyleFilter>& filters = mFrame->StyleEffects()->mFilters;
|
||||
nsTArray<layers::CSSFilter> cssFilters = nsTArray<layers::CSSFilter>(filters.Length());
|
||||
for (const nsStyleFilter& filter : filters) {
|
||||
cssFilters.AppendElement(ToCSSFilter(filter));
|
||||
}
|
||||
|
||||
container->SetFilterChain(Move(cssFilters));
|
||||
}
|
||||
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
|
@ -8667,7 +8678,25 @@ nsDisplayFilter::GetLayerState(nsDisplayListBuilder* aBuilder,
|
|||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aParameters)
|
||||
{
|
||||
return LAYER_SVG_EFFECTS;
|
||||
if (mFrame->IsFrameOfType(nsIFrame::eSVG)) {
|
||||
return LAYER_SVG_EFFECTS;
|
||||
}
|
||||
|
||||
if (!ShouldUseAdvancedLayer(aManager, gfxPrefs::LayersAllowFilterLayers)) {
|
||||
return LAYER_SVG_EFFECTS;
|
||||
}
|
||||
|
||||
// Due to differences in the way that WebRender filters operate
|
||||
// only the brightness and contrast filters use that path. We
|
||||
// can gradually enable more filters as WebRender bugs are fixed.
|
||||
for (const nsStyleFilter& filter : mFrame->StyleEffects()->mFilters) {
|
||||
if (filter.GetType() != NS_STYLE_FILTER_BRIGHTNESS &&
|
||||
filter.GetType() != NS_STYLE_FILTER_CONTRAST) {
|
||||
return LAYER_SVG_EFFECTS;
|
||||
}
|
||||
}
|
||||
|
||||
return LAYER_ACTIVE;
|
||||
}
|
||||
|
||||
bool nsDisplayFilter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -5740,6 +5740,7 @@ pref("layers.advanced.outline-layers", 2);
|
|||
pref("layers.advanced.solid-color", 2);
|
||||
pref("layers.advanced.table", 2);
|
||||
pref("layers.advanced.text-layers", 2);
|
||||
pref("layers.advanced.filter-layers", 2);
|
||||
|
||||
// Whether webrender should be used as much as possible.
|
||||
pref("gfx.webrendest.enabled", false);
|
||||
|
|
Загрузка…
Ссылка в новой задаче