Backed out changeset 8e078c86db82 (bug 1509182) for bustage on WebRenderTypes.h:789. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 10 Jan 2019 18:15:42 +0200
changeset 453289 aadaa3b39509d0e1597135844e44be8006901107
parent 453288 8e078c86db82c28b65d7adbfec81627f6133a6a5
child 453290 ff2df6d75dd4ed98f6b29cb84f447c5abba63b68
push id35352
push userdvarga@mozilla.com
push dateFri, 11 Jan 2019 04:12:48 +0000
treeherdermozilla-central@65326bd78f83 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1509182
milestone66.0a1
backs out8e078c86db82c28b65d7adbfec81627f6133a6a5
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 8e078c86db82 (bug 1509182) for bustage on WebRenderTypes.h:789. CLOSED TREE
gfx/layers/wr/AsyncImagePipelineManager.cpp
gfx/layers/wr/StackingContextHelper.cpp
gfx/layers/wr/StackingContextHelper.h
gfx/layers/wr/WebRenderCommandBuilder.cpp
gfx/layers/wr/WebRenderCommandBuilder.h
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
layout/base/PresShell.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/svg/nsFilterInstance.cpp
layout/svg/nsFilterInstance.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGIntegrationUtils.h
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -398,17 +398,17 @@ void AsyncImagePipelineManager::ApplyAsy
                              aPipeline->mScBounds.Height()};
   wr::DisplayListBuilder builder(aPipelineId, contentSize);
 
   float opacity = 1.0f;
   Maybe<wr::WrSpatialId> referenceFrameId = builder.PushStackingContext(
       wr::ToRoundedLayoutRect(aPipeline->mScBounds), nullptr, nullptr, &opacity,
       aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform,
       wr::TransformStyle::Flat, nullptr, aPipeline->mMixBlendMode,
-      nsTArray<wr::FilterOp>(), true,
+      nsTArray<wr::WrFilterOp>(), true,
       // This is fine to do unconditionally because we only push images here.
       wr::RasterSpace::Screen());
 
   Maybe<wr::SpaceAndClipChainHelper> spaceAndClipChainHelper;
   if (referenceFrameId) {
     spaceAndClipChainHelper.emplace(builder, referenceFrameId.ref());
   }
 
--- a/gfx/layers/wr/StackingContextHelper.cpp
+++ b/gfx/layers/wr/StackingContextHelper.cpp
@@ -19,17 +19,17 @@ StackingContextHelper::StackingContextHe
       mIsPreserve3D(false),
       mRasterizeLocally(false) {
   // mOrigin remains at 0,0
 }
 
 StackingContextHelper::StackingContextHelper(
     const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr,
     nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem,
-    wr::DisplayListBuilder& aBuilder, const nsTArray<wr::FilterOp>& aFilters,
+    wr::DisplayListBuilder& aBuilder, const nsTArray<wr::WrFilterOp>& aFilters,
     const LayoutDeviceRect& aBounds, const gfx::Matrix4x4* aBoundTransform,
     const wr::WrAnimationProperty* aAnimation, const float* aOpacityPtr,
     const gfx::Matrix4x4* aTransformPtr, const gfx::Matrix4x4* aPerspectivePtr,
     const gfx::CompositionOp& aMixBlendMode, bool aBackfaceVisible,
     bool aIsPreserve3D,
     const Maybe<nsDisplayTransform*>& aDeferredTransformItem,
     const wr::WrClipId* aClipNodeId, bool aAnimated)
     : mBuilder(&aBuilder),
