Merge "Track the size in memory of the texture cache."
This commit is contained in:
@@ -36,6 +36,10 @@ public:
|
||||
GenerationCache(unsigned int maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { };
|
||||
~GenerationCache() { clear(); };
|
||||
|
||||
enum Capacity {
|
||||
kUnlimitedCapacity,
|
||||
};
|
||||
|
||||
void setOnEntryRemovedListener(OnEntryRemoved<K*, V*>* listener);
|
||||
|
||||
void clear();
|
||||
@@ -44,12 +48,11 @@ public:
|
||||
V* get(K* key);
|
||||
void put(K* key, V* value);
|
||||
V* remove(K* key);
|
||||
void removeOldest();
|
||||
|
||||
unsigned int size() const;
|
||||
|
||||
private:
|
||||
void removeOldest();
|
||||
|
||||
template<typename EntryKey, typename EntryValue>
|
||||
struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
|
||||
Entry() { }
|
||||
@@ -124,7 +127,7 @@ V* GenerationCache<K, V>::get(K* key) {
|
||||
|
||||
template<typename K, typename V>
|
||||
void GenerationCache<K, V>::put(K* key, V* value) {
|
||||
if (mCache.size() >= mMaxCapacity) {
|
||||
if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
|
||||
removeOldest();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <SkCanvas.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "OpenGLRenderer.h"
|
||||
@@ -33,7 +34,15 @@ namespace uirenderer {
|
||||
// Defines
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MAX_TEXTURE_COUNT 128
|
||||
// These properties are defined in mega-bytes
|
||||
#define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
|
||||
#define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
|
||||
|
||||
// Converts a number of mega-bytes into bytes
|
||||
#define MB(s) s * 1024 * 1024
|
||||
|
||||
#define DEFAULT_TEXTURE_CACHE_SIZE MB(20)
|
||||
#define DEFAULT_LAYER_CACHE_SIZE MB(10)
|
||||
|
||||
#define SV(x, y) { { x, y } }
|
||||
#define FV(x, y, u, v) { { x, y }, { u, v } }
|
||||
@@ -83,9 +92,14 @@ static const Blender gBlends[] = {
|
||||
// Constructors/destructor
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OpenGLRenderer::OpenGLRenderer(): mTextureCache(MAX_TEXTURE_COUNT) {
|
||||
OpenGLRenderer::OpenGLRenderer(): mTextureCache(DEFAULT_TEXTURE_CACHE_SIZE) {
|
||||
LOGD("Create OpenGLRenderer");
|
||||
|
||||
char property[PROPERTY_VALUE_MAX];
|
||||
if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) {
|
||||
mTextureCache.setMaxSize(MB(atoi(property)));
|
||||
}
|
||||
|
||||
mDrawColorShader = new DrawColorProgram;
|
||||
mDrawTextureShader = new DrawTextureProgram;
|
||||
|
||||
@@ -397,6 +411,8 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)
|
||||
|
||||
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
|
||||
const Texture* texture = mTextureCache.get(bitmap);
|
||||
LOGD("Texture cache size %d", mTextureCache.getSize());
|
||||
LOGD(" max size %d", mTextureCache.getMaxSize());
|
||||
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "OpenGLRenderer"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "TextureCache.h"
|
||||
@@ -21,7 +23,13 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
TextureCache::TextureCache(unsigned int maxEntries): mCache(maxEntries) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Constructors/destructor
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TextureCache::TextureCache(unsigned int maxByteSize):
|
||||
mCache(GenerationCache<SkBitmap, Texture>::kUnlimitedCapacity),
|
||||
mSize(0), mMaxSize(maxByteSize) {
|
||||
mCache.setOnEntryRemovedListener(this);
|
||||
}
|
||||
|
||||
@@ -29,28 +37,71 @@ TextureCache::~TextureCache() {
|
||||
mCache.clear();
|
||||
}
|
||||
|
||||
void TextureCache::operator()(SkBitmap* key, Texture* value) {
|
||||
LOGD("Entry removed");
|
||||
if (value) {
|
||||
glDeleteTextures(1, &value->id);
|
||||
delete value;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Size management
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int TextureCache::getSize() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
unsigned int TextureCache::getMaxSize() {
|
||||
return mMaxSize;
|
||||
}
|
||||
|
||||
void TextureCache::setMaxSize(unsigned int maxSize) {
|
||||
mMaxSize = maxSize;
|
||||
while (mSize > mMaxSize) {
|
||||
mCache.removeOldest();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TextureCache::operator()(SkBitmap* bitmap, Texture* texture) {
|
||||
if (bitmap) {
|
||||
const unsigned int size = bitmap->rowBytes() * bitmap->height();
|
||||
mSize -= size;
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
glDeleteTextures(1, &texture->id);
|
||||
delete texture;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Caching
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Texture* TextureCache::get(SkBitmap* bitmap) {
|
||||
Texture* texture = mCache.get(bitmap);
|
||||
if (!texture) {
|
||||
const unsigned int size = bitmap->rowBytes() * bitmap->height();
|
||||
// Don't even try to cache a bitmap that's bigger than the cache
|
||||
if (size < mMaxSize) {
|
||||
while (mSize + size > mMaxSize) {
|
||||
mCache.removeOldest();
|
||||
}
|
||||
}
|
||||
|
||||
texture = new Texture;
|
||||
generateTexture(bitmap, texture, false);
|
||||
mCache.put(bitmap, texture);
|
||||
|
||||
if (size < mMaxSize) {
|
||||
mSize += size;
|
||||
mCache.put(bitmap, texture);
|
||||
}
|
||||
} else if (bitmap->getGenerationID() != texture->generation) {
|
||||
generateTexture(bitmap, texture, true);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
Texture* TextureCache::remove(SkBitmap* bitmap) {
|
||||
return mCache.remove(bitmap);
|
||||
void TextureCache::remove(SkBitmap* bitmap) {
|
||||
mCache.remove(bitmap);
|
||||
}
|
||||
|
||||
void TextureCache::clear() {
|
||||
|
||||
@@ -25,21 +25,63 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
/**
|
||||
* A simple LRU texture cache. The cache has a maximum size expressed in bytes.
|
||||
* Any texture added to the cache causing the cache to grow beyond the maximum
|
||||
* allowed size will also cause the oldest texture to be kicked out.
|
||||
*/
|
||||
class TextureCache: public OnEntryRemoved<SkBitmap*, Texture*> {
|
||||
public:
|
||||
TextureCache(unsigned int maxEntries);
|
||||
TextureCache(unsigned int maxByteSize);
|
||||
~TextureCache();
|
||||
|
||||
void operator()(SkBitmap* key, Texture* value);
|
||||
/**
|
||||
* Used as a callback when an entry is removed from the cache.
|
||||
* Do not invoke directly.
|
||||
*/
|
||||
void operator()(SkBitmap* bitmap, Texture* texture);
|
||||
|
||||
/**
|
||||
* Returns the texture associated with the specified bitmap. If the texture
|
||||
* cannot be found in the cache, a new texture is generated.
|
||||
*/
|
||||
Texture* get(SkBitmap* bitmap);
|
||||
Texture* remove(SkBitmap* bitmap);
|
||||
/**
|
||||
* Removes the texture associated with the specified bitmap. Returns NULL
|
||||
* if the texture cannot be found. Upon remove the texture is freed.
|
||||
*/
|
||||
void remove(SkBitmap* bitmap);
|
||||
/**
|
||||
* Clears the cache. This causes all textures to be deleted.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Sets the maximum size of the cache in bytes.
|
||||
*/
|
||||
void setMaxSize(unsigned int maxSize);
|
||||
/**
|
||||
* Returns the maximum size of the cache in bytes.
|
||||
*/
|
||||
unsigned int getMaxSize();
|
||||
/**
|
||||
* Returns the current size of the cache in bytes.
|
||||
*/
|
||||
unsigned int getSize();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Generates the texture from a bitmap into the specified texture structure.
|
||||
*
|
||||
* @param regenerate If true, the bitmap data is reuploaded into the texture, but
|
||||
* no new texture is generated.
|
||||
*/
|
||||
void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
|
||||
|
||||
GenerationCache<SkBitmap, Texture> mCache;
|
||||
|
||||
unsigned int mSize;
|
||||
unsigned int mMaxSize;
|
||||
}; // class TextureCache
|
||||
|
||||
}; // namespace uirenderer
|
||||
|
||||
Reference in New Issue
Block a user