Home | History | Annotate | Download | only in resources
      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 "third_party/khronos/GLES2/gl2.h"
     21 #include "ui/gfx/size.h"
     22 
     23 #if defined(COMPILER_GCC)
     24 namespace BASE_HASH_NAMESPACE {
     25 template <> struct hash<cc::PrioritizedResource*> {
     26   size_t operator()(cc::PrioritizedResource* ptr) const {
     27     return hash<size_t>()(reinterpret_cast<size_t>(ptr));
     28   }
     29 };
     30 }  // namespace BASE_HASH_NAMESPACE
     31 #endif  // COMPILER
     32 
     33 namespace cc {
     34 
     35 class PriorityCalculator;
     36 class Proxy;
     37 
     38 class CC_EXPORT PrioritizedResourceManager {
     39  public:
     40   static scoped_ptr<PrioritizedResourceManager> Create(const Proxy* proxy) {
     41     return make_scoped_ptr(new PrioritizedResourceManager(proxy));
     42   }
     43   scoped_ptr<PrioritizedResource> CreateTexture(gfx::Size size, GLenum 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 
     81   // Return the amount of texture memory required at particular cutoffs.
     82   size_t MemoryVisibleBytes() const;
     83   size_t MemoryVisibleAndNearbyBytes() const;
     84 
     85   void PrioritizeTextures();
     86   void ClearPriorities();
     87 
     88   // Delete contents textures' backing resources until they use only
     89   // limit_bytes bytes. This may be called on the impl thread while the main
     90   // thread is running. Returns true if resources are indeed evicted as a
     91   // result of this call.
     92   bool ReduceMemoryOnImplThread(size_t limit_bytes,
     93                                 int priority_cutoff,
     94                                 ResourceProvider* resource_provider);
     95 
     96   // Delete contents textures' backing resources that can be recycled. This
     97   // may be called on the impl thread while the main thread is running.
     98   void ReduceWastedMemoryOnImplThread(ResourceProvider* resource_provider);
     99 
    100   // Returns true if there exist any textures that are linked to backings that
    101   // have had their resources evicted. Only when we commit a tree that has no
    102   // textures linked to evicted backings may we allow drawing. After an
    103   // eviction, this will not become true until unlinkAndClearEvictedBackings
    104   // is called.
    105   bool LinkedEvictedBackingsExist() const;
    106 
    107   // Unlink the list of contents textures' backings from their owning textures
    108   // and delete the evicted backings' structures. This is called just before
    109   // updating layers, and is only ever called on the main thread.
    110   void UnlinkAndClearEvictedBackings();
    111 
    112   bool RequestLate(PrioritizedResource* texture);
    113 
    114   void ReduceWastedMemory(ResourceProvider* resource_provider);
    115   void ReduceMemory(ResourceProvider* resource_provider);
    116   void ClearAllMemory(ResourceProvider* resource_provider);
    117 
    118   void AcquireBackingTextureIfNeeded(PrioritizedResource* texture,
    119                                      ResourceProvider* resource_provider);
    120 
    121   void RegisterTexture(PrioritizedResource* texture);
    122   void UnregisterTexture(PrioritizedResource* texture);
    123   void ReturnBackingTexture(PrioritizedResource* texture);
    124 
    125   // Update all backings' priorities from their owning texture.
    126   void PushTexturePrioritiesToBackings();
    127 
    128   // Mark all textures' backings as being in the drawing impl tree.
    129   void UpdateBackingsInDrawingImplTree();
    130 
    131   const Proxy* ProxyForDebug() const;
    132 
    133  private:
    134   friend class PrioritizedResourceTest;
    135 
    136   enum EvictionPolicy {
    137     EVICT_ONLY_RECYCLABLE,
    138     EVICT_ANYTHING,
    139   };
    140   enum UnlinkPolicy {
    141     DO_NOT_UNLINK_BACKINGS,
    142     UNLINK_BACKINGS,
    143   };
    144 
    145   // Compare textures. Highest priority first.
    146   static inline bool CompareTextures(PrioritizedResource* a,
    147                                      PrioritizedResource* b) {
    148     if (a->request_priority() == b->request_priority())
    149       return a < b;
    150     return PriorityCalculator::priority_is_higher(a->request_priority(),
    151                                                   b->request_priority());
    152   }
    153   // Compare backings. Lowest priority first.
    154   static inline bool CompareBackings(PrioritizedResource::Backing* a,
    155                                      PrioritizedResource::Backing* b) {
    156     // Make textures that can be recycled appear first
    157     if (a->CanBeRecycled() != b->CanBeRecycled())
    158       return (a->CanBeRecycled() > b->CanBeRecycled());
    159     // Then sort by being above or below the priority cutoff.
    160     if (a->was_above_priority_cutoff_at_last_priority_update() !=
    161         b->was_above_priority_cutoff_at_last_priority_update())
    162       return (a->was_above_priority_cutoff_at_last_priority_update() <
    163               b->was_above_priority_cutoff_at_last_priority_update());
    164     // Then sort by priority (note that backings that no longer have owners will
    165     // always have the lowest priority)
    166     if (a->request_priority_at_last_priority_update() !=
    167         b->request_priority_at_last_priority_update())
    168       return PriorityCalculator::priority_is_lower(
    169           a->request_priority_at_last_priority_update(),
    170           b->request_priority_at_last_priority_update());
    171     // Finally sort by being in the impl tree versus being completely
    172     // unreferenced
    173     if (a->in_drawing_impl_tree() != b->in_drawing_impl_tree())
    174       return (a->in_drawing_impl_tree() < b->in_drawing_impl_tree());
    175     return a < b;
    176   }
    177 
    178   explicit PrioritizedResourceManager(const Proxy* proxy);
    179 
    180   bool EvictBackingsToReduceMemory(size_t limit_bytes,
    181                                    int priority_cutoff,
    182                                    EvictionPolicy eviction_policy,
    183                                    UnlinkPolicy unlink_policy,
    184                                    ResourceProvider* resource_provider);
    185   PrioritizedResource::Backing* CreateBacking(
    186       gfx::Size size,
    187       GLenum format,
    188       ResourceProvider* resource_provider);
    189   void EvictFirstBackingResource(ResourceProvider* resource_provider);
    190   void SortBackings();
    191 
    192   void AssertInvariants();
    193 
    194   size_t max_memory_limit_bytes_;
    195   // The priority cutoff based on memory pressure. This is not a strict
    196   // cutoff -- RequestLate allows textures with priority equal to this
    197   // cutoff to be allowed.
    198   int priority_cutoff_;
    199   // The priority cutoff based on external memory policy. This is a strict
    200   // cutoff -- no textures with priority equal to this cutoff will be allowed.
    201   int external_priority_cutoff_;
    202   size_t memory_use_bytes_;
    203   size_t memory_above_cutoff_bytes_;
    204   size_t max_memory_needed_bytes_;
    205   size_t memory_available_bytes_;
    206 
    207   typedef base::hash_set<PrioritizedResource*> TextureSet;
    208   typedef std::vector<PrioritizedResource*> TextureVector;
    209 
    210   const Proxy* proxy_;
    211 
    212   TextureSet textures_;
    213   // This list is always sorted in eviction order, with the exception the
    214   // newly-allocated or recycled textures at the very end of the tail that
    215   // are not sorted by priority.
    216   BackingList backings_;
    217   bool backings_tail_not_sorted_;
    218 
    219   // The list of backings that have been evicted, but may still be linked
    220   // to textures. This can be accessed concurrently by the main and impl
    221   // threads, and may only be accessed while holding evicted_backings_lock_.
    222   mutable base::Lock evicted_backings_lock_;
    223   BackingList evicted_backings_;
    224 
    225   TextureVector temp_texture_vector_;
    226 
    227   // Statistics about memory usage at priority cutoffs, computed at
    228   // PrioritizeTextures.
    229   size_t memory_visible_bytes_;
    230   size_t memory_visible_and_nearby_bytes_;
    231 
    232   // Statistics copied at the time of PushTexturePrioritiesToBackings.
    233   size_t memory_visible_last_pushed_bytes_;
    234   size_t memory_visible_and_nearby_last_pushed_bytes_;
    235 
    236   DISALLOW_COPY_AND_ASSIGN(PrioritizedResourceManager);
    237 };
    238 
    239 }  // namespace cc
    240 
    241 #endif  // CC_RESOURCES_PRIORITIZED_RESOURCE_MANAGER_H_
    242