blob: 0256f90bf839f3f7fb874be34b99a6698ba3f7ad [file] [log] [blame]
// 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_