diff options
| -rw-r--r-- | libs/hwui/GenerationCache.h | 9 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 20 | ||||
| -rw-r--r-- | libs/hwui/TextureCache.cpp | 69 | ||||
| -rw-r--r-- | libs/hwui/TextureCache.h | 48 |
4 files changed, 129 insertions, 17 deletions
diff --git a/libs/hwui/GenerationCache.h b/libs/hwui/GenerationCache.h index 4a3ca77571a5..e215dafd8f55 100644 --- a/libs/hwui/GenerationCache.h +++ b/libs/hwui/GenerationCache.h @@ -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(); } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 8b4fb9bca24a..095d58b81a89 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -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; diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 7b8b31398188..10e4f9e5df53 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -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() { diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index bf680616c4f0..c974b65b5432 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -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 |