Bug 1359842 - Add a StackingContextHelper to reduce duplicated code. r=nical
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 27 Apr 2017 12:04:25 -0400
changeset 355199 ddeda3ad6b14fc4a9bbbf430d2020fa1c09f918c
parent 355198 3e288b211e767296b3960222da2a48a484f0df00
child 355200 007c9fb80cfa99da87b670f88e6f1a60e8c66326
push id31723
push userkwierso@gmail.com
push dateThu, 27 Apr 2017 18:22:49 +0000
treeherdermozilla-central@c5c2b95e9d7b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1359842
milestone55.0a1
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
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
gfx/layers/moz.build
gfx/layers/wr/StackingContextHelper.cpp
gfx/layers/wr/StackingContextHelper.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderCanvasLayer.cpp
gfx/layers/wr/WebRenderColorLayer.cpp
gfx/layers/wr/WebRenderImageLayer.cpp
gfx/layers/wr/WebRenderLayer.h
gfx/layers/wr/WebRenderPaintedLayer.cpp
--- 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/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -2,16 +2,17 @@
 /* vim: set sw=4 ts=8 et tw=80 : */
 /* 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/WebRenderBridgeParent.h"
 
 #include "CompositableHost.h"
+#include "gfxPrefs.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "mozilla/Range.h"
 #include "mozilla/layers/AnimationHelper.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorThread.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 {
 
@@ -158,47 +159,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;
   }