Upstream version 10.38.222.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkScaledImageCache.cpp
index c436417..dca7596 100644 (file)
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "SkChecksum.h"
 #include "SkScaledImageCache.h"
 #include "SkMipMap.h"
-#include "SkOnce.h"
 #include "SkPixelRef.h"
 #include "SkRect.h"
 
@@ -30,32 +30,6 @@ static inline SkScaledImageCache::Rec* id_to_rec(SkScaledImageCache::ID* id) {
     return reinterpret_cast<SkScaledImageCache::Rec*>(id);
 }
 
- // Implemented from en.wikipedia.org/wiki/MurmurHash.
-static uint32_t compute_hash(const uint32_t data[], int count) {
-    uint32_t hash = 0;
-
-    for (int i = 0; i < count; ++i) {
-        uint32_t k = data[i];
-        k *= 0xcc9e2d51;
-        k = (k << 15) | (k >> 17);
-        k *= 0x1b873593;
-
-        hash ^= k;
-        hash = (hash << 13) | (hash >> 19);
-        hash *= 5;
-        hash += 0xe6546b64;
-    }
-
-    //    hash ^= size;
-    hash ^= hash >> 16;
-    hash *= 0x85ebca6b;
-    hash ^= hash >> 13;
-    hash *= 0xc2b2ae35;
-    hash ^= hash >> 16;
-
-    return hash;
-}
-
 struct SkScaledImageCache::Key {
     Key(uint32_t genID,
         SkScalar scaleX,
@@ -65,7 +39,7 @@ struct SkScaledImageCache::Key {
         , fScaleX(scaleX)
         , fScaleY(scaleY)
         , fBounds(bounds) {
-        fHash = compute_hash(&fGenID, 7);
+        fHash = SkChecksum::Murmur3(&fGenID, 28);
     }
 
     bool operator<(const Key& other) const {
@@ -116,6 +90,9 @@ struct SkScaledImageCache::Rec {
         SkSafeUnref(fMip);
     }
 
+    static const Key& GetKey(const Rec& rec) { return rec.fKey; }
+    static uint32_t Hash(const Key& key) { return key.fHash; }
+
     size_t bytesUsed() const {
         return fMip ? fMip->getSize() : fBitmap.getSize();
     }
@@ -135,25 +112,9 @@ struct SkScaledImageCache::Rec {
 
 #include "SkTDynamicHash.h"
 
-namespace { // can't use static functions w/ template parameters
-const SkScaledImageCache::Key& key_from_rec(const SkScaledImageCache::Rec& rec) {
-    return rec.fKey;
-}
+class SkScaledImageCache::Hash :
+    public SkTDynamicHash<SkScaledImageCache::Rec, SkScaledImageCache::Key> {};
 
-uint32_t hash_from_key(const SkScaledImageCache::Key& key) {
-    return key.fHash;
-}
-
-bool eq_rec_key(const SkScaledImageCache::Rec& rec, const SkScaledImageCache::Key& key) {
-    return rec.fKey == key;
-}
-}
-
-class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec,
-                                                       SkScaledImageCache::Key,
-                                                       key_from_rec,
-                                                       hash_from_key,
-                                                       eq_rec_key> {};
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -179,12 +140,13 @@ void SkScaledImageCache::init() {
 #else
     fHash = NULL;
 #endif
-    fBytesUsed = 0;
+    fTotalBytesUsed = 0;
     fCount = 0;
+    fSingleAllocationByteLimit = 0;
     fAllocator = NULL;
 
     // One of these should be explicit set by the caller after we return.
-    fByteLimit = 0;
+    fTotalByteLimit = 0;
     fDiscardableFactory = NULL;
 }
 
@@ -197,8 +159,6 @@ public:
     SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_t rowBytes);
     ~SkOneShotDiscardablePixelRef();
 
-    SK_DECLARE_UNFLATTENABLE_OBJECT()
-
 protected:
     virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
     virtual void onUnlockPixels() SK_OVERRIDE;
@@ -280,7 +240,8 @@ private:
 bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
                                                        SkColorTable* ctable) {
     size_t size = bitmap->getSize();
-    if (0 == size) {
+    uint64_t size64 = bitmap->computeSize64();
+    if (0 == size || size64 > (uint64_t)size) {
         return false;
     }
 
@@ -290,7 +251,7 @@ bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
     }
 
     // can we relax this?
-    if (kPMColor_SkColorType != bitmap->colorType()) {
+    if (kN32_SkColorType != bitmap->colorType()) {
         return false;
     }
 
@@ -310,7 +271,7 @@ SkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) {
 
 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
     this->init();
-    fByteLimit = byteLimit;
+    fTotalByteLimit = byteLimit;
 }
 
 SkScaledImageCache::~SkScaledImageCache() {
@@ -515,10 +476,10 @@ void SkScaledImageCache::purgeAsNeeded() {
         byteLimit = SK_MaxU32;  // no limit based on bytes
     } else {
         countLimit = SK_MaxS32; // no limit based on count
-        byteLimit = fByteLimit;
+        byteLimit = fTotalByteLimit;
     }
 
-    size_t bytesUsed = fBytesUsed;
+    size_t bytesUsed = fTotalBytesUsed;
     int    countUsed = fCount;
 
     Rec* rec = fTail;
@@ -544,13 +505,13 @@ void SkScaledImageCache::purgeAsNeeded() {
         rec = prev;
     }
 
-    fBytesUsed = bytesUsed;
+    fTotalBytesUsed = bytesUsed;
     fCount = countUsed;
 }
 
-size_t SkScaledImageCache::setByteLimit(size_t newLimit) {
-    size_t prevLimit = fByteLimit;
-    fByteLimit = newLimit;
+size_t SkScaledImageCache::setTotalByteLimit(size_t newLimit) {
+    size_t prevLimit = fTotalByteLimit;
+    fTotalByteLimit = newLimit;
     if (newLimit < prevLimit) {
         this->purgeAsNeeded();
     }
@@ -610,7 +571,7 @@ void SkScaledImageCache::addToHead(Rec* rec) {
     if (!fTail) {
         fTail = rec;
     }
-    fBytesUsed += rec->bytesUsed();
+    fTotalBytesUsed += rec->bytesUsed();
     fCount += 1;
 
     this->validate();
@@ -622,14 +583,14 @@ void SkScaledImageCache::addToHead(Rec* rec) {
 void SkScaledImageCache::validate() const {
     if (NULL == fHead) {
         SkASSERT(NULL == fTail);
-        SkASSERT(0 == fBytesUsed);
+        SkASSERT(0 == fTotalBytesUsed);
         return;
     }
 
     if (fHead == fTail) {
         SkASSERT(NULL == fHead->fPrev);
         SkASSERT(NULL == fHead->fNext);
-        SkASSERT(fHead->bytesUsed() == fBytesUsed);
+        SkASSERT(fHead->bytesUsed() == fTotalBytesUsed);
         return;
     }
 
@@ -644,7 +605,7 @@ void SkScaledImageCache::validate() const {
     while (rec) {
         count += 1;
         used += rec->bytesUsed();
-        SkASSERT(used <= fBytesUsed);
+        SkASSERT(used <= fTotalBytesUsed);
         rec = rec->fNext;
     }
     SkASSERT(fCount == count);
@@ -674,30 +635,48 @@ void SkScaledImageCache::dump() const {
     }
 
     SkDebugf("SkScaledImageCache: count=%d bytes=%d locked=%d %s\n",
-             fCount, fBytesUsed, locked,
+             fCount, fTotalBytesUsed, locked,
              fDiscardableFactory ? "discardable" : "malloc");
 }
 
+size_t SkScaledImageCache::setSingleAllocationByteLimit(size_t newLimit) {
+    size_t oldLimit = fSingleAllocationByteLimit;
+    fSingleAllocationByteLimit = newLimit;
+    return oldLimit;
+}
+
+size_t SkScaledImageCache::getSingleAllocationByteLimit() const {
+    return fSingleAllocationByteLimit;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkThread.h"
 
 SK_DECLARE_STATIC_MUTEX(gMutex);
 static SkScaledImageCache* gScaledImageCache = NULL;
-static void cleanup_gScaledImageCache() { SkDELETE(gScaledImageCache); }
-
-static void create_cache(int) {
-#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
-    gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
-#else
-    gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
+static void cleanup_gScaledImageCache() {
+    // We'll clean this up in our own tests, but disable for clients.
+    // Chrome seems to have funky multi-process things going on in unit tests that
+    // makes this unsafe to delete when the main process atexit()s.
+    // SkLazyPtr does the same sort of thing.
+#if SK_DEVELOPER
+    SkDELETE(gScaledImageCache);
 #endif
 }
 
+/** Must hold gMutex when calling. */
 static SkScaledImageCache* get_cache() {
-    SK_DECLARE_STATIC_ONCE(once);
-    SkOnce(&once, create_cache, 0, cleanup_gScaledImageCache);
-    SkASSERT(NULL != gScaledImageCache);
+    // gMutex is always held when this is called, so we don't need to be fancy in here.
+    gMutex.assertHeld();
+    if (NULL == gScaledImageCache) {
+#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
+        gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
+#else
+        gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
+#endif
+        atexit(cleanup_gScaledImageCache);
+    }
     return gScaledImageCache;
 }
 
@@ -756,19 +735,19 @@ void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) {
 //    get_cache()->dump();
 }
 
-size_t SkScaledImageCache::GetBytesUsed() {
+size_t SkScaledImageCache::GetTotalBytesUsed() {
     SkAutoMutexAcquire am(gMutex);
-    return get_cache()->getBytesUsed();
+    return get_cache()->getTotalBytesUsed();
 }
 
-size_t SkScaledImageCache::GetByteLimit() {
+size_t SkScaledImageCache::GetTotalByteLimit() {
     SkAutoMutexAcquire am(gMutex);
-    return get_cache()->getByteLimit();
+    return get_cache()->getTotalByteLimit();
 }
 
-size_t SkScaledImageCache::SetByteLimit(size_t newLimit) {
+size_t SkScaledImageCache::SetTotalByteLimit(size_t newLimit) {
     SkAutoMutexAcquire am(gMutex);
-    return get_cache()->setByteLimit(newLimit);
+    return get_cache()->setTotalByteLimit(newLimit);
 }
 
 SkBitmap::Allocator* SkScaledImageCache::GetAllocator() {
@@ -781,18 +760,37 @@ void SkScaledImageCache::Dump() {
     get_cache()->dump();
 }
 
+size_t SkScaledImageCache::SetSingleAllocationByteLimit(size_t size) {
+    SkAutoMutexAcquire am(gMutex);
+    return get_cache()->setSingleAllocationByteLimit(size);
+}
+
+size_t SkScaledImageCache::GetSingleAllocationByteLimit() {
+    SkAutoMutexAcquire am(gMutex);
+    return get_cache()->getSingleAllocationByteLimit();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkGraphics.h"
 
-size_t SkGraphics::GetImageCacheBytesUsed() {
-    return SkScaledImageCache::GetBytesUsed();
+size_t SkGraphics::GetImageCacheTotalBytesUsed() {
+    return SkScaledImageCache::GetTotalBytesUsed();
 }
 
-size_t SkGraphics::GetImageCacheByteLimit() {
-    return SkScaledImageCache::GetByteLimit();
+size_t SkGraphics::GetImageCacheTotalByteLimit() {
+    return SkScaledImageCache::GetTotalByteLimit();
 }
 
-size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) {
-    return SkScaledImageCache::SetByteLimit(newLimit);
+size_t SkGraphics::SetImageCacheTotalByteLimit(size_t newLimit) {
+    return SkScaledImageCache::SetTotalByteLimit(newLimit);
 }
+
+size_t SkGraphics::GetImageCacheSingleAllocationByteLimit() {
+    return SkScaledImageCache::GetSingleAllocationByteLimit();
+}
+
+size_t SkGraphics::SetImageCacheSingleAllocationByteLimit(size_t newLimit) {
+    return SkScaledImageCache::SetSingleAllocationByteLimit(newLimit);
+}
+