Index: Source/core/platform/graphics/ImageDecodingStore.cpp |
diff --git a/Source/core/platform/graphics/ImageDecodingStore.cpp b/Source/core/platform/graphics/ImageDecodingStore.cpp |
deleted file mode 100644 |
index 036bf843e3ba70a284194dd299de8e8c562c7aaf..0000000000000000000000000000000000000000 |
--- a/Source/core/platform/graphics/ImageDecodingStore.cpp |
+++ /dev/null |
@@ -1,408 +0,0 @@ |
-/* |
- * Copyright (C) 2012 Google Inc. All rights reserved. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions |
- * are met: |
- * 1. Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright |
- * notice, this list of conditions and the following disclaimer in the |
- * documentation and/or other materials provided with the distribution. |
- * |
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#include "config.h" |
-#include "core/platform/graphics/ImageDecodingStore.h" |
- |
-#include "platform/TraceEvent.h" |
- |
-namespace WebCore { |
- |
-namespace { |
- |
-// 32MB memory limit for cache. |
-static const size_t defaultCacheLimitInBytes = 32768 * 1024; |
-static ImageDecodingStore* s_instance = 0; |
- |
-static void setInstance(ImageDecodingStore* imageDecodingStore) |
-{ |
- delete s_instance; |
- s_instance = imageDecodingStore; |
-} |
- |
-} // namespace |
- |
-ImageDecodingStore::ImageDecodingStore() |
- : m_cacheLimitInBytes(defaultCacheLimitInBytes) |
- , m_memoryUsageInBytes(0) |
-{ |
-} |
- |
-ImageDecodingStore::~ImageDecodingStore() |
-{ |
-#ifndef NDEBUG |
- setCacheLimitInBytes(0); |
- ASSERT(!m_imageCacheMap.size()); |
- ASSERT(!m_decoderCacheMap.size()); |
- ASSERT(!m_orderedCacheList.size()); |
- ASSERT(!m_imageCacheKeyMap.size()); |
- ASSERT(!m_decoderCacheKeyMap.size()); |
-#endif |
-} |
- |
-ImageDecodingStore* ImageDecodingStore::instance() |
-{ |
- return s_instance; |
-} |
- |
-void ImageDecodingStore::initializeOnce() |
-{ |
- setInstance(ImageDecodingStore::create().leakPtr()); |
-} |
- |
-void ImageDecodingStore::shutdown() |
-{ |
- setInstance(0); |
-} |
- |
-bool ImageDecodingStore::lockCache(const ImageFrameGenerator* generator, const SkISize& scaledSize, size_t index, const ScaledImageFragment** cachedImage) |
-{ |
- ASSERT(cachedImage); |
- |
- Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete; |
- { |
- MutexLocker lock(m_mutex); |
- // Public access is restricted to complete images only. |
- ImageCacheMap::iterator iter = m_imageCacheMap.find(ImageCacheEntry::makeCacheKey(generator, scaledSize, index, ScaledImageFragment::CompleteImage)); |
- if (iter == m_imageCacheMap.end()) |
- return false; |
- return lockCacheEntryInternal(iter->value.get(), cachedImage, &cacheEntriesToDelete); |
- } |
-} |
- |
-void ImageDecodingStore::unlockCache(const ImageFrameGenerator* generator, const ScaledImageFragment* cachedImage) |
-{ |
- MutexLocker lock(m_mutex); |
- cachedImage->bitmap().unlockPixels(); |
- ImageCacheMap::iterator iter = m_imageCacheMap.find(ImageCacheEntry::makeCacheKey(generator, cachedImage->scaledSize(), cachedImage->index(), cachedImage->generation())); |
- ASSERT_WITH_SECURITY_IMPLICATION(iter != m_imageCacheMap.end()); |
- |
- CacheEntry* cacheEntry = iter->value.get(); |
- cacheEntry->decrementUseCount(); |
- |
- // Put the entry to the end of list. |
- m_orderedCacheList.remove(cacheEntry); |
- m_orderedCacheList.append(cacheEntry); |
-} |
- |
-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::lockDecoder(const ImageFrameGenerator* generator, const SkISize& scaledSize, ImageDecoder** decoder) |
-{ |
- ASSERT(decoder); |
- |
- MutexLocker lock(m_mutex); |
- DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::makeCacheKey(generator, scaledSize)); |
- if (iter == m_decoderCacheMap.end()) |
- return false; |
- |
- DecoderCacheEntry* cacheEntry = iter->value.get(); |
- |
- // There can only be one user of a decoder at a time. |
- ASSERT(!cacheEntry->useCount()); |
- cacheEntry->incrementUseCount(); |
- *decoder = cacheEntry->cachedDecoder(); |
- return true; |
-} |
- |
-void ImageDecodingStore::unlockDecoder(const ImageFrameGenerator* generator, const ImageDecoder* decoder) |
-{ |
- MutexLocker lock(m_mutex); |
- DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::makeCacheKey(generator, decoder)); |
- ASSERT_WITH_SECURITY_IMPLICATION(iter != m_decoderCacheMap.end()); |
- |
- CacheEntry* cacheEntry = iter->value.get(); |
- cacheEntry->decrementUseCount(); |
- |
- // Put the entry to the end of list. |
- m_orderedCacheList.remove(cacheEntry); |
- m_orderedCacheList.append(cacheEntry); |
-} |
- |
-void ImageDecodingStore::insertDecoder(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable) |
-{ |
- // Prune old cache entries to give space for the new one. |
- prune(); |
- |
- OwnPtr<DecoderCacheEntry> newCacheEntry = DecoderCacheEntry::create(generator, decoder, isDiscardable); |
- |
- MutexLocker lock(m_mutex); |
- ASSERT(!m_decoderCacheMap.contains(newCacheEntry->cacheKey())); |
- insertCacheInternal(newCacheEntry.release(), &m_decoderCacheMap, &m_decoderCacheKeyMap); |
-} |
- |
-void ImageDecodingStore::removeDecoder(const ImageFrameGenerator* generator, const ImageDecoder* decoder) |
-{ |
- Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete; |
- { |
- MutexLocker lock(m_mutex); |
- DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::makeCacheKey(generator, decoder)); |
- ASSERT_WITH_SECURITY_IMPLICATION(iter != m_decoderCacheMap.end()); |
- |
- CacheEntry* cacheEntry = iter->value.get(); |
- ASSERT(cacheEntry->useCount()); |
- cacheEntry->decrementUseCount(); |
- |
- // Delete only one decoder cache entry. Ownership of the cache entry |
- // is transfered to cacheEntriesToDelete such that object can be deleted |
- // outside of the lock. |
- removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete); |
- |
- // Remove from LRU list. |
- removeFromCacheListInternal(cacheEntriesToDelete); |
- } |
-} |
- |
-bool ImageDecodingStore::isCached(const ImageFrameGenerator* generator, const SkISize& scaledSize, size_t index) |
-{ |
- MutexLocker lock(m_mutex); |
- ImageCacheMap::iterator iter = m_imageCacheMap.find(ImageCacheEntry::makeCacheKey(generator, scaledSize, index, ScaledImageFragment::CompleteImage)); |
- if (iter == m_imageCacheMap.end()) |
- return false; |
- return true; |
-} |
- |
-void ImageDecodingStore::removeCacheIndexedByGenerator(const ImageFrameGenerator* generator) |
-{ |
- Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete; |
- { |
- MutexLocker lock(m_mutex); |
- |
- // Remove image cache objects and decoder cache objects associated |
- // with a ImageFrameGenerator. |
- removeCacheIndexedByGeneratorInternal(&m_imageCacheMap, &m_imageCacheKeyMap, generator, &cacheEntriesToDelete); |
- removeCacheIndexedByGeneratorInternal(&m_decoderCacheMap, &m_decoderCacheKeyMap, generator, &cacheEntriesToDelete); |
- |
- // Remove from LRU list as well. |
- removeFromCacheListInternal(cacheEntriesToDelete); |
- } |
-} |
- |
-void ImageDecodingStore::clear() |
-{ |
- size_t cacheLimitInBytes; |
- { |
- MutexLocker lock(m_mutex); |
- cacheLimitInBytes = m_cacheLimitInBytes; |
- m_cacheLimitInBytes = 0; |
- } |
- |
- prune(); |
- |
- { |
- MutexLocker lock(m_mutex); |
- m_cacheLimitInBytes = cacheLimitInBytes; |
- } |
-} |
- |
-void ImageDecodingStore::setCacheLimitInBytes(size_t cacheLimit) |
-{ |
- { |
- MutexLocker lock(m_mutex); |
- m_cacheLimitInBytes = cacheLimit; |
- } |
- prune(); |
-} |
- |
-size_t ImageDecodingStore::memoryUsageInBytes() |
-{ |
- MutexLocker lock(m_mutex); |
- return m_memoryUsageInBytes; |
-} |
- |
-int ImageDecodingStore::cacheEntries() |
-{ |
- MutexLocker lock(m_mutex); |
- return m_imageCacheMap.size() + m_decoderCacheMap.size(); |
-} |
- |
-int ImageDecodingStore::imageCacheEntries() |
-{ |
- MutexLocker lock(m_mutex); |
- return m_imageCacheMap.size(); |
-} |
- |
-int ImageDecodingStore::decoderCacheEntries() |
-{ |
- MutexLocker lock(m_mutex); |
- return m_decoderCacheMap.size(); |
-} |
- |
-void ImageDecodingStore::prune() |
-{ |
- TRACE_EVENT0("webkit", "ImageDecodingStore::prune"); |
- |
- Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete; |
- { |
- MutexLocker lock(m_mutex); |
- |
- // Head of the list is the least recently used entry. |
- const CacheEntry* cacheEntry = m_orderedCacheList.head(); |
- |
- // Walk the list of cache entries starting from the least recently used |
- // and then keep them for deletion later. |
- while (cacheEntry && (m_memoryUsageInBytes > m_cacheLimitInBytes || !m_cacheLimitInBytes)) { |
- // Cache is not used; Remove it. |
- if (!cacheEntry->useCount()) |
- removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete); |
- cacheEntry = cacheEntry->next(); |
- } |
- |
- // Remove from cache list as well. |
- removeFromCacheListInternal(cacheEntriesToDelete); |
- } |
-} |
- |
-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; |
-} |
- |
-template<class T, class U, class V> |
-void ImageDecodingStore::insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap) |
-{ |
- // Usage of discardable memory is not counted because we want to use more |
- // than the cache limit allows. Cache limit only applies to non-discardable |
- // objects. |
- if (!cacheEntry->isDiscardable()) |
- incrementMemoryUsage(cacheEntry->memoryUsageInBytes()); |
- |
- // m_orderedCacheList is used to support LRU operations to reorder cache |
- // entries quickly. |
- m_orderedCacheList.append(cacheEntry.get()); |
- |
- typename U::KeyType key = cacheEntry->cacheKey(); |
- typename V::AddResult result = identifierMap->add(cacheEntry->generator(), typename V::MappedType()); |
- result.iterator->value.add(key); |
- cacheMap->add(key, cacheEntry); |
- |
- TRACE_COUNTER1("webkit", "ImageDecodingStoreMemoryUsageBytes", m_memoryUsageInBytes); |
- TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfImages", m_imageCacheMap.size()); |
- TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfDecoders", m_decoderCacheMap.size()); |
-} |
- |
-template<class T, class U, class V> |
-void ImageDecodingStore::removeFromCacheInternal(const T* cacheEntry, U* cacheMap, V* identifierMap, Vector<OwnPtr<CacheEntry> >* deletionList) |
-{ |
- if (!cacheEntry->isDiscardable()) |
- decrementMemoryUsage(cacheEntry->memoryUsageInBytes()); |
- |
- // Remove entry from identifier map. |
- typename V::iterator iter = identifierMap->find(cacheEntry->generator()); |
- ASSERT(iter != identifierMap->end()); |
- iter->value.remove(cacheEntry->cacheKey()); |
- if (!iter->value.size()) |
- identifierMap->remove(iter); |
- |
- // Remove entry from cache map. |
- deletionList->append(cacheMap->take(cacheEntry->cacheKey())); |
- |
- TRACE_COUNTER1("webkit", "ImageDecodingStoreMemoryUsageBytes", m_memoryUsageInBytes); |
- TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfImages", m_imageCacheMap.size()); |
- TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfDecoders", m_decoderCacheMap.size()); |
-} |
- |
-void ImageDecodingStore::removeFromCacheInternal(const CacheEntry* cacheEntry, Vector<OwnPtr<CacheEntry> >* deletionList) |
-{ |
- if (cacheEntry->type() == CacheEntry::TypeImage) { |
- removeFromCacheInternal(static_cast<const ImageCacheEntry*>(cacheEntry), &m_imageCacheMap, &m_imageCacheKeyMap, deletionList); |
- } else if (cacheEntry->type() == CacheEntry::TypeDecoder) { |
- removeFromCacheInternal(static_cast<const DecoderCacheEntry*>(cacheEntry), &m_decoderCacheMap, &m_decoderCacheKeyMap, deletionList); |
- } else { |
- ASSERT(false); |
- } |
-} |
- |
-template<class U, class V> |
-void ImageDecodingStore::removeCacheIndexedByGeneratorInternal(U* cacheMap, V* identifierMap, const ImageFrameGenerator* generator, Vector<OwnPtr<CacheEntry> >* deletionList) |
-{ |
- typename V::iterator iter = identifierMap->find(generator); |
- if (iter == identifierMap->end()) |
- return; |
- |
- // Get all cache identifiers associated with generator. |
- Vector<typename U::KeyType> cacheIdentifierList; |
- copyToVector(iter->value, cacheIdentifierList); |
- |
- // For each cache identifier find the corresponding CacheEntry and remove it. |
- for (size_t i = 0; i < cacheIdentifierList.size(); ++i) { |
- ASSERT(cacheMap->contains(cacheIdentifierList[i])); |
- const typename U::MappedType::PtrType cacheEntry = cacheMap->get(cacheIdentifierList[i]); |
- ASSERT(!cacheEntry->useCount()); |
- removeFromCacheInternal(cacheEntry, cacheMap, identifierMap, deletionList); |
- } |
-} |
- |
-void ImageDecodingStore::removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry> >& deletionList) |
-{ |
- for (size_t i = 0; i < deletionList.size(); ++i) |
- m_orderedCacheList.remove(deletionList[i].get()); |
-} |
- |
-} // namespace WebCore |