Bug 1359842 - Add a StackingContextHelper to reduce duplicated code. r?nical draft
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 26 Apr 2017 16:37:16 -0400
changeset 568973 fca7f45a1451d0bc8bea569642a1e144fbdb04f5
parent 568972 5b30cbc2c96f4f76afc478551b3d6453c95d0f77
child 568974 2a87c0e57690892498f96bd0543ae99870dcfa1d
push id56034
push userkgupta@mozilla.com
push dateWed, 26 Apr 2017 20:37:45 +0000
reviewersnical
bugs1359842
milestone55.0a1
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/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/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;
   }