summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/jni/android/graphics/Path.cpp10
-rw-r--r--libs/hwui/DisplayList.cpp15
-rw-r--r--libs/hwui/DisplayList.h3
-rw-r--r--libs/hwui/DisplayListRenderer.h19
-rw-r--r--libs/hwui/PathCache.cpp61
-rw-r--r--libs/hwui/PathCache.h17
-rw-r--r--libs/hwui/ResourceCache.cpp44
-rw-r--r--libs/hwui/ResourceCache.h7
8 files changed, 36 insertions, 140 deletions
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 831ce09..f7b5dc2 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -27,7 +27,7 @@
#include "SkPath.h"
#include "SkPathOps.h"
-#include <ResourceCache.h>
+#include <Caches.h>
#include <vector>
#include <map>
@@ -38,11 +38,11 @@ public:
static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- if (android::uirenderer::ResourceCache::hasInstance()) {
- android::uirenderer::ResourceCache::getInstance().destructor(obj);
- } else {
- delete obj;
+ // Purge entries from the HWUI path cache if this path's data is unique
+ if (obj->unique() && android::uirenderer::Caches::hasInstance()) {
+ android::uirenderer::Caches::getInstance().pathCache.removeDeferred(obj);
}
+ delete obj;
}
static jlong init1(JNIEnv* env, jobject clazz) {
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 317e395..4540bec 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -49,18 +49,21 @@ void DisplayListData::cleanupResources() {
resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
}
- for (size_t i = 0; i < sourcePaths.size(); i++) {
- resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
- }
-
resourceCache.unlock();
+ for (size_t i = 0; i < pathResources.size(); i++) {
+ const SkPath* path = pathResources.itemAt(i);
+ if (path->unique() && Caches::hasInstance()) {
+ Caches::getInstance().pathCache.removeDeferred(path);
+ }
+ delete path;
+ }
+
bitmapResources.clear();
patchResources.clear();
- sourcePaths.clear();
+ pathResources.clear();
paints.clear();
regions.clear();
- paths.clear();
}
size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 011b509..3178584 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -134,12 +134,11 @@ public:
int projectionReceiveIndex;
Vector<const SkBitmap*> bitmapResources;
+ Vector<const SkPath*> pathResources;
Vector<const Res_png_9patch*> patchResources;
std::vector<std::unique_ptr<const SkPaint>> paints;
std::vector<std::unique_ptr<const SkRegion>> regions;
- std::vector<std::unique_ptr<const SkPath>> paths;
- SortedVector<const SkPath*> sourcePaths;
Vector<Functor*> functors;
const Vector<Chunk>& getChunks() const {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index d313c18..48ecd69 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -282,21 +282,10 @@ private:
inline const SkPath* refPath(const SkPath* path) {
if (!path) return nullptr;
- const SkPath* cachedPath = mPathMap.valueFor(path);
- if (cachedPath == nullptr || cachedPath->getGenerationID() != path->getGenerationID()) {
- SkPath* newPathCopy = new SkPath(*path);
- newPathCopy->setSourcePath(path);
- cachedPath = newPathCopy;
- std::unique_ptr<const SkPath> copy(newPathCopy);
- mDisplayListData->paths.push_back(std::move(copy));
-
- // replaceValueFor() performs an add if the entry doesn't exist
- mPathMap.replaceValueFor(path, cachedPath);
- }
- if (mDisplayListData->sourcePaths.indexOf(path) < 0) {
- mResourceCache.incrementRefcount(path);
- mDisplayListData->sourcePaths.add(path);
- }
+ // The points/verbs within the path are refcounted so this copy operation
+ // is inexpensive and maintains the generationID of the original path.
+ const SkPath* cachedPath = new SkPath(*path);
+ mDisplayListData->pathResources.add(cachedPath);
return cachedPath;
}
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index e2caf8b..5b2e5e2 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -362,22 +362,9 @@ void PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) {
// Paths
///////////////////////////////////////////////////////////////////////////////
-void PathCache::remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair) {
- LruCache<PathDescription, PathTexture*>::Iterator i(mCache);
-
- while (i.next()) {
- const PathDescription& key = i.key();
- if (key.type == kShapePath &&
- (key.shape.path.mPath == pair.getFirst() ||
- key.shape.path.mPath == pair.getSecond())) {
- pathsToRemove.push(key);
- }
- }
-}
-
-void PathCache::removeDeferred(SkPath* path) {
+void PathCache::removeDeferred(const SkPath* path) {
Mutex::Autolock l(mLock);
- mGarbage.push(path_pair_t(path, const_cast<SkPath*>(path->getSourcePath())));
+ mGarbage.push(path->getGenerationID());
}
void PathCache::clearGarbage() {
@@ -387,9 +374,15 @@ void PathCache::clearGarbage() {
Mutex::Autolock l(mLock);
size_t count = mGarbage.size();
for (size_t i = 0; i < count; i++) {
- const path_pair_t& pair = mGarbage.itemAt(i);
- remove(pathsToRemove, pair);
- delete pair.getFirst();
+ const uint32_t generationID = mGarbage.itemAt(i);
+
+ LruCache<PathDescription, PathTexture*>::Iterator iter(mCache);
+ while (iter.next()) {
+ const PathDescription& key = iter.key();
+ if (key.type == kShapePath && key.shape.path.mGenerationID == generationID) {
+ pathsToRemove.push(key);
+ }
+ }
}
mGarbage.clear();
}
@@ -399,27 +392,9 @@ void PathCache::clearGarbage() {
}
}
-/**
- * To properly handle path mutations at draw time we always make a copy
- * of paths objects when recording display lists. The source path points
- * to the path we originally copied the path from. This ensures we use
- * the original path as a cache key the first time a path is inserted
- * in the cache. The source path is also used to reclaim garbage when a
- * Dalvik Path object is collected.
- */
-static const SkPath* getSourcePath(const SkPath* path) {
- const SkPath* sourcePath = path->getSourcePath();
- if (sourcePath && sourcePath->getGenerationID() == path->getGenerationID()) {
- return const_cast<SkPath*>(sourcePath);
- }
- return path;
-}
-
PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) {
- path = getSourcePath(path);
-
PathDescription entry(kShapePath, paint);
- entry.shape.path.mPath = path;
+ entry.shape.path.mGenerationID = path->getGenerationID();
PathTexture* texture = mCache.get(entry);
@@ -442,11 +417,6 @@ PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) {
texture = nullptr;
mCache.remove(entry);
}
- } else if (path->getGenerationID() != texture->generation) {
- // The size of the path might have changed so we first
- // remove the entry from the cache
- mCache.remove(entry);
- texture = addTexture(entry, path, paint);
}
}
@@ -458,19 +428,14 @@ void PathCache::precache(const SkPath* path, const SkPaint* paint) {
return;
}
- path = getSourcePath(path);
-
PathDescription entry(kShapePath, paint);
- entry.shape.path.mPath = path;
+ entry.shape.path.mGenerationID = path->getGenerationID();
PathTexture* texture = mCache.get(entry);
bool generate = false;
if (!texture) {
generate = true;
- } else if (path->getGenerationID() != texture->generation) {
- mCache.remove(entry);
- generate = true;
}
if (generate) {
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 7378018..23e35cb 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -118,7 +118,7 @@ struct PathDescription {
SkPathEffect* pathEffect;
union Shape {
struct Path {
- const SkPath* mPath;
+ uint32_t mGenerationID;
} path;
struct RoundRect {
float mWidth;
@@ -198,7 +198,7 @@ public:
* Removes the specified path. This is meant to be called from threads
* that are not the EGL context thread.
*/
- void removeDeferred(SkPath* path);
+ ANDROID_API void removeDeferred(const SkPath* path);
/**
* Process deferred removals.
*/
@@ -227,8 +227,6 @@ public:
float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
private:
- typedef Pair<SkPath*, SkPath*> path_pair_t;
-
PathTexture* addTexture(const PathDescription& entry,
const SkPath *path, const SkPaint* paint);
PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap);
@@ -245,12 +243,6 @@ private:
}
/**
- * Removes an entry.
- * The pair must define first=path, second=sourcePath
- */
- void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair);
-
- /**
* Ensures there is enough space in the cache for a texture of the specified
* dimensions.
*/
@@ -279,8 +271,7 @@ private:
delete future()->get();
}
- // copied, since input path not refcounted / guaranteed to survive for duration of task
- // TODO: avoid deep copy with refcounting
+ // copied, since input path not guaranteed to survive for duration of task
const SkPath path;
// copied, since input paint may not be immutable
@@ -308,7 +299,7 @@ private:
sp<PathProcessor> mProcessor;
- Vector<path_pair_t> mGarbage;
+ Vector<uint32_t> mGarbage;
mutable Mutex mLock;
}; // class PathCache
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 2d1adc5..d3b8d70 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -79,10 +79,6 @@ void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType)
incrementRefcountLocked(resource, resourceType);
}
-void ResourceCache::incrementRefcount(const SkPath* pathResource) {
- incrementRefcount((void*) pathResource, kPath);
-}
-
void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
incrementRefcount((void*) patchResource, kNinePatch);
}
@@ -107,10 +103,6 @@ void ResourceCache::decrementRefcount(const SkBitmap* bitmapResource) {
decrementRefcountLocked(bitmapResource);
}
-void ResourceCache::decrementRefcount(const SkPath* pathResource) {
- decrementRefcount((void*) pathResource);
-}
-
void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
@@ -145,37 +137,10 @@ void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) {
}
}
-void ResourceCache::decrementRefcountLocked(const SkPath* pathResource) {
- decrementRefcountLocked((void*) pathResource);
-}
-
void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
decrementRefcountLocked((void*) patchResource);
}
-void ResourceCache::destructor(SkPath* resource) {
- Mutex::Autolock _l(mLock);
- destructorLocked(resource);
-}
-
-void ResourceCache::destructorLocked(SkPath* resource) {
- ssize_t index = mCache->indexOfKey(resource);
- ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
- if (ref == nullptr) {
- // If we're not tracking this resource, just delete it
- if (Caches::hasInstance()) {
- Caches::getInstance().pathCache.removeDeferred(resource);
- } else {
- delete resource;
- }
- return;
- }
- ref->destroyed = true;
- if (ref->refCount == 0) {
- deleteResourceReferenceLocked(resource, ref);
- }
-}
-
void ResourceCache::destructor(Res_png_9patch* resource) {
Mutex::Autolock _l(mLock);
destructorLocked(resource);
@@ -208,15 +173,6 @@ void ResourceCache::destructorLocked(Res_png_9patch* resource) {
void ResourceCache::deleteResourceReferenceLocked(const void* resource, ResourceReference* ref) {
if (ref->destroyed) {
switch (ref->resourceType) {
- case kPath: {
- SkPath* path = (SkPath*) resource;
- if (Caches::hasInstance()) {
- Caches::getInstance().pathCache.removeDeferred(path);
- } else {
- delete path;
- }
- }
- break;
case kNinePatch: {
if (Caches::hasInstance()) {
Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 4333792..fae55d1 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -20,7 +20,6 @@
#include <cutils/compiler.h>
#include <SkBitmap.h>
-#include <SkPath.h>
#include <SkPixelRef.h>
#include <utils/KeyedVector.h>
@@ -38,7 +37,6 @@ class Layer;
*/
enum ResourceType {
kNinePatch,
- kPath
};
class ResourceReference {
@@ -105,21 +103,16 @@ public:
*/
const SkBitmap* insert(const SkBitmap* resource);
- void incrementRefcount(const SkPath* resource);
void incrementRefcount(const Res_png_9patch* resource);
void decrementRefcount(const SkBitmap* resource);
- void decrementRefcount(const SkPath* resource);
void decrementRefcount(const Res_png_9patch* resource);
void decrementRefcountLocked(const SkBitmap* resource);
- void decrementRefcountLocked(const SkPath* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
- void destructor(SkPath* resource);
void destructor(Res_png_9patch* resource);
- void destructorLocked(SkPath* resource);
void destructorLocked(Res_png_9patch* resource);
private: