From 9aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Wed, 8 Sep 2010 15:15:43 -0700 Subject: [PATCH] Fix possible infinite loop when purging textures. Change-Id: Ib05b398ae03e734da2dab0496df416fed4570b1c --- core/jni/android/graphics/Bitmap.cpp | 5 +++++ libs/hwui/GenerationCache.h | 6 +----- libs/hwui/PatchCache.h | 2 ++ libs/hwui/Texture.h | 5 +++++ libs/hwui/TextureCache.cpp | 21 ++++++++++++++++----- libs/hwui/TextureCache.h | 2 ++ 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index b062264166219..95bb24fb11832 100644 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -12,6 +12,8 @@ #include +#include + #if 0 #define TRACE_BITMAP(code) code #else @@ -251,6 +253,9 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src, } static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) { +#ifdef USE_OPENGL_RENDERER + android::uirenderer::Caches::getInstance().textureCache.remove(bitmap); +#endif delete bitmap; } diff --git a/libs/hwui/GenerationCache.h b/libs/hwui/GenerationCache.h index c358c8096cfdd..c42a5d8852c43 100644 --- a/libs/hwui/GenerationCache.h +++ b/libs/hwui/GenerationCache.h @@ -143,11 +143,7 @@ void GenerationCache::put(K key, V value) { } ssize_t index = mCache.indexOfKey(key); - if (index >= 0) { - sp > entry = mCache.valueAt(index); - detachFromCache(entry); - addToCache(entry, key, value); - } else { + if (index < 0) { sp > entry = new Entry; addToCache(entry, key, value); } diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h index e874a1686e5c3..6dad8314d0696 100644 --- a/libs/hwui/PatchCache.h +++ b/libs/hwui/PatchCache.h @@ -17,6 +17,8 @@ #ifndef ANDROID_UI_PATCH_CACHE_H #define ANDROID_UI_PATCH_CACHE_H +#include + #include "Patch.h" #include "GenerationCache.h" diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index 90f548b5621d5..817f1436bd3c1 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -28,6 +28,7 @@ namespace uirenderer { struct Texture { Texture() { cleanup = false; + bitmapSize = 0; } /** @@ -54,6 +55,10 @@ struct Texture { * Indicates whether this texture should be cleaned up after use. */ bool cleanup; + /** + * Optional, size of the original bitmap. + */ + uint32_t bitmapSize; }; // struct Texture class AutoTexture { diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 753c5446b5bc4..e5588708127a8 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -18,6 +18,8 @@ #include +#include + #include "TextureCache.h" #include "Properties.h" @@ -49,6 +51,7 @@ TextureCache::TextureCache(uint32_t maxByteSize): } TextureCache::~TextureCache() { + Mutex::Autolock _l(mLock); mCache.clear(); } @@ -64,14 +67,17 @@ void TextureCache::init() { /////////////////////////////////////////////////////////////////////////////// uint32_t TextureCache::getSize() { + Mutex::Autolock _l(mLock); return mSize; } uint32_t TextureCache::getMaxSize() { + Mutex::Autolock _l(mLock); return mMaxSize; } void TextureCache::setMaxSize(uint32_t maxSize) { + Mutex::Autolock _l(mLock); mMaxSize = maxSize; while (mSize > mMaxSize) { mCache.removeOldest(); @@ -83,12 +89,9 @@ void TextureCache::setMaxSize(uint32_t maxSize) { /////////////////////////////////////////////////////////////////////////////// void TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) { - if (bitmap) { - const uint32_t size = bitmap->rowBytes() * bitmap->height(); - mSize -= size; - } - + // This will be called already locked if (texture) { + mSize -= texture->bitmapSize; glDeleteTextures(1, &texture->id); delete texture; } @@ -99,6 +102,8 @@ void TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) { /////////////////////////////////////////////////////////////////////////////// Texture* TextureCache::get(SkBitmap* bitmap) { + Mutex::Autolock _l(mLock); + Texture* texture = mCache.get(bitmap); if (!texture) { if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) { @@ -115,6 +120,7 @@ Texture* TextureCache::get(SkBitmap* bitmap) { } texture = new Texture; + texture->bitmapSize = size; generateTexture(bitmap, texture, false); if (size < mMaxSize) { @@ -131,15 +137,18 @@ Texture* TextureCache::get(SkBitmap* bitmap) { } void TextureCache::remove(SkBitmap* bitmap) { + Mutex::Autolock _l(mLock); mCache.remove(bitmap); } void TextureCache::clear() { + Mutex::Autolock _l(mLock); mCache.clear(); } void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) { SkAutoLockPixels alp(*bitmap); + if (!bitmap->readyToDraw()) { LOGE("Cannot generate texture from bitmap"); return; @@ -159,6 +168,7 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege switch (bitmap->getConfig()) { case SkBitmap::kA8_Config: texture->blend = true; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap->getPixels()); break; @@ -175,6 +185,7 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege texture->blend = !bitmap->isOpaque(); break; default: + LOGW("Unsupported bitmap config"); break; } diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index b5e4c7c19038f..847d69c93d11e 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -86,6 +86,8 @@ private: uint32_t mSize; uint32_t mMaxSize; GLint mMaxTextureSize; + + mutable Mutex mLock; }; // class TextureCache }; // namespace uirenderer