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.
5 #ifndef CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
6 #define CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
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/public/common/gpu_memory_stats.h"
18 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
19 #include "gpu/command_buffer/service/memory_tracking.h"
23 class GpuChannelManager;
24 class GpuMemoryManagerClient;
25 class GpuMemoryManagerClientState;
26 class GpuMemoryTrackingGroup;
28 class CONTENT_EXPORT GpuMemoryManager :
29 public base::SupportsWeakPtr<GpuMemoryManager> {
31 #if defined(OS_ANDROID) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
32 enum { kDefaultMaxSurfacesWithFrontbufferSoftLimit = 1 };
34 enum { kDefaultMaxSurfacesWithFrontbufferSoftLimit = 8 };
36 enum ScheduleManageTime {
37 // Add a call to Manage to the thread's message loop immediately.
39 // Add a Manage call to the thread's message loop for execution 1/60th of
40 // of a second from now.
44 GpuMemoryManager(GpuChannelManager* channel_manager,
45 uint64 max_surfaces_with_frontbuffer_soft_limit);
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);
55 // Retrieve GPU Resource consumption statistics for the task manager
56 void GetVideoMemoryUsageStats(
57 content::GPUVideoMemoryUsageStats* video_memory_usage_stats) const;
59 GpuMemoryManagerClientState* CreateClientState(
60 GpuMemoryManagerClient* client, bool has_surface, bool visible);
62 GpuMemoryTrackingGroup* CreateTrackingGroup(
63 base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker);
66 friend class GpuMemoryManagerTest;
67 friend class GpuMemoryTrackingGroup;
68 friend class GpuMemoryManagerClientState;
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,
94 FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
95 AllowNonvisibleMemory);
96 FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
97 BackgroundDiscardPersistent);
98 FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
100 FRIEND_TEST_ALL_PREFIXES(GpuMemoryManagerTest,
103 typedef std::map<gpu::gles2::MemoryTracker*, GpuMemoryTrackingGroup*>
106 typedef std::list<GpuMemoryManagerClientState*> ClientStateList;
109 void SetClientsHibernatedState() const;
110 void AssignSurfacesAllocations();
111 void AssignNonSurfacesAllocations();
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);
117 // Compute the allocation for clients when visible and not visible.
118 void ComputeVisibleSurfacesAllocations();
119 void DistributeRemainingMemoryToVisibleSurfaces();
121 // Compute the budget for a client. Allow at most bytes_above_required_cap
122 // bytes above client_state's required level. Allow at most
123 // bytes_above_minimum_cap bytes above client_state's minimum level. Allow
124 // at most bytes_overall_cap bytes total.
125 uint64 ComputeClientAllocationWhenVisible(
126 GpuMemoryManagerClientState* client_state,
127 uint64 bytes_above_required_cap,
128 uint64 bytes_above_minimum_cap,
129 uint64 bytes_overall_cap);
131 // Update the amount of GPU memory we think we have in the system, based
132 // on what the stubs' contexts report.
133 void UpdateAvailableGpuMemory();
134 void UpdateUnmanagedMemoryLimits();
136 // The amount of video memory which is available for allocation.
137 uint64 GetAvailableGpuMemory() const;
139 // Minimum value of available GPU memory, no matter how little the GPU
140 // reports. This is the default value.
141 uint64 GetDefaultAvailableGpuMemory() const;
143 // Maximum cap on total GPU memory, no matter how much the GPU reports.
144 uint64 GetMaximumTotalGpuMemory() const;
146 // The maximum and minimum amount of memory that a client may be assigned.
147 uint64 GetMaximumClientAllocation() const;
148 uint64 GetMinimumClientAllocation() const {
149 return bytes_minimum_per_client_;
151 // The default amount of memory that a client is assigned, if it has not
152 // reported any memory usage stats yet.
153 uint64 GetDefaultClientAllocation() const {
154 return bytes_default_per_client_;
157 static uint64 CalcAvailableFromGpuTotal(uint64 total_gpu_memory);
159 // Send memory usage stats to the browser process.
160 void SendUmaStatsToBrowser();
162 // Get the current number of bytes allocated.
163 uint64 GetCurrentUsage() const {
164 return bytes_allocated_managed_current_ +
165 bytes_allocated_unmanaged_current_;
168 // GpuMemoryTrackingGroup interface
169 void TrackMemoryAllocatedChange(
170 GpuMemoryTrackingGroup* tracking_group,
173 gpu::gles2::MemoryTracker::Pool tracking_pool);
174 void OnDestroyTrackingGroup(GpuMemoryTrackingGroup* tracking_group);
175 bool EnsureGPUMemoryAvailable(uint64 size_needed);
177 // GpuMemoryManagerClientState interface
178 void SetClientStateVisible(
179 GpuMemoryManagerClientState* client_state, bool visible);
180 void SetClientStateManagedMemoryStats(
181 GpuMemoryManagerClientState* client_state,
182 const gpu::ManagedMemoryStats& stats);
183 void OnDestroyClientState(GpuMemoryManagerClientState* client);
185 // Add or remove a client from its clients list (visible, nonvisible, or
186 // nonsurface). When adding the client, add it to the front of the list.
187 void AddClientToList(GpuMemoryManagerClientState* client_state);
188 void RemoveClientFromList(GpuMemoryManagerClientState* client_state);
189 ClientStateList* GetClientList(GpuMemoryManagerClientState* client_state);
191 // Interfaces for testing
192 void TestingDisableScheduleManage() { disable_schedule_manage_ = true; }
193 void TestingSetAvailableGpuMemory(uint64 bytes) {
194 bytes_available_gpu_memory_ = bytes;
195 bytes_available_gpu_memory_overridden_ = true;
198 void TestingSetMinimumClientAllocation(uint64 bytes) {
199 bytes_minimum_per_client_ = bytes;
202 void TestingSetDefaultClientAllocation(uint64 bytes) {
203 bytes_default_per_client_ = bytes;
206 void TestingSetUnmanagedLimitStep(uint64 bytes) {
207 bytes_unmanaged_limit_step_ = bytes;
210 GpuChannelManager* channel_manager_;
212 // A list of all visible and nonvisible clients, in most-recently-used
213 // order (most recently used is first).
214 ClientStateList clients_visible_mru_;
215 ClientStateList clients_nonvisible_mru_;
217 // A list of all clients that don't have a surface.
218 ClientStateList clients_nonsurface_;
220 // All context groups' tracking structures
221 TrackingGroupMap tracking_groups_;
223 base::CancelableClosure delayed_manage_callback_;
224 bool manage_immediate_scheduled_;
226 uint64 max_surfaces_with_frontbuffer_soft_limit_;
228 // The maximum amount of memory that may be allocated for GPU resources
229 uint64 bytes_available_gpu_memory_;
230 bool bytes_available_gpu_memory_overridden_;
232 // The minimum and default allocations for a single client.
233 uint64 bytes_minimum_per_client_;
234 uint64 bytes_default_per_client_;
236 // The current total memory usage, and historical maximum memory usage
237 uint64 bytes_allocated_managed_current_;
238 uint64 bytes_allocated_unmanaged_current_;
239 uint64 bytes_allocated_historical_max_;
241 // If bytes_allocated_unmanaged_current_ leaves the interval [low_, high_),
242 // then ScheduleManage to take the change into account.
243 uint64 bytes_allocated_unmanaged_high_;
244 uint64 bytes_allocated_unmanaged_low_;
246 // Update bytes_allocated_unmanaged_low/high_ in intervals of step_.
247 uint64 bytes_unmanaged_limit_step_;
249 // Used to disable automatic changes to Manage() in testing.
250 bool disable_schedule_manage_;
252 DISALLOW_COPY_AND_ASSIGN(GpuMemoryManager);
255 } // namespace content
257 #endif // CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_