Merge "Purge Skia objects from GL caches as needed."
This commit is contained in:
@@ -254,7 +254,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);
|
||||
if (android::uirenderer::Caches::hasInstance()) {
|
||||
android::uirenderer::Caches::getInstance().textureCache.remove(bitmap);
|
||||
}
|
||||
#endif
|
||||
delete bitmap;
|
||||
}
|
||||
|
||||
@@ -26,12 +26,19 @@
|
||||
|
||||
#include "SkPath.h"
|
||||
|
||||
#include <Caches.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class SkPathGlue {
|
||||
public:
|
||||
|
||||
static void finalizer(JNIEnv* env, jobject clazz, SkPath* obj) {
|
||||
#ifdef USE_OPENGL_RENDERER
|
||||
if (android::uirenderer::Caches::hasInstance()) {
|
||||
android::uirenderer::Caches::getInstance().pathCache.remove(obj);
|
||||
}
|
||||
#endif
|
||||
delete obj;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "SkXfermode.h"
|
||||
|
||||
#include <SkiaShader.h>
|
||||
#include <Caches.h>
|
||||
|
||||
using namespace android::uirenderer;
|
||||
|
||||
@@ -52,6 +53,11 @@ static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArra
|
||||
|
||||
static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader)
|
||||
{
|
||||
#ifdef USE_OPENGL_RENDERER
|
||||
if (android::uirenderer::Caches::hasInstance()) {
|
||||
android::uirenderer::Caches::getInstance().gradientCache.remove(shader);
|
||||
}
|
||||
#endif
|
||||
delete skiaShader;
|
||||
shader->safeUnref();
|
||||
}
|
||||
|
||||
@@ -37,6 +37,11 @@ public:
|
||||
}
|
||||
return *instance;
|
||||
}
|
||||
|
||||
static bool hasInstance() {
|
||||
Mutex::Autolock _l(sLock);
|
||||
return sInstance != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
~Singleton() { };
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
|
||||
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();
|
||||
@@ -121,6 +122,11 @@ bool GenerationCache<K, V>::contains(K key) const {
|
||||
return mCache.indexOfKey(key) >= 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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(uint32_t maxByteSize):
|
||||
}
|
||||
|
||||
GradientCache::~GradientCache() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mCache.clear();
|
||||
}
|
||||
|
||||
@@ -60,14 +63,17 @@ GradientCache::~GradientCache() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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::setMaxSize(uint32_t maxSize) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 @@ void GradientCache::operator()(SkShader*& shader, Texture*& texture) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 @@ Texture* GradientCache::addLinearGradient(SkShader* shader, float* bounds, uint3
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,12 @@ private:
|
||||
|
||||
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
|
||||
|
||||
@@ -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(uint32_t maxByteSize):
|
||||
}
|
||||
|
||||
PathCache::~PathCache() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mCache.clear();
|
||||
}
|
||||
|
||||
@@ -67,14 +70,17 @@ void PathCache::init() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 @@ void PathCache::operator()(PathCacheEntry& path, PathTexture*& texture) {
|
||||
// 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 @@ PathTexture* PathCache::addTexture(const PathCacheEntry& entry,
|
||||
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 @@ PathTexture* PathCache::addTexture(const PathCacheEntry& entry,
|
||||
generateTexture(bitmap, texture);
|
||||
|
||||
if (size < mMaxSize) {
|
||||
mLock.lock();
|
||||
mSize += size;
|
||||
mCache.put(entry, texture);
|
||||
mLock.unlock();
|
||||
} else {
|
||||
texture->cleanup = true;
|
||||
}
|
||||
@@ -167,6 +193,7 @@ PathTexture* PathCache::addTexture(const PathCacheEntry& entry,
|
||||
}
|
||||
|
||||
void PathCache::clear() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mCache.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,10 @@ public:
|
||||
* 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 @@ private:
|
||||
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
|
||||
|
||||
@@ -102,9 +102,10 @@ void TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 @@ Texture* TextureCache::get(SkBitmap* bitmap) {
|
||||
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 @@ Texture* TextureCache::get(SkBitmap* bitmap) {
|
||||
generateTexture(bitmap, texture, false);
|
||||
|
||||
if (size < mMaxSize) {
|
||||
mLock.lock();
|
||||
mSize += size;
|
||||
mCache.put(bitmap, texture);
|
||||
mLock.unlock();
|
||||
} else {
|
||||
texture->cleanup = true;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,10 @@ private:
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user