tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */