diff --git a/gfx/layers/ipc/WebRenderMessages.ipdlh b/gfx/layers/ipc/WebRenderMessages.ipdlh index 962a8a032aef..bb608d4493cf 100644 --- a/gfx/layers/ipc/WebRenderMessages.ipdlh +++ b/gfx/layers/ipc/WebRenderMessages.ipdlh @@ -15,6 +15,7 @@ using WrTextureFilter from "mozilla/webrender/webrender_ffi.h"; using WrLayoutSize from "mozilla/webrender/webrender_ffi.h"; using WrRect from "mozilla/webrender/webrender_ffi.h"; using WrGlyphArray from "mozilla/webrender/webrender_ffi.h"; +using WrMixBlendMode from "mozilla/webrender/webrender_ffi.h"; using MaybeImageMask from "mozilla/webrender/WebRenderTypes.h"; using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h"; using mozilla::wr::ByteBuffer from "mozilla/webrender/WebRenderTypes.h"; @@ -30,6 +31,7 @@ struct OpDPPushStackingContext { MaybeImageMask mask; Animation[] animations; Matrix4x4 matrix; + WrMixBlendMode mixBlendMode; uint64_t scrollid; }; diff --git a/gfx/layers/wr/WebRenderBorderLayer.cpp b/gfx/layers/wr/WebRenderBorderLayer.cpp index 22a13b594238..95c9ba22679a 100644 --- a/gfx/layers/wr/WebRenderBorderLayer.cpp +++ b/gfx/layers/wr/WebRenderBorderLayer.cpp @@ -9,6 +9,7 @@ #include "mozilla/gfx/Rect.h" #include "mozilla/webrender/webrender_ffi.h" #include "mozilla/layers/WebRenderBridgeChild.h" +#include "mozilla/webrender/WebRenderTypes.h" namespace mozilla { namespace layers { @@ -39,6 +40,7 @@ WebRenderBorderLayer::RenderLayer() Nothing(), GetAnimations(), transform, + WrMixBlendMode::Normal, FrameMetrics::NULL_SCROLL_ID)); WrBridge()->AddWebRenderCommand( diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 57053ba3f5dc..e696e5207d21 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -311,7 +311,7 @@ WebRenderBridgeParent::ProcessWebrenderCommands(InfallibleTArray mask = buildMaskLayer(); WrTextureFilter filter = (mSamplingFilter == gfx::SamplingFilter::POINT) ? WrTextureFilter::Point : WrTextureFilter::Linear; + WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode()); WrBridge()->AddWebRenderCommand( OpDPPushStackingContext(wr::ToWrRect(relBounds), @@ -83,6 +84,7 @@ WebRenderCanvasLayer::RenderLayer() mask, GetAnimations(), transform, + mixBlendMode, FrameMetrics::NULL_SCROLL_ID)); WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(LayerIntRegion(), wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, mExternalImageId)); WrBridge()->AddWebRenderCommand(OpDPPopStackingContext()); diff --git a/gfx/layers/wr/WebRenderColorLayer.cpp b/gfx/layers/wr/WebRenderColorLayer.cpp index 018a776628cf..4e8bb2cc102f 100644 --- a/gfx/layers/wr/WebRenderColorLayer.cpp +++ b/gfx/layers/wr/WebRenderColorLayer.cpp @@ -7,6 +7,7 @@ #include "LayersLogging.h" #include "mozilla/webrender/webrender_ffi.h" +#include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/layers/WebRenderBridgeChild.h" namespace mozilla { @@ -32,6 +33,7 @@ WebRenderColorLayer::RenderLayer() gfx::Matrix4x4 transform;// = GetTransform(); gfx::Rect relBounds = TransformedVisibleBoundsRelativeToParent(); gfx::Rect overflow(0, 0, relBounds.width, relBounds.height); + WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode()); Maybe mask = buildMaskLayer(); @@ -41,6 +43,7 @@ WebRenderColorLayer::RenderLayer() mask, GetAnimations(), transform, + mixBlendMode, FrameMetrics::NULL_SCROLL_ID)); WrBridge()->AddWebRenderCommand( OpDPPushRect(wr::ToWrRect(rect), wr::ToWrRect(clip), mColor.r, mColor.g, mColor.b, mColor.a)); diff --git a/gfx/layers/wr/WebRenderContainerLayer.cpp b/gfx/layers/wr/WebRenderContainerLayer.cpp index 0ee7d5570066..f9bdd08269d1 100644 --- a/gfx/layers/wr/WebRenderContainerLayer.cpp +++ b/gfx/layers/wr/WebRenderContainerLayer.cpp @@ -7,6 +7,7 @@ #include #include "mozilla/layers/WebRenderBridgeChild.h" +#include "mozilla/webrender/WebRenderTypes.h" #include "LayersLogging.h" namespace mozilla { @@ -23,6 +24,8 @@ WebRenderContainerLayer::RenderLayer() gfx::Rect overflow(0, 0, relBounds.width, relBounds.height); gfx::Matrix4x4 transform;// = GetTransform(); if (gfxPrefs::LayersDump()) printf_stderr("ContainerLayer %p using %s as bounds, %s as overflow, %s as transform\n", this, Stringify(relBounds).c_str(), Stringify(overflow).c_str(), Stringify(transform).c_str()); + WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode()); + Maybe mask = buildMaskLayer(); @@ -32,6 +35,7 @@ WebRenderContainerLayer::RenderLayer() mask, GetLayer()->GetAnimations(), transform, + mixBlendMode, FrameMetrics::NULL_SCROLL_ID)); for (LayerPolygon& child : children) { if (child.layer->IsBackfaceHidden()) { diff --git a/gfx/layers/wr/WebRenderImageLayer.cpp b/gfx/layers/wr/WebRenderImageLayer.cpp index 4f3d8e7b882b..840c2e95a494 100644 --- a/gfx/layers/wr/WebRenderImageLayer.cpp +++ b/gfx/layers/wr/WebRenderImageLayer.cpp @@ -144,6 +144,7 @@ WebRenderImageLayer::RenderLayer() Matrix4x4 transform;// = GetTransform(); Maybe mask = buildMaskLayer(); WrTextureFilter filter = (mSamplingFilter == gfx::SamplingFilter::POINT) ? WrTextureFilter::Point : WrTextureFilter::Linear; + WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode()); WrBridge()->AddWebRenderCommand( OpDPPushStackingContext(wr::ToWrRect(relBounds), @@ -151,6 +152,7 @@ WebRenderImageLayer::RenderLayer() mask, GetAnimations(), transform, + mixBlendMode, FrameMetrics::NULL_SCROLL_ID)); WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(LayerIntRegion(), wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, mExternalImageId)); WrBridge()->AddWebRenderCommand(OpDPPopStackingContext()); diff --git a/gfx/layers/wr/WebRenderLayerManager.cpp b/gfx/layers/wr/WebRenderLayerManager.cpp index 79dfccd5dc61..521967271241 100644 --- a/gfx/layers/wr/WebRenderLayerManager.cpp +++ b/gfx/layers/wr/WebRenderLayerManager.cpp @@ -163,6 +163,7 @@ WrScrollFrameStackingContextGenerator::WrScrollFrameStackingContextGenerator( Nothing(), layer->GetAnimations(), identity, + WrMixBlendMode::Normal, fm.GetScrollId())); } } diff --git a/gfx/layers/wr/WebRenderMessageUtils.h b/gfx/layers/wr/WebRenderMessageUtils.h index 7b0451c2557d..5de29efdbaf0 100644 --- a/gfx/layers/wr/WebRenderMessageUtils.h +++ b/gfx/layers/wr/WebRenderMessageUtils.h @@ -272,6 +272,15 @@ struct ParamTraits { }; +template<> +struct ParamTraits + : public ContiguousEnumSerializer< + WrMixBlendMode, + WrMixBlendMode::Normal, + WrMixBlendMode::Sentinel> +{ +}; + } // namespace IPC #endif // GFX_WEBRENDERMESSAGEUTILS_H diff --git a/gfx/layers/wr/WebRenderPaintedLayer.cpp b/gfx/layers/wr/WebRenderPaintedLayer.cpp index 10bf922ef4f6..16fbaf3de63f 100644 --- a/gfx/layers/wr/WebRenderPaintedLayer.cpp +++ b/gfx/layers/wr/WebRenderPaintedLayer.cpp @@ -143,6 +143,7 @@ WebRenderPaintedLayer::RenderLayer() Rect relBounds = TransformedVisibleBoundsRelativeToParent(); Rect overflow(0, 0, relBounds.width, relBounds.height); Matrix4x4 transform;// = GetTransform(); + WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode()); WrBridge()->AddWebRenderCommand( OpDPPushStackingContext(wr::ToWrRect(relBounds), @@ -150,6 +151,7 @@ WebRenderPaintedLayer::RenderLayer() mask, GetAnimations(), transform, + mixBlendMode, FrameMetrics::NULL_SCROLL_ID)); ContentClientRemoteBuffer* contentClientRemote = static_cast(mContentClient.get()); diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp index 5646c178e547..19a29608c87f 100644 --- a/gfx/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -300,10 +300,11 @@ void DisplayListBuilder::PushStackingContext(const WrRect& aBounds, const WrRect& aOverflow, const WrImageMask* aMask, - const gfx::Matrix4x4& aTransform) + const gfx::Matrix4x4& aTransform, + const WrMixBlendMode& aMixBlendMode) { wr_dp_push_stacking_context(mWrState, aBounds, aOverflow, aMask, - &aTransform.components[0]); + &aTransform.components[0], aMixBlendMode); } void diff --git a/gfx/webrender_bindings/WebRenderAPI.h b/gfx/webrender_bindings/WebRenderAPI.h index 016693f565be..d8250c09a75f 100644 --- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -108,7 +108,8 @@ public: void PushStackingContext(const WrRect& aBounds, // TODO: We should work with strongly typed rects const WrRect& aOverflow, const WrImageMask* aMask, // TODO: needs a wrapper. - const gfx::Matrix4x4& aTransform); + const gfx::Matrix4x4& aTransform, + const WrMixBlendMode& aMixBlendMode); void PopStackingContext(); diff --git a/gfx/webrender_bindings/WebRenderTypes.h b/gfx/webrender_bindings/WebRenderTypes.h index c67df599385a..29daca5b1086 100644 --- a/gfx/webrender_bindings/WebRenderTypes.h +++ b/gfx/webrender_bindings/WebRenderTypes.h @@ -8,6 +8,7 @@ #include "mozilla/webrender/webrender_ffi.h" #include "mozilla/Maybe.h" +#include "mozilla/gfx/Types.h" // The infrastructure and plumbing to use the render thread is not entirely in // place yet. In order to land code and work in parallel we have to maintain @@ -28,6 +29,45 @@ typedef mozilla::Maybe MaybeImageMask; namespace mozilla { namespace wr { +static inline WrMixBlendMode ToWrMixBlendMode(gfx::CompositionOp compositionOp) +{ + switch (compositionOp) + { + case gfx::CompositionOp::OP_MULTIPLY: + return WrMixBlendMode::Multiply; + case gfx::CompositionOp::OP_SCREEN: + return WrMixBlendMode::Screen; + case gfx::CompositionOp::OP_OVERLAY: + return WrMixBlendMode::Overlay; + case gfx::CompositionOp::OP_DARKEN: + return WrMixBlendMode::Darken; + case gfx::CompositionOp::OP_LIGHTEN: + return WrMixBlendMode::Lighten; + case gfx::CompositionOp::OP_COLOR_DODGE: + return WrMixBlendMode::ColorDodge; + case gfx::CompositionOp::OP_COLOR_BURN: + return WrMixBlendMode::ColorBurn; + case gfx::CompositionOp::OP_HARD_LIGHT: + return WrMixBlendMode::HardLight; + case gfx::CompositionOp::OP_SOFT_LIGHT: + return WrMixBlendMode::SoftLight; + case gfx::CompositionOp::OP_DIFFERENCE: + return WrMixBlendMode::Difference; + case gfx::CompositionOp::OP_EXCLUSION: + return WrMixBlendMode::Exclusion; + case gfx::CompositionOp::OP_HUE: + return WrMixBlendMode::Hue; + case gfx::CompositionOp::OP_SATURATION: + return WrMixBlendMode::Saturation; + case gfx::CompositionOp::OP_COLOR: + return WrMixBlendMode::Color; + case gfx::CompositionOp::OP_LUMINOSITY: + return WrMixBlendMode::Luminosity; + default: + return WrMixBlendMode::Normal; + } +} + static inline WrColor ToWrColor(const gfx::Color& color) { WrColor c; diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 0a22dbbe6fe6..488a603e16c3 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -8,7 +8,7 @@ use gleam::gl; use webrender_traits::{BorderSide, BorderStyle, BorderRadius}; use webrender_traits::{PipelineId, ClipRegion}; use webrender_traits::{Epoch, ColorF, GlyphInstance}; -use webrender_traits::{ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, RendererKind}; +use webrender_traits::{ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, RendererKind, MixBlendMode}; use webrender_traits::{ExternalImageId, RenderApi, FontKey}; use webrender_traits::{DeviceUintSize, ExternalEvent}; use webrender_traits::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform}; @@ -401,6 +401,53 @@ impl ExternalImageHandler for WrExternalImageHandler { } } +#[repr(C)] +pub enum WrMixBlendMode +{ + Normal, + Multiply, + Screen, + Overlay, + Darken, + Lighten, + ColorDodge, + ColorBurn, + HardLight, + SoftLight, + Difference, + Exclusion, + Hue, + Saturation, + Color, + Luminosity, +} + +impl WrMixBlendMode +{ + pub fn to_mix_blend_mode(self) -> MixBlendMode + { + match self + { + WrMixBlendMode::Normal => MixBlendMode::Normal, + WrMixBlendMode::Multiply => MixBlendMode::Multiply, + WrMixBlendMode::Screen => MixBlendMode::Screen, + WrMixBlendMode::Overlay => MixBlendMode::Overlay, + WrMixBlendMode::Darken => MixBlendMode::Darken, + WrMixBlendMode::Lighten => MixBlendMode::Lighten, + WrMixBlendMode::ColorDodge => MixBlendMode::ColorDodge, + WrMixBlendMode::ColorBurn => MixBlendMode::ColorBurn, + WrMixBlendMode::HardLight => MixBlendMode::HardLight, + WrMixBlendMode::SoftLight => MixBlendMode::SoftLight, + WrMixBlendMode::Difference => MixBlendMode::Difference, + WrMixBlendMode::Exclusion => MixBlendMode::Exclusion, + WrMixBlendMode::Hue => MixBlendMode::Hue, + WrMixBlendMode::Saturation => MixBlendMode::Saturation, + WrMixBlendMode::Color => MixBlendMode::Color, + WrMixBlendMode::Luminosity => MixBlendMode::Luminosity, + } + } +} + // TODO: Remove. #[no_mangle] pub extern fn wr_init_window(root_pipeline_id: u64, @@ -489,14 +536,14 @@ pub extern fn wr_window_dp_begin(window: &mut WrWindowState, state: &mut WrState } #[no_mangle] -pub extern fn wr_dp_push_stacking_context(state:&mut WrState, bounds: WrRect, overflow: WrRect, mask: *const WrImageMask, transform: &LayoutTransform) +pub extern fn wr_dp_push_stacking_context(state:&mut WrState, bounds: WrRect, overflow: WrRect, mask: *const WrImageMask, transform: &LayoutTransform, mix_blend_mode: WrMixBlendMode) { assert!( unsafe { is_in_compositor_thread() }); state.z_index += 1; let bounds = bounds.to_rect(); let overflow = overflow.to_rect(); - + let mix_blend_mode = mix_blend_mode.to_mix_blend_mode(); // convert from the C type to the Rust type let mask = unsafe { mask.as_ref().map(|&WrImageMask{image, ref rect,repeat}| ImageMask{image: image, rect: rect.to_rect(), repeat: repeat}) }; @@ -508,7 +555,7 @@ pub extern fn wr_dp_push_stacking_context(state:&mut WrState, bounds: WrRect, ov state.z_index, transform, &LayoutTransform::identity(), - webrender_traits::MixBlendMode::Normal, + mix_blend_mode, Vec::new()); } diff --git a/gfx/webrender_bindings/webrender_ffi.h b/gfx/webrender_bindings/webrender_ffi.h index 562960f1f7e2..ce43c6f1a5d5 100644 --- a/gfx/webrender_bindings/webrender_ffi.h +++ b/gfx/webrender_bindings/webrender_ffi.h @@ -178,6 +178,27 @@ struct WrExternalImageIdHandler { ReleaseExternalImageCallback release_func; }; +enum class WrMixBlendMode +{ + Normal, + Multiply, + Screen, + Overlay, + Darken, + Lighten, + ColorDodge, + ColorBurn, + HardLight, + SoftLight, + Difference, + Exclusion, + Hue, + Saturation, + Color, + Luminosity, + Sentinel, +}; + struct WrWindowState; #ifdef MOZ_ENABLE_WEBRENDER @@ -303,7 +324,7 @@ WR_FUNC; WR_INLINE void wr_dp_push_stacking_context(WrState *wrState, WrRect bounds, WrRect overflow, const WrImageMask *mask, - const float* matrix) + const float* matrix, WrMixBlendMode mixBlendMode) WR_FUNC; //XXX: matrix should use a proper type