#ifndef ImageDecodingStore_h
#define ImageDecodingStore_h
#include "SkSize.h"
#include "SkTypes.h"
#include "platform/PlatformExport.h"
#include "platform/graphics/DiscardablePixelRef.h"
#include "platform/graphics/ScaledImageFragment.h"
#include "platform/graphics/skia/SkSizeHash.h"
#include "platform/image-decoders/ImageDecoder.h"
#include "wtf/DoublyLinkedList.h"
#include "wtf/HashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/ThreadingPrimitives.h"
#include "wtf/Vector.h"
namespace WebCore {
class ImageFrameGenerator;
class SharedBuffer;
class PLATFORM_EXPORT ImageDecodingStore {
public:
static PassOwnPtr<ImageDecodingStore> create() { return adoptPtr(new ImageDecodingStore); }
~ImageDecodingStore();
static ImageDecodingStore* instance();
static void initializeOnce();
static void shutdown();
static void setImageCachingEnabled(bool);
bool lockCache(const ImageFrameGenerator*, const SkISize& scaledSize, size_t index, const ScaledImageFragment**);
void unlockCache(const ImageFrameGenerator*, const ScaledImageFragment*);
const ScaledImageFragment* insertAndLockCache(const ImageFrameGenerator*, PassOwnPtr<ScaledImageFragment>);
bool lockDecoder(const ImageFrameGenerator*, const SkISize& scaledSize, ImageDecoder**);
void unlockDecoder(const ImageFrameGenerator*, const ImageDecoder*);
void insertDecoder(const ImageFrameGenerator*, PassOwnPtr<ImageDecoder>, bool isDiscardable);
void removeDecoder(const ImageFrameGenerator*, const ImageDecoder*);
bool isCached(const ImageFrameGenerator*, const SkISize& scaledSize, size_t index);
void removeCacheIndexedByGenerator(const ImageFrameGenerator*);
void clear();
void setCacheLimitInBytes(size_t);
size_t memoryUsageInBytes();
int cacheEntries();
int imageCacheEntries();
int decoderCacheEntries();
private:
typedef std::pair<const ImageFrameGenerator*, SkISize> DecoderCacheKey;
typedef std::pair<size_t, size_t> IndexAndGeneration;
typedef std::pair<DecoderCacheKey, IndexAndGeneration> ImageCacheKey;
class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
friend class WTF::DoublyLinkedListNode<CacheEntry>;
public:
enum CacheType {
TypeImage,
TypeDecoder,
};
CacheEntry(const ImageFrameGenerator* generator, int useCount, bool isDiscardable)
: m_generator(generator)
, m_useCount(useCount)
, m_isDiscardable(isDiscardable)
, m_prev(0)
, m_next(0)
{
}
virtual ~CacheEntry()
{
ASSERT(!m_useCount);
}
const ImageFrameGenerator* generator() const { return m_generator; }
int useCount() const { return m_useCount; }
void incrementUseCount() { ++m_useCount; }
void decrementUseCount() { --m_useCount; ASSERT(m_useCount >= 0); }
bool isDiscardable() const { return m_isDiscardable; }
virtual size_t memoryUsageInBytes() const = 0;
virtual CacheType type() const = 0;
protected:
const ImageFrameGenerator* m_generator;
int m_useCount;
bool m_isDiscardable;
private:
CacheEntry* m_prev;
CacheEntry* m_next;
};
class ImageCacheEntry FINAL : public CacheEntry {
public:
static PassOwnPtr<ImageCacheEntry> createAndUse(const ImageFrameGenerator* generator, PassOwnPtr<ScaledImageFragment> image)
{
return adoptPtr(new ImageCacheEntry(generator, 1, image));
}
ImageCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ScaledImageFragment> image)
: CacheEntry(generator, count, DiscardablePixelRef::isDiscardable(image->bitmap().pixelRef()))
, m_cachedImage(image)
{
}
virtual size_t memoryUsageInBytes() const OVERRIDE { return cachedImage()->bitmap().getSafeSize(); }
virtual CacheType type() const OVERRIDE { return TypeImage; }
static ImageCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size, size_t index, size_t generation)
{
return std::make_pair(std::make_pair(generator, size), std::make_pair(index, generation));
}
ImageCacheKey cacheKey() const { return makeCacheKey(m_generator, m_cachedImage->scaledSize(), m_cachedImage->index(), m_cachedImage->generation()); }
const ScaledImageFragment* cachedImage() const { return m_cachedImage.get(); }
ScaledImageFragment* cachedImage() { return m_cachedImage.get(); }
private:
OwnPtr<ScaledImageFragment> m_cachedImage;
};
class DecoderCacheEntry FINAL : public CacheEntry {
public:
static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable)
{
return adoptPtr(new DecoderCacheEntry(generator, 0, decoder, isDiscardable));
}
DecoderCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable)
: CacheEntry(generator, count, isDiscardable)
, m_cachedDecoder(decoder)
, m_size(SkISize::Make(m_cachedDecoder->decodedSize().width(), m_cachedDecoder->decodedSize().height()))
{
}
virtual size_t memoryUsageInBytes() const OVERRIDE { return m_size.width() * m_size.height() * 4; }
virtual CacheType type() const OVERRIDE { return TypeDecoder; }
static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size)
{
return std::make_pair(generator, size);
}
static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const ImageDecoder* decoder)
{
return std::make_pair(generator, SkISize::Make(decoder->decodedSize().width(), decoder->decodedSize().height()));
}
DecoderCacheKey cacheKey() const { return makeCacheKey(m_generator, m_size); }
ImageDecoder* cachedDecoder() const { return m_cachedDecoder.get(); }
private:
OwnPtr<ImageDecoder> m_cachedDecoder;
SkISize m_size;
};
ImageDecodingStore();
void prune();
bool lockCacheEntryInternal(ImageCacheEntry*, const ScaledImageFragment**, Vector<OwnPtr<CacheEntry> >* deletionList);
template<class T, class U, class V> void insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap);
template<class T, class U, class V> void removeFromCacheInternal(const T* cacheEntry, U* cacheMap, V* identifierMap, Vector<OwnPtr<CacheEntry> >* deletionList);
void removeFromCacheInternal(const CacheEntry*, Vector<OwnPtr<CacheEntry> >* deletionList);
template<class U, class V> void removeCacheIndexedByGeneratorInternal(U* cacheMap, V* identifierMap, const ImageFrameGenerator*, Vector<OwnPtr<CacheEntry> >* deletionList);
void removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry> >& deletionList);
DoublyLinkedList<CacheEntry> m_orderedCacheList;
typedef HashMap<ImageCacheKey, OwnPtr<ImageCacheEntry> > ImageCacheMap;
ImageCacheMap m_imageCacheMap;
typedef HashMap<DecoderCacheKey, OwnPtr<DecoderCacheEntry> > DecoderCacheMap;
DecoderCacheMap m_decoderCacheMap;
typedef HashSet<ImageCacheKey> ImageCacheKeySet;
typedef HashMap<const ImageFrameGenerator*, ImageCacheKeySet> ImageCacheKeyMap;
ImageCacheKeyMap m_imageCacheKeyMap;
typedef HashSet<DecoderCacheKey> DecoderCacheKeySet;
typedef HashMap<const ImageFrameGenerator*, DecoderCacheKeySet> DecoderCacheKeyMap;
DecoderCacheKeyMap m_decoderCacheKeyMap;
size_t m_heapLimitInBytes;
size_t m_heapMemoryUsageInBytes;
size_t m_discardableMemoryUsageInBytes;
Mutex m_mutex;
};
}
#endif