1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef GFX_STACKINGCONTEXTHELPER_H 8 #define GFX_STACKINGCONTEXTHELPER_H 9 10 #include "mozilla/Attributes.h" 11 #include "mozilla/gfx/MatrixFwd.h" 12 #include "mozilla/webrender/WebRenderAPI.h" 13 #include "mozilla/webrender/WebRenderTypes.h" 14 #include "Units.h" 15 #include "nsSVGIntegrationUtils.h" // for WrFiltersHolder 16 17 class nsDisplayTransform; 18 19 namespace mozilla { 20 21 struct ActiveScrolledRoot; 22 23 namespace layers { 24 25 /** 26 * This is a helper class that pushes/pops a stacking context, and manages 27 * some of the coordinate space transformations needed. 28 */ 29 class MOZ_RAII StackingContextHelper { 30 public: 31 StackingContextHelper(const StackingContextHelper& aParentSC, 32 const ActiveScrolledRoot* aAsr, 33 nsIFrame* aContainerFrame, 34 nsDisplayItem* aContainerItem, 35 wr::DisplayListBuilder& aBuilder, 36 const wr::StackingContextParams& aParams, 37 const LayoutDeviceRect& aBounds = LayoutDeviceRect()); 38 39 // This version of the constructor should only be used at the root level 40 // of the tree, so that we have a StackingContextHelper to pass down into 41 // the RenderLayer traversal, but don't actually want it to push a stacking 42 // context on the display list builder. 43 StackingContextHelper(); 44 45 // Pops the stacking context, if one was pushed during the constructor. 46 ~StackingContextHelper(); 47 48 // Export the inherited scale GetInheritedScale()49 gfx::Size GetInheritedScale() const { return mScale; } 50 GetInheritedTransform()51 const gfx::Matrix& GetInheritedTransform() const { 52 return mInheritedTransform; 53 } 54 GetSnappingSurfaceTransform()55 const gfx::Matrix& GetSnappingSurfaceTransform() const { 56 return mSnappingSurfaceTransform; 57 } 58 59 const Maybe<nsDisplayTransform*>& GetDeferredTransformItem() const; 60 Maybe<gfx::Matrix4x4> GetDeferredTransformMatrix() const; 61 AffectsClipPositioning()62 bool AffectsClipPositioning() const { return mAffectsClipPositioning; } ReferenceFrameId()63 Maybe<wr::WrSpatialId> ReferenceFrameId() const { return mReferenceFrameId; } 64 GetOrigin()65 const LayoutDevicePoint& GetOrigin() const { return mOrigin; } 66 67 private: 68 wr::DisplayListBuilder* mBuilder; 69 gfx::Size mScale; 70 gfx::Matrix mInheritedTransform; 71 LayoutDevicePoint mOrigin; 72 73 // The "snapping surface" defines the space that we want to snap in. 74 // You can think of it as the nearest physical surface. 75 // Animated transforms create a new snapping surface, so that changes to their 76 // transform don't affect the snapping of their contents. Non-animated 77 // transforms do *not* create a new snapping surface, so that for example the 78 // existence of a non-animated identity transform does not affect snapping. 79 gfx::Matrix mSnappingSurfaceTransform; 80 bool mAffectsClipPositioning; 81 Maybe<wr::WrSpatialId> mReferenceFrameId; 82 Maybe<wr::SpaceAndClipChainHelper> mSpaceAndClipChainHelper; 83 84 // The deferred transform item is used when building the WebRenderScrollData 85 // structure. The backstory is that APZ needs to know about transforms that 86 // apply to the different APZC instances. Prior to bug 1423370, we would do 87 // this by creating a new WebRenderLayerScrollData for each nsDisplayTransform 88 // item we encountered. However, this was unnecessarily expensive because it 89 // turned out a lot of nsDisplayTransform items didn't have new ASRs defined 90 // as descendants, so we'd create the WebRenderLayerScrollData and send it 91 // over to APZ even though the transform information was not needed in that 92 // case. 93 // 94 // In bug 1423370 and friends, this was optimized by "deferring" a 95 // nsDisplayTransform item when we encountered it during display list 96 // traversal. If we found a descendant of that transform item that had a 97 // new ASR or otherwise was "relevant to APZ", we would then pluck the 98 // transform matrix off the deferred item and put it on the 99 // WebRenderLayerScrollData instance created for that APZ-relevant descendant. 100 // 101 // One complication with this is if there are multiple nsDisplayTransform 102 // items in the ancestor chain for the APZ-relevant item. As we traverse the 103 // display list, we will defer the outermost nsDisplayTransform item, and when 104 // we encounter the next one we will need to merge it with the already- 105 // deferred one somehow. What we do in this case is have 106 // mDeferredTransformItem always point to the "innermost" deferred transform 107 // item (i.e. the closest ancestor nsDisplayTransform item of the item that 108 // created this StackingContextHelper). And then we use 109 // mDeferredAncestorTransform to store the product of all the other transforms 110 // that were deferred. As a result, there is an invariant here that if 111 // mDeferredTransformItem is Nothing(), mDeferredAncestorTransform will also 112 // be Nothing(). Note that we can only do this if the nsDisplayTransform items 113 // share the same ASR. If we are processing an nsDisplayTransform item with a 114 // different ASR than the previously-deferred item, we assume that the 115 // previously-deferred transform will get sent to APZ as part of a separate 116 // WebRenderLayerScrollData item, and so we don't need to bother with any 117 // merging. (The merging probably wouldn't even make sense because the 118 // coordinate spaces might be different in the face of async scrolling). This 119 // behaviour of forcing a WebRenderLayerScrollData item to be generated when 120 // the ASR changes is implemented in 121 // WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList. 122 Maybe<nsDisplayTransform*> mDeferredTransformItem; 123 Maybe<gfx::Matrix4x4> mDeferredAncestorTransform; 124 125 bool mRasterizeLocally; 126 }; 127 128 } // namespace layers 129 } // namespace mozilla 130 131 #endif /* GFX_STACKINGCONTEXTHELPER_H */ 132