| // Copyright 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CC_PRIORITIZED_RESOURCE_MANAGER_H_ |
| #define CC_PRIORITIZED_RESOURCE_MANAGER_H_ |
| |
| #include <list> |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/hash_tables.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "cc/cc_export.h" |
| #include "cc/proxy.h" |
| #include "cc/prioritized_resource.h" |
| #include "cc/priority_calculator.h" |
| #include "cc/resource.h" |
| #include "third_party/khronos/GLES2/gl2.h" |
| #include "ui/gfx/size.h" |
| |
| #if defined(COMPILER_GCC) |
| namespace BASE_HASH_NAMESPACE { |
| template<> |
| struct hash<cc::PrioritizedResource*> { |
| size_t operator()(cc::PrioritizedResource* ptr) const { |
| return hash<size_t>()(reinterpret_cast<size_t>(ptr)); |
| } |
| }; |
| } // namespace BASE_HASH_NAMESPACE |
| #endif // COMPILER |
| |
| namespace cc { |
| |
| class PriorityCalculator; |
| class Proxy; |
| |
| class CC_EXPORT PrioritizedResourceManager { |
| public: |
| static scoped_ptr<PrioritizedResourceManager> create(int pool, const Proxy* proxy) |
| { |
| return make_scoped_ptr(new PrioritizedResourceManager(pool, proxy)); |
| } |
| scoped_ptr<PrioritizedResource> createTexture(gfx::Size size, GLenum format) |
| { |
| return make_scoped_ptr(new PrioritizedResource(this, size, format)); |
| } |
| ~PrioritizedResourceManager(); |
| |
| typedef std::list<PrioritizedResource::Backing*> BackingList; |
| |
| // FIXME (http://crbug.com/137094): This 64MB default is a straggler from the |
| // old texture manager and is just to give us a default memory allocation before |
| // we get a callback from the GPU memory manager. We should probaby either: |
| // - wait for the callback before rendering anything instead |
| // - push this into the GPU memory manager somehow. |
| static size_t defaultMemoryAllocationLimit() { return 64 * 1024 * 1024; } |
| |
| // memoryUseBytes() describes the number of bytes used by existing allocated textures. |
| // memoryAboveCutoffBytes() describes the number of bytes that would be used if all |
| // textures that are above the cutoff were allocated. |
| // memoryUseBytes() <= memoryAboveCutoffBytes() should always be true. |
| size_t memoryUseBytes() const { return m_memoryUseBytes; } |
| size_t memoryAboveCutoffBytes() const { return m_memoryAboveCutoffBytes; } |
| size_t memoryForSelfManagedTextures() const { return m_maxMemoryLimitBytes - m_memoryAvailableBytes; } |
| |
| void setMaxMemoryLimitBytes(size_t bytes) { m_maxMemoryLimitBytes = bytes; } |
| size_t maxMemoryLimitBytes() const { return m_maxMemoryLimitBytes; } |
| |
| // Sepecify a external priority cutoff. Only textures that have a strictly higher priority |
| // than this cutoff will be allowed. |
| void setExternalPriorityCutoff(int priorityCutoff) { m_externalPriorityCutoff = priorityCutoff; } |
| |
| // Return the amount of texture memory required at particular cutoffs. |
| size_t memoryVisibleBytes() const; |
| size_t memoryVisibleAndNearbyBytes() const; |
| |
| void prioritizeTextures(); |
| void clearPriorities(); |
| |
| // Delete contents textures' backing resources until they use only bytesLimit bytes. This may |
| // be called on the impl thread while the main thread is running. Returns true if resources are |
| // indeed evicted as a result of this call. |
| bool reduceMemoryOnImplThread(size_t limitBytes, int priorityCutoff, ResourceProvider*); |
| // Returns true if there exist any textures that are linked to backings that have had their |
| // resources evicted. Only when we commit a tree that has no textures linked to evicted backings |
| // may we allow drawing. |
| bool linkedEvictedBackingsExist() const; |
| // Retrieve the list of all contents textures' backings that have been evicted, to pass to the |
| // main thread to unlink them from their owning textures. |
| void getEvictedBackings(BackingList& evictedBackings); |
| // Unlink the list of contents textures' backings from their owning textures on the main thread |
| // before updating layers. |
| void unlinkEvictedBackings(const BackingList& evictedBackings); |
| |
| bool requestLate(PrioritizedResource*); |
| |
| void reduceMemory(ResourceProvider*); |
| void clearAllMemory(ResourceProvider*); |
| |
| void acquireBackingTextureIfNeeded(PrioritizedResource*, ResourceProvider*); |
| |
| void registerTexture(PrioritizedResource*); |
| void unregisterTexture(PrioritizedResource*); |
| void returnBackingTexture(PrioritizedResource*); |
| |
| // Update all backings' priorities from their owning texture. |
| void pushTexturePrioritiesToBackings(); |
| |
| // Mark all textures' backings as being in the drawing impl tree. |
| void updateBackingsInDrawingImplTree(); |
| |
| const Proxy* proxyForDebug() const; |
| |
| private: |
| friend class PrioritizedResourceTest; |
| |
| enum EvictionPolicy { |
| EvictOnlyRecyclable, |
| EvictAnything, |
| }; |
| enum UnlinkPolicy { |
| DoNotUnlinkBackings, |
| UnlinkBackings, |
| }; |
| |
| // Compare textures. Highest priority first. |
| static inline bool compareTextures(PrioritizedResource* a, PrioritizedResource* b) |
| { |
| if (a->requestPriority() == b->requestPriority()) |
| return a < b; |
| return PriorityCalculator::priorityIsHigher(a->requestPriority(), b->requestPriority()); |
| } |
| // Compare backings. Lowest priority first. |
| static inline bool compareBackings(PrioritizedResource::Backing* a, PrioritizedResource::Backing* b) |
| { |
| // Make textures that can be recycled appear first |
| if (a->canBeRecycled() != b->canBeRecycled()) |
| return (a->canBeRecycled() > b->canBeRecycled()); |
| // Then sort by being above or below the priority cutoff. |
| if (a->wasAbovePriorityCutoffAtLastPriorityUpdate() != b->wasAbovePriorityCutoffAtLastPriorityUpdate()) |
| return (a->wasAbovePriorityCutoffAtLastPriorityUpdate() < b->wasAbovePriorityCutoffAtLastPriorityUpdate()); |
| // Then sort by priority (note that backings that no longer have owners will |
| // always have the lowest priority) |
| if (a->requestPriorityAtLastPriorityUpdate() != b->requestPriorityAtLastPriorityUpdate()) |
| return PriorityCalculator::priorityIsLower(a->requestPriorityAtLastPriorityUpdate(), b->requestPriorityAtLastPriorityUpdate()); |
| // Finally sort by being in the impl tree versus being completely unreferenced |
| if (a->inDrawingImplTree() != b->inDrawingImplTree()) |
| return (a->inDrawingImplTree() < b->inDrawingImplTree()); |
| return a < b; |
| } |
| |
| PrioritizedResourceManager(int pool, const Proxy* proxy); |
| |
| bool evictBackingsToReduceMemory(size_t limitBytes, |
| int priorityCutoff, |
| EvictionPolicy, |
| UnlinkPolicy, |
| ResourceProvider*); |
| PrioritizedResource::Backing* createBacking(gfx::Size, GLenum format, ResourceProvider*); |
| void evictFirstBackingResource(ResourceProvider*); |
| void deleteAllEvictedBackings(); |
| void sortBackings(); |
| |
| void assertInvariants(); |
| |
| size_t m_maxMemoryLimitBytes; |
| // The priority cutoff based on memory pressure. This is not a strict |
| // cutoff -- requestLate allows textures with priority equal to this |
| // cutoff to be allowed. |
| int m_priorityCutoff; |
| // The priority cutoff based on external memory policy. This is a strict |
| // cutoff -- no textures with priority equal to this cutoff will be allowed. |
| int m_externalPriorityCutoff; |
| size_t m_memoryUseBytes; |
| size_t m_memoryAboveCutoffBytes; |
| size_t m_memoryAvailableBytes; |
| int m_pool; |
| |
| typedef base::hash_set<PrioritizedResource*> TextureSet; |
| typedef std::vector<PrioritizedResource*> TextureVector; |
| |
| const Proxy* m_proxy; |
| |
| TextureSet m_textures; |
| // This list is always sorted in eviction order, with the exception the |
| // newly-allocated or recycled textures at the very end of the tail that |
| // are not sorted by priority. |
| BackingList m_backings; |
| bool m_backingsTailNotSorted; |
| BackingList m_evictedBackings; |
| |
| TextureVector m_tempTextureVector; |
| |
| // Statistics about memory usage at priority cutoffs, computed at prioritizeTextures. |
| size_t m_memoryVisibleBytes; |
| size_t m_memoryVisibleAndNearbyBytes; |
| |
| // Statistics copied at the time of pushTexturePrioritiesToBackings. |
| size_t m_memoryVisibleLastPushedBytes; |
| size_t m_memoryVisibleAndNearbyLastPushedBytes; |
| |
| DISALLOW_COPY_AND_ASSIGN(PrioritizedResourceManager); |
| }; |
| |
| } // namespace cc |
| |
| #endif // CC_PRIORITIZED_RESOURCE_MANAGER_H_ |