• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 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 CC_RESOURCES_PRIORITIZED_RESOURCE_MANAGER_H_
6 #define CC_RESOURCES_PRIORITIZED_RESOURCE_MANAGER_H_
7 
8 #include <list>
9 #include <vector>
10 
11 #include "base/basictypes.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/synchronization/lock.h"
15 #include "cc/base/cc_export.h"
16 #include "cc/resources/prioritized_resource.h"
17 #include "cc/resources/priority_calculator.h"
18 #include "cc/resources/resource.h"
19 #include "cc/trees/proxy.h"
20 #include "ui/gfx/size.h"
21 
22 #if defined(COMPILER_GCC)
23 namespace BASE_HASH_NAMESPACE {
24 template <> struct hash<cc::PrioritizedResource*> {
25   size_t operator()(cc::PrioritizedResource* ptr) const {
26     return hash<size_t>()(reinterpret_cast<size_t>(ptr));
27   }
28 };
29 }  // namespace BASE_HASH_NAMESPACE
30 #endif  // COMPILER
31 
32 namespace cc {
33 
34 class PriorityCalculator;
35 class Proxy;
36 
37 class CC_EXPORT PrioritizedResourceManager {
38  public:
39   static scoped_ptr<PrioritizedResourceManager> Create(const Proxy* proxy) {
40     return make_scoped_ptr(new PrioritizedResourceManager(proxy));
41   }
42   scoped_ptr<PrioritizedResource> CreateTexture(
43       gfx::Size size, ResourceFormat format) {
44     return make_scoped_ptr(new PrioritizedResource(this, size, format));
45   }
46   ~PrioritizedResourceManager();
47 
48   typedef std::list<PrioritizedResource::Backing*> BackingList;
49 
50   // TODO(epenner): (http://crbug.com/137094) This 64MB default is a straggler
51   // from the old texture manager and is just to give us a default memory
52   // allocation before we get a callback from the GPU memory manager. We
53   // should probaby either:
54   // - wait for the callback before rendering anything instead
55   // - push this into the GPU memory manager somehow.
56   static size_t DefaultMemoryAllocationLimit() { return 64 * 1024 * 1024; }
57 
58   // MemoryUseBytes() describes the number of bytes used by existing allocated
59   // textures.
60   size_t MemoryUseBytes() const { return memory_use_bytes_; }
61   // MemoryAboveCutoffBytes() describes the number of bytes that
62   // would be used if all textures that are above the cutoff were allocated.
63   // MemoryUseBytes() <= MemoryAboveCutoffBytes() should always be true.
64   size_t MemoryAboveCutoffBytes() const { return memory_above_cutoff_bytes_; }
65   // MaxMemoryNeededBytes() describes the number of bytes that would be used
66   // by textures if there were no limit on memory usage.
67   size_t MaxMemoryNeededBytes() const { return max_memory_needed_bytes_; }
68   size_t MemoryForSelfManagedTextures() const {
69     return max_memory_limit_bytes_ - memory_available_bytes_;
70   }
71 
72   void SetMaxMemoryLimitBytes(size_t bytes) { max_memory_limit_bytes_ = bytes; }
73   size_t MaxMemoryLimitBytes() const { return max_memory_limit_bytes_; }
74 
75   // Sepecify a external priority cutoff. Only textures that have a strictly
76   // higher priority than this cutoff will be allowed.
77   void SetExternalPriorityCutoff(int priority_cutoff) {
78     external_priority_cutoff_ = priority_cutoff;
79   }
80   int ExternalPriorityCutoff() const {
81     return external_priority_cutoff_;
82   }
83 
84   // Return the amount of texture memory required at particular cutoffs.
85   size_t MemoryVisibleBytes() const;
86   size_t MemoryVisibleAndNearbyBytes() const;
87 
88   void PrioritizeTextures();
89   void ClearPriorities();
90 
91   // Delete contents textures' backing resources until they use only
92   // limit_bytes bytes. This may be called on the impl thread while the main
93   // thread is running. Returns true if resources are indeed evicted as a
94   // result of this call.
95   bool ReduceMemoryOnImplThread(size_t limit_bytes,
96                                 int priority_cutoff,
97                                 ResourceProvider* resource_provider);
98 
99   // Returns true if there exist any textures that are linked to backings that
100   // have had their resources evicted. Only when we commit a tree that has no
101   // textures linked to evicted backings may we allow drawing. After an
102   // eviction, this will not become true until unlinkAndClearEvictedBackings
103   // is called.
104   bool LinkedEvictedBackingsExist() const;
105 
106   // Unlink the list of contents textures' backings from their owning textures
107   // and delete the evicted backings' structures. This is called just before
108   // updating layers, and is only ever called on the main thread.
109   void UnlinkAndClearEvictedBackings();
110 
111   bool RequestLate(PrioritizedResource* texture);
112 
113   void ReduceWastedMemory(ResourceProvider* resource_provider);
114   void ReduceMemory(ResourceProvider* resource_provider);
115   void ClearAllMemory(ResourceProvider* resource_provider);
116 
117   void AcquireBackingTextureIfNeeded(PrioritizedResource* texture,
118                                      ResourceProvider* resource_provider);
119 
120   void RegisterTexture(PrioritizedResource* texture);
121   void UnregisterTexture(PrioritizedResource* texture);
122   void ReturnBackingTexture(PrioritizedResource* texture);
123 
124   // Update all backings' priorities from their owning texture.
125   void PushTexturePrioritiesToBackings();
126 
127   // Mark all textures' backings as being in the drawing impl tree.
128   void UpdateBackingsState(ResourceProvider* resource_provider);
129 
130   const Proxy* ProxyForDebug() const;
131 
132  private:
133   friend class PrioritizedResourceTest;
134 
135   enum EvictionPolicy {
136     EVICT_ONLY_RECYCLABLE,
137     EVICT_ANYTHING,
138   };
139   enum UnlinkPolicy {
140     DO_NOT_UNLINK_BACKINGS,
141     UNLINK_BACKINGS,
142   };
143 
144   // Compare textures. Highest priority first.
145   static inline bool CompareTextures(PrioritizedResource* a,
146                                      PrioritizedResource* b) {
147     if (a->request_priority() == b->request_priority())
148       return a < b;
149     return PriorityCalculator::priority_is_higher(a->request_priority(),
150                                                   b->request_priority());
151   }
152   // Compare backings. Lowest priority first.
153   static inline bool CompareBackings(PrioritizedResource::Backing* a,
154                                      PrioritizedResource::Backing* b) {
155     // Make textures that can be recycled appear first.
156     if (a->CanBeRecycledIfNotInExternalUse() !=
157         b->CanBeRecycledIfNotInExternalUse())
158       return (a->CanBeRecycledIfNotInExternalUse() >
159               b->CanBeRecycledIfNotInExternalUse());
160     // Then sort by being above or below the priority cutoff.
161     if (a->was_above_priority_cutoff_at_last_priority_update() !=
162         b->was_above_priority_cutoff_at_last_priority_update())
163       return (a->was_above_priority_cutoff_at_last_priority_update() <
164               b->was_above_priority_cutoff_at_last_priority_update());
165     // Then sort by priority (note that backings that no longer have owners will
166     // always have the lowest priority).
167     if (a->request_priority_at_last_priority_update() !=
168         b->request_priority_at_last_priority_update())
169       return PriorityCalculator::priority_is_lower(
170           a->request_priority_at_last_priority_update(),
171           b->request_priority_at_last_priority_update());
172     // Then sort by being in the impl tree versus being completely
173     // unreferenced.
174     if (a->in_drawing_impl_tree() != b->in_drawing_impl_tree())
175       return (a->in_drawing_impl_tree() < b->in_drawing_impl_tree());
176     // Finally, prefer to evict textures in the parent compositor because
177     // they will otherwise take another roundtrip to the parent compositor
178     // before they are evicted.
179     if (a->in_parent_compositor() != b->in_parent_compositor())
180       return (a->in_parent_compositor() > b->in_parent_compositor());
181     return a < b;
182   }
183 
184   explicit PrioritizedResourceManager(const Proxy* proxy);
185 
186   bool EvictBackingsToReduceMemory(size_t limit_bytes,
187                                    int priority_cutoff,
188                                    EvictionPolicy eviction_policy,
189                                    UnlinkPolicy unlink_policy,
190                                    ResourceProvider* resource_provider);
191   PrioritizedResource::Backing* CreateBacking(
192       gfx::Size size,
193       ResourceFormat format,
194       ResourceProvider* resource_provider);
195   void EvictFirstBackingResource(ResourceProvider* resource_provider);
196   void SortBackings();
197 
198   void AssertInvariants();
199 
200   size_t max_memory_limit_bytes_;
201   // The priority cutoff based on memory pressure. This is not a strict
202   // cutoff -- RequestLate allows textures with priority equal to this
203   // cutoff to be allowed.
204   int priority_cutoff_;
205   // The priority cutoff based on external memory policy. This is a strict
206   // cutoff -- no textures with priority equal to this cutoff will be allowed.
207   int external_priority_cutoff_;
208   size_t memory_use_bytes_;
209   size_t memory_above_cutoff_bytes_;
210   size_t max_memory_needed_bytes_;
211   size_t memory_available_bytes_;
212 
213   typedef base::hash_set<PrioritizedResource*> TextureSet;
214   typedef std::vector<PrioritizedResource*> TextureVector;
215 
216   const Proxy* proxy_;
217 
218   TextureSet textures_;
219   // This list is always sorted in eviction order, with the exception the
220   // newly-allocated or recycled textures at the very end of the tail that
221   // are not sorted by priority.
222   BackingList backings_;
223   bool backings_tail_not_sorted_;
224 
225   // The list of backings that have been evicted, but may still be linked
226   // to textures. This can be accessed concurrently by the main and impl
227   // threads, and may only be accessed while holding evicted_backings_lock_.
228   mutable base::Lock evicted_backings_lock_;
229   BackingList evicted_backings_;
230 
231   TextureVector temp_texture_vector_;
232 
233   // Statistics about memory usage at priority cutoffs, computed at
234   // PrioritizeTextures.
235   size_t memory_visible_bytes_;
236   size_t memory_visible_and_nearby_bytes_;
237 
238   // Statistics copied at the time of PushTexturePrioritiesToBackings.
239   size_t memory_visible_last_pushed_bytes_;
240   size_t memory_visible_and_nearby_last_pushed_bytes_;
241 
242   DISALLOW_COPY_AND_ASSIGN(PrioritizedResourceManager);
243 };
244 
245 }  // namespace cc
246 
247 #endif  // CC_RESOURCES_PRIORITIZED_RESOURCE_MANAGER_H_
248