Fix possible infinite loop when purging textures.
Change-Id: Ib05b398ae03e734da2dab0496df416fed4570b1c
diff --git a/libs/hwui/GenerationCache.h b/libs/hwui/GenerationCache.h
index c358c80..c42a5d8 100644
--- a/libs/hwui/GenerationCache.h
+++ b/libs/hwui/GenerationCache.h
@@ -143,11 +143,7 @@
}
ssize_t index = mCache.indexOfKey(key);
- if (index >= 0) {
- sp<Entry<K, V> > entry = mCache.valueAt(index);
- detachFromCache(entry);
- addToCache(entry, key, value);
- } else {
+ if (index < 0) {
sp<Entry<K, V> > entry = new Entry<K, V>;
addToCache(entry, key, value);
}
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index e874a16..6dad831 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 <utils/ResourceTypes.h>
+
#include "Patch.h"
#include "GenerationCache.h"
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 90f548b..817f143 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -28,6 +28,7 @@
struct Texture {
Texture() {
cleanup = false;
+ bitmapSize = 0;
}
/**
@@ -54,6 +55,10 @@
* 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 753c544..e558870 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -18,6 +18,8 @@
#include <GLES2/gl2.h>
+#include <utils/threads.h>
+
#include "TextureCache.h"
#include "Properties.h"
@@ -49,6 +51,7 @@
}
TextureCache::~TextureCache() {
+ Mutex::Autolock _l(mLock);
mCache.clear();
}
@@ -64,14 +67,17 @@
///////////////////////////////////////////////////////////////////////////////
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::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 @@
///////////////////////////////////////////////////////////////////////////////
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 = new Texture;
+ texture->bitmapSize = size;
generateTexture(bitmap, texture, false);
if (size < mMaxSize) {
@@ -131,15 +137,18 @@
}
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 @@
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 @@
texture->blend = !bitmap->isOpaque();
break;
default:
+ LOGW("Unsupported bitmap config");
break;
}
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index b5e4c7c..847d69c 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -86,6 +86,8 @@
uint32_t mSize;
uint32_t mMaxSize;
GLint mMaxTextureSize;
+
+ mutable Mutex mLock;
}; // class TextureCache
}; // namespace uirenderer