gpu_memory_manager.h revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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#include <list>
9#include <map>
10
11#include "base/basictypes.h"
12#include "base/cancelable_callback.h"
13#include "base/containers/hash_tables.h"
14#include "base/gtest_prod_util.h"
15#include "base/memory/weak_ptr.h"
16#include "content/common/content_export.h"
17#include "content/common/gpu/gpu_memory_allocation.h"
18#include "content/public/common/gpu_memory_stats.h"
19#include "gpu/command_buffer/service/memory_tracking.h"
20
21namespace content {
22
23class GpuChannelManager;
24class GpuMemoryManagerClient;
25class GpuMemoryManagerClientState;
26class GpuMemoryTrackingGroup;
27
28class CONTENT_EXPORT GpuMemoryManager :
29    public base::SupportsWeakPtr<GpuMemoryManager> {
30 public:
31#if defined(OS_ANDROID) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
32  enum { kDefaultMaxSurfacesWithFrontbufferSoftLimit = 1 };
33#else
34  enum { kDefaultMaxSurfacesWithFrontbufferSoftLimit = 8 };
35#endif
36  enum ScheduleManageTime {
37    // Add a call to Manage to the thread's message loop immediately.
38    kScheduleManageNow,
39    // Add a Manage call to the thread's message loop for execution 1/60th of
40    // of a second from now.
41    kScheduleManageLater,
42  };
43
44  GpuMemoryManager(GpuChannelManager* channel_manager,
45                   uint64 max_surfaces_with_frontbuffer_soft_limit);
46  ~GpuMemoryManager();
47
48  // Schedule a Manage() call. If immediate is true, we PostTask without delay.
49  // Otherwise PostDelayedTask using a CancelableClosure and allow multiple
50  // delayed calls to "queue" up. This way, we do not spam clients in certain
51  // lower priority situations. An immediate schedule manage will cancel any
52  // queued delayed manage.
53  void ScheduleManage(ScheduleManageTime schedule_manage_time);
54
55  // Retrieve GPU Resource consumption statistics for the task manager
56  void GetVideoMemoryUsageStats(
57      content::GPUVideoMemoryUsageStats* video_memory_usage_stats) const;
58
59  GpuMemoryManagerClientState* CreateClientState(
60      GpuMemoryManagerClient* client, bool has_surface, bool visible);
61
62  GpuMemoryTrackingGroup* CreateTrackingGroup(
63      base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker);
64
65 private:
66  friend class GpuMemoryManagerTest;
67  friend class GpuMemoryTrackingGroup;
68  friend class GpuMemoryManagerClientState;
69
70  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
71                           TestManageBasicFunctionality);
72  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
73                           TestManageChangingVisibility);
74  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
75                           TestManageManyVisibleStubs);
76  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
77                           TestManageManyNotVisibleStubs);
78  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
79                           TestManageChangingLastUsedTime);
80  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
81                           TestManageChangingImportanceShareGroup);
82  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
83                           TestForegroundStubsGetBonusAllocation);
84  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
85                           TestUpdateAvailableGpuMemory);
86  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
87                           GpuMemoryAllocationCompareTests);
88  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
89                           StubMemoryStatsForLastManageTests);
90  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
91                           TestManagedUsageTracking);
92  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
93                           BackgroundMru);
94  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
95                           AllowNonvisibleMemory);
96  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
97                           BackgroundDiscardPersistent);
98  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
99                           UnmanagedTracking);
100  FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
101                           DefaultAllocation);
102
103  typedef std::map<gpu::gles2::MemoryTracker*, GpuMemoryTrackingGroup*>
104      TrackingGroupMap;
105
106  typedef std::list<GpuMemoryManagerClientState*> ClientStateList;
107
108  void Manage();
109  void SetClientsHibernatedState() const;
110  void AssignSurfacesAllocations();
111  void AssignNonSurfacesAllocations();
112
113  // Math helper function to compute the maximum value of cap such that
114  // sum_i min(bytes[i], cap) <= bytes_sum_limit
115  static uint64 ComputeCap(std::vector<uint64> bytes, uint64 bytes_sum_limit);
116
117  // Compute the allocation for clients when visible and not visible.
118  void ComputeVisibleSurfacesAllocations();
119  void ComputeNonvisibleSurfacesAllocations();
120  void DistributeRemainingMemoryToVisibleSurfaces();
121
122  // Compute the budget for a client. Allow at most bytes_above_required_cap
123  // bytes above client_state's required level. Allow at most
124  // bytes_above_minimum_cap bytes above client_state's minimum level. Allow
125  // at most bytes_overall_cap bytes total.
126  uint64 ComputeClientAllocationWhenVisible(
127      GpuMemoryManagerClientState* client_state,
128      uint64 bytes_above_required_cap,
129      uint64 bytes_above_minimum_cap,
130      uint64 bytes_overall_cap);
131  uint64 ComputeClientAllocationWhenNonvisible(
132      GpuMemoryManagerClientState* client_state);
133
134  // Update the amount of GPU memory we think we have in the system, based
135  // on what the stubs' contexts report.
136  void UpdateAvailableGpuMemory();
137  void UpdateUnmanagedMemoryLimits();
138
139  // The amount of video memory which is available for allocation.
140  uint64 GetAvailableGpuMemory() const;
141
142  // Minimum value of available GPU memory, no matter how little the GPU
143  // reports. This is the default value.
144  uint64 GetDefaultAvailableGpuMemory() const;
145
146  // Maximum cap on total GPU memory, no matter how much the GPU reports.
147  uint64 GetMaximumTotalGpuMemory() const;
148
149  // The maximum and minimum amount of memory that a client may be assigned.
150  uint64 GetMaximumClientAllocation() const;
151  uint64 GetMinimumClientAllocation() const {
152    return bytes_minimum_per_client_;
153  }
154  // The default amount of memory that a client is assigned, if it has not
155  // reported any memory usage stats yet.
156  uint64 GetDefaultClientAllocation() const {
157    return bytes_default_per_client_;
158  }
159
160  static uint64 CalcAvailableFromGpuTotal(uint64 total_gpu_memory);
161
162  // Send memory usage stats to the browser process.
163  void SendUmaStatsToBrowser();
164
165  // Get the current number of bytes allocated.
166  uint64 GetCurrentUsage() const {
167    return bytes_allocated_managed_current_ +
168        bytes_allocated_unmanaged_current_;
169  }
170
171  // GpuMemoryTrackingGroup interface
172  void TrackMemoryAllocatedChange(
173      GpuMemoryTrackingGroup* tracking_group,
174      uint64 old_size,
175      uint64 new_size,
176      gpu::gles2::MemoryTracker::Pool tracking_pool);
177  void OnDestroyTrackingGroup(GpuMemoryTrackingGroup* tracking_group);
178  bool EnsureGPUMemoryAvailable(uint64 size_needed);
179
180  // GpuMemoryManagerClientState interface
181  void SetClientStateVisible(
182      GpuMemoryManagerClientState* client_state, bool visible);
183  void SetClientStateManagedMemoryStats(
184      GpuMemoryManagerClientState* client_state,
185      const GpuManagedMemoryStats& stats);
186  void OnDestroyClientState(GpuMemoryManagerClientState* client);
187
188  // Add or remove a client from its clients list (visible, nonvisible, or
189  // nonsurface). When adding the client, add it to the front of the list.
190  void AddClientToList(GpuMemoryManagerClientState* client_state);
191  void RemoveClientFromList(GpuMemoryManagerClientState* client_state);
192  ClientStateList* GetClientList(GpuMemoryManagerClientState* client_state);
193
194  // Interfaces for testing
195  void TestingDisableScheduleManage() { disable_schedule_manage_ = true; }
196  void TestingSetAvailableGpuMemory(uint64 bytes) {
197    bytes_available_gpu_memory_ = bytes;
198    bytes_available_gpu_memory_overridden_ = true;
199  }
200
201  void TestingSetMinimumClientAllocation(uint64 bytes) {
202    bytes_minimum_per_client_ = bytes;
203  }
204
205  void TestingSetDefaultClientAllocation(uint64 bytes) {
206    bytes_default_per_client_ = bytes;
207  }
208
209  void TestingSetUnmanagedLimitStep(uint64 bytes) {
210    bytes_unmanaged_limit_step_ = bytes;
211  }
212
213  GpuChannelManager* channel_manager_;
214
215  // A list of all visible and nonvisible clients, in most-recently-used
216  // order (most recently used is first).
217  ClientStateList clients_visible_mru_;
218  ClientStateList clients_nonvisible_mru_;
219
220  // A list of all clients that don't have a surface.
221  ClientStateList clients_nonsurface_;
222
223  // All context groups' tracking structures
224  TrackingGroupMap tracking_groups_;
225
226  base::CancelableClosure delayed_manage_callback_;
227  bool manage_immediate_scheduled_;
228
229  uint64 max_surfaces_with_frontbuffer_soft_limit_;
230
231  // The maximum amount of memory that may be allocated for GPU resources
232  uint64 bytes_available_gpu_memory_;
233  bool bytes_available_gpu_memory_overridden_;
234
235  // Whether or not clients can be allocated memory when nonvisible.
236  bool allow_nonvisible_memory_;
237
238  // The minimum and default allocations for a single client.
239  uint64 bytes_minimum_per_client_;
240  uint64 bytes_default_per_client_;
241
242  // The current total memory usage, and historical maximum memory usage
243  uint64 bytes_allocated_managed_current_;
244  uint64 bytes_allocated_managed_visible_;
245  uint64 bytes_allocated_managed_nonvisible_;
246  uint64 bytes_allocated_unmanaged_current_;
247  uint64 bytes_allocated_historical_max_;
248
249  // If bytes_allocated_unmanaged_current_ leaves the interval [low_, high_),
250  // then ScheduleManage to take the change into account.
251  uint64 bytes_allocated_unmanaged_high_;
252  uint64 bytes_allocated_unmanaged_low_;
253
254  // Update bytes_allocated_unmanaged_low/high_ in intervals of step_.
255  uint64 bytes_unmanaged_limit_step_;
256
257  // Used to disable automatic changes to Manage() in testing.
258  bool disable_schedule_manage_;
259
260  DISALLOW_COPY_AND_ASSIGN(GpuMemoryManager);
261};
262
263}  // namespace content
264
265#endif // CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
266