Merge "Fix crash when Paths are GCd in hw accelerated apps" into honeycomb

This commit is contained in:
Mike Cleron
2011-02-04 15:29:28 -08:00
committed by Android (Google) Code Review
5 changed files with 67 additions and 1 deletions

View File

@@ -36,7 +36,8 @@ public:
static void finalizer(JNIEnv* env, jobject clazz, SkPath* obj) { static void finalizer(JNIEnv* env, jobject clazz, SkPath* obj) {
#ifdef USE_OPENGL_RENDERER #ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) { if (android::uirenderer::Caches::hasInstance()) {
android::uirenderer::Caches::getInstance().pathCache.removeDeferred(obj); android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
return;
} }
#endif #endif
delete obj; delete obj;

View File

@@ -95,6 +95,10 @@ void DisplayList::clearResources() {
delete mPaths.itemAt(i); delete mPaths.itemAt(i);
} }
mPaths.clear(); mPaths.clear();
for (size_t i = 0; i < mOriginalPaths.size(); i++) {
caches.resourceCache.decrementRefcount(mOriginalPaths.itemAt(i));
}
mOriginalPaths.clear();
for (size_t i = 0; i < mMatrices.size(); i++) { for (size_t i = 0; i < mMatrices.size(); i++) {
delete mMatrices.itemAt(i); delete mMatrices.itemAt(i);
@@ -146,6 +150,13 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
mPaths.add(paths.itemAt(i)); mPaths.add(paths.itemAt(i));
} }
const Vector<SkPath*> &originalPaths = recorder.getOriginalPaths();
for (size_t i = 0; i < originalPaths.size(); i++) {
SkPath* path = originalPaths.itemAt(i);
mOriginalPaths.add(path);
caches.resourceCache.incrementRefcount(path);
}
const Vector<SkMatrix*> &matrices = recorder.getMatrices(); const Vector<SkMatrix*> &matrices = recorder.getMatrices();
for (size_t i = 0; i < matrices.size(); i++) { for (size_t i = 0; i < matrices.size(); i++) {
mMatrices.add(matrices.itemAt(i)); mMatrices.add(matrices.itemAt(i));
@@ -519,6 +530,12 @@ void DisplayListRenderer::reset() {
} }
mBitmapResources.clear(); mBitmapResources.clear();
for (size_t i = 0; i < mOriginalPaths.size(); i++) {
SkPath* resource = mOriginalPaths.itemAt(i);
caches.resourceCache.decrementRefcount(resource);
}
mOriginalPaths.clear();
for (size_t i = 0; i < mShaders.size(); i++) { for (size_t i = 0; i < mShaders.size(); i++) {
caches.resourceCache.decrementRefcount(mShaders.itemAt(i)); caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
} }

View File

@@ -190,6 +190,7 @@ private:
Vector<SkPaint*> mPaints; Vector<SkPaint*> mPaints;
Vector<SkPath*> mPaths; Vector<SkPath*> mPaths;
Vector<SkPath*> mOriginalPaths;
Vector<SkMatrix*> mMatrices; Vector<SkMatrix*> mMatrices;
Vector<SkiaShader*> mShaders; Vector<SkiaShader*> mShaders;
@@ -293,6 +294,10 @@ public:
return mPaths; return mPaths;
} }
const Vector<SkPath*>& getOriginalPaths() const {
return mOriginalPaths;
}
const Vector<SkMatrix*>& getMatrices() const { const Vector<SkMatrix*>& getMatrices() const {
return mMatrices; return mMatrices;
} }
@@ -371,6 +376,9 @@ private:
if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) { if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
if (pathCopy == NULL) { if (pathCopy == NULL) {
pathCopy = path; pathCopy = path;
mOriginalPaths.add(path);
Caches& caches = Caches::getInstance();
caches.resourceCache.incrementRefcount(path);
} else { } else {
pathCopy = new SkPath(*path); pathCopy = new SkPath(*path);
mPaths.add(pathCopy); mPaths.add(pathCopy);
@@ -452,6 +460,7 @@ private:
Vector<SkPaint*> mPaints; Vector<SkPaint*> mPaints;
DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap; DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
Vector<SkPath*> mOriginalPaths;
Vector<SkPath*> mPaths; Vector<SkPath*> mPaths;
DefaultKeyedVector<SkPath*, SkPath*> mPathMap; DefaultKeyedVector<SkPath*, SkPath*> mPathMap;

View File

@@ -65,6 +65,10 @@ void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
incrementRefcount((void*)bitmapResource, kBitmap); incrementRefcount((void*)bitmapResource, kBitmap);
} }
void ResourceCache::incrementRefcount(SkPath* pathResource) {
incrementRefcount((void*)pathResource, kPath);
}
void ResourceCache::incrementRefcount(SkiaShader* shaderResource) { void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
shaderResource->getSkShader()->safeRef(); shaderResource->getSkShader()->safeRef();
incrementRefcount((void*) shaderResource, kShader); incrementRefcount((void*) shaderResource, kShader);
@@ -94,6 +98,10 @@ void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
decrementRefcount((void*) bitmapResource); decrementRefcount((void*) bitmapResource);
} }
void ResourceCache::decrementRefcount(SkPath* pathResource) {
decrementRefcount((void*) pathResource);
}
void ResourceCache::decrementRefcount(SkiaShader* shaderResource) { void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
shaderResource->getSkShader()->safeUnref(); shaderResource->getSkShader()->safeUnref();
decrementRefcount((void*) shaderResource); decrementRefcount((void*) shaderResource);
@@ -122,6 +130,24 @@ void ResourceCache::recycle(SkBitmap* resource) {
} }
} }
void ResourceCache::destructor(SkPath* resource) {
Mutex::Autolock _l(mLock);
ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
if (ref == NULL) {
// If we're not tracking this resource, just delete it
if (Caches::hasInstance()) {
Caches::getInstance().pathCache.removeDeferred(resource);
}
delete resource;
return;
}
ref->destroyed = true;
if (ref->refCount == 0) {
deleteResourceReference(resource, ref);
return;
}
}
void ResourceCache::destructor(SkBitmap* resource) { void ResourceCache::destructor(SkBitmap* resource) {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
@@ -192,6 +218,15 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r
delete bitmap; delete bitmap;
} }
break; break;
case kPath:
{
SkPath* path = (SkPath*)resource;
if (Caches::hasInstance()) {
Caches::getInstance().pathCache.removeDeferred(path);
}
delete path;
}
break;
case kShader: case kShader:
{ {
SkiaShader* shader = (SkiaShader*)resource; SkiaShader* shader = (SkiaShader*)resource;

View File

@@ -32,6 +32,7 @@ enum ResourceType {
kBitmap, kBitmap,
kShader, kShader,
kColorFilter, kColorFilter,
kPath,
}; };
class ResourceReference { class ResourceReference {
@@ -53,15 +54,18 @@ class ResourceCache {
public: public:
ResourceCache(); ResourceCache();
~ResourceCache(); ~ResourceCache();
void incrementRefcount(SkPath* resource);
void incrementRefcount(SkBitmap* resource); void incrementRefcount(SkBitmap* resource);
void incrementRefcount(SkiaShader* resource); void incrementRefcount(SkiaShader* resource);
void incrementRefcount(SkiaColorFilter* resource); void incrementRefcount(SkiaColorFilter* resource);
void incrementRefcount(const void* resource, ResourceType resourceType); void incrementRefcount(const void* resource, ResourceType resourceType);
void decrementRefcount(void* resource); void decrementRefcount(void* resource);
void decrementRefcount(SkBitmap* resource); void decrementRefcount(SkBitmap* resource);
void decrementRefcount(SkPath* resource);
void decrementRefcount(SkiaShader* resource); void decrementRefcount(SkiaShader* resource);
void decrementRefcount(SkiaColorFilter* resource); void decrementRefcount(SkiaColorFilter* resource);
void recycle(SkBitmap* resource); void recycle(SkBitmap* resource);
void destructor(SkPath* resource);
void destructor(SkBitmap* resource); void destructor(SkBitmap* resource);
void destructor(SkiaShader* resource); void destructor(SkiaShader* resource);
void destructor(SkiaColorFilter* resource); void destructor(SkiaColorFilter* resource);