gpu_memory_manager.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 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 CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
6#define CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
7
8#if defined(ENABLE_GPU)
9
10#include <set>
11#include <vector>
12
13#include "base/basictypes.h"
14#include "base/cancelable_callback.h"
15#include "base/gtest_prod_util.h"
16#include "base/hash_tables.h"
17#include "base/memory/weak_ptr.h"
18#include "content/common/content_export.h"
19#include "content/common/gpu/gpu_memory_allocation.h"
20#include "content/public/common/gpu_memory_stats.h"
21#include "gpu/command_buffer/service/memory_tracking.h"
22#include "ui/gfx/size.h"
23
24namespace content {
25class GpuMemoryManagerClient;
26}
27
28#if defined(COMPILER_GCC)
29namespace BASE_HASH_NAMESPACE {
30template<>
31struct hash<content::GpuMemoryManagerClient*> {
32  size_t operator()(content::GpuMemoryManagerClient* ptr) const {
33    return hash<size_t>()(reinterpret_cast<size_t>(ptr));
34  }
35};
36} // namespace BASE_HASH_NAMESPACE
37#endif // COMPILER
38
39namespace content {
40class GpuMemoryManagerClient;
41class GpuMemoryTrackingGroup;
42
43class CONTENT_EXPORT GpuMemoryManager :
44    public base::SupportsWeakPtr<GpuMemoryManager> {
45 public:
46  enum { kDefaultMaxSurfacesWithFrontbufferSoftLimit = 8 };
47
48  explicit GpuMemoryManager(size_t max_surfaces_with_frontbuffer_soft_limit);
49  ~GpuMemoryManager();
50
51  // Schedule a Manage() call. If immediate is true, we PostTask without delay.
52  // Otherwise PostDelayedTask using a CancelableClosure and allow multiple
53  // delayed calls to "queue" up. This way, we do not spam clients in certain
54  // lower priority situations. An immediate schedule manage will cancel any
55  // queued delayed manage.
56  void ScheduleManage(bool immediate);
57
58  // Retrieve GPU Resource consumption statistics for the task manager
59  void GetVideoMemoryUsageStats(
60      content::GPUVideoMemoryUsageStats& video_memory_usage_stats) const;
61  void SetWindowCount(uint32 count);
62
63  // Add and remove clients
64  void AddClient(GpuMemoryManagerClient* client,
65                 bool has_surface,
66                 bool visible,
67                 base::TimeTicks last_used_time);
68  void RemoveClient(GpuMemoryManagerClient* client);
69  void SetClientVisible(GpuMemoryManagerClient* client, bool visible);
70  void SetClientManagedMemoryStats(GpuMemoryManagerClient* client,
71                                   const GpuManagedMemoryStats& stats);
72
73  // Add and remove structures to track context groups' memory consumption
74  void AddTrackingGroup(GpuMemoryTrackingGroup* tracking_group);
75  void RemoveTrackingGroup(GpuMemoryTrackingGroup* tracking_group);
76
77  // Track a change in memory allocated by any context
78  void TrackMemoryAllocatedChange(size_t old_size, size_t new_size);
79
80 private:
81  friend class GpuMemoryManagerTest;
82  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
83                           ComparatorTests);
84  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
85                           TestManageBasicFunctionality);
86  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
87                           TestManageChangingVisibility);
88  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
89                           TestManageManyVisibleStubs);
90  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
91                           TestManageManyNotVisibleStubs);
92  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
93                           TestManageChangingLastUsedTime);
94  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
95                           TestManageChangingImportanceShareGroup);
96  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
97                           TestForegroundStubsGetBonusAllocation);
98  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
99                           TestUpdateAvailableGpuMemory);
100  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
101                           GpuMemoryAllocationCompareTests);
102  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
103                           StubMemoryStatsForLastManageTests);
104  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
105                           TestManagedUsageTracking);
106  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
107                           TestBackgroundCutoff);
108  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
109                           TestBackgroundMru);
110
111  struct ClientState {
112    ClientState(GpuMemoryManagerClient* client,
113                bool has_surface,
114                bool visible,
115                base::TimeTicks last_used_time);
116    // The client to send allocations to.
117    GpuMemoryManagerClient* client;
118
119    // Offscreen commandbuffers will not have a surface.
120    bool has_surface;
121
122    // The last used time is determined by the last time that visibility
123    // was changed.
124    bool visible;
125    base::TimeTicks last_used_time;
126
127    // Statistics about memory usage.
128    GpuManagedMemoryStats managed_memory_stats;
129
130    // Set to disable allocating a frontbuffer or to disable allocations
131    // for clients that don't have surfaces.
132    bool hibernated;
133  };
134
135  class CONTENT_EXPORT ClientsComparator {
136   public:
137    bool operator()(ClientState* lhs,
138                    ClientState* rhs);
139  };
140
141  typedef std::map<GpuMemoryManagerClient*, ClientState*> ClientMap;
142
143  typedef std::vector<ClientState*> ClientStateVector;
144
145  void Manage();
146  void SetClientsHibernatedState(const ClientStateVector& clients) const;
147  size_t GetVisibleClientAllocation(const ClientStateVector& clients) const;
148  size_t GetCurrentBackgroundedAvailableGpuMemory() const;
149
150  // Update the amount of GPU memory we think we have in the system, based
151  // on what the stubs' contexts report.
152  void UpdateAvailableGpuMemory(const ClientStateVector& clients);
153  void UpdateBackgroundedAvailableGpuMemory();
154
155  // The amount of video memory which is available for allocation.
156  size_t GetAvailableGpuMemory() const;
157
158  // Minimum value of available GPU memory, no matter how little the GPU
159  // reports. This is the default value.
160  size_t GetDefaultAvailableGpuMemory() const;
161
162  // Maximum cap on total GPU memory, no matter how much the GPU reports.
163  size_t GetMaximumTotalGpuMemory() const;
164
165  // The maximum and minimum amount of memory that a tab may be assigned.
166  size_t GetMaximumTabAllocation() const;
167  size_t GetMinimumTabAllocation() const;
168
169  // Get a reasonable memory limit from a viewport's surface area.
170  static size_t CalcAvailableFromViewportArea(int viewport_area);
171  static size_t CalcAvailableFromGpuTotal(size_t total_gpu_memory);
172
173  // Interfaces for testing
174  void TestingSetClientVisible(GpuMemoryManagerClient* client, bool visible);
175  void TestingSetClientLastUsedTime(GpuMemoryManagerClient* client,
176                                    base::TimeTicks last_used_time);
177  void TestingSetClientHasSurface(GpuMemoryManagerClient* client,
178                                  bool has_surface);
179  bool TestingCompareClients(GpuMemoryManagerClient* lhs,
180                             GpuMemoryManagerClient* rhs) const;
181  void TestingDisableScheduleManage() { disable_schedule_manage_ = true; }
182  void TestingSetAvailableGpuMemory(size_t bytes) {
183    bytes_available_gpu_memory_ = bytes;
184    bytes_available_gpu_memory_overridden_ = true;
185  }
186
187  void TestingSetBackgroundedAvailableGpuMemory(size_t bytes) {
188    bytes_backgrounded_available_gpu_memory_ = bytes;
189  }
190
191  // All clients of this memory manager which have callbacks we
192  // can use to adjust memory usage
193  ClientMap clients_;
194
195  // All context groups' tracking structures
196  std::set<GpuMemoryTrackingGroup*> tracking_groups_;
197
198  base::CancelableClosure delayed_manage_callback_;
199  bool manage_immediate_scheduled_;
200
201  size_t max_surfaces_with_frontbuffer_soft_limit_;
202
203  // The maximum amount of memory that may be allocated for GPU resources
204  size_t bytes_available_gpu_memory_;
205  bool bytes_available_gpu_memory_overridden_;
206
207  // The maximum amount of memory that can be allocated for GPU resources
208  // in backgrounded renderers.
209  size_t bytes_backgrounded_available_gpu_memory_;
210
211  // The current total memory usage, and historical maximum memory usage
212  size_t bytes_allocated_current_;
213  size_t bytes_allocated_managed_visible_;
214  size_t bytes_allocated_managed_backgrounded_;
215
216  // The number of browser windows that exist. If we ever receive a
217  // GpuMsg_SetVideoMemoryWindowCount, then we use this to compute memory
218  // budgets, instead of doing more complicated stub-based calculations.
219  bool window_count_has_been_received_;
220  uint32 window_count_;
221
222  // Used to disable automatic changes to Manage() in testing.
223  bool disable_schedule_manage_;
224
225  DISALLOW_COPY_AND_ASSIGN(GpuMemoryManager);
226};
227
228class CONTENT_EXPORT GpuMemoryManagerClient {
229 public:
230  virtual ~GpuMemoryManagerClient() {}
231
232  // Returns surface size.
233  virtual gfx::Size GetSurfaceSize() const = 0;
234
235  // Returns the memory tracker for this stub.
236  virtual gpu::gles2::MemoryTracker* GetMemoryTracker() const = 0;
237
238  // Sets buffer usage depending on Memory Allocation
239  virtual void SetMemoryAllocation(
240      const GpuMemoryAllocation& allocation) = 0;
241
242  // Returns in bytes the total amount of GPU memory for the GPU which this
243  // context is currently rendering on. Returns false if no extension exists
244  // to get the exact amount of GPU memory.
245  virtual bool GetTotalGpuMemory(size_t* bytes) = 0;
246};
247
248}  // namespace content
249
250#endif
251
252#endif // CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
253