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