const ScaledImageFragment* ImageDecodingStore::insertAndLockCache(const ImageFrameGenerator* generator, PassOwnPtr<ScaledImageFragment> image) { // Prune old cache entries to give space for the new one. prune(); ScaledImageFragment* newImage = image.get(); OwnPtr<ImageCacheEntry> newCacheEntry = ImageCacheEntry::createAndUse(generator, image); Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete; { MutexLocker lock(m_mutex); ImageCacheMap::iterator iter = m_imageCacheMap.find(newCacheEntry->cacheKey()); // It is rare but possible that the key of a new cache entry is found. // This happens if the generation ID of the image object wraps around. // In this case we will try to return the existing cached object and // discard the new cache object. if (iter != m_imageCacheMap.end()) { const ScaledImageFragment* oldImage; if (lockCacheEntryInternal(iter->value.get(), &oldImage, &cacheEntriesToDelete)) { newCacheEntry->decrementUseCount(); return oldImage; } } // The new image is not locked yet so do it here. newImage->bitmap().lockPixels(); insertCacheInternal(newCacheEntry.release(), &m_imageCacheMap, &m_imageCacheKeyMap); } return newImage; }
bool ImageDecodingStore::lockCacheEntryInternal(ImageCacheEntry* cacheEntry, const ScaledImageFragment** cachedImage, Vector<OwnPtr<CacheEntry> >* deletionList) { ScaledImageFragment* image = cacheEntry->cachedImage(); image->bitmap().lockPixels(); // Memory for this image entry might be discarded already. // In this case remove the entry. if (!image->bitmap().getPixels()) { image->bitmap().unlockPixels(); removeFromCacheInternal(cacheEntry, &m_imageCacheMap, &m_imageCacheKeyMap, deletionList); removeFromCacheListInternal(*deletionList); return false; } cacheEntry->incrementUseCount(); *cachedImage = image; return true; }
const ScaledImageFragment* ImageDecodingStore::insertAndLockCache(const ImageFrameGenerator* generator, PassOwnPtr<ScaledImageFragment> image, PassOwnPtr<ImageDecoder> decoder) { // Prune old cache entries to give space for the new one. prune(); ScaledImageFragment* cachedImage = image.get(); OwnPtr<CacheEntry> newCacheEntry; // ImageDecoder is not used any more if cache is complete. if (image->isComplete()) newCacheEntry = CacheEntry::createAndUse(generator, image); else newCacheEntry = CacheEntry::createAndUse(generator, image, decoder); MutexLocker lock(m_mutex); // Lock the underlying SkBitmap to prevent it from being purged. cachedImage->bitmap().lockPixels(); ASSERT(!m_cacheMap.contains(newCacheEntry->cacheKey())); insertCacheInternal(newCacheEntry.release()); return cachedImage; }
bool ImageDecodingStore::lockCache(const ImageFrameGenerator* generator, const SkISize& scaledSize, CacheCondition condition, const ScaledImageFragment** cachedImage, ImageDecoder** decoder) { ASSERT(cachedImage); CacheEntry* cacheEntry = 0; Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete; { MutexLocker lock(m_mutex); CacheMap::iterator iter = m_cacheMap.find(std::make_pair(generator, scaledSize)); if (iter == m_cacheMap.end()) return false; cacheEntry = iter->value.get(); ScaledImageFragment* image = cacheEntry->cachedImage(); if (condition == CacheMustBeComplete && !image->isComplete()) return false; // Incomplete cache entry cannot be used more than once. ASSERT(image->isComplete() || !cacheEntry->useCount()); image->bitmap().lockPixels(); if (image->bitmap().getPixels()) { // Increment use count such that it doesn't get evicted. cacheEntry->incrementUseCount(); // Complete cache entry doesn't have a decoder. ASSERT(!image->isComplete() || !cacheEntry->cachedDecoder()); if (decoder) *decoder = cacheEntry->cachedDecoder(); *cachedImage = image; } else { image->bitmap().unlockPixels(); removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete); removeFromCacheListInternal(cacheEntriesToDelete); return false; } } return true; }