RetainedDisplayListHelpers.h (5446B)
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 RETAINEDDISPLAYLISTHELPERS_H_ 8 #define RETAINEDDISPLAYLISTHELPERS_H_ 9 10 #include "PLDHashTable.h" 11 #include "mozilla/Span.h" 12 13 class nsIFrame; 14 15 namespace mozilla { 16 17 struct DisplayItemKey { 18 bool operator==(const DisplayItemKey&) const = default; 19 20 nsIFrame* mFrame; 21 uint32_t mPerFrameKey; 22 }; 23 24 class DisplayItemHashEntry : public PLDHashEntryHdr { 25 public: 26 typedef DisplayItemKey KeyType; 27 typedef const DisplayItemKey* KeyTypePointer; 28 29 explicit DisplayItemHashEntry(KeyTypePointer aKey) : mKey(*aKey) {} 30 DisplayItemHashEntry(DisplayItemHashEntry&&) = default; 31 32 ~DisplayItemHashEntry() = default; 33 34 KeyType GetKey() const { return mKey; } 35 bool KeyEquals(KeyTypePointer aKey) const { return mKey == *aKey; } 36 37 static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; } 38 static PLDHashNumber HashKey(KeyTypePointer aKey) { 39 if (!aKey) { 40 return 0; 41 } 42 43 return mozilla::HashGeneric(aKey->mFrame, aKey->mPerFrameKey); 44 } 45 enum { ALLOW_MEMMOVE = true }; 46 47 DisplayItemKey mKey; 48 }; 49 50 template <typename T> 51 bool SpanContains(mozilla::Span<const T>& aSpan, T aItem) { 52 for (const T& i : aSpan) { 53 if (i == aItem) { 54 return true; 55 } 56 } 57 return false; 58 } 59 60 class OldListUnits {}; 61 class MergedListUnits {}; 62 63 template <typename Units> 64 struct Index { 65 Index() = default; 66 explicit Index(size_t aVal) : val(aVal) { 67 MOZ_RELEASE_ASSERT(aVal < std::numeric_limits<uint32_t>::max(), 68 "List index overflowed"); 69 } 70 71 bool operator==(const Index<Units>&) const = default; 72 73 uint32_t val = 0; 74 }; 75 typedef Index<OldListUnits> OldListIndex; 76 typedef Index<MergedListUnits> MergedListIndex; 77 78 template <typename T> 79 class DirectedAcyclicGraph { 80 public: 81 DirectedAcyclicGraph() = default; 82 DirectedAcyclicGraph(DirectedAcyclicGraph&& aOther) 83 : mNodesInfo(std::move(aOther.mNodesInfo)), 84 mDirectPredecessorList(std::move(aOther.mDirectPredecessorList)) {} 85 86 DirectedAcyclicGraph& operator=(DirectedAcyclicGraph&& aOther) { 87 mNodesInfo = std::move(aOther.mNodesInfo); 88 mDirectPredecessorList = std::move(aOther.mDirectPredecessorList); 89 return *this; 90 } 91 92 Index<T> AddNode( 93 mozilla::Span<const Index<T>> aDirectPredecessors, 94 const mozilla::Maybe<Index<T>>& aExtraPredecessor = mozilla::Nothing()) { 95 size_t index = mNodesInfo.Length(); 96 mNodesInfo.AppendElement(NodeInfo(mDirectPredecessorList.Length(), 97 aDirectPredecessors.Length())); 98 if (aExtraPredecessor && 99 !SpanContains(aDirectPredecessors, aExtraPredecessor.value())) { 100 mNodesInfo.LastElement().mDirectPredecessorCount++; 101 mDirectPredecessorList.SetCapacity(mDirectPredecessorList.Length() + 102 aDirectPredecessors.Length() + 1); 103 mDirectPredecessorList.AppendElements(aDirectPredecessors); 104 mDirectPredecessorList.AppendElement(aExtraPredecessor.value()); 105 } else { 106 mDirectPredecessorList.AppendElements(aDirectPredecessors); 107 } 108 return Index<T>(index); 109 } 110 111 size_t Length() { return mNodesInfo.Length(); } 112 113 mozilla::Span<Index<T>> GetDirectPredecessors(Index<T> aNodeIndex) { 114 NodeInfo& node = mNodesInfo[aNodeIndex.val]; 115 const auto span = mozilla::Span{mDirectPredecessorList}; 116 return span.Subspan(node.mIndexInDirectPredecessorList, 117 node.mDirectPredecessorCount); 118 } 119 120 template <typename OtherUnits> 121 void EnsureCapacityFor(const DirectedAcyclicGraph<OtherUnits>& aOther) { 122 mNodesInfo.SetCapacity(aOther.mNodesInfo.Length()); 123 mDirectPredecessorList.SetCapacity(aOther.mDirectPredecessorList.Length()); 124 } 125 126 void Clear() { 127 mNodesInfo.Clear(); 128 mDirectPredecessorList.Clear(); 129 } 130 131 struct NodeInfo { 132 NodeInfo(size_t aIndexInDirectPredecessorList, 133 size_t aDirectPredecessorCount) 134 : mIndexInDirectPredecessorList(aIndexInDirectPredecessorList), 135 mDirectPredecessorCount(aDirectPredecessorCount) {} 136 size_t mIndexInDirectPredecessorList; 137 size_t mDirectPredecessorCount; 138 }; 139 140 nsTArray<NodeInfo> mNodesInfo; 141 nsTArray<Index<T>> mDirectPredecessorList; 142 }; 143 144 class RetainedDisplayListBuilder; 145 class nsDisplayItem; 146 147 struct OldItemInfo { 148 explicit OldItemInfo(nsDisplayItem* aItem); 149 150 void AddedToMergedList(MergedListIndex aIndex) { 151 MOZ_ASSERT(!IsUsed()); 152 mUsed = true; 153 mIndex = aIndex; 154 mItem = nullptr; 155 } 156 157 void AddedMatchToMergedList(RetainedDisplayListBuilder* aBuilder, 158 MergedListIndex aIndex); 159 void Discard(RetainedDisplayListBuilder* aBuilder, 160 nsTArray<MergedListIndex>&& aDirectPredecessors); 161 bool IsUsed() { return mUsed; } 162 163 bool IsDiscarded() { 164 MOZ_ASSERT(IsUsed()); 165 return mDiscarded; 166 } 167 168 bool IsChanged(); 169 170 nsDisplayItem* mItem; 171 nsTArray<MergedListIndex> mDirectPredecessors; 172 MergedListIndex mIndex; 173 bool mUsed; 174 bool mDiscarded; 175 bool mOwnsItem; 176 }; 177 178 bool AnyContentAncestorModified(nsIFrame* aFrame, 179 nsIFrame* aStopAtFrame = nullptr); 180 181 } // namespace mozilla 182 183 #endif // RETAINEDDISPLAYLISTHELPERS_H_