Bug 1359842 - Add a StackingContextHelper to reduce duplicated code. r?nical
This class is a RAII class that can be used to push a stacking context
with properties from a WebRenderLayer. It can also then be used to
convert rects in the layer coordinate system to be relative to the
stacking context, which is what we want for passing to WR.
MozReview-Commit-ID: 1WVrfRYqLqc
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -194,16 +194,17 @@ EXPORTS.mozilla.layers += [
'PersistentBufferProvider.h',
'RenderTrace.h',
'SourceSurfaceSharedData.h',
'SourceSurfaceVolatileData.h',
'TextureSourceProvider.h',
'TextureWrapperImage.h',
'TransactionIdAllocator.h',
'UpdateImageHelper.h',
+ 'wr/StackingContextHelper.h',
'wr/WebRenderBridgeChild.h',
'wr/WebRenderBridgeParent.h',
'wr/WebRenderCompositableHolder.h',
'wr/WebRenderDisplayItemLayer.h',
'wr/WebRenderImageHost.h',
'wr/WebRenderLayer.h',
'wr/WebRenderLayerManager.h',
'wr/WebRenderLayersLogging.h',
@@ -388,16 +389,17 @@ UNIFIED_SOURCES += [
'ReadbackProcessor.cpp',
'RenderTrace.cpp',
'RotatedBuffer.cpp',
'ShareableCanvasLayer.cpp',
'SourceSurfaceSharedData.cpp',
'SourceSurfaceVolatileData.cpp',
'TextureSourceProvider.cpp',
'TextureWrapperImage.cpp',
+ 'wr/StackingContextHelper.cpp',
'wr/WebRenderBridgeChild.cpp',
'wr/WebRenderBridgeParent.cpp',
'wr/WebRenderCanvasLayer.cpp',
'wr/WebRenderColorLayer.cpp',
'wr/WebRenderCompositableHolder.cpp',
'wr/WebRenderContainerLayer.cpp',
'wr/WebRenderDisplayItemLayer.cpp',
'wr/WebRenderImageHost.cpp',
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/StackingContextHelper.cpp
@@ -0,0 +1,40 @@
+/* -*- 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 "mozilla/layers/StackingContextHelper.h"
+
+#include "mozilla/layers/WebRenderLayer.h"
+
+namespace mozilla {
+namespace layers {
+
+StackingContextHelper::StackingContextHelper(wr::DisplayListBuilder& aBuilder,
+ WebRenderLayer* aLayer,
+ const Maybe<gfx::Matrix4x4>& aTransform)
+ : mBuilder(&aBuilder)
+{
+ LayerRect scBounds = aLayer->RelativeToParent(aLayer->BoundsForStackingContext());
+ Layer* layer = aLayer->GetLayer();
+ gfx::Matrix4x4 transform = aTransform.valueOr(layer->GetTransform());
+ mBuilder->PushStackingContext(wr::ToWrRect(scBounds),
+ 1.0f,
+ transform,
+ wr::ToWrMixBlendMode(layer->GetMixBlendMode()));
+ mOrigin = aLayer->Bounds().TopLeft();
+}
+
+StackingContextHelper::~StackingContextHelper()
+{
+ mBuilder->PopStackingContext();
+}
+
+WrRect
+StackingContextHelper::ToRelativeWrRect(const LayerRect& aRect)
+{
+ return wr::ToWrRect(aRect - mOrigin);
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/StackingContextHelper.h
@@ -0,0 +1,52 @@
+/* -*- 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/. */
+
+#ifndef GFX_STACKINGCONTEXTHELPER_H
+#define GFX_STACKINGCONTEXTHELPER_H
+
+#include "mozilla/Attributes.h"
+#include "mozilla/gfx/MatrixFwd.h"
+#include "mozilla/webrender/WebRenderAPI.h"
+#include "mozilla/webrender/WebRenderTypes.h"
+#include "Units.h"
+
+namespace mozilla {
+namespace layers {
+
+class WebRenderLayer;
+
+/**
+ * This is a helper class that pushes/pops a stacking context, and manages
+ * some of the coordinate space transformations needed.
+ */
+class MOZ_RAII StackingContextHelper
+{
+public:
+ // Pushes a stacking context onto the provided DisplayListBuilder. It uses
+ // the transform if provided, otherwise takes the transform from the layer.
+ // It also takes the mix-blend-mode and bounds from the layer, and uses 1.0
+ // for the opacity.
+ StackingContextHelper(wr::DisplayListBuilder& aBuilder,
+ WebRenderLayer* aLayer,
+ const Maybe<gfx::Matrix4x4>& aTransform = Nothing());
+ // Pops the stacking context
+ ~StackingContextHelper();
+
+ // When this StackingContextHelper is in scope, this function can be used
+ // to convert a rect from the layer system's coordinate space to a WrRect
+ // that is relative to the stacking context. This is useful because most
+ // things that are pushed inside the stacking context need to be relative
+ // to the stacking context.
+ WrRect ToRelativeWrRect(const LayerRect& aRect);
+
+private:
+ wr::DisplayListBuilder* mBuilder;
+ LayerPoint mOrigin;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif /* GFX_STACKINGCONTEXTHELPER_H */
--- a/gfx/layers/wr/WebRenderCanvasLayer.cpp
+++ b/gfx/layers/wr/WebRenderCanvasLayer.cpp
@@ -7,16 +7,17 @@
#include "AsyncCanvasRenderer.h"
#include "gfxPrefs.h"
#include "gfxUtils.h"
#include "GLContext.h"
#include "GLScreenBuffer.h"
#include "LayersLogging.h"
#include "mozilla/gfx/2D.h"
+#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "PersistentBufferProvider.h"
#include "SharedSurface.h"
#include "SharedSurfaceGL.h"
#include "mozilla/webrender/WebRenderTypes.h"
namespace mozilla {
@@ -49,49 +50,46 @@ void
WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
{
UpdateCompositableClient();
if (mExternalImageId.isNothing()) {
mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mCanvasClient));
}
- gfx::Matrix4x4 transform = GetTransform();
+ Maybe<gfx::Matrix4x4> transform;
const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
if (needsYFlip) {
- transform.PreTranslate(0, mBounds.height, 0).PreScale(1, -1, 1);
+ transform = Some(GetTransform().PreTranslate(0, mBounds.height, 0).PreScale(1, -1, 1));
}
- LayerRect relBounds = GetWrRelBounds();
- LayerRect rect = RelativeToVisible(LayerRect(0, 0, mBounds.width, mBounds.height));
+ StackingContextHelper sc(aBuilder, this, transform);
+
+ LayerRect rect(0, 0, mBounds.width, mBounds.height);
+ DumpLayerInfo("CanvasLayer", rect);
- LayerRect clipRect = GetWrClipRect(rect);
+ LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(true);
- WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect), mask.ptrOr(nullptr));
+ WrClipRegion clip = aBuilder.BuildClipRegion(
+ sc.ToRelativeWrRect(clipRect),
+ mask.ptrOr(nullptr));
wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
- wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
- DumpLayerInfo("CanvasLayer", rect);
if (gfxPrefs::LayersDump()) {
printf_stderr("CanvasLayer %p texture-filter=%s\n",
this->GetLayer(),
Stringify(filter).c_str());
}
WrImageKey key = GetImageKey();
WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId.value(), key));
Manager()->AddImageKeyForDiscard(key);
- aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
- 1.0f,
- transform,
- mixBlendMode);
- aBuilder.PushImage(wr::ToWrRect(rect), clip, filter, key);
- aBuilder.PopStackingContext();
+ aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, key);
}
void
WebRenderCanvasLayer::AttachCompositable()
{
mCanvasClient->Connect();
}
--- a/gfx/layers/wr/WebRenderColorLayer.cpp
+++ b/gfx/layers/wr/WebRenderColorLayer.cpp
@@ -4,40 +4,35 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebRenderColorLayer.h"
#include "gfxPrefs.h"
#include "LayersLogging.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/webrender/WebRenderTypes.h"
+#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
void
WebRenderColorLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
{
- gfx::Matrix4x4 transform = GetTransform();
- LayerRect relBounds = GetWrRelBounds();
- LayerRect rect = GetWrBoundsRect();
+ StackingContextHelper sc(aBuilder, this);
- LayerRect clipRect = GetWrClipRect(rect);
- Maybe<WrImageMask> mask = BuildWrMaskLayer(true);
- WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect), mask.ptrOr(nullptr));
-
- wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
-
+ LayerRect rect = Bounds();
DumpLayerInfo("ColorLayer", rect);
- aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
- 1.0f,
- transform,
- mixBlendMode);
- aBuilder.PushRect(wr::ToWrRect(rect), clip, wr::ToWrColor(mColor));
- aBuilder.PopStackingContext();
+ LayerRect clipRect = ClipRect().valueOr(rect);
+ Maybe<WrImageMask> mask = BuildWrMaskLayer(true);
+ WrClipRegion clip = aBuilder.BuildClipRegion(
+ sc.ToRelativeWrRect(clipRect),
+ mask.ptrOr(nullptr));
+
+ aBuilder.PushRect(sc.ToRelativeWrRect(rect), clip, wr::ToWrColor(mColor));
}
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/wr/WebRenderImageLayer.cpp
+++ b/gfx/layers/wr/WebRenderImageLayer.cpp
@@ -3,16 +3,17 @@
* 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 "WebRenderImageLayer.h"
#include "gfxPrefs.h"
#include "LayersLogging.h"
#include "mozilla/layers/ImageClient.h"
+#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TextureClientRecycleAllocator.h"
#include "mozilla/layers/TextureWrapperImage.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/webrender/WebRenderTypes.h"
namespace mozilla {
namespace layers {
@@ -139,47 +140,41 @@ WebRenderImageLayer::RenderLayer(wr::Dis
mKey,
mExternalImageId.ref());
}
if (mKey.isNothing()) {
return;
}
- gfx::Matrix4x4 transform = GetTransform();
- LayerRect relBounds = GetWrRelBounds();
+ StackingContextHelper sc(aBuilder, this);
LayerRect rect(0, 0, size.width, size.height);
if (mScaleMode != ScaleMode::SCALE_NONE) {
NS_ASSERTION(mScaleMode == ScaleMode::STRETCH,
"No other scalemodes than stretch and none supported yet.");
rect = LayerRect(0, 0, mScaleToSize.width, mScaleToSize.height);
}
- rect = RelativeToVisible(rect);
- LayerRect clipRect = GetWrClipRect(rect);
+ LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(true);
- WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect), mask.ptrOr(nullptr));
+ WrClipRegion clip = aBuilder.BuildClipRegion(
+ sc.ToRelativeWrRect(clipRect),
+ mask.ptrOr(nullptr));
wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
- wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
DumpLayerInfo("Image Layer", rect);
if (gfxPrefs::LayersDump()) {
printf_stderr("ImageLayer %p texture-filter=%s \n",
GetLayer(),
Stringify(filter).c_str());
}
- aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
- 1.0f,
- transform,
- mixBlendMode);
- aBuilder.PushImage(wr::ToWrRect(rect), clip, filter, mKey.value());
- aBuilder.PopStackingContext();
+ aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
}
Maybe<WrImageMask>
WebRenderImageLayer::RenderMaskLayer(const gfx::Matrix4x4& aTransform)
{
if (!mContainer) {
return Nothing();
}
--- a/gfx/layers/wr/WebRenderLayer.h
+++ b/gfx/layers/wr/WebRenderLayer.h
@@ -47,20 +47,21 @@ public:
WrImageKey GetImageKey();
LayerRect RelativeToVisible(const LayerRect& aRect);
LayerRect RelativeToParent(const LayerRect& aRect);
LayerRect RelativeToParent(const LayoutDeviceRect& aRect);
LayerRect VisibleBoundsRelativeToParent();
LayerPoint GetOffsetToParent();
gfx::Rect TransformedVisibleBoundsRelativeToParent();
-protected:
+
LayerRect Bounds();
+ LayerRect BoundsForStackingContext();
+protected:
BoundsTransformMatrix BoundsTransform();
- LayerRect BoundsForStackingContext();
LayerRect ParentBounds();
Maybe<LayerRect> ClipRect();
LayerRect GetWrBoundsRect();
LayerRect GetWrRelBounds();
LayerRect GetWrClipRect(const LayerRect& aRect);
void DumpLayerInfo(const char* aLayerType, const LayerRect& aRect);
Maybe<WrImageMask> BuildWrMaskLayer(bool aUnapplyLayerTransform);
--- a/gfx/layers/wr/WebRenderPaintedLayer.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayer.cpp
@@ -2,16 +2,17 @@
* 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 "WebRenderPaintedLayer.h"
#include "LayersLogging.h"
#include "mozilla/ArrayUtils.h"
+#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/UpdateImageHelper.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "gfxPrefs.h"
#include "gfxUtils.h"
namespace mozilla {
namespace layers {
@@ -85,42 +86,32 @@ WebRenderPaintedLayer::UpdateImageClient
}
return true;
}
void
WebRenderPaintedLayer::CreateWebRenderDisplayList(wr::DisplayListBuilder& aBuilder)
{
- LayerIntRegion visibleRegion = GetVisibleRegion();
- LayerIntRect bounds = visibleRegion.GetBounds();
- LayerIntSize size = bounds.Size();
+ StackingContextHelper sc(aBuilder, this);
- gfx::Matrix4x4 transform = GetTransform();
- LayerRect relBounds = GetWrRelBounds();
- LayerRect rect(0, 0, size.width, size.height);
+ LayerRect rect = Bounds();
+ DumpLayerInfo("PaintedLayer", rect);
- LayerRect clipRect = GetWrClipRect(rect);
+ LayerRect clipRect = ClipRect().valueOr(rect);
Maybe<WrImageMask> mask = BuildWrMaskLayer(true);
- WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect), mask.ptrOr(nullptr));
-
- wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
-
- DumpLayerInfo("PaintedLayer", rect);
+ WrClipRegion clip = aBuilder.BuildClipRegion(
+ sc.ToRelativeWrRect(clipRect),
+ mask.ptrOr(nullptr));
WrImageKey key = GetImageKey();
WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId.value(), key));
Manager()->AddImageKeyForDiscard(key);
- aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
- 1.0f,
- transform,
- mixBlendMode);
- aBuilder.PushImage(wr::ToWrRect(rect), clip, wr::ImageRendering::Auto, key);
- aBuilder.PopStackingContext();
+ aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, wr::ImageRendering::Auto, key);
}
void
WebRenderPaintedLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
{
if (!SetupExternalImages()) {
return;
}