// correctly, such as creating the bitmap from scratch, drawing with it, changing its
// contents, and drawing again. The only fix would be to always copy it the first time,
// which doesn't seem worth the extra cycles for this unlikely case.
- const SkBitmap* cachedBitmap = mResourceCache.insert(bitmap);
- mDisplayListData->bitmapResources.add(cachedBitmap);
- return cachedBitmap;
+ const SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
+ alloc().autoDestroy(localBitmap);
+ mDisplayListData->bitmapResources.push_back(localBitmap);
+ return localBitmap;
}
inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
mLock.unlock();
}
-const SkBitmap* ResourceCache::insert(const SkBitmap& bitmapResource) {
- Mutex::Autolock _l(mLock);
-
- BitmapKey bitmapKey(bitmapResource);
- ssize_t index = mBitmapCache.indexOfKey(bitmapKey);
- if (index == NAME_NOT_FOUND) {
- SkBitmap* cachedBitmap = new SkBitmap(bitmapResource);
- index = mBitmapCache.add(bitmapKey, cachedBitmap);
- return cachedBitmap;
- }
-
- mBitmapCache.keyAt(index).mRefCount++;
- return mBitmapCache.valueAt(index);
-}
-
void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
Mutex::Autolock _l(mLock);
incrementRefcountLocked(resource, resourceType);
decrementRefcountLocked(resource);
}
-void ResourceCache::decrementRefcount(const SkBitmap* bitmapResource) {
- Mutex::Autolock _l(mLock);
- decrementRefcountLocked(bitmapResource);
-}
-
void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
}
}
-void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) {
- BitmapKey bitmapKey(*bitmapResource);
- ssize_t index = mBitmapCache.indexOfKey(bitmapKey);
-
- LOG_ALWAYS_FATAL_IF(index == NAME_NOT_FOUND,
- "Decrementing the reference of an untracked Bitmap");
-
- const BitmapKey& cacheEntry = mBitmapCache.keyAt(index);
- if (cacheEntry.mRefCount == 1) {
- // delete the bitmap and remove it from the cache
- delete mBitmapCache.valueAt(index);
- mBitmapCache.removeItemsAt(index);
- } else {
- cacheEntry.mRefCount--;
- }
-}
-
void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
decrementRefcountLocked((void*) patchResource);
}
delete ref;
}
-///////////////////////////////////////////////////////////////////////////////
-// Bitmap Key
-///////////////////////////////////////////////////////////////////////////////
-
-void BitmapKey::operator=(const BitmapKey& other) {
- this->mRefCount = other.mRefCount;
- this->mBitmapDimensions = other.mBitmapDimensions;
- this->mPixelRefOrigin = other.mPixelRefOrigin;
- this->mPixelRefStableID = other.mPixelRefStableID;
-}
-
-bool BitmapKey::operator==(const BitmapKey& other) const {
- return mPixelRefStableID == other.mPixelRefStableID &&
- mPixelRefOrigin == other.mPixelRefOrigin &&
- mBitmapDimensions == other.mBitmapDimensions;
-}
-
-bool BitmapKey::operator<(const BitmapKey& other) const {
- if (mPixelRefStableID != other.mPixelRefStableID) {
- return mPixelRefStableID < other.mPixelRefStableID;
- }
- if (mPixelRefOrigin.x() != other.mPixelRefOrigin.x()) {
- return mPixelRefOrigin.x() < other.mPixelRefOrigin.x();
- }
- if (mPixelRefOrigin.y() != other.mPixelRefOrigin.y()) {
- return mPixelRefOrigin.y() < other.mPixelRefOrigin.y();
- }
- if (mBitmapDimensions.width() != other.mBitmapDimensions.width()) {
- return mBitmapDimensions.width() < other.mBitmapDimensions.width();
- }
- return mBitmapDimensions.height() < other.mBitmapDimensions.height();
-}
-
}; // namespace uirenderer
}; // namespace android
ResourceType resourceType;
};
-class BitmapKey {
-public:
- BitmapKey(const SkBitmap& bitmap)
- : mRefCount(1)
- , mBitmapDimensions(bitmap.dimensions())
- , mPixelRefOrigin(bitmap.pixelRefOrigin())
- , mPixelRefStableID(bitmap.pixelRef()->getStableID()) { }
-
- void operator=(const BitmapKey& other);
- bool operator==(const BitmapKey& other) const;
- bool operator<(const BitmapKey& other) const;
-
-private:
- // This constructor is only used by the KeyedVector implementation
- BitmapKey()
- : mRefCount(-1)
- , mBitmapDimensions(SkISize::Make(0,0))
- , mPixelRefOrigin(SkIPoint::Make(0,0))
- , mPixelRefStableID(0) { }
-
- // reference count of all HWUI object using this bitmap
- mutable int mRefCount;
-
- SkISize mBitmapDimensions;
- SkIPoint mPixelRefOrigin;
- uint32_t mPixelRefStableID;
-
- friend class ResourceCache;
- friend struct android::key_value_pair_t<BitmapKey, SkBitmap*>;
-};
-
class ANDROID_API ResourceCache: public Singleton<ResourceCache> {
ResourceCache();
~ResourceCache();
void lock();
void unlock();
- /**
- * The cache stores a copy of the provided resource or refs an existing resource
- * if the bitmap has previously been inserted and returns the cached copy.
- */
- const SkBitmap* insert(const SkBitmap& resource);
-
void incrementRefcount(const Res_png_9patch* resource);
- void decrementRefcount(const SkBitmap* resource);
void decrementRefcount(const Res_png_9patch* resource);
- void decrementRefcountLocked(const SkBitmap* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
void destructor(Res_png_9patch* resource);
mutable Mutex mLock;
KeyedVector<const void*, ResourceReference*>* mCache;
- KeyedVector<BitmapKey, SkBitmap*> mBitmapCache;
};
}; // namespace uirenderer