diff options
author | Digish Pandya <digishp@codeaurora.org> | 2015-11-04 11:00:28 +0530 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2015-11-11 09:49:36 -0800 |
commit | 2ddda0b9eaec9da3579d1ffa53345172a57223b9 (patch) | |
tree | 324eb7055df6ccc5dc6c26ff3b3ee39772d79d91 /libs | |
parent | cad38223498ab06b33112039d9b5590092ba2264 (diff) | |
download | frameworks_base-2ddda0b9eaec9da3579d1ffa53345172a57223b9.zip frameworks_base-2ddda0b9eaec9da3579d1ffa53345172a57223b9.tar.gz frameworks_base-2ddda0b9eaec9da3579d1ffa53345172a57223b9.tar.bz2 |
Fix HWUI Path Cache dangling pointer
When precache, PathTexture is added to PathCache, and it is released after drawn if we want to clean it.
But the PathCache LRU still holds the entry of the PathTexture object. When trim the cache in
the end of each frame, LRU finds that its mListener is not NULL and invoke the functor, however,
mListerer points to the released PathTexture object and is a dangling pointer, thus leads to crash.
Smart pointer don't help here since they only manage scopes, while PathTexture is also controled by
its cleanup field.
The fix is to also remove the LRU entry of PathTexture*, it will also release the texture object
and there won't be texture leaks.
Change-Id: Iaa0621df5dc71532e9e75b38ad94384353930b95
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/PathCache.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/PathCache.h | 1 |
3 files changed, 12 insertions, 1 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 2292ef4..9621b54 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2325,12 +2325,15 @@ void OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) { PathTexture* texture = mCaches.pathCache.get(path, paint); if (!texture) return; - const AutoTexture autoCleanup(texture); const float x = texture->left - texture->offset; const float y = texture->top - texture->offset; drawPathTexture(texture, x, y, paint); + + if (texture->cleanup) { + mCaches.pathCache.remove(path, paint); + } mDirty = true; } diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 3af640f..3236f6f 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -400,6 +400,13 @@ PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) { return texture; } +void PathCache::remove(const SkPath* path, const SkPaint* paint) +{ + PathDescription entry(kShapePath, paint); + entry.shape.path.mGenerationID = path->getGenerationID(); + mCache.remove(entry); +} + void PathCache::precache(const SkPath* path, const SkPaint* paint) { if (!Caches::getInstance().tasks.canRunTasks()) { return; diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index 7014863..c529915 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -201,6 +201,7 @@ public: PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint); PathTexture* get(const SkPath* path, const SkPaint* paint); + void remove(const SkPath* path, const SkPaint* paint); /** * Removes the specified path. This is meant to be called from threads |