DisplayItemCache.h (6029B)
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_DISPLAY_ITEM_CACHE_H 8 #define GFX_DISPLAY_ITEM_CACHE_H 9 10 #include "mozilla/webrender/WebRenderAPI.h" 11 #include "nsTArray.h" 12 13 namespace mozilla { 14 15 class nsDisplayList; 16 class nsDisplayListBuilder; 17 class nsPaintedDisplayItem; 18 19 namespace wr { 20 class DisplayListBuilder; 21 } // namespace wr 22 23 namespace layers { 24 25 class CacheStats { 26 public: 27 CacheStats() = default; 28 29 void Reset() { mCached = mReused = mTotal = 0; } 30 31 void Print() { 32 static uint64_t avgC = 1; 33 static uint64_t avgR = 1; 34 static uint64_t avgT = 1; 35 36 avgC += mCached; 37 avgR += mReused; 38 avgT += mTotal; 39 40 printf("Cached: %zu (avg: %f), Reused: %zu (avg: %f), Total: %zu\n", 41 mCached, (double)avgC / (double)avgT, mReused, 42 (double)avgR / (double)avgT, mTotal); 43 } 44 45 void AddCached() { mCached++; } 46 void AddReused() { mReused++; } 47 void AddTotal() { mTotal++; } 48 49 private: 50 size_t mCached = 0; 51 size_t mReused = 0; 52 size_t mTotal = 0; 53 }; 54 55 /** 56 * DisplayItemCache keeps track of which Gecko display items have already had 57 * their respective WebRender display items sent to WebRender backend. 58 * 59 * Ideally creating the WR display items for a Gecko display item would not 60 * depend on any external state. However currently pipeline id, clip id, and 61 * spatial id can change between display lists, even if the Gecko display items 62 * have not. This state is tracked by DisplayItemCache. 63 */ 64 class DisplayItemCache final { 65 public: 66 DisplayItemCache(); 67 68 /** 69 * Clears the cache. 70 */ 71 void Clear(); 72 73 /** 74 * Sets the initial and max cache size to given |aInitialSize| and |aMaxSize|. 75 */ 76 void SetCapacity(const size_t aInitialSize, const size_t aMaximumSize); 77 78 /** 79 * Sets the display list used by the cache. 80 */ 81 void SetDisplayList(nsDisplayListBuilder* aBuilder, nsDisplayList* aList); 82 83 /** 84 * Sets the pipeline id used by the cache. 85 */ 86 void SetPipelineId(const wr::PipelineId& aPipelineId); 87 88 /** 89 * Enables caching immediately if the cache is valid, and display list is set. 90 */ 91 void SkipWaitingForPartialDisplayList() { 92 mCaching = mDisplayList && !mInvalid; 93 } 94 95 /** 96 * Returns true if display item caching is enabled, otherwise false. 97 */ 98 bool IsEnabled() const { return !mSuppressed && mMaximumSize > 0; } 99 100 /** 101 * Suppress display item caching. This doesn't clear any existing cached 102 * items or change the underlying capacity, it just makes IsEnabled() return 103 * false. 104 * It will also make CanReuseItem return false for the duration of the 105 * suppression. 106 */ 107 bool SetSuppressed(bool aSuppressed) { 108 if (aSuppressed == mSuppressed) { 109 return mSuppressed; 110 } 111 mSuppressed = aSuppressed; 112 return !mSuppressed; 113 } 114 115 /** 116 * Returns true if there are no cached items, otherwise false. 117 */ 118 bool IsEmpty() const { return mFreeSlots.Length() == CurrentSize(); } 119 120 /** 121 * Returns true if the cache has reached the maximum size, otherwise false. 122 */ 123 bool IsFull() const { 124 return mFreeSlots.IsEmpty() && CurrentSize() == mMaximumSize; 125 } 126 127 /** 128 * Returns the current cache size. 129 */ 130 size_t CurrentSize() const { return mSlots.Length(); } 131 132 /** 133 * If there are free slots in the cache, assigns a cache slot to the given 134 * display item |aItem| and returns it. Otherwise returns Nothing(). 135 */ 136 Maybe<uint16_t> AssignSlot(nsPaintedDisplayItem* aItem); 137 138 /** 139 * Marks the slot with the given |slotIndex| occupied and used. 140 * Also stores the current space and clipchain |aSpaceAndClip|. 141 */ 142 void MarkSlotOccupied(uint16_t slotIndex, 143 const wr::WrSpaceAndClipChain& aSpaceAndClip); 144 145 /** 146 * Returns the slot index of the the given display item |aItem|, if the item 147 * can be reused. The current space and clipchain |aSpaceAndClip| is used to 148 * check whether the cached item is still valid. 149 * If the item cannot be reused, returns Nothing(). 150 */ 151 Maybe<uint16_t> CanReuseItem(nsPaintedDisplayItem* aItem, 152 const wr::WrSpaceAndClipChain& aSpaceAndClip); 153 154 CacheStats& Stats() { return mCacheStats; } 155 156 private: 157 struct Slot { 158 Slot() : mSpaceAndClip{}, mOccupied(false), mUsed(false) {} 159 160 wr::WrSpaceAndClipChain mSpaceAndClip; 161 bool mOccupied; 162 bool mUsed; 163 }; 164 165 void FreeUnusedSlots(); 166 Maybe<uint16_t> GetNextFreeSlot(); 167 bool GrowIfPossible(); 168 void UpdateState(); 169 170 // The lifetime of display lists exceed the lifetime of DisplayItemCache. 171 // This pointer stores the address of the display list that is using this 172 // cache, and it is only used for pointer comparisons. 173 nsDisplayList* mDisplayList; 174 175 size_t mMaximumSize; 176 nsTArray<Slot> mSlots; 177 nsTArray<uint16_t> mFreeSlots; 178 179 wr::PipelineId mPipelineId; 180 bool mCaching; 181 bool mInvalid; 182 bool mSuppressed; 183 184 CacheStats mCacheStats; 185 }; 186 187 class MOZ_RAII AutoDisplayItemCacheSuppressor { 188 public: 189 explicit AutoDisplayItemCacheSuppressor(DisplayItemCache* aCache) 190 : mCache(aCache) { 191 mWasSuppressed = !mCache || mCache->SetSuppressed(true); 192 } 193 194 // Note that this restores the original state rather than unconditionally 195 // unsuppressing the cache for future-proofing/robustification. Currently 196 // we only ever use this RAII in one non-recursive function, but we might 197 // decide to expand its usage to other scenarios and end up with nested 198 // suppressions, in which case restoring the state back to what we found it 199 // is better. 200 ~AutoDisplayItemCacheSuppressor() { 201 if (mCache) { 202 mCache->SetSuppressed(mWasSuppressed); 203 } 204 } 205 206 private: 207 DisplayItemCache* mCache; 208 bool mWasSuppressed; 209 }; 210 211 } // namespace layers 212 } // namespace mozilla 213 214 #endif /* GFX_DISPLAY_ITEM_CACHE_H */