Loading libs/hwui/GenerationCache.h +6 −3 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,10 @@ public: GenerationCache(unsigned int maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { }; GenerationCache(unsigned int maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { }; ~GenerationCache() { clear(); }; ~GenerationCache() { clear(); }; enum Capacity { kUnlimitedCapacity, }; void setOnEntryRemovedListener(OnEntryRemoved<K*, V*>* listener); void setOnEntryRemovedListener(OnEntryRemoved<K*, V*>* listener); void clear(); void clear(); Loading @@ -44,12 +48,11 @@ public: V* get(K* key); V* get(K* key); void put(K* key, V* value); void put(K* key, V* value); V* remove(K* key); V* remove(K* key); void removeOldest(); unsigned int size() const; unsigned int size() const; private: private: void removeOldest(); template<typename EntryKey, typename EntryValue> template<typename EntryKey, typename EntryValue> struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > { struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > { Entry() { } Entry() { } Loading Loading @@ -124,7 +127,7 @@ V* GenerationCache<K, V>::get(K* key) { template<typename K, typename V> template<typename K, typename V> void GenerationCache<K, V>::put(K* key, V* value) { void GenerationCache<K, V>::put(K* key, V* value) { if (mCache.size() >= mMaxCapacity) { if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) { removeOldest(); removeOldest(); } } Loading libs/hwui/OpenGLRenderer.cpp +18 −2 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <SkCanvas.h> #include <SkCanvas.h> #include <cutils/properties.h> #include <utils/Log.h> #include <utils/Log.h> #include "OpenGLRenderer.h" #include "OpenGLRenderer.h" Loading @@ -33,7 +34,15 @@ namespace uirenderer { // Defines // 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 SV(x, y) { { x, y } } #define FV(x, y, u, v) { { x, y }, { u, v } } #define FV(x, y, u, v) { { x, y }, { u, v } } Loading Loading @@ -83,9 +92,14 @@ static const Blender gBlends[] = { // Constructors/destructor // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// OpenGLRenderer::OpenGLRenderer(): mTextureCache(MAX_TEXTURE_COUNT) { OpenGLRenderer::OpenGLRenderer(): mTextureCache(DEFAULT_TEXTURE_CACHE_SIZE) { LOGD("Create OpenGLRenderer"); 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; mDrawColorShader = new DrawColorProgram; mDrawTextureShader = new DrawTextureProgram; mDrawTextureShader = new DrawTextureProgram; Loading Loading @@ -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) { void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) { const Texture* texture = mTextureCache.get(bitmap); const Texture* texture = mTextureCache.get(bitmap); LOGD("Texture cache size %d", mTextureCache.getSize()); LOGD(" max size %d", mTextureCache.getMaxSize()); int alpha; int alpha; SkXfermode::Mode mode; SkXfermode::Mode mode; Loading libs/hwui/TextureCache.cpp +60 −9 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. * limitations under the License. */ */ #define LOG_TAG "OpenGLRenderer" #include <GLES2/gl2.h> #include <GLES2/gl2.h> #include "TextureCache.h" #include "TextureCache.h" Loading @@ -21,7 +23,13 @@ namespace android { namespace android { namespace uirenderer { 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); mCache.setOnEntryRemovedListener(this); } } Loading @@ -29,28 +37,71 @@ TextureCache::~TextureCache() { mCache.clear(); mCache.clear(); } } void TextureCache::operator()(SkBitmap* key, Texture* value) { /////////////////////////////////////////////////////////////////////////////// LOGD("Entry removed"); // Size management if (value) { /////////////////////////////////////////////////////////////////////////////// glDeleteTextures(1, &value->id); delete value; 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* TextureCache::get(SkBitmap* bitmap) { Texture* texture = mCache.get(bitmap); Texture* texture = mCache.get(bitmap); if (!texture) { 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; texture = new Texture; generateTexture(bitmap, texture, false); generateTexture(bitmap, texture, false); if (size < mMaxSize) { mSize += size; mCache.put(bitmap, texture); mCache.put(bitmap, texture); } } else if (bitmap->getGenerationID() != texture->generation) { } else if (bitmap->getGenerationID() != texture->generation) { generateTexture(bitmap, texture, true); generateTexture(bitmap, texture, true); } } return texture; return texture; } } Texture* TextureCache::remove(SkBitmap* bitmap) { void TextureCache::remove(SkBitmap* bitmap) { return mCache.remove(bitmap); mCache.remove(bitmap); } } void TextureCache::clear() { void TextureCache::clear() { Loading libs/hwui/TextureCache.h +45 −3 Original line number Original line Diff line number Diff line Loading @@ -25,21 +25,63 @@ namespace android { namespace android { namespace uirenderer { 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*> { class TextureCache: public OnEntryRemoved<SkBitmap*, Texture*> { public: public: TextureCache(unsigned int maxEntries); TextureCache(unsigned int maxByteSize); ~TextureCache(); ~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* 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(); 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: 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); void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false); GenerationCache<SkBitmap, Texture> mCache; GenerationCache<SkBitmap, Texture> mCache; unsigned int mSize; unsigned int mMaxSize; }; // class TextureCache }; // class TextureCache }; // namespace uirenderer }; // namespace uirenderer Loading Loading
libs/hwui/GenerationCache.h +6 −3 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,10 @@ public: GenerationCache(unsigned int maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { }; GenerationCache(unsigned int maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { }; ~GenerationCache() { clear(); }; ~GenerationCache() { clear(); }; enum Capacity { kUnlimitedCapacity, }; void setOnEntryRemovedListener(OnEntryRemoved<K*, V*>* listener); void setOnEntryRemovedListener(OnEntryRemoved<K*, V*>* listener); void clear(); void clear(); Loading @@ -44,12 +48,11 @@ public: V* get(K* key); V* get(K* key); void put(K* key, V* value); void put(K* key, V* value); V* remove(K* key); V* remove(K* key); void removeOldest(); unsigned int size() const; unsigned int size() const; private: private: void removeOldest(); template<typename EntryKey, typename EntryValue> template<typename EntryKey, typename EntryValue> struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > { struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > { Entry() { } Entry() { } Loading Loading @@ -124,7 +127,7 @@ V* GenerationCache<K, V>::get(K* key) { template<typename K, typename V> template<typename K, typename V> void GenerationCache<K, V>::put(K* key, V* value) { void GenerationCache<K, V>::put(K* key, V* value) { if (mCache.size() >= mMaxCapacity) { if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) { removeOldest(); removeOldest(); } } Loading
libs/hwui/OpenGLRenderer.cpp +18 −2 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <SkCanvas.h> #include <SkCanvas.h> #include <cutils/properties.h> #include <utils/Log.h> #include <utils/Log.h> #include "OpenGLRenderer.h" #include "OpenGLRenderer.h" Loading @@ -33,7 +34,15 @@ namespace uirenderer { // Defines // 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 SV(x, y) { { x, y } } #define FV(x, y, u, v) { { x, y }, { u, v } } #define FV(x, y, u, v) { { x, y }, { u, v } } Loading Loading @@ -83,9 +92,14 @@ static const Blender gBlends[] = { // Constructors/destructor // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// OpenGLRenderer::OpenGLRenderer(): mTextureCache(MAX_TEXTURE_COUNT) { OpenGLRenderer::OpenGLRenderer(): mTextureCache(DEFAULT_TEXTURE_CACHE_SIZE) { LOGD("Create OpenGLRenderer"); 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; mDrawColorShader = new DrawColorProgram; mDrawTextureShader = new DrawTextureProgram; mDrawTextureShader = new DrawTextureProgram; Loading Loading @@ -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) { void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) { const Texture* texture = mTextureCache.get(bitmap); const Texture* texture = mTextureCache.get(bitmap); LOGD("Texture cache size %d", mTextureCache.getSize()); LOGD(" max size %d", mTextureCache.getMaxSize()); int alpha; int alpha; SkXfermode::Mode mode; SkXfermode::Mode mode; Loading
libs/hwui/TextureCache.cpp +60 −9 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. * limitations under the License. */ */ #define LOG_TAG "OpenGLRenderer" #include <GLES2/gl2.h> #include <GLES2/gl2.h> #include "TextureCache.h" #include "TextureCache.h" Loading @@ -21,7 +23,13 @@ namespace android { namespace android { namespace uirenderer { 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); mCache.setOnEntryRemovedListener(this); } } Loading @@ -29,28 +37,71 @@ TextureCache::~TextureCache() { mCache.clear(); mCache.clear(); } } void TextureCache::operator()(SkBitmap* key, Texture* value) { /////////////////////////////////////////////////////////////////////////////// LOGD("Entry removed"); // Size management if (value) { /////////////////////////////////////////////////////////////////////////////// glDeleteTextures(1, &value->id); delete value; 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* TextureCache::get(SkBitmap* bitmap) { Texture* texture = mCache.get(bitmap); Texture* texture = mCache.get(bitmap); if (!texture) { 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; texture = new Texture; generateTexture(bitmap, texture, false); generateTexture(bitmap, texture, false); if (size < mMaxSize) { mSize += size; mCache.put(bitmap, texture); mCache.put(bitmap, texture); } } else if (bitmap->getGenerationID() != texture->generation) { } else if (bitmap->getGenerationID() != texture->generation) { generateTexture(bitmap, texture, true); generateTexture(bitmap, texture, true); } } return texture; return texture; } } Texture* TextureCache::remove(SkBitmap* bitmap) { void TextureCache::remove(SkBitmap* bitmap) { return mCache.remove(bitmap); mCache.remove(bitmap); } } void TextureCache::clear() { void TextureCache::clear() { Loading
libs/hwui/TextureCache.h +45 −3 Original line number Original line Diff line number Diff line Loading @@ -25,21 +25,63 @@ namespace android { namespace android { namespace uirenderer { 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*> { class TextureCache: public OnEntryRemoved<SkBitmap*, Texture*> { public: public: TextureCache(unsigned int maxEntries); TextureCache(unsigned int maxByteSize); ~TextureCache(); ~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* 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(); 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: 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); void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false); GenerationCache<SkBitmap, Texture> mCache; GenerationCache<SkBitmap, Texture> mCache; unsigned int mSize; unsigned int mMaxSize; }; // class TextureCache }; // class TextureCache }; // namespace uirenderer }; // namespace uirenderer Loading