1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_VIZ_CLIENT_FRAME_EVICTION_MANAGER_H_
6 #define COMPONENTS_VIZ_CLIENT_FRAME_EVICTION_MANAGER_H_
7 
8 #include <stddef.h>
9 
10 #include <list>
11 #include <map>
12 
13 #include "base/macros.h"
14 #include "base/memory/memory_pressure_listener.h"
15 #include "base/memory/singleton.h"
16 #include "base/optional.h"
17 #include "components/viz/client/viz_client_export.h"
18 
19 namespace viz {
20 
21 class FrameEvictionManagerClient {
22  public:
~FrameEvictionManagerClient()23   virtual ~FrameEvictionManagerClient() {}
24   virtual void EvictCurrentFrame() = 0;
25 };
26 
27 // This class is responsible for globally managing which renderers keep their
28 // compositor frame when offscreen. We actively discard compositor frames for
29 // offscreen tabs, but keep a minimum amount, as an LRU cache, to make switching
30 // between a small set of tabs faster. The limit is a soft limit, because
31 // clients can lock their frame to prevent it from being discarded, e.g. if the
32 // tab is visible, or while capturing a screenshot.
33 class VIZ_CLIENT_EXPORT FrameEvictionManager {
34  public:
35   // Pauses frame eviction within its scope.
36   class VIZ_CLIENT_EXPORT ScopedPause {
37    public:
38     ScopedPause();
39     ~ScopedPause();
40 
41    private:
42     DISALLOW_COPY_AND_ASSIGN(ScopedPause);
43   };
44 
45   static FrameEvictionManager* GetInstance();
46 
47   void AddFrame(FrameEvictionManagerClient*, bool locked);
48   void RemoveFrame(FrameEvictionManagerClient*);
49   void LockFrame(FrameEvictionManagerClient*);
50   void UnlockFrame(FrameEvictionManagerClient*);
51 
52   size_t GetMaxNumberOfSavedFrames() const;
53 
54   // For testing only
set_max_number_of_saved_frames(size_t max_number_of_saved_frames)55   void set_max_number_of_saved_frames(size_t max_number_of_saved_frames) {
56     max_number_of_saved_frames_ = max_number_of_saved_frames;
57   }
58 
59   // React on memory pressure events to adjust the number of cached frames.
60   // Please make this private when crbug.com/443824 has been fixed.
61   void OnMemoryPressure(
62       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
63 
64   // Purges all unlocked frames, allowing us to reclaim resources.
65   void PurgeAllUnlockedFrames();
66 
67  private:
68   friend struct base::DefaultSingletonTraits<FrameEvictionManager>;
69 
70   FrameEvictionManager();
71   ~FrameEvictionManager();
72 
73   void CullUnlockedFrames(size_t saved_frame_limit);
74 
75   void PurgeMemory(int percentage);
76 
77   // Pauses/unpauses frame eviction.
78   void Pause();
79   void Unpause();
80 
81   // Listens for system under pressure notifications and adjusts number of
82   // cached frames accordingly.
83   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
84 
85   std::map<FrameEvictionManagerClient*, size_t> locked_frames_;
86   std::list<FrameEvictionManagerClient*> unlocked_frames_;
87   size_t max_number_of_saved_frames_;
88 
89   // Counter of the outstanding pauses.
90   int pause_count_ = 0;
91 
92   // Argument of the last CullUnlockedFrames call while paused.
93   base::Optional<size_t> pending_unlocked_frame_limit_;
94 
95   DISALLOW_COPY_AND_ASSIGN(FrameEvictionManager);
96 };
97 
98 }  // namespace viz
99 
100 #endif  // COMPONENTS_VIZ_CLIENT_FRAME_EVICTION_MANAGER_H_
101