Purge Skia objects from GL caches as needed.
Change-Id: I754c671cf790ad5ae8bf047ad328034217da4ecc
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index fda57b8..9c67885 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -17,7 +17,9 @@
#ifndef ANDROID_UI_CACHES_H
#define ANDROID_UI_CACHES_H
-#define LOG_TAG "OpenGLRenderer"
+#ifndef LOG_TAG
+ #define LOG_TAG "OpenGLRenderer"
+#endif
#include <utils/Singleton.h>
diff --git a/libs/hwui/GenerationCache.h b/libs/hwui/GenerationCache.h
index c42a5d8..070e33f 100644
--- a/libs/hwui/GenerationCache.h
+++ b/libs/hwui/GenerationCache.h
@@ -61,6 +61,7 @@
bool contains(K key) const;
V get(K key);
+ K getKeyAt(uint32_t index) const;
void put(K key, V value);
V remove(K key);
V removeOldest();
@@ -122,6 +123,11 @@
}
template<typename K, typename V>
+K GenerationCache<K, V>::getKeyAt(uint32_t index) const {
+ return mCache.keyAt(index);
+}
+
+template<typename K, typename V>
V GenerationCache<K, V>::get(K key) {
ssize_t index = mCache.indexOfKey(key);
if (index >= 0) {
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 58920bd..9957370 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -21,6 +21,8 @@
#include <SkCanvas.h>
#include <SkGradientShader.h>
+#include <utils/threads.h>
+
#include "GradientCache.h"
#include "Properties.h"
@@ -52,6 +54,7 @@
}
GradientCache::~GradientCache() {
+ Mutex::Autolock _l(mLock);
mCache.clear();
}
@@ -60,14 +63,17 @@
///////////////////////////////////////////////////////////////////////////////
uint32_t GradientCache::getSize() {
+ Mutex::Autolock _l(mLock);
return mSize;
}
uint32_t GradientCache::getMaxSize() {
+ Mutex::Autolock _l(mLock);
return mMaxSize;
}
void GradientCache::setMaxSize(uint32_t maxSize) {
+ Mutex::Autolock _l(mLock);
mMaxSize = maxSize;
while (mSize > mMaxSize) {
mCache.removeOldest();
@@ -79,6 +85,7 @@
///////////////////////////////////////////////////////////////////////////////
void GradientCache::operator()(SkShader*& shader, Texture*& texture) {
+ // Already locked here
if (shader) {
const uint32_t size = texture->width * texture->height * 4;
mSize -= size;
@@ -95,14 +102,17 @@
///////////////////////////////////////////////////////////////////////////////
Texture* GradientCache::get(SkShader* shader) {
+ Mutex::Autolock _l(mLock);
return mCache.get(shader);
}
void GradientCache::remove(SkShader* shader) {
+ Mutex::Autolock _l(mLock);
mCache.remove(shader);
}
void GradientCache::clear() {
+ Mutex::Autolock _l(mLock);
mCache.clear();
}
@@ -128,17 +138,21 @@
canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p);
+ mLock.lock();
// Asume the cache is always big enough
const uint32_t size = bitmap.rowBytes() * bitmap.height();
while (mSize + size > mMaxSize) {
mCache.removeOldest();
}
+ mLock.unlock();
Texture* texture = new Texture;
generateTexture(&bitmap, texture);
+ mLock.lock();
mSize += size;
mCache.put(shader, texture);
+ mLock.unlock();
return texture;
}
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 8795920..51a8c01 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -82,6 +82,12 @@
uint32_t mSize;
uint32_t mMaxSize;
+
+ /**
+ * Used to access mCache and mSize. All methods are accessed from a single
+ * thread except for remove().
+ */
+ mutable Mutex mLock;
}; // class GradientCache
}; // namespace uirenderer
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 158c0cc..e8afe37 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -21,6 +21,8 @@
#include <SkCanvas.h>
#include <SkRect.h>
+#include <utils/threads.h>
+
#include "PathCache.h"
#include "Properties.h"
@@ -51,6 +53,7 @@
}
PathCache::~PathCache() {
+ Mutex::Autolock _l(mLock);
mCache.clear();
}
@@ -67,14 +70,17 @@
///////////////////////////////////////////////////////////////////////////////
uint32_t PathCache::getSize() {
+ Mutex::Autolock _l(mLock);
return mSize;
}
uint32_t PathCache::getMaxSize() {
+ Mutex::Autolock _l(mLock);
return mMaxSize;
}
void PathCache::setMaxSize(uint32_t maxSize) {
+ Mutex::Autolock _l(mLock);
mMaxSize = maxSize;
while (mSize > mMaxSize) {
mCache.removeOldest();
@@ -99,14 +105,30 @@
// Caching
///////////////////////////////////////////////////////////////////////////////
+void PathCache::remove(SkPath* path) {
+ Mutex::Autolock _l(mLock);
+ // TODO: Linear search...
+ for (uint32_t i = 0; i < mCache.size(); i++) {
+ if (mCache.getKeyAt(i).path == path) {
+ mCache.removeAt(i);
+ return;
+ }
+ }
+}
+
PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
PathCacheEntry entry(path, paint);
+
+ mLock.lock();
PathTexture* texture = mCache.get(entry);
+ mLock.unlock();
if (!texture) {
texture = addTexture(entry, path, paint);
} else if (path->getGenerationID() != texture->generation) {
+ mLock.lock();
mCache.remove(entry);
+ mLock.unlock();
texture = addTexture(entry, path, paint);
}
@@ -132,9 +154,11 @@
const uint32_t size = width * height;
// Don't even try to cache a bitmap that's bigger than the cache
if (size < mMaxSize) {
+ mLock.lock();
while (mSize + size > mMaxSize) {
mCache.removeOldest();
}
+ mLock.unlock();
}
PathTexture* texture = new PathTexture;
@@ -157,8 +181,10 @@
generateTexture(bitmap, texture);
if (size < mMaxSize) {
+ mLock.lock();
mSize += size;
mCache.put(entry, texture);
+ mLock.unlock();
} else {
texture->cleanup = true;
}
@@ -167,6 +193,7 @@
}
void PathCache::clear() {
+ Mutex::Autolock _l(mLock);
mCache.clear();
}
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 522e5e0..bde0e7d 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -114,6 +114,10 @@
* Clears the cache. This causes all textures to be deleted.
*/
void clear();
+ /**
+ * Removes an entry.
+ */
+ void remove(SkPath* path);
/**
* Sets the maximum size of the cache in bytes.
@@ -143,6 +147,12 @@
uint32_t mSize;
uint32_t mMaxSize;
GLuint mMaxTextureSize;
+
+ /**
+ * Used to access mCache and mSize. All methods are accessed from a single
+ * thread except for remove().
+ */
+ mutable Mutex mLock;
}; // class PathCache
}; // namespace uirenderer
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index e558870..927070a 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -102,9 +102,10 @@
///////////////////////////////////////////////////////////////////////////////
Texture* TextureCache::get(SkBitmap* bitmap) {
- Mutex::Autolock _l(mLock);
-
+ mLock.lock();
Texture* texture = mCache.get(bitmap);
+ mLock.unlock();
+
if (!texture) {
if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
LOGW("Bitmap too large to be uploaded into a texture");
@@ -114,9 +115,11 @@
const uint32_t size = bitmap->rowBytes() * bitmap->height();
// Don't even try to cache a bitmap that's bigger than the cache
if (size < mMaxSize) {
+ mLock.lock();
while (mSize + size > mMaxSize) {
mCache.removeOldest();
}
+ mLock.unlock();
}
texture = new Texture;
@@ -124,8 +127,10 @@
generateTexture(bitmap, texture, false);
if (size < mMaxSize) {
+ mLock.lock();
mSize += size;
mCache.put(bitmap, texture);
+ mLock.unlock();
} else {
texture->cleanup = true;
}
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 847d69c..a63789a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -87,6 +87,10 @@
uint32_t mMaxSize;
GLint mMaxTextureSize;
+ /**
+ * Used to access mCache and mSize. All methods are accessed from a single
+ * thread except for remove().
+ */
mutable Mutex mLock;
}; // class TextureCache