--- a/gfx/layers/wr/StackingContextHelper.h
+++ b/gfx/layers/wr/StackingContextHelper.h
@@ -26,17 +26,17 @@ namespace layers {
  * some of the coordinate space transformations needed.
  */
 class MOZ_RAII StackingContextHelper {
  public:
   StackingContextHelper(
       const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr,
       nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem,
       wr::DisplayListBuilder& aBuilder,
-      const nsTArray<wr::FilterOp>& aFilters = nsTArray<wr::FilterOp>(),
+      const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
       const LayoutDeviceRect& aBounds = LayoutDeviceRect(),
       const gfx::Matrix4x4* aBoundTransform = nullptr,
       const wr::WrAnimationProperty* aAnimation = nullptr,
       const float* aOpacityPtr = nullptr,
       const gfx::Matrix4x4* aTransformPtr = nullptr,
       const gfx::Matrix4x4* aPerspectivePtr = nullptr,
       const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
       bool aBackfaceVisible = true, bool aIsPreserve3D = false,
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -1427,17 +1427,17 @@ void WebRenderCommandBuilder::EmptyTrans
 bool WebRenderCommandBuilder::NeedsEmptyTransaction() {
   return !mLastCanvasDatas.IsEmpty();
 }
 
 void WebRenderCommandBuilder::BuildWebRenderCommands(
     wr::DisplayListBuilder& aBuilder,
     wr::IpcResourceUpdateQueue& aResourceUpdates, nsDisplayList* aDisplayList,
     nsDisplayListBuilder* aDisplayListBuilder, WebRenderScrollData& aScrollData,
-    wr::LayoutSize& aContentSize, const nsTArray<wr::FilterOp>& aFilters) {
+    wr::LayoutSize& aContentSize, const nsTArray<wr::WrFilterOp>& aFilters) {
   StackingContextHelper sc;
   aScrollData = WebRenderScrollData(mManager);
   MOZ_ASSERT(mLayerScrollData.empty());
   mLastCanvasDatas.Clear();
   mLastAsr = nullptr;
   mBuilderDumpIndex = 0;
   mContainsSVGGroup = false;
   MOZ_ASSERT(mDumpIndent == 0);
--- a/gfx/layers/wr/WebRenderCommandBuilder.h
+++ b/gfx/layers/wr/WebRenderCommandBuilder.h
@@ -52,17 +52,17 @@ class WebRenderCommandBuilder {
   bool NeedsEmptyTransaction();
 
   void BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder,
                               wr::IpcResourceUpdateQueue& aResourceUpdates,
                               nsDisplayList* aDisplayList,
                               nsDisplayListBuilder* aDisplayListBuilder,
                               WebRenderScrollData& aScrollData,
                               wr::LayoutSize& aContentSize,
-                              const nsTArray<wr::FilterOp>& aFilters);
+                              const nsTArray<wr::WrFilterOp>& aFilters);
 
   void PushOverrideForASR(const ActiveScrolledRoot* aASR,
                           const wr::WrSpatialId& aSpatialId);
   void PopOverrideForASR(const ActiveScrolledRoot* aASR);
 
   Maybe<wr::ImageKey> CreateImageKey(
       nsDisplayItem* aItem, ImageContainer* aContainer,
       mozilla::wr::DisplayListBuilder& aBuilder,
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -241,17 +241,17 @@ void WebRenderLayerManager::EndTransacti
                                            EndTransactionFlags aFlags) {
   // This should never get called, all callers should use
   // EndTransactionWithoutLayer instead.
   MOZ_ASSERT(false);
 }
 
 void WebRenderLayerManager::EndTransactionWithoutLayer(
     nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
-    const nsTArray<wr::FilterOp>& aFilters,
+    const nsTArray<wr::WrFilterOp>& aFilters,
     WebRenderBackgroundData* aBackground) {
   AUTO_PROFILER_TRACING("Paint", "RenderLayers");
 
   // Since we don't do repeat transactions right now, just set the time
   mAnimationReadyTime = TimeStamp::Now();
 
   WrBridge()->BeginTransaction();
 
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -74,17 +74,17 @@ class WebRenderLayerManager final : publ
 
   virtual bool BeginTransactionWithTarget(gfxContext* aTarget,
                                           const nsCString& aURL) override;
   virtual bool BeginTransaction(const nsCString& aURL) override;
   virtual bool EndEmptyTransaction(
       EndTransactionFlags aFlags = END_DEFAULT) override;
   void EndTransactionWithoutLayer(
       nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
-      const nsTArray<wr::FilterOp>& aFilters = nsTArray<wr::FilterOp>(),
+      const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
       WebRenderBackgroundData* aBackground = nullptr);
   virtual void EndTransaction(
       DrawPaintedLayerCallback aCallback, void* aCallbackData,
       EndTransactionFlags aFlags = END_DEFAULT) override;
 
   virtual LayersBackend GetBackendType() override {
     return LayersBackend::LAYERS_WR;
   }
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -671,17 +671,17 @@ void DisplayListBuilder::Finalize(wr::La
                           &aOutDisplayList.dl.inner);
 }
 
 Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
     const wr::LayoutRect& aBounds, const wr::WrClipId* aClipNodeId,
     const WrAnimationProperty* aAnimation, const float* aOpacity,
     const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
     const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
-    const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
+    const nsTArray<wr::WrFilterOp>& aFilters, bool aIsBackfaceVisible,
     const wr::RasterSpace& aRasterSpace) {
   MOZ_ASSERT(mClipChainLeaf.isNothing(),
              "Non-empty leaf from clip chain given, but not used with SC!");
 
   wr::LayoutTransform matrix;
   if (aTransform) {
     matrix = ToLayoutTransform(*aTransform);
   }
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -330,17 +330,17 @@ class DisplayListBuilder {
 
   Maybe<wr::WrSpatialId> PushStackingContext(
       const wr::LayoutRect&
           aBounds,  // TODO: We should work with strongly typed rects
       const wr::WrClipId* aClipNodeId,
       const wr::WrAnimationProperty* aAnimation, const float* aOpacity,
       const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
       const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
-      const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
+      const nsTArray<wr::WrFilterOp>& aFilters, bool aIsBackfaceVisible,
       const wr::RasterSpace& aRasterSpace);
   void PopStackingContext(bool aIsReferenceFrame);
 
   wr::WrClipChainId DefineClipChain(const Maybe<wr::WrClipChainId>& aParent,
                                     const nsTArray<wr::WrClipId>& aClips);
 
   wr::WrClipId DefineClip(
       const Maybe<wr::WrSpaceAndClip>& aParent, const wr::LayoutRect& aClipRect,
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -766,17 +766,43 @@ struct ByteBuffer {
   bool mOwned;
 };
 
 struct BuiltDisplayList {
   wr::VecU8 dl;
   wr::BuiltDisplayListDescriptor dl_desc;
 };
 
-extern WrClipId RootScrollNode();
+static inline wr::WrFilterOpType ToWrFilterOpType(uint32_t type) {
+  switch (type) {
+    case NS_STYLE_FILTER_BLUR:
+      return wr::WrFilterOpType::Blur;
+    case NS_STYLE_FILTER_BRIGHTNESS:
+      return wr::WrFilterOpType::Brightness;
+    case NS_STYLE_FILTER_CONTRAST:
+      return wr::WrFilterOpType::Contrast;
+    case NS_STYLE_FILTER_GRAYSCALE:
+      return wr::WrFilterOpType::Grayscale;
+    case NS_STYLE_FILTER_HUE_ROTATE:
+      return wr::WrFilterOpType::HueRotate;
+    case NS_STYLE_FILTER_INVERT:
+      return wr::WrFilterOpType::Invert;
+    case NS_STYLE_FILTER_OPACITY:
+      return wr::WrFilterOpType::Opacity;
+    case NS_STYLE_FILTER_SATURATE:
+      return wr::WrFilterOpType::Saturate;
+    case NS_STYLE_FILTER_SEPIA:
+      return wr::WrFilterOpType::Sepia;
+    case NS_STYLE_FILTER_DROP_SHADOW:
+      return wr::WrFilterOpType::DropShadow;
+  }
+  MOZ_ASSERT_UNREACHABLE("Tried to convert unknown filter type.");
+  return wr::WrFilterOpType::Grayscale;
+}
+
 
 // Corresponds to a clip id for a clip chain in webrender. Similar to
 // WrClipId but a separate struct so we don't get them mixed up in C++.
 struct WrClipChainId {
   uint64_t id;
 
   bool operator==(const WrClipChainId& other) const { return id == other.id; }
 
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -472,16 +472,44 @@ pub enum WrAnimationType {
 }
 
 #[repr(C)]
 pub struct WrAnimationProperty {
     effect_type: WrAnimationType,
     id: 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,
+  DropShadow = 9,
+  ColorMatrix = 10,
+  SrgbToLinear = 11,
+  LinearToSrgb = 12,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct WrFilterOp {
+    filter_type: WrFilterOpType,
+    argument: c_float, // holds radius for DropShadow; value for other filters
+    offset: LayoutVector2D, // only used for DropShadow
+    color: ColorF, // only used for DropShadow
+    matrix: [f32;20], // only used in ColorMatrix
+}
+
 /// cbindgen:derive-eq=false
 #[repr(C)]
 #[derive(Debug)]
 pub struct WrTransformProperty {
     pub id: u64,
     pub transform: LayoutTransform,
 }
 
@@ -1879,26 +1907,42 @@ pub extern "C" fn wr_dp_push_stacking_co
                                               spatial_id: WrSpatialId,
                                               clip_node_id: *const WrClipId,
                                               animation: *const WrAnimationProperty,
                                               opacity: *const f32,
                                               transform: *const LayoutTransform,
                                               transform_style: TransformStyle,
                                               perspective: *const LayoutTransform,
                                               mix_blend_mode: MixBlendMode,
-                                              filters: *const FilterOp,
+                                              filters: *const WrFilterOp,
                                               filter_count: usize,
                                               is_backface_visible: bool,
                                               glyph_raster_space: RasterSpace,
                                               ) -> WrSpatialId {
     debug_assert!(unsafe { !is_in_render_thread() });
 
     let c_filters = make_slice(filters, filter_count);
     let mut filters : Vec<FilterOp> = c_filters.iter().map(|c_filter| {
-                                                           *c_filter
+        match c_filter.filter_type {
+            WrFilterOpType::Blur => FilterOp::Blur(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), c_filter.argument),
+            WrFilterOpType::Saturate => FilterOp::Saturate(c_filter.argument),
+            WrFilterOpType::Sepia => FilterOp::Sepia(c_filter.argument),
+            WrFilterOpType::DropShadow => FilterOp::DropShadow(c_filter.offset,
+                                                               c_filter.argument,
+                                                               c_filter.color),
+            WrFilterOpType::ColorMatrix => FilterOp::ColorMatrix(c_filter.matrix),
+            WrFilterOpType::SrgbToLinear => FilterOp::SrgbToLinear,
+            WrFilterOpType::LinearToSrgb => FilterOp::LinearToSrgb,
+        }
     }).collect();
 
     let clip_node_id_ref = unsafe { clip_node_id.as_ref() };
 
     let transform_ref = unsafe { transform.as_ref() };
     let mut transform_binding = match transform_ref {
         Some(transform) => Some(PropertyBinding::Value(transform.clone())),
         None => None,
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -239,16 +239,34 @@ enum class WrExternalImageBufferType {
 enum class WrExternalImageType : uint32_t {
   RawData,
   NativeTexture,
   Invalid,
 
   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,
+  DropShadow = 9,
+  ColorMatrix = 10,
+  SrgbToLinear = 11,
+  LinearToSrgb = 12,
+
+  Sentinel /* this must be last for serialization purposes. */
+};
+
 enum class YuvColorSpace : uint32_t {
   Rec601 = 0,
   Rec709 = 1,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
 template<typename T>
@@ -894,395 +912,22 @@ struct TypedTransform3D {
            m42 == aOther.m42 &&
            m43 == aOther.m43 &&
            m44 == aOther.m44;
   }
 };
 
 using LayoutTransform = TypedTransform3D<float, LayoutPixel, LayoutPixel>;
 
-struct PropertyBindingId {
-  IdNamespace namespace_;
-  uint32_t uid;
-
-  bool operator==(const PropertyBindingId& aOther) const {
-    return namespace_ == aOther.namespace_ &&
-           uid == aOther.uid;
-  }
-};
-
-/// A unique key that is used for connecting animated property
-/// values to bindings in the display list.
-template<typename T>
-struct PropertyBindingKey {
-  PropertyBindingId id;
-
-  bool operator==(const PropertyBindingKey& aOther) const {
-    return id == aOther.id;
-  }
-};
-
-/// A binding property can either be a specific value
-/// (the normal, non-animated case) or point to a binding location
-/// to fetch the current value from.
-/// Note that Binding has also a non-animated value, the value is
-/// used for the case where the animation is still in-delay phase
-/// (i.e. the animation doesn't produce any animation values).
-template<typename T>
-struct PropertyBinding {
-  enum class Tag {
-    Value,
-    Binding,
-
-    Sentinel /* this must be last for serialization purposes. */
-  };
-
-  struct Value_Body {
-    T _0;
-
-    bool operator==(const Value_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct Binding_Body {
-    PropertyBindingKey<T> _0;
-    T _1;
-
-    bool operator==(const Binding_Body& aOther) const {
-      return _0 == aOther._0 &&
-             _1 == aOther._1;
-    }
-  };
-
-  Tag tag;
-  union {
-    Value_Body value;
-    Binding_Body binding;
-  };
-
-  static PropertyBinding Value(const T &a0) {
-    PropertyBinding result;
-    result.value._0 = a0;
-    result.tag = Tag::Value;
-    return result;
-  }
-
-  static PropertyBinding Binding(const PropertyBindingKey<T> &a0,
-                                 const T &a1) {
-    PropertyBinding result;
-    result.binding._0 = a0;
-    result.binding._1 = a1;
-    result.tag = Tag::Binding;
-    return result;
-  }
-
-  bool IsValue() const {
-    return tag == Tag::Value;
-  }
-
-  bool IsBinding() const {
-    return tag == Tag::Binding;
-  }
-
-  bool operator==(const PropertyBinding& aOther) const {
-    if (tag != aOther.tag) {
-      return false;
-    }
-    switch (tag) {
-      case Tag::Value: return value == aOther.value;
-      case Tag::Binding: return binding == aOther.binding;
-      default: return true;
-    }
-  }
-};
-
-struct FilterOp {
-  enum class Tag {
-    /// Filter that does no transformation of the colors, needed for
-    /// debug purposes only.
-    Identity,
-    Blur,
-    Brightness,
-    Contrast,
-    Grayscale,
-    HueRotate,
-    Invert,
-    Opacity,
-    Saturate,
-    Sepia,
-    DropShadow,
-    ColorMatrix,
-    SrgbToLinear,
-    LinearToSrgb,
-
-    Sentinel /* this must be last for serialization purposes. */
-  };
-
-  struct Blur_Body {
-    float _0;
-
-    bool operator==(const Blur_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct Brightness_Body {
-    float _0;
-
-    bool operator==(const Brightness_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct Contrast_Body {
-    float _0;
-
-    bool operator==(const Contrast_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct Grayscale_Body {
-    float _0;
-
-    bool operator==(const Grayscale_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct HueRotate_Body {
-    float _0;
-
-    bool operator==(const HueRotate_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct Invert_Body {
-    float _0;
-
-    bool operator==(const Invert_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct Opacity_Body {
-    PropertyBinding<float> _0;
-    float _1;
-
-    bool operator==(const Opacity_Body& aOther) const {
-      return _0 == aOther._0 &&
-             _1 == aOther._1;
-    }
-  };
-
-  struct Saturate_Body {
-    float _0;
-
-    bool operator==(const Saturate_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct Sepia_Body {
-    float _0;
-
-    bool operator==(const Sepia_Body& aOther) const {
-      return _0 == aOther._0;
-    }
-  };
-
-  struct DropShadow_Body {
-    LayoutVector2D _0;
-    float _1;
-    ColorF _2;
-
-    bool operator==(const DropShadow_Body& aOther) const {
-      return _0 == aOther._0 &&
-             _1 == aOther._1 &&
-             _2 == aOther._2;
-    }
-  };
-
-  struct ColorMatrix_Body {
-    float _0[20];
-  };
-
-  Tag tag;
-  union {
-    Blur_Body blur;
-    Brightness_Body brightness;
-    Contrast_Body contrast;
-    Grayscale_Body grayscale;
-    HueRotate_Body hue_rotate;
-    Invert_Body invert;
-    Opacity_Body opacity;
-    Saturate_Body saturate;
-    Sepia_Body sepia;
-    DropShadow_Body drop_shadow;
-    ColorMatrix_Body color_matrix;
-  };
-
-  static FilterOp Identity() {
-    FilterOp result;
-    result.tag = Tag::Identity;
-    return result;
-  }
-
-  static FilterOp Blur(const float &a0) {
-    FilterOp result;
-    result.blur._0 = a0;
-    result.tag = Tag::Blur;
-    return result;
-  }
-
-  static FilterOp Brightness(const float &a0) {
-    FilterOp result;
-    result.brightness._0 = a0;
-    result.tag = Tag::Brightness;
-    return result;
-  }
-
-  static FilterOp Contrast(const float &a0) {
-    FilterOp result;
-    result.contrast._0 = a0;
-    result.tag = Tag::Contrast;
-    return result;
-  }
-
-  static FilterOp Grayscale(const float &a0) {
-    FilterOp result;
-    result.grayscale._0 = a0;
-    result.tag = Tag::Grayscale;
-    return result;
-  }
-
-  static FilterOp HueRotate(const float &a0) {
-    FilterOp result;
-    result.hue_rotate._0 = a0;
-    result.tag = Tag::HueRotate;
-    return result;
-  }
-
-  static FilterOp Invert(const float &a0) {
-    FilterOp result;
-    result.invert._0 = a0;
-    result.tag = Tag::Invert;
-    return result;
-  }
-
-  static FilterOp Opacity(const PropertyBinding<float> &a0,
-                          const float &a1) {
-    FilterOp result;
-    result.opacity._0 = a0;
-    result.opacity._1 = a1;
-    result.tag = Tag::Opacity;
-    return result;
-  }
-
-  static FilterOp Saturate(const float &a0) {
-    FilterOp result;
-    result.saturate._0 = a0;
-    result.tag = Tag::Saturate;
-    return result;
-  }
-
-  static FilterOp Sepia(const float &a0) {
-    FilterOp result;
-    result.sepia._0 = a0;
-    result.tag = Tag::Sepia;
-    return result;
-  }
-
-  static FilterOp DropShadow(const LayoutVector2D &a0,
-                             const float &a1,
-                             const ColorF &a2) {
-    FilterOp result;
-    result.drop_shadow._0 = a0;
-    result.drop_shadow._1 = a1;
-    result.drop_shadow._2 = a2;
-    result.tag = Tag::DropShadow;
-    return result;
-  }
-
-  static FilterOp ColorMatrix(const float (&a0)[20]) {
-    FilterOp result;
-    for (int i = 0; i < 20; i++) {result.color_matrix._0[i] = a0[i];}
-    result.tag = Tag::ColorMatrix;
-    return result;
-  }
-
-  static FilterOp SrgbToLinear() {
-    FilterOp result;
-    result.tag = Tag::SrgbToLinear;
-    return result;
-  }
-
-  static FilterOp LinearToSrgb() {
-    FilterOp result;
-    result.tag = Tag::LinearToSrgb;
-    return result;
-  }
-
-  bool IsIdentity() const {
-    return tag == Tag::Identity;
-  }
-
-  bool IsBlur() const {
-    return tag == Tag::Blur;
-  }
-
-  bool IsBrightness() const {
-    return tag == Tag::Brightness;
-  }
-
-  bool IsContrast() const {
-    return tag == Tag::Contrast;
-  }
-
-  bool IsGrayscale() const {
-    return tag == Tag::Grayscale;
-  }
-
-  bool IsHueRotate() const {
-    return tag == Tag::HueRotate;
-  }
-
-  bool IsInvert() const {
-    return tag == Tag::Invert;
-  }
-
-  bool IsOpacity() const {
-    return tag == Tag::Opacity;
-  }
-
-  bool IsSaturate() const {
-    return tag == Tag::Saturate;
-  }
-
-  bool IsSepia() const {
-    return tag == Tag::Sepia;
-  }
-
-  bool IsDropShadow() const {
-    return tag == Tag::DropShadow;
-  }
-
-  bool IsColorMatrix() const {
-    return tag == Tag::ColorMatrix;
-  }
-
-  bool IsSrgbToLinear() const {
-    return tag == Tag::SrgbToLinear;
-  }
-
-  bool IsLinearToSrgb() const {
-    return tag == Tag::LinearToSrgb;
-  }
+struct WrFilterOp {
+  WrFilterOpType filter_type;
+  float argument;
+  LayoutVector2D offset;
+  ColorF color;
+  float matrix[20];
 };
 
 /// Configure whether the contents of a stacking context
 /// should be rasterized in local space or screen space.
 /// Local space rasterized pictures are typically used
 /// when we want to cache the output, and performance is
 /// important. Note that this is a performance hint only,
 /// which WR may choose to ignore.
@@ -1939,17 +1584,17 @@ WrSpatialId wr_dp_push_stacking_context(
                                         WrSpatialId aSpatialId,
                                         const WrClipId *aClipNodeId,
                                         const WrAnimationProperty *aAnimation,
                                         const float *aOpacity,
                                         const LayoutTransform *aTransform,
                                         TransformStyle aTransformStyle,
                                         const LayoutTransform *aPerspective,
                                         MixBlendMode aMixBlendMode,
-                                        const FilterOp *aFilters,
+                                        const WrFilterOp *aFilters,
                                         uintptr_t aFilterCount,
                                         bool aIsBackfaceVisible,
                                         RasterSpace aGlyphRasterSpace)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_push_text(WrState *aState,
                      LayoutRect aBounds,
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -6040,17 +6040,17 @@ void PresShell::Paint(nsView* aViewToPai
 
   if (layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
     nsPresContext* pc = GetPresContext();
     LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
         pc->GetVisibleArea(), pc->AppUnitsPerDevPixel());
     bgcolor = NS_ComposeColors(bgcolor, mCanvasBackgroundColor);
     WebRenderBackgroundData data(wr::ToLayoutRect(bounds),
                                  wr::ToColorF(ToDeviceColor(bgcolor)));
-    nsTArray<wr::FilterOp> wrFilters;
+    nsTArray<wr::WrFilterOp> wrFilters;
 
     MaybeSetupTransactionIdAllocator(layerManager, presContext);
     layerManager->AsWebRenderLayerManager()->EndTransactionWithoutLayer(
         nullptr, nullptr, wrFilters, &data);
     return;
   }
 
   RefPtr<ColorLayer> root = layerManager->CreateColorLayer();
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2611,22 +2611,24 @@ already_AddRefed<LayerManager> nsDisplay
         }
         // This must be called even if PluginGeometryUpdates were not computed.
         rootPresContext->CollectPluginGeometryUpdates(layerManager);
       }
 
       auto* wrManager = static_cast<WebRenderLayerManager*>(layerManager.get());
 
       nsIDocShell* docShell = presContext->GetDocShell();
-      nsTArray<wr::FilterOp> wrFilters;
+      nsTArray<wr::WrFilterOp> wrFilters;
       gfx::Matrix5x4* colorMatrix =
           nsDocShell::Cast(docShell)->GetColorMatrix();
       if (colorMatrix) {
-        wrFilters.AppendElement(
-            wr::FilterOp::ColorMatrix(colorMatrix->components));
+        wr::WrFilterOp gs = {wr::WrFilterOpType::ColorMatrix};
+        MOZ_ASSERT(sizeof(gs.matrix) == sizeof(colorMatrix->components));
+        memcpy(&(gs.matrix), colorMatrix->components, sizeof(gs.matrix));
+        wrFilters.AppendElement(gs);
       }
 
       wrManager->EndTransactionWithoutLayer(this, aBuilder, wrFilters);
     }
 
     // For layers-free mode, we check the invalidation state bits in the
     // EndTransaction. So we clear the invalidation state bits after
     // EndTransaction.
@@ -6063,17 +6065,17 @@ bool nsDisplayOpacity::CreateWebRenderCo
 
   uint64_t animationsId = AddAnimationsForWebRender(
       this, eCSSProperty_opacity, aManager, aDisplayListBuilder);
   wr::WrAnimationProperty prop{
       wr::WrAnimationType::Opacity,
       animationsId,
   };
 
-  nsTArray<mozilla::wr::FilterOp> filters;
+  nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
                            filters, LayoutDeviceRect(), nullptr,
                            animationsId ? &prop : nullptr, opacityForSC);
 
   aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(
       &mList, this, aDisplayListBuilder, sc, aBuilder, aResources);
   return true;
 }
@@ -6102,17 +6104,17 @@ LayerState nsDisplayBlendMode::GetLayerS
 }
 
 bool nsDisplayBlendMode::CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc,
     mozilla::layers::RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
-  nsTArray<mozilla::wr::FilterOp> filters;
+  nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
                            filters, LayoutDeviceRect(), nullptr, nullptr,
                            nullptr, nullptr, nullptr,
                            nsCSSRendering::GetGFXBlendMode(mBlendMode));
 
   return nsDisplayWrapList::CreateWebRenderCommands(
       aBuilder, aResources, sc, aManager, aDisplayListBuilder);
 }
@@ -6334,17 +6336,17 @@ bool nsDisplayOwnLayer::CreateWebRenderC
   animationInfo.EnsureAnimationsId();
   mWrAnimationId = animationInfo.GetCompositorAnimationsId();
 
   wr::WrAnimationProperty prop;
   prop.id = mWrAnimationId;
   prop.effect_type = wr::WrAnimationType::Transform;
 
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
-                           nsTArray<wr::FilterOp>(), LayoutDeviceRect(),
+                           nsTArray<wr::WrFilterOp>(), LayoutDeviceRect(),
                            nullptr, &prop);
 
   nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                              aDisplayListBuilder);
   return true;
 }
 
 bool nsDisplayOwnLayer::UpdateScrollData(
@@ -7851,17 +7853,17 @@ bool nsDisplayTransform::CreateWebRender
 
   uint64_t animationsId = AddAnimationsForWebRender(
       this, eCSSProperty_transform, aManager, aDisplayListBuilder);
   wr::WrAnimationProperty prop{
       wr::WrAnimationType::Transform,
       animationsId,
   };
 
-  nsTArray<mozilla::wr::FilterOp> filters;
+  nsTArray<mozilla::wr::WrFilterOp> filters;
   Maybe<nsDisplayTransform*> deferredTransformItem;
   if (!mFrame->ChildrenHavePerspective()) {
     // If it has perspective, we create a new scroll data via the
     // UpdateScrollData call because that scenario is more complex. Otherwise
     // we can just stash the transform on the StackingContextHelper and
     // apply it to any scroll data that are created inside this
     // nsDisplayTransform.
     deferredTransformItem = Some(this);
@@ -8458,17 +8460,17 @@ bool nsDisplayPerspective::CreateWebRend
               0.0f);
   Point3D roundedOrigin(NS_round(newOrigin.x), NS_round(newOrigin.y), 0);
 
   gfx::Matrix4x4 transformForSC = gfx::Matrix4x4::Translation(roundedOrigin);
 
   nsIFrame* perspectiveFrame =
       mFrame->GetContainingBlock(nsIFrame::SKIP_SCROLLED_FRAME);
 
-  nsTArray<mozilla::wr::FilterOp> filters;
+  nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
                            filters, LayoutDeviceRect(), nullptr, nullptr,
                            nullptr, &transformForSC, &perspectiveMatrix,
                            gfx::CompositionOp::OP_OVER, !BackfaceIsHidden(),
                            perspectiveFrame->Extend3DContext());
 
   return mList.CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                        aDisplayListBuilder);
@@ -9055,17 +9057,17 @@ bool nsDisplayMasksAndClipPaths::CreateW
 
     wr::WrClipId clipId = clip->first();
 
     Maybe<float> opacity = clip->second() == HandleOpacity::Yes
                                ? Some(mFrame->StyleEffects()->mOpacity)
                                : Nothing();
 
     layer.emplace(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
-                  /*aFilters: */ nsTArray<wr::FilterOp>(),
+                  /*aFilters: */ nsTArray<wr::WrFilterOp>(),
                   /*aBounds: */ bounds,
                   /*aBoundTransform: */ nullptr,
                   /*aAnimation: */ nullptr,
                   /*aOpacity: */ opacity.ptrOr(nullptr),
                   /*aTransform: */ nullptr,
                   /*aPerspective: */ nullptr,
                   /*aMixBlendMode: */ gfx::CompositionOp::OP_OVER,
                   /*aBackfaceVisible: */ true,
@@ -9234,92 +9236,83 @@ void nsDisplayFilters::PaintAsLayer(nsDi
 }
 
 static float ClampStdDeviation(float aStdDeviation) {
   // Cap software blur radius for performance reasons.
   return std::min(std::max(0.0f, aStdDeviation), 100.0f);
 }
 
 bool nsDisplayFilters::CreateWebRenderCSSFilters(
-    nsTArray<mozilla::wr::FilterOp>& wrFilters) {
+    nsTArray<mozilla::wr::WrFilterOp>& wrFilters) {
   // All CSS filters are supported by WebRender. SVG filters are not fully
   // supported, those use NS_STYLE_FILTER_URL and are handled separately.
   const nsTArray<nsStyleFilter>& filters = mFrame->StyleEffects()->mFilters;
   for (const nsStyleFilter& filter : filters) {
     switch (filter.GetType()) {
       case NS_STYLE_FILTER_BRIGHTNESS:
-        wrFilters.AppendElement(wr::FilterOp::Brightness(
-            filter.GetFilterParameter().GetFactorOrPercentValue()));
-        break;
       case NS_STYLE_FILTER_CONTRAST:
-        wrFilters.AppendElement(wr::FilterOp::Contrast(
-            filter.GetFilterParameter().GetFactorOrPercentValue()));
-        break;
       case NS_STYLE_FILTER_GRAYSCALE:
-        wrFilters.AppendElement(wr::FilterOp::Grayscale(
-            filter.GetFilterParameter().GetFactorOrPercentValue()));
-        break;
       case NS_STYLE_FILTER_INVERT:
-        wrFilters.AppendElement(wr::FilterOp::Invert(
-            filter.GetFilterParameter().GetFactorOrPercentValue()));
-        break;
-      case NS_STYLE_FILTER_OPACITY: {
-        float opacity = filter.GetFilterParameter().GetFactorOrPercentValue();
-        wrFilters.AppendElement(wr::FilterOp::Opacity(
-            wr::PropertyBinding<float>::Value(opacity), opacity));
-        break;
-      }
+      case NS_STYLE_FILTER_OPACITY:
       case NS_STYLE_FILTER_SATURATE:
-        wrFilters.AppendElement(wr::FilterOp::Saturate(
-            filter.GetFilterParameter().GetFactorOrPercentValue()));
-        break;
       case NS_STYLE_FILTER_SEPIA: {
-        wrFilters.AppendElement(wr::FilterOp::Sepia(
-            filter.GetFilterParameter().GetFactorOrPercentValue()));
+        mozilla::wr::WrFilterOp filterOp = {
+            wr::ToWrFilterOpType(filter.GetType()),
+            filter.GetFilterParameter().GetFactorOrPercentValue(),
+        };
+        wrFilters.AppendElement(filterOp);
         break;
       }
       case NS_STYLE_FILTER_HUE_ROTATE: {
-        wrFilters.AppendElement(wr::FilterOp::HueRotate(
-            (float)filter.GetFilterParameter().GetAngleValueInDegrees()));
+        mozilla::wr::WrFilterOp filterOp = {
+            wr::ToWrFilterOpType(filter.GetType()),
+            (float)filter.GetFilterParameter().GetAngleValueInDegrees(),
+        };
+        wrFilters.AppendElement(filterOp);
         break;
       }
       case NS_STYLE_FILTER_BLUR: {
         float appUnitsPerDevPixel =
             mFrame->PresContext()->AppUnitsPerDevPixel();
-        wrFilters.AppendElement(mozilla::wr::FilterOp::Blur(ClampStdDeviation(
-            NSAppUnitsToFloatPixels(filter.GetFilterParameter().GetCoordValue(),
-                                    appUnitsPerDevPixel))));
+        mozilla::wr::WrFilterOp filterOp = {
+            wr::ToWrFilterOpType(filter.GetType()),
+            ClampStdDeviation(NSAppUnitsToFloatPixels(
+                filter.GetFilterParameter().GetCoordValue(),
+                appUnitsPerDevPixel)),
+        };
+        wrFilters.AppendElement(filterOp);
         break;
       }
       case NS_STYLE_FILTER_DROP_SHADOW: {
         float appUnitsPerDevPixel =
             mFrame->PresContext()->AppUnitsPerDevPixel();
         nsCSSShadowArray* shadows = filter.GetDropShadow();
         if (!shadows || shadows->Length() != 1) {
           MOZ_ASSERT_UNREACHABLE(
               "Exactly one drop shadow should have been "
               "parsed.");
           return false;
         }
 
         nsCSSShadowItem* shadow = shadows->ShadowAt(0);
         nscolor color = shadow->mColor.CalcColor(mFrame);
 
-        auto filterOp = wr::FilterOp::DropShadow(
+        mozilla::wr::WrFilterOp filterOp = {
+            wr::ToWrFilterOpType(filter.GetType()),
+            NSAppUnitsToFloatPixels(shadow->mRadius, appUnitsPerDevPixel),
             {
                 NSAppUnitsToFloatPixels(shadow->mXOffset, appUnitsPerDevPixel),
                 NSAppUnitsToFloatPixels(shadow->mYOffset, appUnitsPerDevPixel),
             },
-            NSAppUnitsToFloatPixels(shadow->mRadius, appUnitsPerDevPixel),
             {
                 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(filterOp);
         break;
       }
       default:
         return false;
     }
   }
@@ -9336,17 +9329,17 @@ bool nsDisplayFilters::CreateWebRenderCo
   bool snap;
   float auPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   nsRect displayBounds = GetBounds(aDisplayListBuilder, &snap);
   auto postFilterBounds = LayoutDeviceIntRect::Round(
       LayoutDeviceRect::FromAppUnits(displayBounds, auPerDevPixel));
   auto preFilterBounds = LayoutDeviceIntRect::Round(
       LayoutDeviceRect::FromAppUnits(mBounds, auPerDevPixel));
 
-  nsTArray<mozilla::wr::FilterOp> wrFilters;
+  nsTArray<mozilla::wr::WrFilterOp> wrFilters;
   if (!CreateWebRenderCSSFilters(wrFilters) &&
       !nsSVGIntegrationUtils::BuildWebRenderFilters(
           mFrame, preFilterBounds, wrFilters, postFilterBounds)) {
     return false;
   }
 
   wr::WrClipId clipId =
       aBuilder.DefineClip(Nothing(), wr::ToLayoutRect(postFilterBounds));
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -6347,17 +6347,17 @@ class nsDisplayFilters : public nsDispla
 
   bool CreateWebRenderCommands(
       mozilla::wr::DisplayListBuilder& aBuilder,
       mozilla::wr::IpcResourceUpdateQueue& aResources,
       const StackingContextHelper& aSc,
       mozilla::layers::RenderRootStateManager* aManager,
       nsDisplayListBuilder* aDisplayListBuilder) override;
 
-  bool CreateWebRenderCSSFilters(nsTArray<mozilla::wr::FilterOp>& wrFilters);
+  bool CreateWebRenderCSSFilters(nsTArray<mozilla::wr::WrFilterOp>& wrFilters);
 
  private:
   // relative to mFrame
   nsRect mEffectsBounds;
 };
 
 /* A display item that applies a transformation to all of its descendant
  * elements.  This wrapper should only be used if there is a transform applied
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -90,17 +90,17 @@ void nsFilterInstance::PaintFilteredFram
                             nullptr, nullptr, nullptr);
   if (instance.IsInitialized()) {
     instance.Render(aCtx, aImgParams, aOpacity);
   }
 }
 
 bool nsFilterInstance::BuildWebRenderFilters(
     nsIFrame* aFilteredFrame, const LayoutDeviceIntRect& aPreFilterBounds,
-    nsTArray<wr::FilterOp>& aWrFilters,
+    nsTArray<wr::WrFilterOp>& aWrFilters,
     LayoutDeviceIntRect& aPostFilterBounds) {
   aWrFilters.Clear();
 
   auto& filterChain = aFilteredFrame->StyleEffects()->mFilters;
   UniquePtr<UserSpaceMetrics> metrics =
       UserSpaceMetricsForFrame(aFilteredFrame);
 
   // TODO: simply using an identity matrix here, was pulling the scale from a
@@ -140,20 +140,22 @@ bool nsFilterInstance::BuildWebRenderFil
   bool filterIsAffectedByPrimSubregion = false;
 
   for (const auto& primitive : instance.mFilterDescription.mPrimitives) {
     chainIsAffectedByPrimSubregion |= filterIsAffectedByPrimSubregion;
     filterIsAffectedByPrimSubregion = false;
 
     bool primIsSrgb = primitive.OutputColorSpace() == gfx::ColorSpace::SRGB;
     if (srgb && !primIsSrgb) {
-      aWrFilters.AppendElement(wr::FilterOp::SrgbToLinear());
+      wr::WrFilterOp filterOp = {wr::WrFilterOpType::SrgbToLinear};
+      aWrFilters.AppendElement(filterOp);
       srgb = false;
     } else if (!srgb && primIsSrgb) {
-      aWrFilters.AppendElement(wr::FilterOp::LinearToSrgb());
+      wr::WrFilterOp filterOp = {wr::WrFilterOpType::LinearToSrgb};
+      aWrFilters.AppendElement(filterOp);
       srgb = true;
     }
 
     const PrimitiveAttributes& attr = primitive.Attributes();
     auto subregion = LayoutDeviceIntRect::FromUnknownRect(
         primitive.PrimitiveSubregion() +
         aPreFilterBounds.TopLeft().ToUnknownPoint());
 
@@ -173,18 +175,18 @@ bool nsFilterInstance::BuildWebRenderFil
         return false;
       }
     }
 
     bool filterIsNoop = false;
 
     if (attr.is<OpacityAttributes>()) {
       float opacity = attr.as<OpacityAttributes>().mOpacity;
-      aWrFilters.AppendElement(wr::FilterOp::Opacity(
-          wr::PropertyBinding<float>::Value(opacity), opacity));
+      wr::WrFilterOp filterOp = {wr::WrFilterOpType::Opacity, opacity};
+      aWrFilters.AppendElement(filterOp);
     } else if (attr.is<ColorMatrixAttributes>()) {
       const ColorMatrixAttributes& attributes =
           attr.as<ColorMatrixAttributes>();
 
       float transposed[20];
       if (!gfx::ComputeColorMatrix(attributes, transposed)) {
         filterIsNoop = true;
         continue;
@@ -206,17 +208,19 @@ bool nsFilterInstance::BuildWebRenderFil
 
       float matrix[20] = {
           transposed[0], transposed[5], transposed[10], transposed[15],
           transposed[1], transposed[6], transposed[11], transposed[16],
           transposed[2], transposed[7], transposed[12], transposed[17],
           transposed[3], transposed[8], transposed[13], transposed[18],
           transposed[4], transposed[9], transposed[14], transposed[19]};
 
-      aWrFilters.AppendElement(wr::FilterOp::ColorMatrix(matrix));
+      wr::WrFilterOp filterOp = {wr::WrFilterOpType::ColorMatrix};
+      PodCopy(filterOp.matrix, matrix, 20);
+      aWrFilters.AppendElement(filterOp);
     } else if (attr.is<GaussianBlurAttributes>()) {
       if (chainIsAffectedByPrimSubregion) {
         // There's a clip that needs to apply before the blur filter, but
         // WebRender only lets us apply the clip at the end of the filter
         // chain. Clipping after a blur is not equivalent to clipping before
         // a blur, so bail out.
         return false;
       }
@@ -225,61 +229,66 @@ bool nsFilterInstance::BuildWebRenderFil
 
       const Size& stdDev = blur.mStdDeviation;
       if (stdDev.width != stdDev.height) {
         return false;
       }
 
       float radius = stdDev.width;
       if (radius != 0.0) {
-        aWrFilters.AppendElement(wr::FilterOp::Blur(radius));
+        wr::WrFilterOp filterOp = {wr::WrFilterOpType::Blur, radius};
+        aWrFilters.AppendElement(filterOp);
       } else {
         filterIsNoop = true;
       }
     } else if (attr.is<DropShadowAttributes>()) {
       if (chainIsAffectedByPrimSubregion) {
         // We have to bail out for the same reason we would with a blur filter.
         return false;
       }
 
       const DropShadowAttributes& shadow = attr.as<DropShadowAttributes>();
 
       const Size& stdDev = shadow.mStdDeviation;
       if (stdDev.width != stdDev.height) {
         return false;
       }
 
-      wr::LayoutVector2D offset = {(float)shadow.mOffset.x,
-                                   (float)shadow.mOffset.y};
       float radius = stdDev.width;
-      wr::FilterOp filterOp =
-          wr::FilterOp::DropShadow(offset, radius, wr::ToColorF(shadow.mColor));
+      wr::WrFilterOp filterOp = {
+          wr::WrFilterOpType::DropShadow,
+          radius,
+          {(float)shadow.mOffset.x, (float)shadow.mOffset.y},
+          wr::ToColorF(shadow.mColor)};
 
       aWrFilters.AppendElement(filterOp);
     } else {
       return false;
     }
 
     if (filterIsNoop && aWrFilters.Length() > 0 &&
-        (aWrFilters.LastElement().tag == wr::FilterOp::Tag::SrgbToLinear ||
-         aWrFilters.LastElement().tag == wr::FilterOp::Tag::LinearToSrgb)) {
+        (aWrFilters.LastElement().filter_type ==
+             wr::WrFilterOpType::SrgbToLinear ||
+         aWrFilters.LastElement().filter_type ==
+             wr::WrFilterOpType::LinearToSrgb)) {
       // We pushed a color space conversion filter in prevision of applying
       // another filter which turned out to be a no-op, so the conversion is
       // unnecessary. Remove it from the filter list.
       // This is both an optimization and a way to pass the wptest
       // css/filter-effects/filter-scale-001.html for which the needless
       // sRGB->linear->no-op->sRGB roundtrip introduces a slight error and we
       // cannot add fuzziness to the test.
       Unused << aWrFilters.PopLastElement();
       srgb = !srgb;
     }
   }
 
   if (!srgb) {
-    aWrFilters.AppendElement(wr::FilterOp::LinearToSrgb());
+    wr::WrFilterOp filterOp = {wr::WrFilterOpType::LinearToSrgb};
+    aWrFilters.AppendElement(filterOp);
   }
 
   // Only adjust the post filter clip if we are able to render this without
   // fallback.
   if (finalClip.isSome()) {
     aPostFilterBounds = finalClip.value();
   }
 
--- a/layout/svg/nsFilterInstance.h
+++ b/layout/svg/nsFilterInstance.h
@@ -120,17 +120,17 @@ class nsFilterInstance {
 
   /**
    * Try to build WebRender filters for a frame if the filters applied to it are
    * supported.
    */
   static bool BuildWebRenderFilters(
       nsIFrame* aFilteredFrame,
       const mozilla::LayoutDeviceIntRect& aPreFilterBounds,
-      nsTArray<mozilla::wr::FilterOp>& aWrFilters,
+      nsTArray<mozilla::wr::WrFilterOp>& aWrFilters,
       mozilla::LayoutDeviceIntRect& aPostFilterBounds);
 
  private:
   /**
    * @param aTargetFrame The frame of the filtered element under consideration,
    *   may be null.
    * @param aTargetContent The filtered element itself.
    * @param aMetrics The metrics to resolve SVG lengths against.
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -1091,17 +1091,17 @@ void nsSVGIntegrationUtils::PaintFilter(
 
   nsFilterInstance::PaintFilteredFrame(frame, &context, &callback, &dirtyRegion,
                                        aParams.imgParams, opacity);
 }
 
 bool nsSVGIntegrationUtils::BuildWebRenderFilters(
     nsIFrame* aFilteredFrame,
     const mozilla::LayoutDeviceIntRect& aPreFilterBounds,
-    nsTArray<mozilla::wr::FilterOp>& aWrFilters,
+    nsTArray<mozilla::wr::WrFilterOp>& aWrFilters,
     mozilla::LayoutDeviceIntRect& aPostFilterBounds) {
   return nsFilterInstance::BuildWebRenderFilters(
       aFilteredFrame, aPreFilterBounds, aWrFilters, aPostFilterBounds);
 }
 
 class PaintFrameCallback : public gfxDrawingCallback {
  public:
   PaintFrameCallback(nsIFrame* aFrame, const nsSize aPaintServerSize,
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -193,17 +193,17 @@ class nsSVGIntegrationUtils final {
 
   /**
    * Try to build WebRender filters for a frame if the filters applied to it are
    * supported.
    */
   static bool BuildWebRenderFilters(
       nsIFrame* aFilteredFrame,
       const mozilla::LayoutDeviceIntRect& aPreFilterBounds,
-      nsTArray<mozilla::wr::FilterOp>& aWrFilters,
+      nsTArray<mozilla::wr::WrFilterOp>& aWrFilters,
       mozilla::LayoutDeviceIntRect& aPostFilterBounds);
 
   /**
    * @param aRenderingContext the target rendering context in which the paint
    * server will be rendered
    * @param aTarget the target frame onto which the paint server will be
    * rendered
    * @param aPaintServer a first-continuation frame to use as the source